addr.c 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. /*
  2. * lib/addr.c Network Address
  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-2013 Thomas Graf <tgraf@suug.ch>
  10. */
  11. /**
  12. * @ingroup core_types
  13. * @defgroup addr Network Address
  14. *
  15. * Abstract data type representing any kind of network address
  16. *
  17. * Related sections in the development guide:
  18. * - @core_doc{_abstract_address, Network Addresses}
  19. *
  20. * @{
  21. *
  22. * Header
  23. * ------
  24. * ~~~~{.c}
  25. * #include <netlink/addr.h>
  26. * ~~~~
  27. */
  28. #include <netlink-private/netlink.h>
  29. #include <netlink/netlink.h>
  30. #include <netlink/utils.h>
  31. #include <netlink/addr.h>
  32. #include <linux/socket.h>
  33. /* All this DECnet stuff is stolen from iproute2, thanks to whoever wrote
  34. * this, probably Alexey. */
  35. static inline uint16_t dn_ntohs(uint16_t addr)
  36. {
  37. union {
  38. uint8_t byte[2];
  39. uint16_t word;
  40. } u = {
  41. .word = addr,
  42. };
  43. return ((uint16_t) u.byte[0]) | (((uint16_t) u.byte[1]) << 8);
  44. }
  45. static inline int do_digit(char *str, uint16_t *addr, uint16_t scale,
  46. size_t *pos, size_t len, int *started)
  47. {
  48. uint16_t tmp = *addr / scale;
  49. if (*pos == len)
  50. return 1;
  51. if (((tmp) > 0) || *started || (scale == 1)) {
  52. *str = tmp + '0';
  53. *started = 1;
  54. (*pos)++;
  55. *addr -= (tmp * scale);
  56. }
  57. return 0;
  58. }
  59. static const char *dnet_ntop(char *addrbuf, size_t addrlen, char *str,
  60. size_t len)
  61. {
  62. uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf);
  63. uint16_t area = addr >> 10;
  64. size_t pos = 0;
  65. int started = 0;
  66. if (addrlen != 2)
  67. return NULL;
  68. addr &= 0x03ff;
  69. if (len == 0)
  70. return str;
  71. if (do_digit(str + pos, &area, 10, &pos, len, &started))
  72. return str;
  73. if (do_digit(str + pos, &area, 1, &pos, len, &started))
  74. return str;
  75. if (pos == len)
  76. return str;
  77. *(str + pos) = '.';
  78. pos++;
  79. started = 0;
  80. if (do_digit(str + pos, &addr, 1000, &pos, len, &started))
  81. return str;
  82. if (do_digit(str + pos, &addr, 100, &pos, len, &started))
  83. return str;
  84. if (do_digit(str + pos, &addr, 10, &pos, len, &started))
  85. return str;
  86. if (do_digit(str + pos, &addr, 1, &pos, len, &started))
  87. return str;
  88. if (pos == len)
  89. return str;
  90. *(str + pos) = 0;
  91. return str;
  92. }
  93. static int dnet_num(const char *src, uint16_t * dst)
  94. {
  95. int rv = 0;
  96. int tmp;
  97. *dst = 0;
  98. while ((tmp = *src++) != 0) {
  99. tmp -= '0';
  100. if ((tmp < 0) || (tmp > 9))
  101. return rv;
  102. rv++;
  103. (*dst) *= 10;
  104. (*dst) += tmp;
  105. }
  106. return rv;
  107. }
  108. static inline int dnet_pton(const char *src, char *addrbuf)
  109. {
  110. uint16_t area = 0;
  111. uint16_t node = 0;
  112. int pos;
  113. pos = dnet_num(src, &area);
  114. if ((pos == 0) || (area > 63) ||
  115. ((*(src + pos) != '.') && (*(src + pos) != ',')))
  116. return -NLE_INVAL;
  117. pos = dnet_num(src + pos + 1, &node);
  118. if ((pos == 0) || (node > 1023))
  119. return -NLE_INVAL;
  120. *(uint16_t *)addrbuf = dn_ntohs((area << 10) | node);
  121. return 1;
  122. }
  123. static void addr_destroy(struct nl_addr *addr)
  124. {
  125. if (!addr)
  126. return;
  127. if (addr->a_refcnt != 1)
  128. BUG();
  129. free(addr);
  130. }
  131. /**
  132. * @name Creating Abstract Network Addresses
  133. * @{
  134. */
  135. /**
  136. * Allocate empty abstract address
  137. * @arg maxsize Upper limit of the binary address to be stored
  138. *
  139. * The new address object will be empty with a prefix length of 0 and will
  140. * be capable of holding binary addresses up to the specified limit.
  141. *
  142. * @see nl_addr_build()
  143. * @see nl_addr_parse()
  144. * @see nl_addr_put()
  145. *
  146. * @return Allocated address object or NULL upon failure.
  147. */
  148. struct nl_addr *nl_addr_alloc(size_t maxsize)
  149. {
  150. struct nl_addr *addr;
  151. addr = calloc(1, sizeof(*addr) + maxsize);
  152. if (!addr)
  153. return NULL;
  154. addr->a_refcnt = 1;
  155. addr->a_maxsize = maxsize;
  156. return addr;
  157. }
  158. /**
  159. * Allocate abstract address based on a binary address.
  160. * @arg family Address family
  161. * @arg buf Binary address
  162. * @arg size Length of binary address
  163. *
  164. * This function will allocate an abstract address capable of holding the
  165. * binary address specified. The prefix length will be set to the full
  166. * length of the binary address provided.
  167. *
  168. * @see nl_addr_alloc()
  169. * @see nl_addr_alloc_attr()
  170. * @see nl_addr_parse()
  171. * @see nl_addr_put()
  172. *
  173. * @return Allocated address object or NULL upon failure.
  174. */
  175. struct nl_addr *nl_addr_build(int family, void *buf, size_t size)
  176. {
  177. struct nl_addr *addr;
  178. addr = nl_addr_alloc(size);
  179. if (!addr)
  180. return NULL;
  181. addr->a_family = family;
  182. addr->a_len = size;
  183. addr->a_prefixlen = size*8;
  184. if (size)
  185. memcpy(addr->a_addr, buf, size);
  186. return addr;
  187. }
  188. /**
  189. * Allocate abstract address based on Netlink attribute.
  190. * @arg nla Netlink attribute
  191. * @arg family Address family.
  192. *
  193. * Allocates an abstract address based on the specified Netlink attribute
  194. * by interpreting the payload of the Netlink attribute as the binary
  195. * address.
  196. *
  197. * This function is identical to:
  198. * @code
  199. * nl_addr_build(family, nla_data(nla), nla_len(nla));
  200. * @endcode
  201. *
  202. * @see nl_addr_alloc()
  203. * @see nl_addr_build()
  204. * @see nl_addr_parse()
  205. * @see nl_addr_put()
  206. *
  207. * @return Allocated address object or NULL upon failure.
  208. */
  209. struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family)
  210. {
  211. return nl_addr_build(family, nla_data(nla), nla_len(nla));
  212. }
  213. /**
  214. * Allocate abstract address based on character string
  215. * @arg addrstr Address represented as character string.
  216. * @arg hint Address family hint or AF_UNSPEC.
  217. * @arg result Pointer to store resulting address.
  218. *
  219. * Regognizes the following address formats:
  220. * @code
  221. * Format Len Family
  222. * ----------------------------------------------------------------
  223. * IPv6 address format 16 AF_INET6
  224. * ddd.ddd.ddd.ddd 4 AF_INET
  225. * HH:HH:HH:HH:HH:HH 6 AF_LLC
  226. * AA{.|,}NNNN 2 AF_DECnet
  227. * HH:HH:HH:... variable AF_UNSPEC
  228. * @endcode
  229. *
  230. * Special values:
  231. * - none: All bits and length set to 0.
  232. * - {default|all|any}: All bits set to 0, length based on hint or
  233. * AF_INET if no hint is given.
  234. *
  235. * The prefix length may be appened at the end prefixed with a
  236. * slash, e.g. 10.0.0.0/8.
  237. *
  238. * @see nl_addr_alloc()
  239. * @see nl_addr_build()
  240. * @see nl_addr_put()
  241. *
  242. * @return 0 on success or a negative error code.
  243. */
  244. int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result)
  245. {
  246. int err, copy = 0, len = 0, family = AF_UNSPEC;
  247. char *str, *prefix, buf[32];
  248. struct nl_addr *addr = NULL; /* gcc ain't that smart */
  249. str = strdup(addrstr);
  250. if (!str) {
  251. err = -NLE_NOMEM;
  252. goto errout;
  253. }
  254. prefix = strchr(str, '/');
  255. if (prefix)
  256. *prefix = '\0';
  257. if (!strcasecmp(str, "none")) {
  258. family = hint;
  259. goto prefix;
  260. }
  261. if (!strcasecmp(str, "default") ||
  262. !strcasecmp(str, "all") ||
  263. !strcasecmp(str, "any")) {
  264. len = 0;
  265. switch (hint) {
  266. case AF_INET:
  267. case AF_UNSPEC:
  268. /* Kind of a hack, we assume that if there is
  269. * no hint given the user wants to have a IPv4
  270. * address given back. */
  271. family = AF_INET;
  272. goto prefix;
  273. case AF_INET6:
  274. family = AF_INET6;
  275. goto prefix;
  276. case AF_LLC:
  277. family = AF_LLC;
  278. goto prefix;
  279. default:
  280. err = -NLE_AF_NOSUPPORT;
  281. goto errout;
  282. }
  283. }
  284. copy = 1;
  285. if (hint == AF_INET || hint == AF_UNSPEC) {
  286. if (inet_pton(AF_INET, str, buf) > 0) {
  287. family = AF_INET;
  288. len = 4;
  289. goto prefix;
  290. }
  291. if (hint == AF_INET) {
  292. err = -NLE_NOADDR;
  293. goto errout;
  294. }
  295. }
  296. if (hint == AF_INET6 || hint == AF_UNSPEC) {
  297. if (inet_pton(AF_INET6, str, buf) > 0) {
  298. family = AF_INET6;
  299. len = 16;
  300. goto prefix;
  301. }
  302. if (hint == AF_INET6) {
  303. err = -NLE_NOADDR;
  304. goto errout;
  305. }
  306. }
  307. if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str, ':')) {
  308. unsigned int a, b, c, d, e, f;
  309. if (sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
  310. &a, &b, &c, &d, &e, &f) == 6) {
  311. family = AF_LLC;
  312. len = 6;
  313. buf[0] = (unsigned char) a;
  314. buf[1] = (unsigned char) b;
  315. buf[2] = (unsigned char) c;
  316. buf[3] = (unsigned char) d;
  317. buf[4] = (unsigned char) e;
  318. buf[5] = (unsigned char) f;
  319. goto prefix;
  320. }
  321. if (hint == AF_LLC) {
  322. err = -NLE_NOADDR;
  323. goto errout;
  324. }
  325. }
  326. if ((hint == AF_DECnet || hint == AF_UNSPEC) &&
  327. (strchr(str, '.') || strchr(str, ','))) {
  328. if (dnet_pton(str, buf) > 0) {
  329. family = AF_DECnet;
  330. len = 2;
  331. goto prefix;
  332. }
  333. if (hint == AF_DECnet) {
  334. err = -NLE_NOADDR;
  335. goto errout;
  336. }
  337. }
  338. if (hint == AF_UNSPEC && strchr(str, ':')) {
  339. size_t i = 0;
  340. char *s = str, *p;
  341. for (;;) {
  342. long l = strtol(s, &p, 16);
  343. if (s == p || l > 0xff || i >= sizeof(buf)) {
  344. err = -NLE_INVAL;
  345. goto errout;
  346. }
  347. buf[i++] = (unsigned char) l;
  348. if (*p == '\0')
  349. break;
  350. s = ++p;
  351. }
  352. len = i;
  353. family = AF_UNSPEC;
  354. goto prefix;
  355. }
  356. err = -NLE_NOADDR;
  357. goto errout;
  358. prefix:
  359. addr = nl_addr_alloc(len);
  360. if (!addr) {
  361. err = -NLE_NOMEM;
  362. goto errout;
  363. }
  364. nl_addr_set_family(addr, family);
  365. if (copy)
  366. nl_addr_set_binary_addr(addr, buf, len);
  367. if (prefix) {
  368. char *p;
  369. long pl = strtol(++prefix, &p, 0);
  370. if (p == prefix) {
  371. addr_destroy(addr);
  372. err = -NLE_INVAL;
  373. goto errout;
  374. }
  375. nl_addr_set_prefixlen(addr, pl);
  376. } else
  377. nl_addr_set_prefixlen(addr, len * 8);
  378. *result = addr;
  379. err = 0;
  380. errout:
  381. free(str);
  382. return err;
  383. }
  384. /**
  385. * Clone existing abstract address object
  386. * @arg addr Abstract address object
  387. *
  388. * Allocates new abstract address representing an identical clone of an
  389. * existing address.
  390. *
  391. * @see nl_addr_alloc()
  392. * @see nl_addr_put()
  393. *
  394. * @return Allocated abstract address or NULL upon failure.
  395. */
  396. struct nl_addr *nl_addr_clone(struct nl_addr *addr)
  397. {
  398. struct nl_addr *new;
  399. new = nl_addr_build(addr->a_family, addr->a_addr, addr->a_len);
  400. if (new)
  401. new->a_prefixlen = addr->a_prefixlen;
  402. return new;
  403. }
  404. /** @} */
  405. /**
  406. * @name Managing Usage References
  407. * @{
  408. */
  409. /**
  410. * Increase the reference counter of an abstract address
  411. * @arg addr Abstract address
  412. *
  413. * Increases the reference counter of the address and thus prevents the
  414. * release of the memory resources until the reference is given back
  415. * using the function nl_addr_put().
  416. *
  417. * @see nl_addr_put()
  418. *
  419. * @return Pointer to the existing abstract address
  420. */
  421. struct nl_addr *nl_addr_get(struct nl_addr *addr)
  422. {
  423. addr->a_refcnt++;
  424. return addr;
  425. }
  426. /**
  427. * Decrease the reference counter of an abstract address
  428. * @arg addr Abstract addr
  429. *
  430. * @note The resources of the abstract address will be freed after the
  431. * last reference to the address has been returned.
  432. *
  433. * @see nl_addr_get()
  434. */
  435. void nl_addr_put(struct nl_addr *addr)
  436. {
  437. if (!addr)
  438. return;
  439. if (addr->a_refcnt == 1)
  440. addr_destroy(addr);
  441. else
  442. addr->a_refcnt--;
  443. }
  444. /**
  445. * Check whether an abstract address is shared.
  446. * @arg addr Abstract address object.
  447. *
  448. * @return Non-zero if the abstract address is shared, otherwise 0.
  449. */
  450. int nl_addr_shared(struct nl_addr *addr)
  451. {
  452. return addr->a_refcnt > 1;
  453. }
  454. /** @} */
  455. /**
  456. * @name Miscellaneous
  457. * @{
  458. */
  459. /**
  460. * Compare abstract addresses
  461. * @arg a An abstract address
  462. * @arg b Another abstract address
  463. *
  464. * Verifies whether the address family, address length, prefix length, and
  465. * binary addresses of two abstract addresses matches.
  466. *
  467. * @note This function will *not* respect the prefix length in the sense
  468. * that only the actual prefix will be compared. Please refer to the
  469. * nl_addr_cmp_prefix() function if you require this functionality.
  470. *
  471. * @see nl_addr_cmp_prefix()
  472. *
  473. * @return Integer less than, equal to or greather than zero if the two
  474. * addresses match.
  475. */
  476. int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
  477. {
  478. int d = a->a_family - b->a_family;
  479. if (d == 0) {
  480. d = a->a_len - b->a_len;
  481. if (a->a_len && d == 0) {
  482. d = memcmp(a->a_addr, b->a_addr, a->a_len);
  483. if (d == 0)
  484. return (a->a_prefixlen - b->a_prefixlen);
  485. }
  486. }
  487. return d;
  488. }
  489. /**
  490. * Compare the prefix of two abstract addresses
  491. * @arg a An abstract address
  492. * @arg b Another abstract address
  493. *
  494. * Verifies whether the address family and the binary address covered by
  495. * the smaller prefix length of the two abstract addresses matches.
  496. *
  497. * @see nl_addr_cmp()
  498. *
  499. * @return Integer less than, equal to or greather than zero if the two
  500. * addresses match.
  501. */
  502. int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b)
  503. {
  504. int d = a->a_family - b->a_family;
  505. if (d == 0) {
  506. int len = min(a->a_prefixlen, b->a_prefixlen);
  507. int bytes = len / 8;
  508. d = memcmp(a->a_addr, b->a_addr, bytes);
  509. if (d == 0 && (len % 8) != 0) {
  510. int mask = (0xFF00 >> (len % 8)) & 0xFF;
  511. d = (a->a_addr[bytes] & mask) -
  512. (b->a_addr[bytes] & mask);
  513. }
  514. }
  515. return d;
  516. }
  517. /**
  518. * Returns true if the address consists of all zeros
  519. * @arg addr Abstract address
  520. *
  521. * @return 1 if the binary address consists of all zeros, 0 otherwise.
  522. */
  523. int nl_addr_iszero(struct nl_addr *addr)
  524. {
  525. unsigned int i;
  526. for (i = 0; i < addr->a_len; i++)
  527. if (addr->a_addr[i])
  528. return 0;
  529. return 1;
  530. }
  531. /**
  532. * Check if address string is parseable for a specific address family
  533. * @arg addr Address represented as character string.
  534. * @arg family Desired address family.
  535. *
  536. * @return 1 if the address is parseable assuming the specified address family,
  537. * otherwise 0 is returned.
  538. */
  539. int nl_addr_valid(char *addr, int family)
  540. {
  541. int ret;
  542. char buf[32];
  543. switch (family) {
  544. case AF_INET:
  545. case AF_INET6:
  546. ret = inet_pton(family, addr, buf);
  547. if (ret <= 0)
  548. return 0;
  549. break;
  550. case AF_DECnet:
  551. ret = dnet_pton(addr, buf);
  552. if (ret <= 0)
  553. return 0;
  554. break;
  555. case AF_LLC:
  556. if (sscanf(addr, "%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6)
  557. return 0;
  558. break;
  559. }
  560. return 1;
  561. }
  562. /**
  563. * Guess address family of abstract address based on address size
  564. * @arg addr Abstract address object.
  565. *
  566. * @return Numeric address family or AF_UNSPEC
  567. */
  568. int nl_addr_guess_family(struct nl_addr *addr)
  569. {
  570. switch (addr->a_len) {
  571. case 4:
  572. return AF_INET;
  573. case 6:
  574. return AF_LLC;
  575. case 16:
  576. return AF_INET6;
  577. default:
  578. return AF_UNSPEC;
  579. }
  580. }
  581. /**
  582. * Fill out sockaddr structure with values from abstract address object.
  583. * @arg addr Abstract address object.
  584. * @arg sa Destination sockaddr structure buffer.
  585. * @arg salen Length of sockaddr structure buffer.
  586. *
  587. * Fills out the specified sockaddr structure with the data found in the
  588. * specified abstract address. The salen argument needs to be set to the
  589. * size of sa but will be modified to the actual size used during before
  590. * the function exits.
  591. *
  592. * @return 0 on success or a negative error code
  593. */
  594. int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa,
  595. socklen_t *salen)
  596. {
  597. switch (addr->a_family) {
  598. case AF_INET: {
  599. struct sockaddr_in *sai = (struct sockaddr_in *) sa;
  600. if (*salen < sizeof(*sai))
  601. return -NLE_INVAL;
  602. sai->sin_family = addr->a_family;
  603. memcpy(&sai->sin_addr, addr->a_addr, 4);
  604. *salen = sizeof(*sai);
  605. }
  606. break;
  607. case AF_INET6: {
  608. struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa;
  609. if (*salen < sizeof(*sa6))
  610. return -NLE_INVAL;
  611. sa6->sin6_family = addr->a_family;
  612. memcpy(&sa6->sin6_addr, addr->a_addr, 16);
  613. *salen = sizeof(*sa6);
  614. }
  615. break;
  616. default:
  617. return -NLE_INVAL;
  618. }
  619. return 0;
  620. }
  621. /** @} */
  622. /**
  623. * @name Getting Information About Addresses
  624. * @{
  625. */
  626. /**
  627. * Call getaddrinfo() for an abstract address object.
  628. * @arg addr Abstract address object.
  629. * @arg result Pointer to store resulting address list.
  630. *
  631. * Calls getaddrinfo() for the specified abstract address in AI_NUMERICHOST
  632. * mode.
  633. *
  634. * @note The caller is responsible for freeing the linked list using the
  635. * interface provided by getaddrinfo(3).
  636. *
  637. * @return 0 on success or a negative error code.
  638. */
  639. int nl_addr_info(struct nl_addr *addr, struct addrinfo **result)
  640. {
  641. int err;
  642. char buf[INET6_ADDRSTRLEN+5];
  643. struct addrinfo hint = {
  644. .ai_flags = AI_NUMERICHOST,
  645. .ai_family = addr->a_family,
  646. };
  647. nl_addr2str(addr, buf, sizeof(buf));
  648. err = getaddrinfo(buf, NULL, &hint, result);
  649. if (err != 0) {
  650. switch (err) {
  651. case EAI_ADDRFAMILY: return -NLE_AF_NOSUPPORT;
  652. case EAI_AGAIN: return -NLE_AGAIN;
  653. case EAI_BADFLAGS: return -NLE_INVAL;
  654. case EAI_FAIL: return -NLE_NOADDR;
  655. case EAI_FAMILY: return -NLE_AF_NOSUPPORT;
  656. case EAI_MEMORY: return -NLE_NOMEM;
  657. case EAI_NODATA: return -NLE_NOADDR;
  658. case EAI_NONAME: return -NLE_OBJ_NOTFOUND;
  659. case EAI_SERVICE: return -NLE_OPNOTSUPP;
  660. case EAI_SOCKTYPE: return -NLE_BAD_SOCK;
  661. default: return -NLE_FAILURE;
  662. }
  663. }
  664. return 0;
  665. }
  666. /**
  667. * Resolve abstract address object to a name using getnameinfo().
  668. * @arg addr Abstract address object.
  669. * @arg host Destination buffer for host name.
  670. * @arg hostlen Length of destination buffer.
  671. *
  672. * Resolves the abstract address to a name and writes the looked up result
  673. * into the host buffer. getnameinfo() is used to perform the lookup and
  674. * is put into NI_NAMEREQD mode so the function will fail if the lookup
  675. * couldn't be performed.
  676. *
  677. * @return 0 on success or a negative error code.
  678. */
  679. int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen)
  680. {
  681. int err;
  682. struct sockaddr_in6 buf;
  683. socklen_t salen = sizeof(buf);
  684. err = nl_addr_fill_sockaddr(addr, (struct sockaddr *) &buf, &salen);
  685. if (err < 0)
  686. return err;
  687. err = getnameinfo((struct sockaddr *) &buf, salen, host, hostlen,
  688. NULL, 0, NI_NAMEREQD);
  689. if (err < 0)
  690. return nl_syserr2nlerr(err);
  691. return 0;
  692. }
  693. /** @} */
  694. /**
  695. * @name Attributes
  696. * @{
  697. */
  698. /**
  699. * Set address family
  700. * @arg addr Abstract address object
  701. * @arg family Address family
  702. *
  703. * @see nl_addr_get_family()
  704. */
  705. void nl_addr_set_family(struct nl_addr *addr, int family)
  706. {
  707. addr->a_family = family;
  708. }
  709. /**
  710. * Return address family
  711. * @arg addr Abstract address object
  712. *
  713. * @see nl_addr_set_family()
  714. *
  715. * @return The numeric address family or `AF_UNSPEC`
  716. */
  717. int nl_addr_get_family(struct nl_addr *addr)
  718. {
  719. return addr->a_family;
  720. }
  721. /**
  722. * Set binary address of abstract address object.
  723. * @arg addr Abstract address object.
  724. * @arg buf Buffer containing binary address.
  725. * @arg len Length of buffer containing binary address.
  726. *
  727. * Modifies the binary address portion of the abstract address. The
  728. * abstract address must be capable of holding the required amount
  729. * or this function will fail.
  730. *
  731. * @note This function will *not* modify the prefix length. It is within
  732. * the responsibility of the caller to set the prefix length to the
  733. * desirable length.
  734. *
  735. * @see nl_addr_alloc()
  736. * @see nl_addr_get_binary_addr()
  737. * @see nl_addr_get_len()
  738. *
  739. * @return 0 on success or a negative error code.
  740. */
  741. int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len)
  742. {
  743. if (len > addr->a_maxsize)
  744. return -NLE_RANGE;
  745. addr->a_len = len;
  746. memset(addr->a_addr, 0, addr->a_maxsize);
  747. if (len)
  748. memcpy(addr->a_addr, buf, len);
  749. return 0;
  750. }
  751. /**
  752. * Get binary address of abstract address object.
  753. * @arg addr Abstract address object.
  754. *
  755. * @see nl_addr_set_binary_addr()
  756. * @see nl_addr_get_len()
  757. *
  758. * @return Pointer to binary address of length nl_addr_get_len()
  759. */
  760. void *nl_addr_get_binary_addr(struct nl_addr *addr)
  761. {
  762. return addr->a_addr;
  763. }
  764. /**
  765. * Get length of binary address of abstract address object.
  766. * @arg addr Abstract address object.
  767. *
  768. * @see nl_addr_get_binary_addr()
  769. * @see nl_addr_set_binary_addr()
  770. */
  771. unsigned int nl_addr_get_len(struct nl_addr *addr)
  772. {
  773. return addr->a_len;
  774. }
  775. /**
  776. * Set the prefix length of an abstract address
  777. * @arg addr Abstract address object
  778. * @arg prefixlen New prefix length
  779. *
  780. * @see nl_addr_get_prefixlen()
  781. */
  782. void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
  783. {
  784. addr->a_prefixlen = prefixlen;
  785. }
  786. /**
  787. * Return prefix length of abstract address object.
  788. * @arg addr Abstract address object
  789. *
  790. * @see nl_addr_set_prefixlen()
  791. */
  792. unsigned int nl_addr_get_prefixlen(struct nl_addr *addr)
  793. {
  794. return addr->a_prefixlen;
  795. }
  796. /** @} */
  797. /**
  798. * @name Translations to Strings
  799. * @{
  800. */
  801. /**
  802. * Convert abstract address object to character string.
  803. * @arg addr Abstract address object.
  804. * @arg buf Destination buffer.
  805. * @arg size Size of destination buffer.
  806. *
  807. * Converts an abstract address to a character string and stores
  808. * the result in the specified destination buffer.
  809. *
  810. * @return Address represented in ASCII stored in destination buffer.
  811. */
  812. char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
  813. {
  814. unsigned int i;
  815. char tmp[16];
  816. if (!addr || !addr->a_len) {
  817. snprintf(buf, size, "none");
  818. if (addr)
  819. goto prefix;
  820. else
  821. return buf;
  822. }
  823. switch (addr->a_family) {
  824. case AF_INET:
  825. inet_ntop(AF_INET, addr->a_addr, buf, size);
  826. break;
  827. case AF_INET6:
  828. inet_ntop(AF_INET6, addr->a_addr, buf, size);
  829. break;
  830. case AF_DECnet:
  831. dnet_ntop(addr->a_addr, addr->a_len, buf, size);
  832. break;
  833. case AF_LLC:
  834. default:
  835. snprintf(buf, size, "%02x",
  836. (unsigned char) addr->a_addr[0]);
  837. for (i = 1; i < addr->a_len; i++) {
  838. snprintf(tmp, sizeof(tmp), ":%02x",
  839. (unsigned char) addr->a_addr[i]);
  840. strncat(buf, tmp, size - strlen(buf) - 1);
  841. }
  842. break;
  843. }
  844. prefix:
  845. if (addr->a_prefixlen != (8 * addr->a_len)) {
  846. snprintf(tmp, sizeof(tmp), "/%u", addr->a_prefixlen);
  847. strncat(buf, tmp, size - strlen(buf) - 1);
  848. }
  849. return buf;
  850. }
  851. /** @} */
  852. /**
  853. * @name Address Family Transformations
  854. * @{
  855. */
  856. static const struct trans_tbl afs[] = {
  857. __ADD(AF_UNSPEC,unspec)
  858. __ADD(AF_UNIX,unix)
  859. __ADD(AF_INET,inet)
  860. __ADD(AF_AX25,ax25)
  861. __ADD(AF_IPX,ipx)
  862. __ADD(AF_APPLETALK,appletalk)
  863. __ADD(AF_NETROM,netrom)
  864. __ADD(AF_BRIDGE,bridge)
  865. __ADD(AF_ATMPVC,atmpvc)
  866. __ADD(AF_X25,x25)
  867. __ADD(AF_INET6,inet6)
  868. __ADD(AF_ROSE,rose)
  869. __ADD(AF_DECnet,decnet)
  870. __ADD(AF_NETBEUI,netbeui)
  871. __ADD(AF_SECURITY,security)
  872. __ADD(AF_KEY,key)
  873. __ADD(AF_NETLINK,netlink)
  874. __ADD(AF_PACKET,packet)
  875. __ADD(AF_ASH,ash)
  876. __ADD(AF_ECONET,econet)
  877. __ADD(AF_ATMSVC,atmsvc)
  878. #ifdef AF_RDS
  879. __ADD(AF_RDS,rds)
  880. #endif
  881. __ADD(AF_SNA,sna)
  882. __ADD(AF_IRDA,irda)
  883. __ADD(AF_PPPOX,pppox)
  884. __ADD(AF_WANPIPE,wanpipe)
  885. __ADD(AF_LLC,llc)
  886. #ifdef AF_CAN
  887. __ADD(AF_CAN,can)
  888. #endif
  889. #ifdef AF_TIPC
  890. __ADD(AF_TIPC,tipc)
  891. #endif
  892. __ADD(AF_BLUETOOTH,bluetooth)
  893. #ifdef AF_IUCV
  894. __ADD(AF_IUCV,iucv)
  895. #endif
  896. #ifdef AF_RXRPC
  897. __ADD(AF_RXRPC,rxrpc)
  898. #endif
  899. #ifdef AF_ISDN
  900. __ADD(AF_ISDN,isdn)
  901. #endif
  902. #ifdef AF_PHONET
  903. __ADD(AF_PHONET,phonet)
  904. #endif
  905. #ifdef AF_IEEE802154
  906. __ADD(AF_IEEE802154,ieee802154)
  907. #endif
  908. #ifdef AF_CAIF
  909. __ADD(AF_CAIF,caif)
  910. #endif
  911. #ifdef AF_ALG
  912. __ADD(AF_ALG,alg)
  913. #endif
  914. #ifdef AF_NFC
  915. __ADD(AF_NFC,nfc)
  916. #endif
  917. };
  918. char *nl_af2str(int family, char *buf, size_t size)
  919. {
  920. return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
  921. }
  922. int nl_str2af(const char *name)
  923. {
  924. int fam = __str2type(name, afs, ARRAY_SIZE(afs));
  925. return fam >= 0 ? fam : -EINVAL;
  926. }
  927. /** @} */
  928. /** @} */