Home | History | Annotate | Download | only in lib
      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 (at) 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  */
     49 int nl_debug = 0;
     50 
     51 /** @cond SKIP */
     52 #ifdef NL_DEBUG
     53 struct nl_dump_params nl_debug_dp = {
     54 	.dp_type = NL_DUMP_DETAILS,
     55 };
     56 
     57 static 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 
     71 int __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  */
    139 double 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  */
    170 double 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 
    196 int 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  */
    227 double 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  */
    264 long 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 
    293 static 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  */
    327 char *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  */
    361 long 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 
    392 static uint32_t user_hz = USER_HZ;
    393 static uint32_t psched_hz = USER_HZ;
    394 
    395 static 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 */
    406 static 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  */
    478 int 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  */
    487 int 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  */
    498 uint32_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  */
    510 uint32_t nl_ticks2us(uint32_t ticks)
    511 {
    512 	get_psched_settings();
    513 	return ticks / ticks_per_usec;
    514 }
    515 
    516 int 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  */
    564 char * 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 
    604 static 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 
    625 char * nl_nlfamily2str(int family, char *buf, size_t size)
    626 {
    627 	return __type2str(family, buf, size, nlfamilies,
    628 			  ARRAY_SIZE(nlfamilies));
    629 }
    630 
    631 int 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 
    645 static 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 
    729 char * nl_llproto2str(int llproto, char *buf, size_t len)
    730 {
    731 	return __type2str(llproto, buf, len, llprotos, ARRAY_SIZE(llprotos));
    732 }
    733 
    734 int 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 
    747 static 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 
    819 char *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 
    825 int 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 
    837 char *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 
    850 int 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  */
    883 void 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 
    903 static 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  */
    932 void 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 
    941 void 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 
    957 int __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 
    973 void __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 
    985 char *__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 
   1000 char *__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 
   1016 char *__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 
   1036 int __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 
   1056 int __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 
   1077 int __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 
   1104 void 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  **/
   1150 int 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