xref: /aosp_15_r20/external/libnl/lib/utils.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker  * Copyright (c) 2003-2012 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker  */
5*4dc78e53SAndroid Build Coastguard Worker 
6*4dc78e53SAndroid Build Coastguard Worker /**
7*4dc78e53SAndroid Build Coastguard Worker  * @ingroup core
8*4dc78e53SAndroid Build Coastguard Worker  * @defgroup utils Utilities
9*4dc78e53SAndroid Build Coastguard Worker  *
10*4dc78e53SAndroid Build Coastguard Worker  * Collection of helper functions
11*4dc78e53SAndroid Build Coastguard Worker  *
12*4dc78e53SAndroid Build Coastguard Worker  * @{
13*4dc78e53SAndroid Build Coastguard Worker  *
14*4dc78e53SAndroid Build Coastguard Worker  * Header
15*4dc78e53SAndroid Build Coastguard Worker  * ------
16*4dc78e53SAndroid Build Coastguard Worker  * ~~~~{.c}
17*4dc78e53SAndroid Build Coastguard Worker  * #include <netlink/utils.h>
18*4dc78e53SAndroid Build Coastguard Worker  * ~~~~
19*4dc78e53SAndroid Build Coastguard Worker  */
20*4dc78e53SAndroid Build Coastguard Worker 
21*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
22*4dc78e53SAndroid Build Coastguard Worker 
23*4dc78e53SAndroid Build Coastguard Worker #include <locale.h>
24*4dc78e53SAndroid Build Coastguard Worker 
25*4dc78e53SAndroid Build Coastguard Worker #include <linux/socket.h>
26*4dc78e53SAndroid Build Coastguard Worker #include <linux/if_arp.h>
27*4dc78e53SAndroid Build Coastguard Worker 
28*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
29*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
30*4dc78e53SAndroid Build Coastguard Worker 
31*4dc78e53SAndroid Build Coastguard Worker #include "nl-core.h"
32*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/object-api.h"
33*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/nl-core.h"
34*4dc78e53SAndroid Build Coastguard Worker #include "nl-aux-core/nl-core.h"
35*4dc78e53SAndroid Build Coastguard Worker 
36*4dc78e53SAndroid Build Coastguard Worker /**
37*4dc78e53SAndroid Build Coastguard Worker  * Global variable indicating the desired level of debugging output.
38*4dc78e53SAndroid Build Coastguard Worker  *
39*4dc78e53SAndroid Build Coastguard Worker  * Level | Messages Printed
40*4dc78e53SAndroid Build Coastguard Worker  * ----- | ---------------------------------------------------------
41*4dc78e53SAndroid Build Coastguard Worker  *     0 | Debugging output disabled
42*4dc78e53SAndroid Build Coastguard Worker  *     1 | Warnings, important events and notifications
43*4dc78e53SAndroid Build Coastguard Worker  *     2 | More or less important debugging messages
44*4dc78e53SAndroid Build Coastguard Worker  *     3 | Repetitive events causing a flood of debugging messages
45*4dc78e53SAndroid Build Coastguard Worker  *     4 | Even less important messages
46*4dc78e53SAndroid Build Coastguard Worker  *
47*4dc78e53SAndroid Build Coastguard Worker  * If available, the variable will be initialized to the value of the
48*4dc78e53SAndroid Build Coastguard Worker  * environment variable `NLDBG`. The default value is 0 (disabled).
49*4dc78e53SAndroid Build Coastguard Worker  *
50*4dc78e53SAndroid Build Coastguard Worker  * For more information, see section @core_doc{_debugging, Debugging}.
51*4dc78e53SAndroid Build Coastguard Worker  */
52*4dc78e53SAndroid Build Coastguard Worker int nl_debug = 0;
53*4dc78e53SAndroid Build Coastguard Worker 
54*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
55*4dc78e53SAndroid Build Coastguard Worker struct nl_dump_params nl_debug_dp = {
56*4dc78e53SAndroid Build Coastguard Worker 	.dp_type = NL_DUMP_DETAILS,
57*4dc78e53SAndroid Build Coastguard Worker };
58*4dc78e53SAndroid Build Coastguard Worker 
nl_debug_init(void)59*4dc78e53SAndroid Build Coastguard Worker static void _nl_init nl_debug_init(void)
60*4dc78e53SAndroid Build Coastguard Worker {
61*4dc78e53SAndroid Build Coastguard Worker 	char *nldbg, *end;
62*4dc78e53SAndroid Build Coastguard Worker 
63*4dc78e53SAndroid Build Coastguard Worker 	if (NL_DEBUG && (nldbg = getenv("NLDBG"))) {
64*4dc78e53SAndroid Build Coastguard Worker 		long level = strtol(nldbg, &end, 0);
65*4dc78e53SAndroid Build Coastguard Worker 		if (nldbg != end)
66*4dc78e53SAndroid Build Coastguard Worker 			nl_debug = level;
67*4dc78e53SAndroid Build Coastguard Worker 	}
68*4dc78e53SAndroid Build Coastguard Worker 
69*4dc78e53SAndroid Build Coastguard Worker 	nl_debug_dp.dp_fd = stderr;
70*4dc78e53SAndroid Build Coastguard Worker }
71*4dc78e53SAndroid Build Coastguard Worker 
__nl_read_num_str_file(const char * path,int (* cb)(long,const char *))72*4dc78e53SAndroid Build Coastguard Worker int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *))
73*4dc78e53SAndroid Build Coastguard Worker {
74*4dc78e53SAndroid Build Coastguard Worker 	FILE *fd;
75*4dc78e53SAndroid Build Coastguard Worker 	char buf[128];
76*4dc78e53SAndroid Build Coastguard Worker 
77*4dc78e53SAndroid Build Coastguard Worker 	fd = fopen(path, "re");
78*4dc78e53SAndroid Build Coastguard Worker 	if (fd == NULL)
79*4dc78e53SAndroid Build Coastguard Worker 		return -nl_syserr2nlerr(errno);
80*4dc78e53SAndroid Build Coastguard Worker 
81*4dc78e53SAndroid Build Coastguard Worker 	while (fgets(buf, sizeof(buf), fd)) {
82*4dc78e53SAndroid Build Coastguard Worker 		int goodlen, err;
83*4dc78e53SAndroid Build Coastguard Worker 		long num;
84*4dc78e53SAndroid Build Coastguard Worker 		char *end;
85*4dc78e53SAndroid Build Coastguard Worker 
86*4dc78e53SAndroid Build Coastguard Worker 		if (*buf == '#' || *buf == '\n' || *buf == '\r')
87*4dc78e53SAndroid Build Coastguard Worker 			continue;
88*4dc78e53SAndroid Build Coastguard Worker 
89*4dc78e53SAndroid Build Coastguard Worker 		num = strtol(buf, &end, 0);
90*4dc78e53SAndroid Build Coastguard Worker 		if (end == buf) {
91*4dc78e53SAndroid Build Coastguard Worker 			fclose(fd);
92*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_INVAL;
93*4dc78e53SAndroid Build Coastguard Worker 		}
94*4dc78e53SAndroid Build Coastguard Worker 
95*4dc78e53SAndroid Build Coastguard Worker 		if (num == LONG_MIN || num == LONG_MAX) {
96*4dc78e53SAndroid Build Coastguard Worker 			fclose(fd);
97*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_RANGE;
98*4dc78e53SAndroid Build Coastguard Worker 		}
99*4dc78e53SAndroid Build Coastguard Worker 
100*4dc78e53SAndroid Build Coastguard Worker 		while (*end == ' ' || *end == '\t')
101*4dc78e53SAndroid Build Coastguard Worker 			end++;
102*4dc78e53SAndroid Build Coastguard Worker 
103*4dc78e53SAndroid Build Coastguard Worker 		goodlen = strcspn(end, "#\r\n\t ");
104*4dc78e53SAndroid Build Coastguard Worker 		if (goodlen == 0) {
105*4dc78e53SAndroid Build Coastguard Worker 			fclose(fd);
106*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_INVAL;
107*4dc78e53SAndroid Build Coastguard Worker 		}
108*4dc78e53SAndroid Build Coastguard Worker 
109*4dc78e53SAndroid Build Coastguard Worker 		end[goodlen] = '\0';
110*4dc78e53SAndroid Build Coastguard Worker 
111*4dc78e53SAndroid Build Coastguard Worker 		err = cb(num, end);
112*4dc78e53SAndroid Build Coastguard Worker 		if (err < 0) {
113*4dc78e53SAndroid Build Coastguard Worker 			fclose(fd);
114*4dc78e53SAndroid Build Coastguard Worker 			return err;
115*4dc78e53SAndroid Build Coastguard Worker 		}
116*4dc78e53SAndroid Build Coastguard Worker 	}
117*4dc78e53SAndroid Build Coastguard Worker 
118*4dc78e53SAndroid Build Coastguard Worker 	fclose(fd);
119*4dc78e53SAndroid Build Coastguard Worker 
120*4dc78e53SAndroid Build Coastguard Worker 	return 0;
121*4dc78e53SAndroid Build Coastguard Worker }
122*4dc78e53SAndroid Build Coastguard Worker 
123*4dc78e53SAndroid Build Coastguard Worker struct trans_list {
124*4dc78e53SAndroid Build Coastguard Worker 	int i;
125*4dc78e53SAndroid Build Coastguard Worker 	char *a;
126*4dc78e53SAndroid Build Coastguard Worker 	struct nl_list_head list;
127*4dc78e53SAndroid Build Coastguard Worker };
128*4dc78e53SAndroid Build Coastguard Worker 
nl_getprotobyname(const char * name)129*4dc78e53SAndroid Build Coastguard Worker int nl_getprotobyname(const char *name)
130*4dc78e53SAndroid Build Coastguard Worker {
131*4dc78e53SAndroid Build Coastguard Worker 	const struct protoent *result;
132*4dc78e53SAndroid Build Coastguard Worker 
133*4dc78e53SAndroid Build Coastguard Worker #if HAVE_DECL_GETPROTOBYNAME_R
134*4dc78e53SAndroid Build Coastguard Worker 	struct protoent result_buf;
135*4dc78e53SAndroid Build Coastguard Worker 	char buf[2048];
136*4dc78e53SAndroid Build Coastguard Worker 	int r;
137*4dc78e53SAndroid Build Coastguard Worker 
138*4dc78e53SAndroid Build Coastguard Worker 	r = getprotobyname_r(name, &result_buf, buf, sizeof(buf),
139*4dc78e53SAndroid Build Coastguard Worker 			     (struct protoent **)&result);
140*4dc78e53SAndroid Build Coastguard Worker 	if (r != 0 || result != &result_buf)
141*4dc78e53SAndroid Build Coastguard Worker 		result = NULL;
142*4dc78e53SAndroid Build Coastguard Worker #else
143*4dc78e53SAndroid Build Coastguard Worker 	result = getprotobyname(name);
144*4dc78e53SAndroid Build Coastguard Worker #endif
145*4dc78e53SAndroid Build Coastguard Worker 
146*4dc78e53SAndroid Build Coastguard Worker 	if (!result)
147*4dc78e53SAndroid Build Coastguard Worker 		return -1;
148*4dc78e53SAndroid Build Coastguard Worker 
149*4dc78e53SAndroid Build Coastguard Worker 	if (result->p_proto < 0 || result->p_proto > UINT8_MAX)
150*4dc78e53SAndroid Build Coastguard Worker 		return -1;
151*4dc78e53SAndroid Build Coastguard Worker 	return (uint8_t)result->p_proto;
152*4dc78e53SAndroid Build Coastguard Worker }
153*4dc78e53SAndroid Build Coastguard Worker 
nl_getprotobynumber(int proto,char * out_name,size_t name_len)154*4dc78e53SAndroid Build Coastguard Worker bool nl_getprotobynumber(int proto, char *out_name, size_t name_len)
155*4dc78e53SAndroid Build Coastguard Worker {
156*4dc78e53SAndroid Build Coastguard Worker 	const struct protoent *result;
157*4dc78e53SAndroid Build Coastguard Worker 
158*4dc78e53SAndroid Build Coastguard Worker #if HAVE_DECL_GETPROTOBYNUMBER_R
159*4dc78e53SAndroid Build Coastguard Worker 	struct protoent result_buf;
160*4dc78e53SAndroid Build Coastguard Worker 	char buf[2048];
161*4dc78e53SAndroid Build Coastguard Worker 	int r;
162*4dc78e53SAndroid Build Coastguard Worker 
163*4dc78e53SAndroid Build Coastguard Worker 	r = getprotobynumber_r(proto, &result_buf, buf, sizeof(buf),
164*4dc78e53SAndroid Build Coastguard Worker 			       (struct protoent **)&result);
165*4dc78e53SAndroid Build Coastguard Worker 	if (r != 0 || result != &result_buf)
166*4dc78e53SAndroid Build Coastguard Worker 		result = NULL;
167*4dc78e53SAndroid Build Coastguard Worker #else
168*4dc78e53SAndroid Build Coastguard Worker 	result = getprotobynumber(proto);
169*4dc78e53SAndroid Build Coastguard Worker #endif
170*4dc78e53SAndroid Build Coastguard Worker 
171*4dc78e53SAndroid Build Coastguard Worker 	if (!result)
172*4dc78e53SAndroid Build Coastguard Worker 		return false;
173*4dc78e53SAndroid Build Coastguard Worker 
174*4dc78e53SAndroid Build Coastguard Worker 	if (strlen(result->p_name) >= name_len)
175*4dc78e53SAndroid Build Coastguard Worker 		return false;
176*4dc78e53SAndroid Build Coastguard Worker 	strcpy(out_name, result->p_name);
177*4dc78e53SAndroid Build Coastguard Worker 	return true;
178*4dc78e53SAndroid Build Coastguard Worker }
179*4dc78e53SAndroid Build Coastguard Worker 
nl_strerror_l(int err)180*4dc78e53SAndroid Build Coastguard Worker const char *nl_strerror_l(int err)
181*4dc78e53SAndroid Build Coastguard Worker {
182*4dc78e53SAndroid Build Coastguard Worker 	const char *buf;
183*4dc78e53SAndroid Build Coastguard Worker #ifdef HAVE_STRERROR_L
184*4dc78e53SAndroid Build Coastguard Worker 	int errno_save = errno;
185*4dc78e53SAndroid Build Coastguard Worker 	locale_t loc = newlocale(LC_MESSAGES_MASK, "", (locale_t)0);
186*4dc78e53SAndroid Build Coastguard Worker 
187*4dc78e53SAndroid Build Coastguard Worker 	if (loc == (locale_t)0) {
188*4dc78e53SAndroid Build Coastguard Worker 		if (errno == ENOENT)
189*4dc78e53SAndroid Build Coastguard Worker 			loc = newlocale(LC_MESSAGES_MASK,
190*4dc78e53SAndroid Build Coastguard Worker 					"POSIX", (locale_t)0);
191*4dc78e53SAndroid Build Coastguard Worker 	}
192*4dc78e53SAndroid Build Coastguard Worker 	if (loc != (locale_t)0) {
193*4dc78e53SAndroid Build Coastguard Worker 		buf = strerror_l(err, loc);
194*4dc78e53SAndroid Build Coastguard Worker 		freelocale(loc);
195*4dc78e53SAndroid Build Coastguard Worker 	} else {
196*4dc78e53SAndroid Build Coastguard Worker 		buf = "newlocale() failed";
197*4dc78e53SAndroid Build Coastguard Worker 	}
198*4dc78e53SAndroid Build Coastguard Worker 
199*4dc78e53SAndroid Build Coastguard Worker 	errno = errno_save;
200*4dc78e53SAndroid Build Coastguard Worker #else
201*4dc78e53SAndroid Build Coastguard Worker 	buf = strerror(err);
202*4dc78e53SAndroid Build Coastguard Worker #endif
203*4dc78e53SAndroid Build Coastguard Worker 	return buf;
204*4dc78e53SAndroid Build Coastguard Worker }
205*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
206*4dc78e53SAndroid Build Coastguard Worker 
207*4dc78e53SAndroid Build Coastguard Worker /**
208*4dc78e53SAndroid Build Coastguard Worker  * @name Pretty Printing of Numbers
209*4dc78e53SAndroid Build Coastguard Worker  * @{
210*4dc78e53SAndroid Build Coastguard Worker  */
211*4dc78e53SAndroid Build Coastguard Worker 
212*4dc78e53SAndroid Build Coastguard Worker /**
213*4dc78e53SAndroid Build Coastguard Worker  * Cancel down a byte counter
214*4dc78e53SAndroid Build Coastguard Worker  * @arg	l		byte counter
215*4dc78e53SAndroid Build Coastguard Worker  * @arg	unit		destination unit pointer
216*4dc78e53SAndroid Build Coastguard Worker  *
217*4dc78e53SAndroid Build Coastguard Worker  * Cancels down a byte counter until it reaches a reasonable
218*4dc78e53SAndroid Build Coastguard Worker  * unit. The chosen unit is assigned to \a unit.
219*4dc78e53SAndroid Build Coastguard Worker  * This function assume 1024 bytes in one kilobyte
220*4dc78e53SAndroid Build Coastguard Worker  *
221*4dc78e53SAndroid Build Coastguard Worker  * @return The cancelled down byte counter in the new unit.
222*4dc78e53SAndroid Build Coastguard Worker  */
nl_cancel_down_bytes(unsigned long long l,char ** unit)223*4dc78e53SAndroid Build Coastguard Worker double nl_cancel_down_bytes(unsigned long long l, char **unit)
224*4dc78e53SAndroid Build Coastguard Worker {
225*4dc78e53SAndroid Build Coastguard Worker 	if (l >= 1099511627776LL) {
226*4dc78e53SAndroid Build Coastguard Worker 		*unit = "TiB";
227*4dc78e53SAndroid Build Coastguard Worker 		return ((double) l) / 1099511627776LL;
228*4dc78e53SAndroid Build Coastguard Worker 	} else if (l >= 1073741824) {
229*4dc78e53SAndroid Build Coastguard Worker 		*unit = "GiB";
230*4dc78e53SAndroid Build Coastguard Worker 		return ((double) l) / 1073741824;
231*4dc78e53SAndroid Build Coastguard Worker 	} else if (l >= 1048576) {
232*4dc78e53SAndroid Build Coastguard Worker 		*unit = "MiB";
233*4dc78e53SAndroid Build Coastguard Worker 		return ((double) l) / 1048576;
234*4dc78e53SAndroid Build Coastguard Worker 	} else if (l >= 1024) {
235*4dc78e53SAndroid Build Coastguard Worker 		*unit = "KiB";
236*4dc78e53SAndroid Build Coastguard Worker 		return ((double) l) / 1024;
237*4dc78e53SAndroid Build Coastguard Worker 	} else {
238*4dc78e53SAndroid Build Coastguard Worker 		*unit = "B";
239*4dc78e53SAndroid Build Coastguard Worker 		return (double) l;
240*4dc78e53SAndroid Build Coastguard Worker 	}
241*4dc78e53SAndroid Build Coastguard Worker }
242*4dc78e53SAndroid Build Coastguard Worker 
243*4dc78e53SAndroid Build Coastguard Worker /**
244*4dc78e53SAndroid Build Coastguard Worker  * Cancel down a bit counter
245*4dc78e53SAndroid Build Coastguard Worker  * @arg	l		bit counter
246*4dc78e53SAndroid Build Coastguard Worker  * @arg unit		destination unit pointer
247*4dc78e53SAndroid Build Coastguard Worker  *
248*4dc78e53SAndroid Build Coastguard Worker  * Cancels down bit counter until it reaches a reasonable
249*4dc78e53SAndroid Build Coastguard Worker  * unit. The chosen unit is assigned to \a unit.
250*4dc78e53SAndroid Build Coastguard Worker  * This function assume 1000 bits in one kilobit
251*4dc78e53SAndroid Build Coastguard Worker  *
252*4dc78e53SAndroid Build Coastguard Worker  * @return The cancelled down bit counter in the new unit.
253*4dc78e53SAndroid Build Coastguard Worker  */
nl_cancel_down_bits(unsigned long long l,char ** unit)254*4dc78e53SAndroid Build Coastguard Worker double nl_cancel_down_bits(unsigned long long l, char **unit)
255*4dc78e53SAndroid Build Coastguard Worker {
256*4dc78e53SAndroid Build Coastguard Worker 	if (l >= 1000000000000ULL) {
257*4dc78e53SAndroid Build Coastguard Worker 		*unit = "Tbit";
258*4dc78e53SAndroid Build Coastguard Worker 		return ((double) l) / 1000000000000ULL;
259*4dc78e53SAndroid Build Coastguard Worker 	}
260*4dc78e53SAndroid Build Coastguard Worker 
261*4dc78e53SAndroid Build Coastguard Worker 	if (l >= 1000000000) {
262*4dc78e53SAndroid Build Coastguard Worker 		*unit = "Gbit";
263*4dc78e53SAndroid Build Coastguard Worker 		return ((double) l) / 1000000000;
264*4dc78e53SAndroid Build Coastguard Worker 	}
265*4dc78e53SAndroid Build Coastguard Worker 
266*4dc78e53SAndroid Build Coastguard Worker 	if (l >= 1000000) {
267*4dc78e53SAndroid Build Coastguard Worker 		*unit = "Mbit";
268*4dc78e53SAndroid Build Coastguard Worker 		return ((double) l) / 1000000;
269*4dc78e53SAndroid Build Coastguard Worker 	}
270*4dc78e53SAndroid Build Coastguard Worker 
271*4dc78e53SAndroid Build Coastguard Worker 	if (l >= 1000) {
272*4dc78e53SAndroid Build Coastguard Worker 		*unit = "Kbit";
273*4dc78e53SAndroid Build Coastguard Worker 		return ((double) l) / 1000;
274*4dc78e53SAndroid Build Coastguard Worker 	}
275*4dc78e53SAndroid Build Coastguard Worker 
276*4dc78e53SAndroid Build Coastguard Worker 	*unit = "bit";
277*4dc78e53SAndroid Build Coastguard Worker 	return (double) l;
278*4dc78e53SAndroid Build Coastguard Worker }
279*4dc78e53SAndroid Build Coastguard Worker 
nl_rate2str(unsigned long long rate,int type,char * buf,size_t len)280*4dc78e53SAndroid Build Coastguard Worker int nl_rate2str(unsigned long long rate, int type, char *buf, size_t len)
281*4dc78e53SAndroid Build Coastguard Worker {
282*4dc78e53SAndroid Build Coastguard Worker 	char *unit;
283*4dc78e53SAndroid Build Coastguard Worker 	double frac;
284*4dc78e53SAndroid Build Coastguard Worker 
285*4dc78e53SAndroid Build Coastguard Worker 	switch (type) {
286*4dc78e53SAndroid Build Coastguard Worker 	case NL_BYTE_RATE:
287*4dc78e53SAndroid Build Coastguard Worker 		frac = nl_cancel_down_bytes(rate, &unit);
288*4dc78e53SAndroid Build Coastguard Worker 		break;
289*4dc78e53SAndroid Build Coastguard Worker 
290*4dc78e53SAndroid Build Coastguard Worker 	case NL_BIT_RATE:
291*4dc78e53SAndroid Build Coastguard Worker 		frac = nl_cancel_down_bits(rate, &unit);
292*4dc78e53SAndroid Build Coastguard Worker 		break;
293*4dc78e53SAndroid Build Coastguard Worker 
294*4dc78e53SAndroid Build Coastguard Worker 	default:
295*4dc78e53SAndroid Build Coastguard Worker 		BUG();
296*4dc78e53SAndroid Build Coastguard Worker 	}
297*4dc78e53SAndroid Build Coastguard Worker 
298*4dc78e53SAndroid Build Coastguard Worker 	return snprintf(buf, len, "%.2f%s/s", frac, unit);
299*4dc78e53SAndroid Build Coastguard Worker }
300*4dc78e53SAndroid Build Coastguard Worker 
301*4dc78e53SAndroid Build Coastguard Worker /**
302*4dc78e53SAndroid Build Coastguard Worker  * Cancel down a micro second value
303*4dc78e53SAndroid Build Coastguard Worker  * @arg	l		micro seconds
304*4dc78e53SAndroid Build Coastguard Worker  * @arg unit		destination unit pointer
305*4dc78e53SAndroid Build Coastguard Worker  *
306*4dc78e53SAndroid Build Coastguard Worker  * Cancels down a microsecond counter until it reaches a
307*4dc78e53SAndroid Build Coastguard Worker  * reasonable unit. The chosen unit is assigned to \a unit.
308*4dc78e53SAndroid Build Coastguard Worker  *
309*4dc78e53SAndroid Build Coastguard Worker  * @return The cancelled down microsecond in the new unit
310*4dc78e53SAndroid Build Coastguard Worker  */
nl_cancel_down_us(uint32_t l,char ** unit)311*4dc78e53SAndroid Build Coastguard Worker double nl_cancel_down_us(uint32_t l, char **unit)
312*4dc78e53SAndroid Build Coastguard Worker {
313*4dc78e53SAndroid Build Coastguard Worker 	if (l >= 1000000) {
314*4dc78e53SAndroid Build Coastguard Worker 		*unit = "s";
315*4dc78e53SAndroid Build Coastguard Worker 		return ((double) l) / 1000000;
316*4dc78e53SAndroid Build Coastguard Worker 	} else if (l >= 1000) {
317*4dc78e53SAndroid Build Coastguard Worker 		*unit = "ms";
318*4dc78e53SAndroid Build Coastguard Worker 		return ((double) l) / 1000;
319*4dc78e53SAndroid Build Coastguard Worker 	} else {
320*4dc78e53SAndroid Build Coastguard Worker 		*unit = "us";
321*4dc78e53SAndroid Build Coastguard Worker 		return (double) l;
322*4dc78e53SAndroid Build Coastguard Worker 	}
323*4dc78e53SAndroid Build Coastguard Worker }
324*4dc78e53SAndroid Build Coastguard Worker 
325*4dc78e53SAndroid Build Coastguard Worker /** @} */
326*4dc78e53SAndroid Build Coastguard Worker 
327*4dc78e53SAndroid Build Coastguard Worker /**
328*4dc78e53SAndroid Build Coastguard Worker  * @name Generic Unit Translations
329*4dc78e53SAndroid Build Coastguard Worker  * @{
330*4dc78e53SAndroid Build Coastguard Worker  */
331*4dc78e53SAndroid Build Coastguard Worker 
332*4dc78e53SAndroid Build Coastguard Worker /**
333*4dc78e53SAndroid Build Coastguard Worker  * Convert a character string to a size
334*4dc78e53SAndroid Build Coastguard Worker  * @arg str		size encoded as character string
335*4dc78e53SAndroid Build Coastguard Worker  *
336*4dc78e53SAndroid Build Coastguard Worker  * Converts the specified size as character to the corresponding
337*4dc78e53SAndroid Build Coastguard Worker  * number of bytes.
338*4dc78e53SAndroid Build Coastguard Worker  *
339*4dc78e53SAndroid Build Coastguard Worker  * Supported formats are:
340*4dc78e53SAndroid Build Coastguard Worker  *  - b,kb/k,m/mb,gb/g for bytes
341*4dc78e53SAndroid Build Coastguard Worker  *  - bit,kbit/mbit/gbit
342*4dc78e53SAndroid Build Coastguard Worker  *
343*4dc78e53SAndroid Build Coastguard Worker  * This function assume 1000 bits in one kilobit and
344*4dc78e53SAndroid Build Coastguard Worker  * 1024 bytes in one kilobyte
345*4dc78e53SAndroid Build Coastguard Worker  *
346*4dc78e53SAndroid Build Coastguard Worker  * @return The number of bytes or -1 if the string is unparseable
347*4dc78e53SAndroid Build Coastguard Worker  */
nl_size2int(const char * str)348*4dc78e53SAndroid Build Coastguard Worker long nl_size2int(const char *str)
349*4dc78e53SAndroid Build Coastguard Worker {
350*4dc78e53SAndroid Build Coastguard Worker 	char *p;
351*4dc78e53SAndroid Build Coastguard Worker 	long l = strtol(str, &p, 0);
352*4dc78e53SAndroid Build Coastguard Worker 	if (p == str)
353*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
354*4dc78e53SAndroid Build Coastguard Worker 
355*4dc78e53SAndroid Build Coastguard Worker 	if (*p) {
356*4dc78e53SAndroid Build Coastguard Worker 		if (!strcasecmp(p, "kb") || !strcasecmp(p, "k"))
357*4dc78e53SAndroid Build Coastguard Worker 			l *= 1024;
358*4dc78e53SAndroid Build Coastguard Worker 		else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g"))
359*4dc78e53SAndroid Build Coastguard Worker 			l *= 1024*1024*1024;
360*4dc78e53SAndroid Build Coastguard Worker 		else if (!strcasecmp(p, "gbit"))
361*4dc78e53SAndroid Build Coastguard Worker 			l *= 1000000000L/8;
362*4dc78e53SAndroid Build Coastguard Worker 		else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m"))
363*4dc78e53SAndroid Build Coastguard Worker 			l *= 1024*1024;
364*4dc78e53SAndroid Build Coastguard Worker 		else if (!strcasecmp(p, "mbit"))
365*4dc78e53SAndroid Build Coastguard Worker 			l *= 1000000/8;
366*4dc78e53SAndroid Build Coastguard Worker 		else if (!strcasecmp(p, "kbit"))
367*4dc78e53SAndroid Build Coastguard Worker 			l *= 1000/8;
368*4dc78e53SAndroid Build Coastguard Worker 		else if (!strcasecmp(p, "bit"))
369*4dc78e53SAndroid Build Coastguard Worker 			l /= 8;
370*4dc78e53SAndroid Build Coastguard Worker 		else if (strcasecmp(p, "b") != 0)
371*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_INVAL;
372*4dc78e53SAndroid Build Coastguard Worker 	}
373*4dc78e53SAndroid Build Coastguard Worker 
374*4dc78e53SAndroid Build Coastguard Worker 	return l;
375*4dc78e53SAndroid Build Coastguard Worker }
376*4dc78e53SAndroid Build Coastguard Worker 
377*4dc78e53SAndroid Build Coastguard Worker static const struct {
378*4dc78e53SAndroid Build Coastguard Worker 	double limit;
379*4dc78e53SAndroid Build Coastguard Worker 	const char *unit;
380*4dc78e53SAndroid Build Coastguard Worker } size_units[] = {
381*4dc78e53SAndroid Build Coastguard Worker 	{ 1024. * 1024. * 1024. * 1024. * 1024., "EiB" },
382*4dc78e53SAndroid Build Coastguard Worker 	{ 1024. * 1024. * 1024. * 1024., "TiB" },
383*4dc78e53SAndroid Build Coastguard Worker 	{ 1024. * 1024. * 1024., "GiB" },
384*4dc78e53SAndroid Build Coastguard Worker 	{ 1024. * 1024., "MiB" },
385*4dc78e53SAndroid Build Coastguard Worker 	{ 1024., "KiB" },
386*4dc78e53SAndroid Build Coastguard Worker 	{ 0., "B" },
387*4dc78e53SAndroid Build Coastguard Worker };
388*4dc78e53SAndroid Build Coastguard Worker 
389*4dc78e53SAndroid Build Coastguard Worker /**
390*4dc78e53SAndroid Build Coastguard Worker  * Convert a size toa character string
391*4dc78e53SAndroid Build Coastguard Worker  * @arg size		Size in number of bytes
392*4dc78e53SAndroid Build Coastguard Worker  * @arg buf		Buffer to write character string to
393*4dc78e53SAndroid Build Coastguard Worker  * @arg len		Size of buf
394*4dc78e53SAndroid Build Coastguard Worker  *
395*4dc78e53SAndroid Build Coastguard Worker  * This function converts a value in bytes to a human readable representation
396*4dc78e53SAndroid Build Coastguard Worker  * of it. The function uses IEC prefixes:
397*4dc78e53SAndroid Build Coastguard Worker  *
398*4dc78e53SAndroid Build Coastguard Worker  * @code
399*4dc78e53SAndroid Build Coastguard Worker  * 1024 bytes => 1 KiB
400*4dc78e53SAndroid Build Coastguard Worker  * 1048576 bytes => 1 MiB
401*4dc78e53SAndroid Build Coastguard Worker  * @endcode
402*4dc78e53SAndroid Build Coastguard Worker  *
403*4dc78e53SAndroid Build Coastguard Worker  * The highest prefix is used which ensures a result of >= 1.0, the result
404*4dc78e53SAndroid Build Coastguard Worker  * is provided as floating point number with a maximum precision of 2 digits:
405*4dc78e53SAndroid Build Coastguard Worker  * @code
406*4dc78e53SAndroid Build Coastguard Worker  * 965176 bytes => 942.55 KiB
407*4dc78e53SAndroid Build Coastguard Worker  * @endcode
408*4dc78e53SAndroid Build Coastguard Worker  *
409*4dc78e53SAndroid Build Coastguard Worker  * @return pointer to buf
410*4dc78e53SAndroid Build Coastguard Worker  */
nl_size2str(const size_t size,char * buf,const size_t len)411*4dc78e53SAndroid Build Coastguard Worker char *nl_size2str(const size_t size, char *buf, const size_t len)
412*4dc78e53SAndroid Build Coastguard Worker {
413*4dc78e53SAndroid Build Coastguard Worker 	size_t i;
414*4dc78e53SAndroid Build Coastguard Worker 
415*4dc78e53SAndroid Build Coastguard Worker 	if (size == 0) {
416*4dc78e53SAndroid Build Coastguard Worker 		snprintf(buf, len, "0B");
417*4dc78e53SAndroid Build Coastguard Worker 		return buf;
418*4dc78e53SAndroid Build Coastguard Worker 	}
419*4dc78e53SAndroid Build Coastguard Worker 
420*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(size_units); i++) {
421*4dc78e53SAndroid Build Coastguard Worker 		if (size >= size_units[i].limit) {
422*4dc78e53SAndroid Build Coastguard Worker 			snprintf(buf, len, "%.2g%s",
423*4dc78e53SAndroid Build Coastguard Worker 				(double) size / size_units[i].limit,
424*4dc78e53SAndroid Build Coastguard Worker 				size_units[i].unit);
425*4dc78e53SAndroid Build Coastguard Worker 			return buf;
426*4dc78e53SAndroid Build Coastguard Worker 		}
427*4dc78e53SAndroid Build Coastguard Worker 	}
428*4dc78e53SAndroid Build Coastguard Worker 
429*4dc78e53SAndroid Build Coastguard Worker 	BUG();
430*4dc78e53SAndroid Build Coastguard Worker }
431*4dc78e53SAndroid Build Coastguard Worker 
432*4dc78e53SAndroid Build Coastguard Worker /**
433*4dc78e53SAndroid Build Coastguard Worker  * Convert a character string to a probability
434*4dc78e53SAndroid Build Coastguard Worker  * @arg str		probability encoded as character string
435*4dc78e53SAndroid Build Coastguard Worker  *
436*4dc78e53SAndroid Build Coastguard Worker  * Converts the specified probability as character to the
437*4dc78e53SAndroid Build Coastguard Worker  * corresponding probability number.
438*4dc78e53SAndroid Build Coastguard Worker  *
439*4dc78e53SAndroid Build Coastguard Worker  * Supported formats are:
440*4dc78e53SAndroid Build Coastguard Worker  *  - 0.0-1.0
441*4dc78e53SAndroid Build Coastguard Worker  *  - 0%-100%
442*4dc78e53SAndroid Build Coastguard Worker  *
443*4dc78e53SAndroid Build Coastguard Worker  * @return The probability relative to NL_PROB_MIN and NL_PROB_MAX
444*4dc78e53SAndroid Build Coastguard Worker  */
nl_prob2int(const char * str)445*4dc78e53SAndroid Build Coastguard Worker long nl_prob2int(const char *str)
446*4dc78e53SAndroid Build Coastguard Worker {
447*4dc78e53SAndroid Build Coastguard Worker 	char *p;
448*4dc78e53SAndroid Build Coastguard Worker 	double d = strtod(str, &p);
449*4dc78e53SAndroid Build Coastguard Worker 
450*4dc78e53SAndroid Build Coastguard Worker 	if (p == str)
451*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
452*4dc78e53SAndroid Build Coastguard Worker 
453*4dc78e53SAndroid Build Coastguard Worker 	if (d > 1.0)
454*4dc78e53SAndroid Build Coastguard Worker 		d /= 100.0f;
455*4dc78e53SAndroid Build Coastguard Worker 
456*4dc78e53SAndroid Build Coastguard Worker 	if (d > 1.0f || d < 0.0f)
457*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_RANGE;
458*4dc78e53SAndroid Build Coastguard Worker 
459*4dc78e53SAndroid Build Coastguard Worker 	if (*p && strcmp(p, "%") != 0)
460*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
461*4dc78e53SAndroid Build Coastguard Worker 
462*4dc78e53SAndroid Build Coastguard Worker 	return (long) (((d * NL_PROB_MAX) + 0.5));
463*4dc78e53SAndroid Build Coastguard Worker }
464*4dc78e53SAndroid Build Coastguard Worker 
465*4dc78e53SAndroid Build Coastguard Worker /** @} */
466*4dc78e53SAndroid Build Coastguard Worker 
467*4dc78e53SAndroid Build Coastguard Worker /**
468*4dc78e53SAndroid Build Coastguard Worker  * @name Time Translations
469*4dc78e53SAndroid Build Coastguard Worker  * @{
470*4dc78e53SAndroid Build Coastguard Worker  */
471*4dc78e53SAndroid Build Coastguard Worker 
472*4dc78e53SAndroid Build Coastguard Worker #ifndef USER_HZ
473*4dc78e53SAndroid Build Coastguard Worker #define USER_HZ 100
474*4dc78e53SAndroid Build Coastguard Worker #endif
475*4dc78e53SAndroid Build Coastguard Worker 
476*4dc78e53SAndroid Build Coastguard Worker static uint32_t user_hz = USER_HZ;
477*4dc78e53SAndroid Build Coastguard Worker static uint32_t psched_hz = USER_HZ;
478*4dc78e53SAndroid Build Coastguard Worker 
479*4dc78e53SAndroid Build Coastguard Worker static double ticks_per_usec = 1.0f;
480*4dc78e53SAndroid Build Coastguard Worker 
481*4dc78e53SAndroid Build Coastguard Worker /* Retrieves the configured HZ and ticks/us value in the kernel.
482*4dc78e53SAndroid Build Coastguard Worker  * The value is cached. Supported ways of getting it:
483*4dc78e53SAndroid Build Coastguard Worker  *
484*4dc78e53SAndroid Build Coastguard Worker  * 1) environment variable
485*4dc78e53SAndroid Build Coastguard Worker  * 2) /proc/net/psched and sysconf
486*4dc78e53SAndroid Build Coastguard Worker  *
487*4dc78e53SAndroid Build Coastguard Worker  * Supports the environment variables:
488*4dc78e53SAndroid Build Coastguard Worker  *   PROC_NET_PSCHED  - may point to psched file in /proc
489*4dc78e53SAndroid Build Coastguard Worker  *   PROC_ROOT        - may point to /proc fs */
get_psched_settings(void)490*4dc78e53SAndroid Build Coastguard Worker static void get_psched_settings(void)
491*4dc78e53SAndroid Build Coastguard Worker {
492*4dc78e53SAndroid Build Coastguard Worker 	char name[FILENAME_MAX];
493*4dc78e53SAndroid Build Coastguard Worker 	FILE *fd;
494*4dc78e53SAndroid Build Coastguard Worker 	int got_hz = 0;
495*4dc78e53SAndroid Build Coastguard Worker 	static volatile int initialized = 0;
496*4dc78e53SAndroid Build Coastguard Worker 	const char *ev;
497*4dc78e53SAndroid Build Coastguard Worker 	NL_LOCK(mutex);
498*4dc78e53SAndroid Build Coastguard Worker 
499*4dc78e53SAndroid Build Coastguard Worker 	if (initialized == 1)
500*4dc78e53SAndroid Build Coastguard Worker 		return;
501*4dc78e53SAndroid Build Coastguard Worker 
502*4dc78e53SAndroid Build Coastguard Worker 	nl_lock(&mutex);
503*4dc78e53SAndroid Build Coastguard Worker 
504*4dc78e53SAndroid Build Coastguard Worker 	if (initialized == 1)
505*4dc78e53SAndroid Build Coastguard Worker 		return;
506*4dc78e53SAndroid Build Coastguard Worker 
507*4dc78e53SAndroid Build Coastguard Worker 	if ((ev = getenv("HZ"))) {
508*4dc78e53SAndroid Build Coastguard Worker 		long hz = strtol(ev, NULL, 0);
509*4dc78e53SAndroid Build Coastguard Worker 
510*4dc78e53SAndroid Build Coastguard Worker 		if (LONG_MIN != hz && LONG_MAX != hz) {
511*4dc78e53SAndroid Build Coastguard Worker 			user_hz = hz;
512*4dc78e53SAndroid Build Coastguard Worker 			got_hz = 1;
513*4dc78e53SAndroid Build Coastguard Worker 		}
514*4dc78e53SAndroid Build Coastguard Worker 	}
515*4dc78e53SAndroid Build Coastguard Worker 
516*4dc78e53SAndroid Build Coastguard Worker 	if (!got_hz)
517*4dc78e53SAndroid Build Coastguard Worker 		user_hz = sysconf(_SC_CLK_TCK);
518*4dc78e53SAndroid Build Coastguard Worker 
519*4dc78e53SAndroid Build Coastguard Worker 	psched_hz = user_hz;
520*4dc78e53SAndroid Build Coastguard Worker 
521*4dc78e53SAndroid Build Coastguard Worker 	if ((ev = getenv("TICKS_PER_USEC"))) {
522*4dc78e53SAndroid Build Coastguard Worker 		double t = strtod(ev, NULL);
523*4dc78e53SAndroid Build Coastguard Worker 		ticks_per_usec = t;
524*4dc78e53SAndroid Build Coastguard Worker 	}
525*4dc78e53SAndroid Build Coastguard Worker 	else {
526*4dc78e53SAndroid Build Coastguard Worker 		if ((ev = getenv("PROC_NET_PSCHED")))
527*4dc78e53SAndroid Build Coastguard Worker 			snprintf(name, sizeof(name), "%s", ev);
528*4dc78e53SAndroid Build Coastguard Worker 		else if ((ev = getenv("PROC_ROOT")))
529*4dc78e53SAndroid Build Coastguard Worker 			snprintf(name, sizeof(name), "%s/net/psched", ev);
530*4dc78e53SAndroid Build Coastguard Worker 		else
531*4dc78e53SAndroid Build Coastguard Worker 			_nl_strncpy_assert(name, "/proc/net/psched", sizeof(name));
532*4dc78e53SAndroid Build Coastguard Worker 
533*4dc78e53SAndroid Build Coastguard Worker 		if ((fd = fopen(name, "re"))) {
534*4dc78e53SAndroid Build Coastguard Worker 			unsigned int ns_per_usec, ns_per_tick, nom, denom;
535*4dc78e53SAndroid Build Coastguard Worker 
536*4dc78e53SAndroid Build Coastguard Worker 			if (fscanf(fd, "%08x %08x %08x %08x",
537*4dc78e53SAndroid Build Coastguard Worker 			       &ns_per_usec, &ns_per_tick, &nom, &denom) != 4) {
538*4dc78e53SAndroid Build Coastguard Worker 				NL_DBG(1, "Fatal error: can not read psched settings from \"%s\". " \
539*4dc78e53SAndroid Build Coastguard Worker 				          "Try to set TICKS_PER_USEC, PROC_NET_PSCHED or PROC_ROOT " \
540*4dc78e53SAndroid Build Coastguard Worker 				          "environment variables\n", name);
541*4dc78e53SAndroid Build Coastguard Worker 				exit(1);
542*4dc78e53SAndroid Build Coastguard Worker 			}
543*4dc78e53SAndroid Build Coastguard Worker 
544*4dc78e53SAndroid Build Coastguard Worker 			ticks_per_usec = (double) ns_per_usec /
545*4dc78e53SAndroid Build Coastguard Worker 					 (double) ns_per_tick;
546*4dc78e53SAndroid Build Coastguard Worker 
547*4dc78e53SAndroid Build Coastguard Worker 			if (nom == 1000000)
548*4dc78e53SAndroid Build Coastguard Worker 				psched_hz = denom;
549*4dc78e53SAndroid Build Coastguard Worker 
550*4dc78e53SAndroid Build Coastguard Worker 			fclose(fd);
551*4dc78e53SAndroid Build Coastguard Worker 		}
552*4dc78e53SAndroid Build Coastguard Worker 	}
553*4dc78e53SAndroid Build Coastguard Worker 	initialized = 1;
554*4dc78e53SAndroid Build Coastguard Worker 
555*4dc78e53SAndroid Build Coastguard Worker 	nl_unlock(&mutex);
556*4dc78e53SAndroid Build Coastguard Worker }
557*4dc78e53SAndroid Build Coastguard Worker 
558*4dc78e53SAndroid Build Coastguard Worker 
559*4dc78e53SAndroid Build Coastguard Worker /**
560*4dc78e53SAndroid Build Coastguard Worker  * Return the value of HZ
561*4dc78e53SAndroid Build Coastguard Worker  */
nl_get_user_hz(void)562*4dc78e53SAndroid Build Coastguard Worker int nl_get_user_hz(void)
563*4dc78e53SAndroid Build Coastguard Worker {
564*4dc78e53SAndroid Build Coastguard Worker 	get_psched_settings();
565*4dc78e53SAndroid Build Coastguard Worker 	return user_hz;
566*4dc78e53SAndroid Build Coastguard Worker }
567*4dc78e53SAndroid Build Coastguard Worker 
568*4dc78e53SAndroid Build Coastguard Worker /**
569*4dc78e53SAndroid Build Coastguard Worker  * Return the value of packet scheduler HZ
570*4dc78e53SAndroid Build Coastguard Worker  */
nl_get_psched_hz(void)571*4dc78e53SAndroid Build Coastguard Worker int nl_get_psched_hz(void)
572*4dc78e53SAndroid Build Coastguard Worker {
573*4dc78e53SAndroid Build Coastguard Worker 	get_psched_settings();
574*4dc78e53SAndroid Build Coastguard Worker 	return psched_hz;
575*4dc78e53SAndroid Build Coastguard Worker }
576*4dc78e53SAndroid Build Coastguard Worker 
577*4dc78e53SAndroid Build Coastguard Worker /**
578*4dc78e53SAndroid Build Coastguard Worker  * Convert micro seconds to ticks
579*4dc78e53SAndroid Build Coastguard Worker  * @arg us		micro seconds
580*4dc78e53SAndroid Build Coastguard Worker  * @return number of ticks
581*4dc78e53SAndroid Build Coastguard Worker  */
nl_us2ticks(uint32_t us)582*4dc78e53SAndroid Build Coastguard Worker uint32_t nl_us2ticks(uint32_t us)
583*4dc78e53SAndroid Build Coastguard Worker {
584*4dc78e53SAndroid Build Coastguard Worker 	get_psched_settings();
585*4dc78e53SAndroid Build Coastguard Worker 	return us * ticks_per_usec;
586*4dc78e53SAndroid Build Coastguard Worker }
587*4dc78e53SAndroid Build Coastguard Worker 
588*4dc78e53SAndroid Build Coastguard Worker 
589*4dc78e53SAndroid Build Coastguard Worker /**
590*4dc78e53SAndroid Build Coastguard Worker  * Convert ticks to micro seconds
591*4dc78e53SAndroid Build Coastguard Worker  * @arg ticks		number of ticks
592*4dc78e53SAndroid Build Coastguard Worker  * @return microseconds
593*4dc78e53SAndroid Build Coastguard Worker  */
nl_ticks2us(uint32_t ticks)594*4dc78e53SAndroid Build Coastguard Worker uint32_t nl_ticks2us(uint32_t ticks)
595*4dc78e53SAndroid Build Coastguard Worker {
596*4dc78e53SAndroid Build Coastguard Worker 	get_psched_settings();
597*4dc78e53SAndroid Build Coastguard Worker 	return ticks / ticks_per_usec;
598*4dc78e53SAndroid Build Coastguard Worker }
599*4dc78e53SAndroid Build Coastguard Worker 
nl_str2msec(const char * str,uint64_t * result)600*4dc78e53SAndroid Build Coastguard Worker int nl_str2msec(const char *str, uint64_t *result)
601*4dc78e53SAndroid Build Coastguard Worker {
602*4dc78e53SAndroid Build Coastguard Worker 	uint64_t total = 0, l;
603*4dc78e53SAndroid Build Coastguard Worker 	int plen;
604*4dc78e53SAndroid Build Coastguard Worker 	char *p;
605*4dc78e53SAndroid Build Coastguard Worker 
606*4dc78e53SAndroid Build Coastguard Worker 	do {
607*4dc78e53SAndroid Build Coastguard Worker 		l = strtoul(str, &p, 0);
608*4dc78e53SAndroid Build Coastguard Worker 		if (p == str)
609*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_INVAL;
610*4dc78e53SAndroid Build Coastguard Worker 		else if (*p) {
611*4dc78e53SAndroid Build Coastguard Worker 			plen = strcspn(p, " \t");
612*4dc78e53SAndroid Build Coastguard Worker 
613*4dc78e53SAndroid Build Coastguard Worker 			if (!plen)
614*4dc78e53SAndroid Build Coastguard Worker 				total += l;
615*4dc78e53SAndroid Build Coastguard Worker 			else if (!strncasecmp(p, "sec", plen))
616*4dc78e53SAndroid Build Coastguard Worker 				total += (l * 1000);
617*4dc78e53SAndroid Build Coastguard Worker 			else if (!strncasecmp(p, "min", plen))
618*4dc78e53SAndroid Build Coastguard Worker 				total += (l * 1000*60);
619*4dc78e53SAndroid Build Coastguard Worker 			else if (!strncasecmp(p, "hour", plen))
620*4dc78e53SAndroid Build Coastguard Worker 				total += (l * 1000*60*60);
621*4dc78e53SAndroid Build Coastguard Worker 			else if (!strncasecmp(p, "day", plen))
622*4dc78e53SAndroid Build Coastguard Worker 				total += (l * 1000*60*60*24);
623*4dc78e53SAndroid Build Coastguard Worker 			else
624*4dc78e53SAndroid Build Coastguard Worker 				return -NLE_INVAL;
625*4dc78e53SAndroid Build Coastguard Worker 
626*4dc78e53SAndroid Build Coastguard Worker 			str = p + plen;
627*4dc78e53SAndroid Build Coastguard Worker 		} else
628*4dc78e53SAndroid Build Coastguard Worker 			total += l;
629*4dc78e53SAndroid Build Coastguard Worker 	} while (*str && *p);
630*4dc78e53SAndroid Build Coastguard Worker 
631*4dc78e53SAndroid Build Coastguard Worker 	*result = total;
632*4dc78e53SAndroid Build Coastguard Worker 
633*4dc78e53SAndroid Build Coastguard Worker 	return 0;
634*4dc78e53SAndroid Build Coastguard Worker }
635*4dc78e53SAndroid Build Coastguard Worker 
636*4dc78e53SAndroid Build Coastguard Worker /**
637*4dc78e53SAndroid Build Coastguard Worker  * Convert milliseconds to a character string
638*4dc78e53SAndroid Build Coastguard Worker  * @arg msec		number of milliseconds
639*4dc78e53SAndroid Build Coastguard Worker  * @arg buf		destination buffer
640*4dc78e53SAndroid Build Coastguard Worker  * @arg len		buffer length
641*4dc78e53SAndroid Build Coastguard Worker  *
642*4dc78e53SAndroid Build Coastguard Worker  * Converts milliseconds to a character string split up in days, hours,
643*4dc78e53SAndroid Build Coastguard Worker  * minutes, seconds, and milliseconds and stores it in the specified
644*4dc78e53SAndroid Build Coastguard Worker  * destination buffer.
645*4dc78e53SAndroid Build Coastguard Worker  *
646*4dc78e53SAndroid Build Coastguard Worker  * @return The destination buffer.
647*4dc78e53SAndroid Build Coastguard Worker  */
nl_msec2str(uint64_t msec,char * buf,size_t len)648*4dc78e53SAndroid Build Coastguard Worker char * nl_msec2str(uint64_t msec, char *buf, size_t len)
649*4dc78e53SAndroid Build Coastguard Worker {
650*4dc78e53SAndroid Build Coastguard Worker 	uint64_t split[5];
651*4dc78e53SAndroid Build Coastguard Worker 	size_t i;
652*4dc78e53SAndroid Build Coastguard Worker 	static const char *units[5] = {"d", "h", "m", "s", "msec"};
653*4dc78e53SAndroid Build Coastguard Worker 	char * const buf_orig = buf;
654*4dc78e53SAndroid Build Coastguard Worker 
655*4dc78e53SAndroid Build Coastguard Worker 	if (msec == 0) {
656*4dc78e53SAndroid Build Coastguard Worker 		snprintf(buf, len, "0msec");
657*4dc78e53SAndroid Build Coastguard Worker 		return buf_orig;
658*4dc78e53SAndroid Build Coastguard Worker 	}
659*4dc78e53SAndroid Build Coastguard Worker 
660*4dc78e53SAndroid Build Coastguard Worker #define _SPLIT(idx, unit) if ((split[idx] = msec / unit)) msec %= unit
661*4dc78e53SAndroid Build Coastguard Worker 	_SPLIT(0, 86400000);	/* days */
662*4dc78e53SAndroid Build Coastguard Worker 	_SPLIT(1, 3600000);	/* hours */
663*4dc78e53SAndroid Build Coastguard Worker 	_SPLIT(2, 60000);	/* minutes */
664*4dc78e53SAndroid Build Coastguard Worker 	_SPLIT(3, 1000);	/* seconds */
665*4dc78e53SAndroid Build Coastguard Worker #undef  _SPLIT
666*4dc78e53SAndroid Build Coastguard Worker 	split[4] = msec;
667*4dc78e53SAndroid Build Coastguard Worker 
668*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(split) && len; i++) {
669*4dc78e53SAndroid Build Coastguard Worker 		int l;
670*4dc78e53SAndroid Build Coastguard Worker 		if (split[i] == 0)
671*4dc78e53SAndroid Build Coastguard Worker 			continue;
672*4dc78e53SAndroid Build Coastguard Worker 		l = snprintf(buf, len, "%s%" PRIu64 "%s",
673*4dc78e53SAndroid Build Coastguard Worker 			(buf==buf_orig) ? "" : " ", split[i], units[i]);
674*4dc78e53SAndroid Build Coastguard Worker 		buf += l;
675*4dc78e53SAndroid Build Coastguard Worker 		len -= l;
676*4dc78e53SAndroid Build Coastguard Worker 	}
677*4dc78e53SAndroid Build Coastguard Worker 
678*4dc78e53SAndroid Build Coastguard Worker 	return buf_orig;
679*4dc78e53SAndroid Build Coastguard Worker }
680*4dc78e53SAndroid Build Coastguard Worker 
681*4dc78e53SAndroid Build Coastguard Worker /** @} */
682*4dc78e53SAndroid Build Coastguard Worker 
683*4dc78e53SAndroid Build Coastguard Worker /**
684*4dc78e53SAndroid Build Coastguard Worker  * @name Netlink Family Translations
685*4dc78e53SAndroid Build Coastguard Worker  * @{
686*4dc78e53SAndroid Build Coastguard Worker  */
687*4dc78e53SAndroid Build Coastguard Worker 
688*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl nlfamilies[] = {
689*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_ROUTE,route),
690*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_USERSOCK,usersock),
691*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_FIREWALL,firewall),
692*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_INET_DIAG,inetdiag),
693*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_NFLOG,nflog),
694*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_XFRM,xfrm),
695*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_SELINUX,selinux),
696*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_ISCSI,iscsi),
697*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_AUDIT,audit),
698*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_FIB_LOOKUP,fib_lookup),
699*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_CONNECTOR,connector),
700*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_NETFILTER,netfilter),
701*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_IP6_FW,ip6_fw),
702*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_DNRTMSG,dnrtmsg),
703*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_KOBJECT_UEVENT,kobject_uevent),
704*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_GENERIC,generic),
705*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_SCSITRANSPORT,scsitransport),
706*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_ECRYPTFS,ecryptfs),
707*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_RDMA,rdma),
708*4dc78e53SAndroid Build Coastguard Worker 	__ADD(NETLINK_CRYPTO,crypto),
709*4dc78e53SAndroid Build Coastguard Worker };
710*4dc78e53SAndroid Build Coastguard Worker 
nl_nlfamily2str(int family,char * buf,size_t size)711*4dc78e53SAndroid Build Coastguard Worker char * nl_nlfamily2str(int family, char *buf, size_t size)
712*4dc78e53SAndroid Build Coastguard Worker {
713*4dc78e53SAndroid Build Coastguard Worker 	return __type2str(family, buf, size, nlfamilies,
714*4dc78e53SAndroid Build Coastguard Worker 			  ARRAY_SIZE(nlfamilies));
715*4dc78e53SAndroid Build Coastguard Worker }
716*4dc78e53SAndroid Build Coastguard Worker 
nl_str2nlfamily(const char * name)717*4dc78e53SAndroid Build Coastguard Worker int nl_str2nlfamily(const char *name)
718*4dc78e53SAndroid Build Coastguard Worker {
719*4dc78e53SAndroid Build Coastguard Worker 	return __str2type(name, nlfamilies, ARRAY_SIZE(nlfamilies));
720*4dc78e53SAndroid Build Coastguard Worker }
721*4dc78e53SAndroid Build Coastguard Worker 
722*4dc78e53SAndroid Build Coastguard Worker /**
723*4dc78e53SAndroid Build Coastguard Worker  * @}
724*4dc78e53SAndroid Build Coastguard Worker  */
725*4dc78e53SAndroid Build Coastguard Worker 
726*4dc78e53SAndroid Build Coastguard Worker /**
727*4dc78e53SAndroid Build Coastguard Worker  * @name Link Layer Protocol Translations
728*4dc78e53SAndroid Build Coastguard Worker  * @{
729*4dc78e53SAndroid Build Coastguard Worker  */
730*4dc78e53SAndroid Build Coastguard Worker 
731*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl llprotos[] = {
732*4dc78e53SAndroid Build Coastguard Worker 	{0, "generic"},
733*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_NETROM,netrom),
734*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_ETHER,ether),
735*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_EETHER,eether),
736*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_AX25,ax25),
737*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_PRONET,pronet),
738*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_CHAOS,chaos),
739*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IEEE802,ieee802),
740*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_ARCNET,arcnet),
741*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_APPLETLK,atalk),
742*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_DLCI,dlci),
743*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_ATM,atm),
744*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_METRICOM,metricom),
745*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IEEE1394,ieee1394),
746*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_EUI64,eui64),
747*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_INFINIBAND,infiniband),
748*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_SLIP,slip),
749*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_CSLIP,cslip),
750*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_SLIP6,slip6),
751*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_CSLIP6,cslip6),
752*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_RSRVD,rsrvd),
753*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_ADAPT,adapt),
754*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_ROSE,rose),
755*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_X25,x25),
756*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_HWX25,hwx25),
757*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_CAN,can),
758*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_PPP,ppp),
759*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_CISCO,cisco),
760*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_HDLC,hdlc),
761*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_LAPB,lapb),
762*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_DDCMP,ddcmp),
763*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_RAWHDLC,rawhdlc),
764*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_TUNNEL,ipip),
765*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_TUNNEL6,tunnel6),
766*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FRAD,frad),
767*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_SKIP,skip),
768*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_LOOPBACK,loopback),
769*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_LOCALTLK,localtlk),
770*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FDDI,fddi),
771*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_BIF,bif),
772*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_SIT,sit),
773*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IPDDP,ip/ddp),
774*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IPGRE,gre),
775*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_PIMREG,pimreg),
776*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_HIPPI,hippi),
777*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_ASH,ash),
778*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_ECONET,econet),
779*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IRDA,irda),
780*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCPP,fcpp),
781*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCAL,fcal),
782*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCPL,fcpl),
783*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC,fcfb_0),
784*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+1,fcfb_1),
785*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+2,fcfb_2),
786*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+3,fcfb_3),
787*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+4,fcfb_4),
788*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+5,fcfb_5),
789*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+6,fcfb_6),
790*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+7,fcfb_7),
791*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+8,fcfb_8),
792*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+9,fcfb_9),
793*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+10,fcfb_10),
794*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+11,fcfb_11),
795*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_FCFABRIC+12,fcfb_12),
796*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IEEE802_TR,tr),
797*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IEEE80211,ieee802.11),
798*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IEEE80211_PRISM,ieee802.11_prism),
799*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IEEE80211_RADIOTAP,ieee802.11_radiotap),
800*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IEEE802154,ieee802.15.4),
801*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IEEE802154_MONITOR,ieee802.15.4_monitor),
802*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_PHONET,phonet),
803*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_PHONET_PIPE,phonet_pipe),
804*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_CAIF,caif),
805*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_IP6GRE,ip6gre),
806*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_NETLINK,netlink),
807*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_6LOWPAN,6lowpan),
808*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_VOID,void),
809*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ARPHRD_NONE,nohdr),
810*4dc78e53SAndroid Build Coastguard Worker };
811*4dc78e53SAndroid Build Coastguard Worker 
nl_llproto2str(int llproto,char * buf,size_t len)812*4dc78e53SAndroid Build Coastguard Worker char * nl_llproto2str(int llproto, char *buf, size_t len)
813*4dc78e53SAndroid Build Coastguard Worker {
814*4dc78e53SAndroid Build Coastguard Worker 	return __type2str(llproto, buf, len, llprotos, ARRAY_SIZE(llprotos));
815*4dc78e53SAndroid Build Coastguard Worker }
816*4dc78e53SAndroid Build Coastguard Worker 
nl_str2llproto(const char * name)817*4dc78e53SAndroid Build Coastguard Worker int nl_str2llproto(const char *name)
818*4dc78e53SAndroid Build Coastguard Worker {
819*4dc78e53SAndroid Build Coastguard Worker 	return __str2type(name, llprotos, ARRAY_SIZE(llprotos));
820*4dc78e53SAndroid Build Coastguard Worker }
821*4dc78e53SAndroid Build Coastguard Worker 
822*4dc78e53SAndroid Build Coastguard Worker /** @} */
823*4dc78e53SAndroid Build Coastguard Worker 
824*4dc78e53SAndroid Build Coastguard Worker 
825*4dc78e53SAndroid Build Coastguard Worker /**
826*4dc78e53SAndroid Build Coastguard Worker  * @name Ethernet Protocol Translations
827*4dc78e53SAndroid Build Coastguard Worker  * @{
828*4dc78e53SAndroid Build Coastguard Worker  */
829*4dc78e53SAndroid Build Coastguard Worker 
830*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl ether_protos[] = {
831*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_LOOP,loop),
832*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_PUP,pup),
833*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_PUPAT,pupat),
834*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_IP,ip),
835*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_X25,x25),
836*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_ARP,arp),
837*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_BPQ,bpq),
838*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_IEEEPUP,ieeepup),
839*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_IEEEPUPAT,ieeepupat),
840*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_DEC,dec),
841*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_DNA_DL,dna_dl),
842*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_DNA_RC,dna_rc),
843*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_DNA_RT,dna_rt),
844*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_LAT,lat),
845*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_DIAG,diag),
846*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_CUST,cust),
847*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_SCA,sca),
848*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_TEB,teb),
849*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_RARP,rarp),
850*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_ATALK,atalk),
851*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_AARP,aarp),
852*4dc78e53SAndroid Build Coastguard Worker #ifdef ETH_P_8021Q
853*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_8021Q,802.1q),
854*4dc78e53SAndroid Build Coastguard Worker #endif
855*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_IPX,ipx),
856*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_IPV6,ipv6),
857*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_PAUSE,pause),
858*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_SLOW,slow),
859*4dc78e53SAndroid Build Coastguard Worker #ifdef ETH_P_WCCP
860*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_WCCP,wccp),
861*4dc78e53SAndroid Build Coastguard Worker #endif
862*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_PPP_DISC,ppp_disc),
863*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_PPP_SES,ppp_ses),
864*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_MPLS_UC,mpls_uc),
865*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_MPLS_MC,mpls_mc),
866*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_ATMMPOA,atmmpoa),
867*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_LINK_CTL,link_ctl),
868*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_ATMFATE,atmfate),
869*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_PAE,pae),
870*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_AOE,aoe),
871*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_TIPC,tipc),
872*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_1588,ieee1588),
873*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_FCOE,fcoe),
874*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_FIP,fip),
875*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_EDSA,edsa),
876*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_EDP2,edp2),
877*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_802_3,802.3),
878*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_AX25,ax25),
879*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_ALL,all),
880*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_802_2,802.2),
881*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_SNAP,snap),
882*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_DDCMP,ddcmp),
883*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_WAN_PPP,wan_ppp),
884*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_PPP_MP,ppp_mp),
885*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_LOCALTALK,localtalk),
886*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_CAN,can),
887*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_PPPTALK,ppptalk),
888*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_TR_802_2,tr_802.2),
889*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_MOBITEX,mobitex),
890*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_CONTROL,control),
891*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_IRDA,irda),
892*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_ECONET,econet),
893*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_HDLC,hdlc),
894*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_ARCNET,arcnet),
895*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_DSA,dsa),
896*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_TRAILER,trailer),
897*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_PHONET,phonet),
898*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_IEEE802154,ieee802154),
899*4dc78e53SAndroid Build Coastguard Worker 	__ADD(ETH_P_CAIF,caif),
900*4dc78e53SAndroid Build Coastguard Worker };
901*4dc78e53SAndroid Build Coastguard Worker 
nl_ether_proto2str(int eproto,char * buf,size_t len)902*4dc78e53SAndroid Build Coastguard Worker char *nl_ether_proto2str(int eproto, char *buf, size_t len)
903*4dc78e53SAndroid Build Coastguard Worker {
904*4dc78e53SAndroid Build Coastguard Worker 	return __type2str(eproto, buf, len, ether_protos,
905*4dc78e53SAndroid Build Coastguard Worker 			    ARRAY_SIZE(ether_protos));
906*4dc78e53SAndroid Build Coastguard Worker }
907*4dc78e53SAndroid Build Coastguard Worker 
nl_str2ether_proto(const char * name)908*4dc78e53SAndroid Build Coastguard Worker int nl_str2ether_proto(const char *name)
909*4dc78e53SAndroid Build Coastguard Worker {
910*4dc78e53SAndroid Build Coastguard Worker 	return __str2type(name, ether_protos, ARRAY_SIZE(ether_protos));
911*4dc78e53SAndroid Build Coastguard Worker }
912*4dc78e53SAndroid Build Coastguard Worker 
913*4dc78e53SAndroid Build Coastguard Worker /** @} */
914*4dc78e53SAndroid Build Coastguard Worker 
915*4dc78e53SAndroid Build Coastguard Worker /**
916*4dc78e53SAndroid Build Coastguard Worker  * @name IP Protocol Translations
917*4dc78e53SAndroid Build Coastguard Worker  * @{
918*4dc78e53SAndroid Build Coastguard Worker  */
919*4dc78e53SAndroid Build Coastguard Worker 
nl_ip_proto2str(int proto,char * buf,size_t len)920*4dc78e53SAndroid Build Coastguard Worker char *nl_ip_proto2str(int proto, char *buf, size_t len)
921*4dc78e53SAndroid Build Coastguard Worker {
922*4dc78e53SAndroid Build Coastguard Worker 	if (nl_getprotobynumber(proto, buf, len))
923*4dc78e53SAndroid Build Coastguard Worker 		return buf;
924*4dc78e53SAndroid Build Coastguard Worker 
925*4dc78e53SAndroid Build Coastguard Worker 	snprintf(buf, len, "0x%x", proto);
926*4dc78e53SAndroid Build Coastguard Worker 	return buf;
927*4dc78e53SAndroid Build Coastguard Worker }
928*4dc78e53SAndroid Build Coastguard Worker 
nl_str2ip_proto(const char * name)929*4dc78e53SAndroid Build Coastguard Worker int nl_str2ip_proto(const char *name)
930*4dc78e53SAndroid Build Coastguard Worker {
931*4dc78e53SAndroid Build Coastguard Worker 	unsigned long l;
932*4dc78e53SAndroid Build Coastguard Worker 	char *end;
933*4dc78e53SAndroid Build Coastguard Worker 	int p;
934*4dc78e53SAndroid Build Coastguard Worker 
935*4dc78e53SAndroid Build Coastguard Worker 	if (!name)
936*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
937*4dc78e53SAndroid Build Coastguard Worker 
938*4dc78e53SAndroid Build Coastguard Worker 	p = nl_getprotobyname(name);
939*4dc78e53SAndroid Build Coastguard Worker 	if (p >= 0)
940*4dc78e53SAndroid Build Coastguard Worker 		return p;
941*4dc78e53SAndroid Build Coastguard Worker 
942*4dc78e53SAndroid Build Coastguard Worker 	l = strtoul(name, &end, 0);
943*4dc78e53SAndroid Build Coastguard Worker 	if (name == end || *end != '\0' || l > (unsigned long)INT_MAX)
944*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_OBJ_NOTFOUND;
945*4dc78e53SAndroid Build Coastguard Worker 
946*4dc78e53SAndroid Build Coastguard Worker 	return (int) l;
947*4dc78e53SAndroid Build Coastguard Worker }
948*4dc78e53SAndroid Build Coastguard Worker 
949*4dc78e53SAndroid Build Coastguard Worker /** @} */
950*4dc78e53SAndroid Build Coastguard Worker 
951*4dc78e53SAndroid Build Coastguard Worker /**
952*4dc78e53SAndroid Build Coastguard Worker  * @name Dumping Helpers
953*4dc78e53SAndroid Build Coastguard Worker  * @{
954*4dc78e53SAndroid Build Coastguard Worker  */
955*4dc78e53SAndroid Build Coastguard Worker 
956*4dc78e53SAndroid Build Coastguard Worker /**
957*4dc78e53SAndroid Build Coastguard Worker  * Handle a new line while dumping
958*4dc78e53SAndroid Build Coastguard Worker  * @arg params		Dumping parameters
959*4dc78e53SAndroid Build Coastguard Worker  *
960*4dc78e53SAndroid Build Coastguard Worker  * This function must be called before dumping any onto a
961*4dc78e53SAndroid Build Coastguard Worker  * new line. It will ensure proper prefixing as specified
962*4dc78e53SAndroid Build Coastguard Worker  * by the dumping parameters.
963*4dc78e53SAndroid Build Coastguard Worker  *
964*4dc78e53SAndroid Build Coastguard Worker  * @note This function will NOT dump any newlines itself
965*4dc78e53SAndroid Build Coastguard Worker  */
nl_new_line(struct nl_dump_params * params)966*4dc78e53SAndroid Build Coastguard Worker void nl_new_line(struct nl_dump_params *params)
967*4dc78e53SAndroid Build Coastguard Worker {
968*4dc78e53SAndroid Build Coastguard Worker 	params->dp_line++;
969*4dc78e53SAndroid Build Coastguard Worker 
970*4dc78e53SAndroid Build Coastguard Worker 	if (params->dp_prefix) {
971*4dc78e53SAndroid Build Coastguard Worker 		int i;
972*4dc78e53SAndroid Build Coastguard Worker 		for (i = 0; i < params->dp_prefix; i++) {
973*4dc78e53SAndroid Build Coastguard Worker 			if (params->dp_fd)
974*4dc78e53SAndroid Build Coastguard Worker 				fprintf(params->dp_fd, " ");
975*4dc78e53SAndroid Build Coastguard Worker 			else if (params->dp_buf)
976*4dc78e53SAndroid Build Coastguard Worker 				strncat(params->dp_buf, " ",
977*4dc78e53SAndroid Build Coastguard Worker 					params->dp_buflen -
978*4dc78e53SAndroid Build Coastguard Worker 					strlen(params->dp_buf) - 1);
979*4dc78e53SAndroid Build Coastguard Worker 		}
980*4dc78e53SAndroid Build Coastguard Worker 	}
981*4dc78e53SAndroid Build Coastguard Worker 
982*4dc78e53SAndroid Build Coastguard Worker 	if (params->dp_nl_cb)
983*4dc78e53SAndroid Build Coastguard Worker 		params->dp_nl_cb(params, params->dp_line);
984*4dc78e53SAndroid Build Coastguard Worker }
985*4dc78e53SAndroid Build Coastguard Worker 
dump_one(struct nl_dump_params * parms,const char * fmt,va_list args)986*4dc78e53SAndroid Build Coastguard Worker static void dump_one(struct nl_dump_params *parms, const char *fmt,
987*4dc78e53SAndroid Build Coastguard Worker 		     va_list args)
988*4dc78e53SAndroid Build Coastguard Worker {
989*4dc78e53SAndroid Build Coastguard Worker 	if (parms->dp_fd)
990*4dc78e53SAndroid Build Coastguard Worker 		vfprintf(parms->dp_fd, fmt, args);
991*4dc78e53SAndroid Build Coastguard Worker 	else if (parms->dp_buf || parms->dp_cb) {
992*4dc78e53SAndroid Build Coastguard Worker 		char *buf = NULL;
993*4dc78e53SAndroid Build Coastguard Worker 		if (vasprintf(&buf, fmt, args) >= 0) {
994*4dc78e53SAndroid Build Coastguard Worker 			if (parms->dp_cb)
995*4dc78e53SAndroid Build Coastguard Worker 				parms->dp_cb(parms, buf);
996*4dc78e53SAndroid Build Coastguard Worker 			else
997*4dc78e53SAndroid Build Coastguard Worker 				strncat(parms->dp_buf, buf,
998*4dc78e53SAndroid Build Coastguard Worker 					parms->dp_buflen -
999*4dc78e53SAndroid Build Coastguard Worker 					strlen(parms->dp_buf) - 1);
1000*4dc78e53SAndroid Build Coastguard Worker 			free(buf);
1001*4dc78e53SAndroid Build Coastguard Worker 		}
1002*4dc78e53SAndroid Build Coastguard Worker 	}
1003*4dc78e53SAndroid Build Coastguard Worker }
1004*4dc78e53SAndroid Build Coastguard Worker 
1005*4dc78e53SAndroid Build Coastguard Worker 
1006*4dc78e53SAndroid Build Coastguard Worker /**
1007*4dc78e53SAndroid Build Coastguard Worker  * Dump a formatted character string
1008*4dc78e53SAndroid Build Coastguard Worker  * @arg params		Dumping parameters
1009*4dc78e53SAndroid Build Coastguard Worker  * @arg fmt		printf style formatting string
1010*4dc78e53SAndroid Build Coastguard Worker  * @arg ...		Arguments to formatting string
1011*4dc78e53SAndroid Build Coastguard Worker  *
1012*4dc78e53SAndroid Build Coastguard Worker  * Dumps a printf style formatting string to the output device
1013*4dc78e53SAndroid Build Coastguard Worker  * as specified by the dumping parameters.
1014*4dc78e53SAndroid Build Coastguard Worker  */
nl_dump(struct nl_dump_params * params,const char * fmt,...)1015*4dc78e53SAndroid Build Coastguard Worker void nl_dump(struct nl_dump_params *params, const char *fmt, ...)
1016*4dc78e53SAndroid Build Coastguard Worker {
1017*4dc78e53SAndroid Build Coastguard Worker 	va_list args;
1018*4dc78e53SAndroid Build Coastguard Worker 
1019*4dc78e53SAndroid Build Coastguard Worker 	va_start(args, fmt);
1020*4dc78e53SAndroid Build Coastguard Worker 	dump_one(params, fmt, args);
1021*4dc78e53SAndroid Build Coastguard Worker 	va_end(args);
1022*4dc78e53SAndroid Build Coastguard Worker }
1023*4dc78e53SAndroid Build Coastguard Worker 
nl_dump_line(struct nl_dump_params * parms,const char * fmt,...)1024*4dc78e53SAndroid Build Coastguard Worker void nl_dump_line(struct nl_dump_params *parms, const char *fmt, ...)
1025*4dc78e53SAndroid Build Coastguard Worker {
1026*4dc78e53SAndroid Build Coastguard Worker 	va_list args;
1027*4dc78e53SAndroid Build Coastguard Worker 
1028*4dc78e53SAndroid Build Coastguard Worker 	nl_new_line(parms);
1029*4dc78e53SAndroid Build Coastguard Worker 
1030*4dc78e53SAndroid Build Coastguard Worker 	va_start(args, fmt);
1031*4dc78e53SAndroid Build Coastguard Worker 	dump_one(parms, fmt, args);
1032*4dc78e53SAndroid Build Coastguard Worker 	va_end(args);
1033*4dc78e53SAndroid Build Coastguard Worker }
1034*4dc78e53SAndroid Build Coastguard Worker 
1035*4dc78e53SAndroid Build Coastguard Worker 
1036*4dc78e53SAndroid Build Coastguard Worker /** @} */
1037*4dc78e53SAndroid Build Coastguard Worker 
1038*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
1039*4dc78e53SAndroid Build Coastguard Worker 
__trans_list_add(int i,const char * a,struct nl_list_head * head)1040*4dc78e53SAndroid Build Coastguard Worker int __trans_list_add(int i, const char *a, struct nl_list_head *head)
1041*4dc78e53SAndroid Build Coastguard Worker {
1042*4dc78e53SAndroid Build Coastguard Worker 	struct trans_list *tl;
1043*4dc78e53SAndroid Build Coastguard Worker 
1044*4dc78e53SAndroid Build Coastguard Worker 	tl = calloc(1, sizeof(*tl));
1045*4dc78e53SAndroid Build Coastguard Worker 	if (!tl)
1046*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
1047*4dc78e53SAndroid Build Coastguard Worker 
1048*4dc78e53SAndroid Build Coastguard Worker 	tl->i = i;
1049*4dc78e53SAndroid Build Coastguard Worker 	tl->a = strdup(a);
1050*4dc78e53SAndroid Build Coastguard Worker 
1051*4dc78e53SAndroid Build Coastguard Worker 	nl_list_add_tail(&tl->list, head);
1052*4dc78e53SAndroid Build Coastguard Worker 
1053*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1054*4dc78e53SAndroid Build Coastguard Worker }
1055*4dc78e53SAndroid Build Coastguard Worker 
__trans_list_clear(struct nl_list_head * head)1056*4dc78e53SAndroid Build Coastguard Worker void __trans_list_clear(struct nl_list_head *head)
1057*4dc78e53SAndroid Build Coastguard Worker {
1058*4dc78e53SAndroid Build Coastguard Worker 	struct trans_list *tl, *next;
1059*4dc78e53SAndroid Build Coastguard Worker 
1060*4dc78e53SAndroid Build Coastguard Worker 	nl_list_for_each_entry_safe(tl, next, head, list) {
1061*4dc78e53SAndroid Build Coastguard Worker 		free(tl->a);
1062*4dc78e53SAndroid Build Coastguard Worker 		free(tl);
1063*4dc78e53SAndroid Build Coastguard Worker 	}
1064*4dc78e53SAndroid Build Coastguard Worker 
1065*4dc78e53SAndroid Build Coastguard Worker 	nl_init_list_head(head);
1066*4dc78e53SAndroid Build Coastguard Worker }
1067*4dc78e53SAndroid Build Coastguard Worker 
__type2str(int type,char * buf,size_t len,const struct trans_tbl * tbl,size_t tbl_len)1068*4dc78e53SAndroid Build Coastguard Worker char *__type2str(int type, char *buf, size_t len,
1069*4dc78e53SAndroid Build Coastguard Worker 		 const struct trans_tbl *tbl, size_t tbl_len)
1070*4dc78e53SAndroid Build Coastguard Worker {
1071*4dc78e53SAndroid Build Coastguard Worker 	size_t i;
1072*4dc78e53SAndroid Build Coastguard Worker 
1073*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; i < tbl_len; i++) {
1074*4dc78e53SAndroid Build Coastguard Worker 		if (tbl[i].i == ((uint64_t)type)) {
1075*4dc78e53SAndroid Build Coastguard Worker 			snprintf(buf, len, "%s", tbl[i].a);
1076*4dc78e53SAndroid Build Coastguard Worker 			return buf;
1077*4dc78e53SAndroid Build Coastguard Worker 		}
1078*4dc78e53SAndroid Build Coastguard Worker 	}
1079*4dc78e53SAndroid Build Coastguard Worker 
1080*4dc78e53SAndroid Build Coastguard Worker 	snprintf(buf, len, "0x%x", (unsigned)type);
1081*4dc78e53SAndroid Build Coastguard Worker 	return buf;
1082*4dc78e53SAndroid Build Coastguard Worker }
1083*4dc78e53SAndroid Build Coastguard Worker 
__list_type2str(int type,char * buf,size_t len,struct nl_list_head * head)1084*4dc78e53SAndroid Build Coastguard Worker char *__list_type2str(int type, char *buf, size_t len,
1085*4dc78e53SAndroid Build Coastguard Worker 		      struct nl_list_head *head)
1086*4dc78e53SAndroid Build Coastguard Worker {
1087*4dc78e53SAndroid Build Coastguard Worker 	struct trans_list *tl;
1088*4dc78e53SAndroid Build Coastguard Worker 
1089*4dc78e53SAndroid Build Coastguard Worker 	nl_list_for_each_entry(tl, head, list) {
1090*4dc78e53SAndroid Build Coastguard Worker 		if (tl->i == type) {
1091*4dc78e53SAndroid Build Coastguard Worker 			snprintf(buf, len, "%s", tl->a);
1092*4dc78e53SAndroid Build Coastguard Worker 			return buf;
1093*4dc78e53SAndroid Build Coastguard Worker 		}
1094*4dc78e53SAndroid Build Coastguard Worker 	}
1095*4dc78e53SAndroid Build Coastguard Worker 
1096*4dc78e53SAndroid Build Coastguard Worker 	snprintf(buf, len, "0x%x", type);
1097*4dc78e53SAndroid Build Coastguard Worker 	return buf;
1098*4dc78e53SAndroid Build Coastguard Worker }
1099*4dc78e53SAndroid Build Coastguard Worker 
__flags2str(int flags,char * buf,size_t len,const struct trans_tbl * tbl,size_t tbl_len)1100*4dc78e53SAndroid Build Coastguard Worker char *__flags2str(int flags, char *buf, size_t len,
1101*4dc78e53SAndroid Build Coastguard Worker 		  const struct trans_tbl *tbl, size_t tbl_len)
1102*4dc78e53SAndroid Build Coastguard Worker {
1103*4dc78e53SAndroid Build Coastguard Worker 	size_t i;
1104*4dc78e53SAndroid Build Coastguard Worker 	int tmp = flags;
1105*4dc78e53SAndroid Build Coastguard Worker 
1106*4dc78e53SAndroid Build Coastguard Worker 	memset(buf, 0, len);
1107*4dc78e53SAndroid Build Coastguard Worker 
1108*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; i < tbl_len; i++) {
1109*4dc78e53SAndroid Build Coastguard Worker 		if (tbl[i].i & tmp) {
1110*4dc78e53SAndroid Build Coastguard Worker 			tmp &= ~tbl[i].i;
1111*4dc78e53SAndroid Build Coastguard Worker 			strncat(buf, tbl[i].a, len - strlen(buf) - 1);
1112*4dc78e53SAndroid Build Coastguard Worker 			if ((tmp & flags))
1113*4dc78e53SAndroid Build Coastguard Worker 				strncat(buf, ",", len - strlen(buf) - 1);
1114*4dc78e53SAndroid Build Coastguard Worker 		}
1115*4dc78e53SAndroid Build Coastguard Worker 	}
1116*4dc78e53SAndroid Build Coastguard Worker 
1117*4dc78e53SAndroid Build Coastguard Worker 	return buf;
1118*4dc78e53SAndroid Build Coastguard Worker }
1119*4dc78e53SAndroid Build Coastguard Worker 
__str2type(const char * buf,const struct trans_tbl * tbl,size_t tbl_len)1120*4dc78e53SAndroid Build Coastguard Worker int __str2type(const char *buf, const struct trans_tbl *tbl, size_t tbl_len)
1121*4dc78e53SAndroid Build Coastguard Worker {
1122*4dc78e53SAndroid Build Coastguard Worker 	unsigned long l;
1123*4dc78e53SAndroid Build Coastguard Worker 	char *end;
1124*4dc78e53SAndroid Build Coastguard Worker 	size_t i;
1125*4dc78e53SAndroid Build Coastguard Worker 
1126*4dc78e53SAndroid Build Coastguard Worker 	if (*buf == '\0')
1127*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
1128*4dc78e53SAndroid Build Coastguard Worker 
1129*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; i < tbl_len; i++)
1130*4dc78e53SAndroid Build Coastguard Worker 		if (!strcasecmp(tbl[i].a, buf))
1131*4dc78e53SAndroid Build Coastguard Worker 			return tbl[i].i;
1132*4dc78e53SAndroid Build Coastguard Worker 
1133*4dc78e53SAndroid Build Coastguard Worker 	l = strtoul(buf, &end, 0);
1134*4dc78e53SAndroid Build Coastguard Worker 	if (l == ULONG_MAX || *end != '\0')
1135*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_OBJ_NOTFOUND;
1136*4dc78e53SAndroid Build Coastguard Worker 
1137*4dc78e53SAndroid Build Coastguard Worker 	return (int) l;
1138*4dc78e53SAndroid Build Coastguard Worker }
1139*4dc78e53SAndroid Build Coastguard Worker 
__list_str2type(const char * buf,struct nl_list_head * head)1140*4dc78e53SAndroid Build Coastguard Worker int __list_str2type(const char *buf, struct nl_list_head *head)
1141*4dc78e53SAndroid Build Coastguard Worker {
1142*4dc78e53SAndroid Build Coastguard Worker 	struct trans_list *tl;
1143*4dc78e53SAndroid Build Coastguard Worker 	unsigned long l;
1144*4dc78e53SAndroid Build Coastguard Worker 	char *end;
1145*4dc78e53SAndroid Build Coastguard Worker 
1146*4dc78e53SAndroid Build Coastguard Worker 	if (*buf == '\0')
1147*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
1148*4dc78e53SAndroid Build Coastguard Worker 
1149*4dc78e53SAndroid Build Coastguard Worker 	nl_list_for_each_entry(tl, head, list) {
1150*4dc78e53SAndroid Build Coastguard Worker 		if (!strcasecmp(tl->a, buf))
1151*4dc78e53SAndroid Build Coastguard Worker 			return tl->i;
1152*4dc78e53SAndroid Build Coastguard Worker 	}
1153*4dc78e53SAndroid Build Coastguard Worker 
1154*4dc78e53SAndroid Build Coastguard Worker 	l = strtoul(buf, &end, 0);
1155*4dc78e53SAndroid Build Coastguard Worker 	if (l == ULONG_MAX || *end != '\0')
1156*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_OBJ_NOTFOUND;
1157*4dc78e53SAndroid Build Coastguard Worker 
1158*4dc78e53SAndroid Build Coastguard Worker 	return (int) l;
1159*4dc78e53SAndroid Build Coastguard Worker }
1160*4dc78e53SAndroid Build Coastguard Worker 
__str2flags(const char * buf,const struct trans_tbl * tbl,size_t tbl_len)1161*4dc78e53SAndroid Build Coastguard Worker int __str2flags(const char *buf, const struct trans_tbl *tbl, size_t tbl_len)
1162*4dc78e53SAndroid Build Coastguard Worker {
1163*4dc78e53SAndroid Build Coastguard Worker 	int flags = 0;
1164*4dc78e53SAndroid Build Coastguard Worker 	size_t i;
1165*4dc78e53SAndroid Build Coastguard Worker 	size_t len; /* ptrdiff_t ? */
1166*4dc78e53SAndroid Build Coastguard Worker 	char *p = (char *) buf, *t;
1167*4dc78e53SAndroid Build Coastguard Worker 
1168*4dc78e53SAndroid Build Coastguard Worker 	for (;;) {
1169*4dc78e53SAndroid Build Coastguard Worker 		if (*p == ' ')
1170*4dc78e53SAndroid Build Coastguard Worker 			p++;
1171*4dc78e53SAndroid Build Coastguard Worker 
1172*4dc78e53SAndroid Build Coastguard Worker 		t = strchr(p, ',');
1173*4dc78e53SAndroid Build Coastguard Worker 		len = t ? ((size_t)(t - p)) : strlen(p);
1174*4dc78e53SAndroid Build Coastguard Worker 		for (i = 0; i < tbl_len; i++)
1175*4dc78e53SAndroid Build Coastguard Worker 			if (len == strlen(tbl[i].a) &&
1176*4dc78e53SAndroid Build Coastguard Worker 			    !strncasecmp(tbl[i].a, p, len))
1177*4dc78e53SAndroid Build Coastguard Worker 				flags |= tbl[i].i;
1178*4dc78e53SAndroid Build Coastguard Worker 
1179*4dc78e53SAndroid Build Coastguard Worker 		if (!t)
1180*4dc78e53SAndroid Build Coastguard Worker 			return flags;
1181*4dc78e53SAndroid Build Coastguard Worker 
1182*4dc78e53SAndroid Build Coastguard Worker 		p = ++t;
1183*4dc78e53SAndroid Build Coastguard Worker 	}
1184*4dc78e53SAndroid Build Coastguard Worker 
1185*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1186*4dc78e53SAndroid Build Coastguard Worker }
1187*4dc78e53SAndroid Build Coastguard Worker 
dump_from_ops(struct nl_object * obj,struct nl_dump_params * params)1188*4dc78e53SAndroid Build Coastguard Worker void dump_from_ops(struct nl_object *obj, struct nl_dump_params *params)
1189*4dc78e53SAndroid Build Coastguard Worker {
1190*4dc78e53SAndroid Build Coastguard Worker 	int type = params->dp_type;
1191*4dc78e53SAndroid Build Coastguard Worker 
1192*4dc78e53SAndroid Build Coastguard Worker 	if (type < 0 || type > NL_DUMP_MAX)
1193*4dc78e53SAndroid Build Coastguard Worker 		BUG();
1194*4dc78e53SAndroid Build Coastguard Worker 
1195*4dc78e53SAndroid Build Coastguard Worker 	params->dp_line = 0;
1196*4dc78e53SAndroid Build Coastguard Worker 
1197*4dc78e53SAndroid Build Coastguard Worker 	if (params->dp_dump_msgtype) {
1198*4dc78e53SAndroid Build Coastguard Worker #if 0
1199*4dc78e53SAndroid Build Coastguard Worker 		/* XXX */
1200*4dc78e53SAndroid Build Coastguard Worker 		char buf[64];
1201*4dc78e53SAndroid Build Coastguard Worker 
1202*4dc78e53SAndroid Build Coastguard Worker 		dp_dump_line(params, 0, "%s ",
1203*4dc78e53SAndroid Build Coastguard Worker 			     nl_cache_mngt_type2name(obj->ce_ops,
1204*4dc78e53SAndroid Build Coastguard Worker 			     			     obj->ce_ops->co_protocol,
1205*4dc78e53SAndroid Build Coastguard Worker 						     obj->ce_msgtype,
1206*4dc78e53SAndroid Build Coastguard Worker 						     buf, sizeof(buf)));
1207*4dc78e53SAndroid Build Coastguard Worker #endif
1208*4dc78e53SAndroid Build Coastguard Worker 		params->dp_pre_dump = 1;
1209*4dc78e53SAndroid Build Coastguard Worker 	}
1210*4dc78e53SAndroid Build Coastguard Worker 
1211*4dc78e53SAndroid Build Coastguard Worker 	if (obj->ce_ops->oo_dump[type])
1212*4dc78e53SAndroid Build Coastguard Worker 		obj->ce_ops->oo_dump[type](obj, params);
1213*4dc78e53SAndroid Build Coastguard Worker }
1214*4dc78e53SAndroid Build Coastguard Worker 
1215*4dc78e53SAndroid Build Coastguard Worker /**
1216*4dc78e53SAndroid Build Coastguard Worker  * Check for library capabilities
1217*4dc78e53SAndroid Build Coastguard Worker  *
1218*4dc78e53SAndroid Build Coastguard Worker  * @arg	capability	capability identifier
1219*4dc78e53SAndroid Build Coastguard Worker  *
1220*4dc78e53SAndroid Build Coastguard Worker  * Check whether the loaded libnl library supports a certain capability.
1221*4dc78e53SAndroid Build Coastguard Worker  * This is useful so that applications can workaround known issues of
1222*4dc78e53SAndroid Build Coastguard Worker  * libnl that are fixed in newer library versions, without
1223*4dc78e53SAndroid Build Coastguard Worker  * having a hard dependency on the new version. It is also useful, for
1224*4dc78e53SAndroid Build Coastguard Worker  * capabilities that cannot easily be detected using autoconf tests.
1225*4dc78e53SAndroid Build Coastguard Worker  * The capabilities are integer constants with name NL_CAPABILITY_*.
1226*4dc78e53SAndroid Build Coastguard Worker  *
1227*4dc78e53SAndroid Build Coastguard Worker  * As this function is intended to detect capabilities at runtime,
1228*4dc78e53SAndroid Build Coastguard Worker  * you might not want to depend during compile time on the NL_CAPABILITY_*
1229*4dc78e53SAndroid Build Coastguard Worker  * names. Instead you can use their numeric values which are guaranteed not to
1230*4dc78e53SAndroid Build Coastguard Worker  * change meaning.
1231*4dc78e53SAndroid Build Coastguard Worker  *
1232*4dc78e53SAndroid Build Coastguard Worker  * @return non zero if libnl supports a certain capability, 0 otherwise.
1233*4dc78e53SAndroid Build Coastguard Worker  **/
nl_has_capability(int capability)1234*4dc78e53SAndroid Build Coastguard Worker int nl_has_capability (int capability)
1235*4dc78e53SAndroid Build Coastguard Worker {
1236*4dc78e53SAndroid Build Coastguard Worker 	static const uint8_t caps[ ( NL_CAPABILITY_MAX + 7 ) / 8  ] = {
1237*4dc78e53SAndroid Build Coastguard Worker #define _NL_ASSERT(expr) ( 0 * sizeof(struct { unsigned int x: ( (!!(expr)) ? 1 : -1 ); }) )
1238*4dc78e53SAndroid Build Coastguard Worker #define _NL_SETV(i, r, v) \
1239*4dc78e53SAndroid Build Coastguard Worker 		( _NL_ASSERT( (v) == 0 || (i) * 8 + (r) == (v) - 1 ) + \
1240*4dc78e53SAndroid Build Coastguard Worker 		  ( (v) == 0 ? 0 : (1 << (r)) ) )
1241*4dc78e53SAndroid Build Coastguard Worker #define _NL_SET(i, v0, v1, v2, v3, v4, v5, v6, v7) \
1242*4dc78e53SAndroid Build Coastguard Worker 		[(i)] = ( \
1243*4dc78e53SAndroid Build Coastguard Worker 			_NL_SETV((i), 0, (v0)) | _NL_SETV((i), 4, (v4)) | \
1244*4dc78e53SAndroid Build Coastguard Worker 			_NL_SETV((i), 1, (v1)) | _NL_SETV((i), 5, (v5)) | \
1245*4dc78e53SAndroid Build Coastguard Worker 			_NL_SETV((i), 2, (v2)) | _NL_SETV((i), 6, (v6)) | \
1246*4dc78e53SAndroid Build Coastguard Worker 			_NL_SETV((i), 3, (v3)) | _NL_SETV((i), 7, (v7)) )
1247*4dc78e53SAndroid Build Coastguard Worker 		_NL_SET(0,
1248*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE,
1249*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE,
1250*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE,
1251*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE,
1252*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP,
1253*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_ROUTE_ADDR_COMPARE_CACHEINFO,
1254*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_2_26,
1255*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_NL_RECV_FAIL_TRUNC_NO_PEEK),
1256*4dc78e53SAndroid Build Coastguard Worker 		_NL_SET(1,
1257*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_LINK_BUILD_CHANGE_REQUEST_SET_CHANGE,
1258*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_RTNL_NEIGH_GET_FILTER_AF_UNSPEC_FIX,
1259*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_2_27,
1260*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_RTNL_LINK_VLAN_PROTOCOL_SERIALZE,
1261*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_RTNL_LINK_PARSE_GRE_REMOTE,
1262*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR,
1263*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_RTNL_LINK_VXLAN_IO_COMPARE,
1264*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_NL_OBJECT_DIFF64),
1265*4dc78e53SAndroid Build Coastguard Worker 		_NL_SET (2,
1266*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_XFRM_SA_KEY_SIZE,
1267*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_RTNL_ADDR_PEER_FIX,
1268*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_2_28,
1269*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_RTNL_ADDR_PEER_ID_FIX,
1270*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_NL_ADDR_FILL_SOCKADDR,
1271*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_XFRM_SEC_CTX_LEN,
1272*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_LINK_BUILD_ADD_REQUEST_SET_CHANGE,
1273*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT),
1274*4dc78e53SAndroid Build Coastguard Worker 		_NL_SET (3,
1275*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_2_29,
1276*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_XFRM_SP_SEC_CTX_LEN,
1277*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_3_0,
1278*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_4_0,
1279*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_ROUTE_FIX_VLAN_SET_EGRESS_MAP,
1280*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_5_0,
1281*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_NL_OBJECT_IDENTICAL_PARTIAL,
1282*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_6_0),
1283*4dc78e53SAndroid Build Coastguard Worker 		_NL_SET (4,
1284*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_7_0,
1285*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_8_0,
1286*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_9_0,
1287*4dc78e53SAndroid Build Coastguard Worker 			NL_CAPABILITY_VERSION_3_10_0,
1288*4dc78e53SAndroid Build Coastguard Worker 			0, /* NL_CAPABILITY_VERSION_3_11_0 */
1289*4dc78e53SAndroid Build Coastguard Worker 			0, /* NL_CAPABILITY_VERSION_3_12_0 */
1290*4dc78e53SAndroid Build Coastguard Worker 			0, /* NL_CAPABILITY_VERSION_3_13_0 */
1291*4dc78e53SAndroid Build Coastguard Worker 			0),
1292*4dc78e53SAndroid Build Coastguard Worker 		/* IMPORTANT: these capability numbers are intended to be universal and stable
1293*4dc78e53SAndroid Build Coastguard Worker 		 * for libnl3. Don't allocate new numbers on your own that differ from upstream
1294*4dc78e53SAndroid Build Coastguard Worker 		 * libnl3.
1295*4dc78e53SAndroid Build Coastguard Worker 		 *
1296*4dc78e53SAndroid Build Coastguard Worker 		 * Instead register a capability number upstream too. We will take patches
1297*4dc78e53SAndroid Build Coastguard Worker 		 * for that. We especially take patches to register a capability number that is
1298*4dc78e53SAndroid Build Coastguard Worker 		 * only implemented in your fork of libnl3.
1299*4dc78e53SAndroid Build Coastguard Worker 		 *
1300*4dc78e53SAndroid Build Coastguard Worker 		 * If you really don't want that, use capabilities in the range 0x7000 to 0x7FFF.
1301*4dc78e53SAndroid Build Coastguard Worker 		 * (NL_CAPABILITY_IS_USER_RESERVED). Upstream libnl3 will not register conflicting
1302*4dc78e53SAndroid Build Coastguard Worker 		 * capabilities in that range.
1303*4dc78e53SAndroid Build Coastguard Worker 		 *
1304*4dc78e53SAndroid Build Coastguard Worker 		 * Obviously, only backport capability numbers to libnl versions that actually
1305*4dc78e53SAndroid Build Coastguard Worker 		 * implement that capability as well. */
1306*4dc78e53SAndroid Build Coastguard Worker #undef _NL_SET
1307*4dc78e53SAndroid Build Coastguard Worker #undef _NL_SETV
1308*4dc78e53SAndroid Build Coastguard Worker #undef _NL_ASSERT
1309*4dc78e53SAndroid Build Coastguard Worker 	};
1310*4dc78e53SAndroid Build Coastguard Worker 
1311*4dc78e53SAndroid Build Coastguard Worker 	if (capability <= 0 || capability > NL_CAPABILITY_MAX)
1312*4dc78e53SAndroid Build Coastguard Worker 		return 0;
1313*4dc78e53SAndroid Build Coastguard Worker 	capability--;
1314*4dc78e53SAndroid Build Coastguard Worker 	return (caps[capability / 8] & (1 << (capability % 8))) != 0;
1315*4dc78e53SAndroid Build Coastguard Worker }
1316*4dc78e53SAndroid Build Coastguard Worker 
1317*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
1318*4dc78e53SAndroid Build Coastguard Worker 
1319*4dc78e53SAndroid Build Coastguard Worker /** @} */
1320