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