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