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