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