summaryrefslogtreecommitdiff
path: root/shared/nm-glib-aux/nm-errno.h
blob: 1d329b258e67ce4683087aa2d558eb3e59e1a2cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// SPDX-License-Identifier: LGPL-2.1+
/*
 * Copyright (C) 2018 Red Hat, Inc.
 */

#ifndef __NM_ERRNO_H__
#define __NM_ERRNO_H__

#include <errno.h>

/*****************************************************************************/

enum _NMErrno {
	_NM_ERRNO_MININT         = G_MININT,
	_NM_ERRNO_MAXINT         = G_MAXINT,
	_NM_ERRNO_RESERVED_FIRST = 100000,


	/* when we cannot represent a number as positive number, we resort to this
	 * number. Basically, the values G_MININT, -NME_ERRNO_SUCCESS, NME_ERRNO_SUCCESS
	 * and G_MAXINT all map to the same value. */
	NME_ERRNO_OUT_OF_RANGE   = G_MAXINT,

	/* Indicate that the original errno was zero. Zero denotes *no error*, but we know something
	 * went wrong and we want to report some error. This is a placeholder to mean, something
	 * was wrong, but errno was zero. */
	NME_ERRNO_SUCCESS        = G_MAXINT - 1,


	/* an unspecified error. */
	NME_UNSPEC = _NM_ERRNO_RESERVED_FIRST,

	/* A bug, for example when an assertion failed.
	 * Should never happen. */
	NME_BUG,

	/* a native error number (from <errno.h>) cannot be mapped as
	 * an nm-error, because it is in the range [_NM_ERRNO_RESERVED_FIRST,
	 * _NM_ERRNO_RESERVED_LAST]. */
	NME_NATIVE_ERRNO,

	/* netlink errors. */
	NME_NL_SEQ_MISMATCH,
	NME_NL_MSG_TRUNC,
	NME_NL_MSG_TOOSHORT,
	NME_NL_DUMP_INTR,
	NME_NL_ATTRSIZE,
	NME_NL_BAD_SOCK,
	NME_NL_NOADDR,
	NME_NL_MSG_OVERFLOW,

	/* platform errors. */
	NME_PL_NOT_FOUND,
	NME_PL_EXISTS,
	NME_PL_WRONG_TYPE,
	NME_PL_NOT_SLAVE,
	NME_PL_NO_FIRMWARE,
	NME_PL_OPNOTSUPP,
	NME_PL_NETLINK,
	NME_PL_CANT_SET_MTU,

	_NM_ERRNO_RESERVED_LAST_PLUS_1,
	_NM_ERRNO_RESERVED_LAST = _NM_ERRNO_RESERVED_LAST_PLUS_1 - 1,
};

/*****************************************************************************/

/* When we receive an errno from a system function, we can safely assume
 * that the error number is not negative. We rely on that, and possibly just
 * "return -errsv;" to signal an error. We also rely on that, because libc
 * is our trusted base: meaning, if it cannot even succeed at setting errno
 * according to specification, all bets are off.
 *
 * This macro returns the input argument, and asserts that the error variable
 * is positive.
 *
 * In a sense, the macro is related to nm_errno_native() function, but the difference
 * is that this macro asserts that @errsv is positive, while nm_errno_native() coerces
 * negative values to be non-negative. */
#define NM_ERRNO_NATIVE(errsv) \
	({ \
		const int _errsv_x = (errsv); \
		\
		nm_assert (_errsv_x > 0); \
		_errsv_x; \
	})

/* Normalize native errno.
 *
 * Our API may return native error codes (<errno.h>) as negative values. This function
 * takes such an errno, and normalizes it to their positive value.
 *
 * The special values G_MININT and zero are coerced to NME_ERRNO_OUT_OF_RANGE and NME_ERRNO_SUCCESS
 * respectively.
 * Other values are coerced to their inverse.
 * Other positive values are returned unchanged.
 *
 * Basically, this normalizes errsv to be positive (taking care of two pathological cases).
 */
static inline int
nm_errno_native (int errsv)
{
	switch (errsv) {
	case 0:                  return NME_ERRNO_SUCCESS;
	case G_MININT:           return NME_ERRNO_OUT_OF_RANGE;
	default:
		return errsv >= 0 ? errsv : -errsv;
	}
}

/* Normalizes an nm-error to be positive.
 *
 * Various API returns negative error codes, and this function converts the negative
 * value to its positive.
 *
 * Note that @nmerr is on the domain of NetworkManager specific error numbers,
 * which is not the same as the native error numbers (errsv from <errno.h>). But
 * as far as normalizing goes, nm_errno() does exactly the same remapping as
 * nm_errno_native(). */
static inline int
nm_errno (int nmerr)
{
	return nm_errno_native (nmerr);
}

/* this maps a native errno to a (always non-negative) nm-error number.
 *
 * Note that nm-error numbers are embedded into the range of regular
 * errno. The only difference is, that nm-error numbers reserve a
 * range (_NM_ERRNO_RESERVED_FIRST, _NM_ERRNO_RESERVED_LAST) for their
 * own purpose.
 *
 * That means, converting an errno to nm-error number means in
 * most cases just returning itself.
 * Only pathological cases need special handling:
 *
 *  - 0 is mapped to NME_ERRNO_SUCCESS;
 *  - G_MININT is mapped to NME_ERRNO_OUT_OF_RANGE;
 *  - values in the range of (+/-) [_NM_ERRNO_RESERVED_FIRST, _NM_ERRNO_RESERVED_LAST]
 *    are mapped to NME_NATIVE_ERRNO
 *  - all other values are their (positive) absolute value.
 */
static inline int
nm_errno_from_native (int errsv)
{
	switch (errsv) {
	case 0:                  return NME_ERRNO_SUCCESS;
	case G_MININT:           return NME_ERRNO_OUT_OF_RANGE;
	default:
		if (errsv < 0)
			errsv = -errsv;
		return   G_UNLIKELY (   errsv >= _NM_ERRNO_RESERVED_FIRST
		                     && errsv <= _NM_ERRNO_RESERVED_LAST)
		       ? NME_NATIVE_ERRNO
		       : errsv;
	}
}

const char *nm_strerror (int nmerr);

/*****************************************************************************/

#define NM_STRERROR_BUFSIZE 1024

const char *nm_strerror_native_r (int errsv, char *buf, gsize buf_size);
const char *nm_strerror_native (int errsv);

/*****************************************************************************/

#endif /* __NM_ERRNO_H__ */