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