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