xref: /aosp_15_r20/external/libnl/include/base/nl-base-utils.h (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * Copyright (c) 2003-2012 Thomas Graf <[email protected]>
4  */
5 
6 #ifndef __NETLINK_BASE_NL_BASE_UTILS_H__
7 #define __NETLINK_BASE_NL_BASE_UTILS_H__
8 
9 #include <byteswap.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <limits.h>
13 #include <inttypes.h>
14 #include <assert.h>
15 #include <unistd.h>
16 #include <errno.h>
17 #include <string.h>
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 
23 #ifndef DISABLE_PTHREADS
24 #include <pthread.h>
25 #endif
26 
27 /*****************************************************************************/
28 
29 #if __BYTE_ORDER == __BIG_ENDIAN
30 #define ntohll(x) (x)
31 #elif __BYTE_ORDER == __LITTLE_ENDIAN
32 #define ntohll(x) bswap_64((x))
33 #endif
34 #define htonll(x) ntohll(x)
35 
36 /*****************************************************************************/
37 
38 #define _NL_STRINGIFY_ARG(contents) #contents
39 #define _NL_STRINGIFY(macro_or_string) _NL_STRINGIFY_ARG(macro_or_string)
40 
41 /*****************************************************************************/
42 
43 #if defined(__GNUC__)
44 #define _NL_PRAGMA_WARNING_DO(warning) \
45 	_NL_STRINGIFY(GCC diagnostic ignored warning)
46 #elif defined(__clang__)
47 #define _NL_PRAGMA_WARNING_DO(warning) \
48 	_NL_STRINGIFY(clang diagnostic ignored warning)
49 #endif
50 
51 /* you can only suppress a specific warning that the compiler
52  * understands. Otherwise you will get another compiler warning
53  * about invalid pragma option.
54  * It's not that bad however, because gcc and clang often have the
55  * same name for the same warning. */
56 
57 #if defined(__GNUC__) && \
58 	(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
59 #define _NL_PRAGMA_WARNING_DISABLE(warning)                 \
60 	_Pragma("GCC diagnostic push")                      \
61 		_Pragma(_NL_PRAGMA_WARNING_DO("-Wpragmas")) \
62 			_Pragma(_NL_PRAGMA_WARNING_DO(warning))
63 #elif defined(__clang__)
64 #define _NL_PRAGMA_WARNING_DISABLE(warning)                                \
65 	_Pragma("clang diagnostic push")                                   \
66 		_Pragma(_NL_PRAGMA_WARNING_DO("-Wunknown-warning-option")) \
67 			_Pragma(_NL_PRAGMA_WARNING_DO(warning))
68 #else
69 #define _NL_PRAGMA_WARNING_DISABLE(warning)
70 #endif
71 
72 #if defined(__GNUC__) && \
73 	(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
74 #define _NL_PRAGMA_WARNING_REENABLE _Pragma("GCC diagnostic pop")
75 #elif defined(__clang__)
76 #define _NL_PRAGMA_WARNING_REENABLE _Pragma("clang diagnostic pop")
77 #else
78 #define _NL_PRAGMA_WARNING_REENABLE
79 #endif
80 
81 /*****************************************************************************/
82 
83 #define _nl_packed __attribute__((__packed__))
84 #define _nl_unused __attribute__((__unused__))
85 #define _nl_always_inline __attribute__((__always_inline__))
86 #define _nl_used __attribute__((__used__))
87 #define _nl_pure __attribute__((__pure__))
88 #define _nl_const __attribute__((__const__))
89 #define _nl_noreturn __attribute__((__noreturn__))
90 #define _nl_warn_unused_result __attribute__((__warn_unused_result__))
91 #define _nl_printf(a, b) __attribute__((__format__(__printf__, a, b)))
92 #define _nl_align(s) __attribute__((__aligned__(s)))
93 #define _nl_section(s) __attribute__((__section__(s)))
94 #define _nl_alignof(type) __alignof(type)
95 #define _nl_alignas(type) _nl_align(_nl_alignof(type))
96 #define _nl_deprecated(msg) __attribute__((__deprecated__(msg)))
97 #define _nl_init __attribute__((constructor))
98 #define _nl_exit __attribute__((destructor))
99 #define _nl_auto(fcn) __attribute__((__cleanup__(fcn)))
100 
101 /*****************************************************************************/
102 
103 #ifdef thread_local
104 #define _nl_thread_local thread_local
105 /*
106  * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__
107  * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769
108  */
109 #elif __STDC_VERSION__ >= 201112L &&                     \
110 	!(defined(__STDC_NO_THREADS__) ||                \
111 	  (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && \
112 	   __GLIBC_MINOR__ < 16))
113 #define _nl_thread_local _Thread_local
114 #else
115 #define _nl_thread_local __thread
116 #endif
117 
118 /*****************************************************************************/
119 
120 #define _NL_STATIC_ASSERT(cond) ((void)sizeof(char[(cond) ? 1 : -1]))
121 
122 /*****************************************************************************/
123 
124 #if defined(NL_MORE_ASSERTS) && NL_MORE_ASSERTS > 0
125 #define _nl_assert(cond) assert(cond)
126 #else
127 #define _nl_assert(cond)              \
128 	do {                          \
129 		if (0) {              \
130 			assert(cond); \
131 		}                     \
132 	} while (0)
133 #endif
134 
135 #define _nl_assert_not_reached() assert(0)
136 
137 /*****************************************************************************/
138 
139 #define _NL_BIT(n) (1ull << (n))
140 
141 /*****************************************************************************/
142 
143 #define _NL_PASTE_ARGS(identifier1, identifier2) identifier1##identifier2
144 #define _NL_PASTE(identifier1, identifier2) \
145 	_NL_PASTE_ARGS(identifier1, identifier2)
146 
147 /* Taken from systemd's UNIQ_T and UNIQ macros. */
148 
149 #define _NL_UNIQ_T(x, uniq) _NL_PASTE(__unique_prefix_, _NL_PASTE(x, uniq))
150 #define _NL_UNIQ __COUNTER__
151 
152 /*****************************************************************************/
153 
154 #define _nl_assert_addr_family_or_unspec(addr_family)             \
155 	do {                                                      \
156 		typeof(addr_family) _addr_family = (addr_family); \
157                                                                   \
158 		_nl_assert(_addr_family == AF_UNSPEC ||           \
159 			   _addr_family == AF_INET ||             \
160 			   _addr_family == AF_INET6);             \
161 	} while (0)
162 
163 #define _nl_assert_addr_family(addr_family)                       \
164 	do {                                                      \
165 		typeof(addr_family) _addr_family = (addr_family); \
166                                                                   \
167 		_nl_assert(_addr_family == AF_INET ||             \
168 			   _addr_family == AF_INET6);             \
169 	} while (0)
170 
171 /*****************************************************************************/
172 
173 #define _NL_SWAP(pa, pb)                   \
174 	do {                               \
175 		typeof(*(pa)) *_pa = (pa); \
176 		typeof(*(pb)) *_pb = (pb); \
177 		typeof(*_pa) _tmp;         \
178                                            \
179 		_nl_assert(_pa);           \
180 		_nl_assert(_pb);           \
181 		_tmp = *_pa;               \
182 		*_pa = *_pb;               \
183 		*_pb = _tmp;               \
184 	} while (0)
185 
186 /*****************************************************************************/
187 
188 #define _NL_N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0]))
189 
190 #define ARRAY_SIZE(arr) _NL_N_ELEMENTS(arr)
191 
192 /*****************************************************************************/
193 
194 /* This is also defined in stddef.h */
195 #ifndef offsetof
196 #define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER)
197 #endif
198 
199 /*****************************************************************************/
200 
_nl_ptr_to_uintptr(const void * p)201 static inline uintptr_t _nl_ptr_to_uintptr(const void *p)
202 {
203 	/* in C, pointers can only be compared (with less-than or greater-than) under certain
204 	 * circumstances. Since uintptr_t is supposed to be able to represent the pointer
205 	 * as a plain integer and also support to convert the integer back to the pointer,
206 	 * it should be safer to compare the pointers directly.
207 	 *
208 	 * Of course, this function isn't very useful beyond that its use makes it clear
209 	 * that we want to compare pointers by value, which otherwise may not be valid. */
210 	return (uintptr_t)p;
211 }
212 
213 /*****************************************************************************/
214 
_nl_strcmp0(const char * s1,const char * s2)215 static inline int _nl_strcmp0(const char *s1, const char *s2)
216 {
217 	int c;
218 
219 	/* like g_strcmp0(), but this is inlinable.
220 	 *
221 	 * Also, it is guaranteed to return either -1, 0, or 1. */
222 	if (s1 == s2)
223 		return 0;
224 	if (!s1)
225 		return -1;
226 	if (!s2)
227 		return 1;
228 	c = strcmp(s1, s2);
229 	if (c < 0)
230 		return -1;
231 	if (c > 0)
232 		return 1;
233 	return 0;
234 }
235 
_nl_streq(const char * a,const char * b)236 static inline bool _nl_streq(const char *a, const char *b)
237 {
238 	return !strcmp(a, b);
239 }
240 
_nl_streq0(const char * a,const char * b)241 static inline bool _nl_streq0(const char *a, const char *b)
242 {
243 	return a == b || (a && b && _nl_streq(a, b));
244 }
245 
_nl_memcmp(const void * s1,const void * s2,size_t n)246 static inline int _nl_memcmp(const void *s1, const void *s2, size_t n)
247 {
248 	/* Workaround undefined behavior in memcmp() with NULL pointers. */
249 	if (n == 0)
250 		return 0;
251 	_nl_assert(s1);
252 	_nl_assert(s2);
253 	return memcmp(s1, s2, n);
254 }
255 
_nl_memeq(const void * s1,const void * s2,size_t len)256 static inline bool _nl_memeq(const void *s1, const void *s2, size_t len)
257 {
258 	return _nl_memcmp(s1, s2, len) == 0;
259 }
260 
_nl_memcpy(void * restrict dest,const void * restrict src,size_t n)261 static inline void *_nl_memcpy(void *restrict dest, const void *restrict src,
262 			       size_t n)
263 {
264 	/* Workaround undefined behavior in memcpy() with NULL pointers. */
265 	if (n == 0)
266 		return dest;
267 
268 	_nl_assert(src);
269 	return memcpy(dest, src, n);
270 }
271 
272 /*****************************************************************************/
273 
274 #define _NL_INT_IS_SIGNED(arg) (!(((typeof(arg))-1) > 0))
275 
276 #define _NL_INT_SAME_SIGNEDNESS(arg1, arg2) \
277 	(_NL_INT_IS_SIGNED(arg1) == _NL_INT_IS_SIGNED(arg2))
278 
279 /*****************************************************************************/
280 
281 /* glib's MIN()/MAX() macros don't have function-like behavior, in that they evaluate
282  * the argument possibly twice.
283  *
284  * Taken from systemd's MIN()/MAX() macros. */
285 
286 #define _NL_MIN(a, b) __NL_MIN(_NL_UNIQ, a, _NL_UNIQ, b)
287 #define __NL_MIN(aq, a, bq, b)                                                 \
288 	({                                                                     \
289 		typeof(a) _NL_UNIQ_T(A, aq) = (a);                             \
290 		typeof(b) _NL_UNIQ_T(B, bq) = (b);                             \
291                                                                                \
292 		_NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(_NL_UNIQ_T(A, aq),   \
293 							  _NL_UNIQ_T(B, bq))); \
294                                                                                \
295 		((_NL_UNIQ_T(A, aq) < _NL_UNIQ_T(B, bq)) ? _NL_UNIQ_T(A, aq) : \
296 							   _NL_UNIQ_T(B, bq)); \
297 	})
298 
299 #define _NL_MAX(a, b) __NL_MAX(_NL_UNIQ, a, _NL_UNIQ, b)
300 #define __NL_MAX(aq, a, bq, b)                                                 \
301 	({                                                                     \
302 		typeof(a) _NL_UNIQ_T(A, aq) = (a);                             \
303 		typeof(b) _NL_UNIQ_T(B, bq) = (b);                             \
304                                                                                \
305 		_NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(_NL_UNIQ_T(A, aq),   \
306 							  _NL_UNIQ_T(B, bq))); \
307                                                                                \
308 		((_NL_UNIQ_T(A, aq) > _NL_UNIQ_T(B, bq)) ? _NL_UNIQ_T(A, aq) : \
309 							   _NL_UNIQ_T(B, bq)); \
310 	})
311 
312 #define _NL_CLAMP(x, low, high) \
313 	__NL_CLAMP(_NL_UNIQ, x, _NL_UNIQ, low, _NL_UNIQ, high)
314 #define __NL_CLAMP(xq, x, lowq, low, highq, high)                     \
315 	({                                                            \
316 		typeof(x) _NL_UNIQ_T(X, xq) = (x);                    \
317 		typeof(low) _NL_UNIQ_T(LOW, lowq) = (low);            \
318 		typeof(high) _NL_UNIQ_T(HIGH, highq) = (high);        \
319                                                                       \
320 		_NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(            \
321 			_NL_UNIQ_T(X, xq), _NL_UNIQ_T(LOW, lowq)));   \
322 		_NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(            \
323 			_NL_UNIQ_T(X, xq), _NL_UNIQ_T(HIGH, highq))); \
324                                                                       \
325 		((_NL_UNIQ_T(X, xq) > _NL_UNIQ_T(HIGH, highq)) ?      \
326 			 _NL_UNIQ_T(HIGH, highq) :                    \
327 		 (_NL_UNIQ_T(X, xq) < _NL_UNIQ_T(LOW, lowq)) ?        \
328 			 _NL_UNIQ_T(LOW, lowq) :                      \
329 			 _NL_UNIQ_T(X, xq));                          \
330 	})
331 
332 #define _NL_MAX_WITH_CMP(cmp, a, b)               \
333 	({                                        \
334 		typeof(a) _a = (a);               \
335 		typeof(b) _b = (b);               \
336                                                   \
337 		(((cmp(_a, _b)) >= 0) ? _a : _b); \
338 	})
339 
340 /* evaluates to (void) if _A or _B are not constant or of different types */
341 #define _NL_CONST_MAX(_A, _B)                                            \
342 	(__builtin_choose_expr(                                          \
343 		(__builtin_constant_p(_A) && __builtin_constant_p(_B) && \
344 		 __builtin_types_compatible_p(typeof(_A), typeof(_B))),  \
345 		((_A) > (_B)) ? (_A) : (_B), ((void)0)))
346 
347 /*****************************************************************************/
348 
349 #define _NL_CMP_RETURN(c)                        \
350 	do {                                     \
351 		const int _cc = (c);             \
352                                                  \
353 		if (_cc)                         \
354 			return _cc < 0 ? -1 : 1; \
355 	} while (0)
356 
357 #define _NL_CMP_RETURN_DIRECT(c)                                  \
358 	/* Usually we want that our CMP functions return strictly
359 	 * -1, 0, or 1. _NL_CMP_RETURN_DIRECT() is like _NL_CMP_RETURN(),
360 	 *  except, it does not clamp the integer value. */ \
361 	do {                                                      \
362 		const int _cc = (c);                              \
363                                                                   \
364 		if (_cc)                                          \
365 			return _cc;                               \
366 	} while (0)
367 
368 #define _NL_CMP_SELF(a, b)          \
369 	do {                        \
370 		typeof(a) _a = (a); \
371 		typeof(b) _b = (b); \
372                                     \
373 		if (_a == _b)       \
374 			return 0;   \
375 		if (!_a)            \
376 			return -1;  \
377 		if (!_b)            \
378 			return 1;   \
379 	} while (0)
380 
381 /*****************************************************************************/
382 
383 #define _NL_CMP_DIRECT(a, b)                                        \
384 	do {                                                        \
385 		typeof(a) _a = (a);                                 \
386 		typeof(b) _b = (b);                                 \
387                                                                     \
388 		_NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(_a, _b)); \
389                                                                     \
390 		if (_a != _b)                                       \
391 			return (_a < _b) ? -1 : 1;                  \
392 	} while (0)
393 
394 #define _NL_CMP_DIRECT_UNSAFE(a, b)                                                     \
395 	/* This variant is "unsafe", because it evaluates the arguments more then once.
396 	 * This is only useful for bitfields, for which typeof() doesn't work.
397 	 * Don't use otherwise. */ \
398 	do {                                                                            \
399 		if ((a) != (b))                                                         \
400 			return ((a) < (b)) ? -1 : 1;                                    \
401 	} while (0)
402 
403 /* In the general case, direct pointer comparison is undefined behavior in C.
404  * Avoid that by casting pointers to void* and then to uintptr_t. This comparison
405  * is not really meaningful, except that it provides some kind of stable sort order
406  * between pointers (that can otherwise not be compared). */
407 #define _NL_CMP_DIRECT_PTR(a, b) \
408 	_NL_CMP_DIRECT(_nl_ptr_to_uintptr(a), _nl_ptr_to_uintptr(b))
409 
410 #define _NL_CMP_DIRECT_BOOL(a, b) _NL_CMP_DIRECT(!!(a), !!(b))
411 
412 #define _NL_CMP_DIRECT_MEMCMP(a, b, size) \
413 	_NL_CMP_RETURN(_nl_memcmp((a), (b), (size)))
414 
415 #define _NL_CMP_DIRECT_STRCMP(a, b) _NL_CMP_RETURN_DIRECT(strcmp((a), (b)))
416 
417 #define _NL_CMP_DIRECT_STRCMP0(a, b) \
418 	_NL_CMP_RETURN_DIRECT(_nl_strcmp0((a), (b)))
419 
420 #define _NL_CMP_DIRECT_STR_INTERNED(a, b)                                                    \
421 	/* This is interned strings, which are first checked for equality only using pointer
422      * comparison. Only in case of differences, the sort order is still determined by strcmp(). */ \
423 	do {                                                                                 \
424 		const char *const _a = (a);                                                  \
425 		const char *const _b = (b);                                                  \
426                                                                                              \
427 		if (_a != _b)                                                                \
428 			_NL_CMP_RETURN_DIRECT(_nl_strcmp0(_a, _b));                          \
429 	} while (0)
430 
431 #define _NL_CMP_DIRECT_IN6ADDR(a, b)                                     \
432 	do {                                                             \
433 		const struct in6_addr *const _a = (a);                   \
434 		const struct in6_addr *const _b = (b);                   \
435                                                                          \
436 		_NL_CMP_RETURN(memcmp(_a, _b, sizeof(struct in6_addr))); \
437 	} while (0)
438 
439 /*****************************************************************************/
440 
441 #define _NL_CMP_FIELD(a, b, field) _NL_CMP_DIRECT(((a)->field), ((b)->field))
442 
443 #define _NL_CMP_FIELD_UNSAFE(a, b, field)                                               \
444 	/* This variant is "unsafe", because it evaluates the arguments more then once.
445 	 * This is only useful for bitfields, for which typeof() doesn't work.
446 	 * Don't use otherwise. */ \
447 	_NL_CMP_DIRECT_UNSAFE(((a)->field), ((b)->field))
448 
449 #define _NL_CMP_FIELD_BOOL(a, b, field) \
450 	_NL_CMP_DIRECT_BOOL(((a)->field), ((b)->field))
451 
452 #define _NL_CMP_FIELD_STR(a, b, field) \
453 	_NL_CMP_DIRECT_STRCMP(((a)->field), ((b)->field))
454 
455 #define _NL_CMP_FIELD_STR0(a, b, field) \
456 	_NL_CMP_DIRECT_STRCMP0(((a)->field), ((b)->field))
457 
458 #define _NL_CMP_FIELD_STR_INTERNED(a, b, field) \
459 	_NL_CMP_DIRECT_STR_INTERNED(((a)->field), ((b)->field))
460 
461 #define _NL_CMP_FIELD_MEMCMP_LEN(a, b, field, len)          \
462 	_NL_CMP_DIRECT_MEMCMP(&((a)->field), &((b)->field), \
463 			      _NL_MIN(len, sizeof((a)->field)))
464 
465 #define _NL_CMP_FIELD_MEMCMP(a, b, field) \
466 	_NL_CMP_DIRECT_MEMCMP(&((a)->field), &((b)->field), sizeof((a)->field))
467 
468 #define _NL_CMP_FIELD_IN6ADDR(a, b, field) \
469 	_NL_CMP_DIRECT_IN6ADDR(&((a)->field), &((b)->field))
470 
471 /*****************************************************************************/
472 
473 /* internal macro to calculate the size of a struct @type up to (and including) @field.
474  * this will be used for .minlen policy fields, so that we require only a field of up
475  * to the given size. */
476 #define _nl_offsetofend(type, field) \
477 	(offsetof(type, field) + sizeof(((type *)NULL)->field))
478 
479 /*****************************************************************************/
480 
481 #define _nl_clear_pointer(pp, destroy)                                         \
482 	({                                                                     \
483 		__typeof__(*(pp)) *_pp = (pp);                                 \
484 		__typeof__(*_pp) _p;                                           \
485 		int _changed = 0;                                              \
486                                                                                \
487 		if (_pp && (_p = *_pp)) {                                      \
488 			_nl_unused const void *const _p_check_is_pointer = _p; \
489                                                                                \
490 			*_pp = NULL;                                           \
491                                                                                \
492 			(destroy)(_p);                                         \
493                                                                                \
494 			_changed = 1;                                          \
495 		}                                                              \
496 		_changed;                                                      \
497 	})
498 
499 #define _nl_clear_free(pp) _nl_clear_pointer(pp, free)
500 
501 #define _nl_steal_pointer(pp)                        \
502 	({                                           \
503 		__typeof__(*(pp)) *const _pp = (pp); \
504 		__typeof__(*_pp) _p = NULL;          \
505                                                      \
506 		if (_pp && (_p = *_pp)) {            \
507 			*_pp = NULL;                 \
508 		}                                    \
509                                                      \
510 		_p;                                  \
511 	})
512 
513 /*****************************************************************************/
514 
515 #define _nl_malloc_maybe_a(alloca_maxlen, bytes, to_free)  \
516 	({                                                 \
517 		const size_t _bytes = (bytes);             \
518 		__typeof__(to_free) _to_free = (to_free);  \
519 		__typeof__(*_to_free) _ptr;                \
520                                                            \
521 		_NL_STATIC_ASSERT((alloca_maxlen) <= 500); \
522 		_nl_assert(_to_free && !*_to_free);        \
523                                                            \
524 		if (_bytes <= (alloca_maxlen)) {           \
525 			_ptr = alloca(_bytes);             \
526 		} else {                                   \
527 			_ptr = malloc(_bytes);             \
528 			*_to_free = _ptr;                  \
529 		};                                         \
530                                                            \
531 		_ptr;                                      \
532 	})
533 
534 /*****************************************************************************/
535 
_nl_strncpy_trunc(char * dst,const char * src,size_t len)536 static inline char *_nl_strncpy_trunc(char *dst, const char *src, size_t len)
537 {
538 	/* we don't use/reimplement strlcpy(), because we want the fill-all-with-NUL
539 	 * behavior of strncpy(). This is just strncpy() with gracefully handling truncation
540 	 * (and disabling the "-Wstringop-truncation" warning).
541 	 *
542 	 * Note that truncation is silently accepted.
543 	 */
544 
545 	_NL_PRAGMA_WARNING_DISABLE("-Wstringop-truncation");
546 	_NL_PRAGMA_WARNING_DISABLE("-Wstringop-overflow");
547 
548 	if (len > 0) {
549 		_nl_assert(dst);
550 		_nl_assert(src);
551 
552 		strncpy(dst, src, len);
553 
554 		dst[len - 1] = '\0';
555 	}
556 
557 	_NL_PRAGMA_WARNING_REENABLE;
558 	_NL_PRAGMA_WARNING_REENABLE;
559 
560 	return dst;
561 }
562 
_nl_strncpy_assert(char * dst,const char * src,size_t len)563 static inline char *_nl_strncpy_assert(char *dst, const char *src, size_t len)
564 {
565 	/* we don't use/reimplement strlcpy(), because we want the fill-all-with-NUL
566 	 * behavior of strncpy(). This is just strncpy() with assertion against truncation
567 	 * (and disabling the "-Wstringop-truncation" warning).
568 	 *
569 	 * Note that truncation is still a bug and there is an _nl_assert()
570 	 * against that.
571 	 */
572 
573 	_NL_PRAGMA_WARNING_DISABLE("-Wstringop-truncation");
574 	_NL_PRAGMA_WARNING_DISABLE("-Wstringop-overflow");
575 
576 	if (len > 0) {
577 		_nl_assert(dst);
578 		_nl_assert(src);
579 
580 		strncpy(dst, src, len);
581 
582 		_nl_assert(dst[len - 1] == '\0');
583 
584 		dst[len - 1] = '\0';
585 	}
586 
587 	_NL_PRAGMA_WARNING_REENABLE;
588 	_NL_PRAGMA_WARNING_REENABLE;
589 
590 	return dst;
591 }
592 
593 #define _NL_RETURN_ON_ERR(cmd)       \
594 	do {                         \
595 		int _err;            \
596                                      \
597 		_err = (cmd);        \
598 		if (_err < 0)        \
599 			return _err; \
600 	} while (0)
601 
602 #define _NL_RETURN_E_ON_ERR(e, cmd)                 \
603 	do {                                        \
604 		int _err;                           \
605                                                     \
606 		_err = (cmd);                       \
607 		if (_err < 0) {                     \
608 			_NL_STATIC_ASSERT((e) > 0); \
609 			return -(e);                \
610 		}                                   \
611 	} while (0)
612 
613 /* _NL_RETURN_ON_PUT_ERR() shall only be used with a put command (nla_put or nlmsg_append).
614  * These commands can either fail with a regular error code (which gets propagated)
615  * or with -NLE_NOMEM. However, they don't really try to allocate memory, so we don't
616  * want to propagate -NLE_NOMEM. Instead, we coerce such failure to -NLE_MSGSIZE. */
617 #define _NL_RETURN_ON_PUT_ERR(put_cmd)                                                                  \
618 	do {                                                                                            \
619 		int _err;                                                                               \
620                                                                                                         \
621 		_err = (put_cmd);                                                                       \
622 		if (_err < 0) {                                                                         \
623 			if (_err == -NLE_NOMEM) {                                                       \
624 				/* nla_put() returns -NLE_NOMEM in case of out of buffer size. We don't
625 				 * want to propagate that error and map it to -NLE_MSGSIZE. */ \
626 				return -NLE_MSGSIZE;                                                    \
627 			}                                                                               \
628 			/* any other error can only be due to invalid parameters. Propagate the
629 			 * error, however also assert that it cannot be reached. */         \
630 			_nl_assert_not_reached();                                                       \
631 			return _err;                                                                    \
632 		} else                                                                                  \
633 			_nl_assert(_err == 0);                                                          \
634 	} while (0)
635 
_nl_close(int fd)636 static inline int _nl_close(int fd)
637 {
638 	int r;
639 
640 	r = close(fd);
641 	_nl_assert(r == 0 || fd < 0 || errno != EBADF);
642 	return r;
643 }
644 
_nl_memdup(const void * ptr,size_t len)645 static inline void *_nl_memdup(const void *ptr, size_t len)
646 {
647 	void *p;
648 
649 	if (len == 0) {
650 		/* malloc() leaves it implementation defined whether to return NULL.
651 		 * Callers rely on returning NULL if len is zero. */
652 		return NULL;
653 	}
654 
655 	p = malloc(len);
656 	if (!p)
657 		return NULL;
658 	memcpy(p, ptr, len);
659 	return p;
660 }
661 
662 #define _nl_memdup_ptr(ptr) ((__typeof__(ptr))_nl_memdup((ptr), sizeof(*(ptr))))
663 
664 /*****************************************************************************/
665 
_nl_addr_family_to_size(int addr_family)666 static inline size_t _nl_addr_family_to_size(int addr_family)
667 {
668 	if (addr_family == AF_INET)
669 		return sizeof(in_addr_t);
670 	if (addr_family == AF_INET6)
671 		return sizeof(struct in6_addr);
672 	return 0;
673 }
674 
675 /*****************************************************************************/
676 
677 typedef union {
678 	in_addr_t addr4;
679 	struct in_addr a4;
680 	struct in6_addr a6;
681 } _NLIPAddr;
682 
_nl_inet_ntop(int addr_family,const void * addr,char * buf)683 static inline char *_nl_inet_ntop(int addr_family, const void *addr, char *buf)
684 {
685 	char *r;
686 
687 	_nl_assert_addr_family(addr_family);
688 	_nl_assert(addr);
689 
690 	/* inet_ntop() is documented to fail, but if we pass a known address family
691 	 * and a suitably large buffer, it cannot. Assert for that. */
692 
693 	r = (char *)inet_ntop(addr_family, addr, buf,
694 			      (addr_family == AF_INET) ? INET_ADDRSTRLEN :
695 							 INET6_ADDRSTRLEN);
696 	_nl_assert(r == buf);
697 	_nl_assert(strlen(r) < ((addr_family == AF_INET) ? INET_ADDRSTRLEN :
698 							   INET6_ADDRSTRLEN));
699 
700 	return r;
701 }
702 
_nl_inet_ntop_dup(int addr_family,const void * addr)703 static inline char *_nl_inet_ntop_dup(int addr_family, const void *addr)
704 {
705 	return (char *)_nl_inet_ntop(addr_family, addr,
706 				     malloc((addr_family == AF_INET) ?
707 						    INET_ADDRSTRLEN :
708 						    INET6_ADDRSTRLEN));
709 }
710 
711 /*****************************************************************************/
712 
713 #define _NL_AUTO_DEFINE_FCN_VOID0(CastType, name, func) \
714 	static inline void name(void *v)                \
715 	{                                               \
716 		if (*((CastType *)v))                   \
717 			func(*((CastType *)v));         \
718 	}                                               \
719 	struct _nl_dummy_for_tailing_semicolon
720 
721 #define _NL_AUTO_DEFINE_FCN_STRUCT(CastType, name, func) \
722 	static inline void name(CastType *v)             \
723 	{                                                \
724 		if (v)                                   \
725 			func(v);                         \
726 	}                                                \
727 	struct _nl_dummy_for_tailing_semicolon
728 
729 #define _NL_AUTO_DEFINE_FCN_TYPED0(CastType, name, func) \
730 	static inline void name(CastType *v)             \
731 	{                                                \
732 		if (*v)                                  \
733 			func(*v);                        \
734 	}                                                \
735 	struct _nl_dummy_for_tailing_semicolon
736 
737 #define _NL_AUTO_DEFINE_FCN_INDIRECT0(CastType, name, func) \
738 	static inline void name(CastType *v)                \
739 	{                                                   \
740 		if (*v)                                     \
741 			func(v);                            \
742 	}                                                   \
743 	struct _nl_dummy_for_tailing_semicolon
744 
745 #define _nl_auto_free _nl_auto(_nl_auto_free_fcn)
746 _NL_AUTO_DEFINE_FCN_VOID0(void *, _nl_auto_free_fcn, free);
747 
748 /*****************************************************************************/
749 
750 #define NSEC_PER_SEC 1000000000L
751 
752 struct trans_tbl {
753 	uint64_t i;
754 	const char *a;
755 };
756 
757 #define __ADD(id, name) { .i = id, .a = #name }
758 
759 #define BUG()                                                                \
760 	do {                                                                 \
761 		fprintf(stderr, "BUG at file position %s:%d:%s\n", __FILE__, \
762 			__LINE__, __func__);                                 \
763 		assert(0);                                                   \
764 	} while (0)
765 
766 #define BUG_ON(condition)      \
767 	do {                   \
768 		if (condition) \
769 			BUG(); \
770 	} while (0)
771 
772 #define APPBUG(msg)                                                          \
773 	do {                                                                 \
774 		fprintf(stderr, "APPLICATION BUG: %s:%d:%s: %s\n", __FILE__, \
775 			__LINE__, __func__, msg);                            \
776 		assert(0);                                                   \
777 	} while (0)
778 
779 /*****************************************************************************/
780 
781 #ifndef DISABLE_PTHREADS
782 #define NL_LOCK(NAME) pthread_mutex_t(NAME) = PTHREAD_MUTEX_INITIALIZER
783 #define NL_RW_LOCK(NAME) pthread_rwlock_t(NAME) = PTHREAD_RWLOCK_INITIALIZER
784 
nl_lock(pthread_mutex_t * lock)785 static inline void nl_lock(pthread_mutex_t *lock)
786 {
787 	pthread_mutex_lock(lock);
788 }
789 
nl_unlock(pthread_mutex_t * lock)790 static inline void nl_unlock(pthread_mutex_t *lock)
791 {
792 	pthread_mutex_unlock(lock);
793 }
794 
nl_read_lock(pthread_rwlock_t * lock)795 static inline void nl_read_lock(pthread_rwlock_t *lock)
796 {
797 	pthread_rwlock_rdlock(lock);
798 }
799 
nl_read_unlock(pthread_rwlock_t * lock)800 static inline void nl_read_unlock(pthread_rwlock_t *lock)
801 {
802 	pthread_rwlock_unlock(lock);
803 }
804 
nl_write_lock(pthread_rwlock_t * lock)805 static inline void nl_write_lock(pthread_rwlock_t *lock)
806 {
807 	pthread_rwlock_wrlock(lock);
808 }
809 
nl_write_unlock(pthread_rwlock_t * lock)810 static inline void nl_write_unlock(pthread_rwlock_t *lock)
811 {
812 	pthread_rwlock_unlock(lock);
813 }
814 
815 #else
816 #define NL_LOCK(NAME) int __unused_lock_##NAME _nl_unused
817 #define NL_RW_LOCK(NAME) int __unused_lock_##NAME _nl_unused
818 
819 #define nl_lock(LOCK) \
820 	do {          \
821 	} while (0)
822 #define nl_unlock(LOCK) \
823 	do {            \
824 	} while (0)
825 #define nl_read_lock(LOCK) \
826 	do {               \
827 	} while (0)
828 #define nl_read_unlock(LOCK) \
829 	do {                 \
830 	} while (0)
831 #define nl_write_lock(LOCK) \
832 	do {                \
833 	} while (0)
834 #define nl_write_unlock(LOCK) \
835 	do {                  \
836 	} while (0)
837 #endif
838 
839 #endif /* __NETLINK_BASE_NL_BASE_UTILS_H__ */
840