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