utils.c 24 KB

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