libnl 1.1
|
00001 /* 00002 * lib/addr.c Abstract Address 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @ingroup utils 00014 * @defgroup addr Abstract Address 00015 * 00016 * @par 1) Transform character string to abstract address 00017 * @code 00018 * struct nl_addr *a = nl_addr_parse("::1", AF_UNSPEC); 00019 * printf("Address family: %s\n", nl_af2str(nl_addr_get_family(a))); 00020 * nl_addr_put(a); 00021 * a = nl_addr_parse("11:22:33:44:55:66", AF_UNSPEC); 00022 * printf("Address family: %s\n", nl_af2str(nl_addr_get_family(a))); 00023 * nl_addr_put(a); 00024 * @endcode 00025 * @{ 00026 */ 00027 00028 #include <netlink-local.h> 00029 #include <netlink/netlink.h> 00030 #include <netlink/utils.h> 00031 #include <netlink/addr.h> 00032 #include <linux/socket.h> 00033 00034 /* All this DECnet stuff is stolen from iproute2, thanks to whoever wrote 00035 * this, probably Alexey. */ 00036 static inline uint16_t dn_ntohs(uint16_t addr) 00037 { 00038 union { 00039 uint8_t byte[2]; 00040 uint16_t word; 00041 } u = { 00042 .word = addr, 00043 }; 00044 00045 return ((uint16_t) u.byte[0]) | (((uint16_t) u.byte[1]) << 8); 00046 } 00047 00048 static inline int do_digit(char *str, uint16_t *addr, uint16_t scale, 00049 size_t *pos, size_t len, int *started) 00050 { 00051 uint16_t tmp = *addr / scale; 00052 00053 if (*pos == len) 00054 return 1; 00055 00056 if (((tmp) > 0) || *started || (scale == 1)) { 00057 *str = tmp + '0'; 00058 *started = 1; 00059 (*pos)++; 00060 *addr -= (tmp * scale); 00061 } 00062 00063 return 0; 00064 } 00065 00066 static const char *dnet_ntop(char *addrbuf, size_t addrlen, char *str, 00067 size_t len) 00068 { 00069 uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf); 00070 uint16_t area = addr >> 10; 00071 size_t pos = 0; 00072 int started = 0; 00073 00074 if (addrlen != 2) 00075 return NULL; 00076 00077 addr &= 0x03ff; 00078 00079 if (len == 0) 00080 return str; 00081 00082 if (do_digit(str + pos, &area, 10, &pos, len, &started)) 00083 return str; 00084 00085 if (do_digit(str + pos, &area, 1, &pos, len, &started)) 00086 return str; 00087 00088 if (pos == len) 00089 return str; 00090 00091 *(str + pos) = '.'; 00092 pos++; 00093 started = 0; 00094 00095 if (do_digit(str + pos, &addr, 1000, &pos, len, &started)) 00096 return str; 00097 00098 if (do_digit(str + pos, &addr, 100, &pos, len, &started)) 00099 return str; 00100 00101 if (do_digit(str + pos, &addr, 10, &pos, len, &started)) 00102 return str; 00103 00104 if (do_digit(str + pos, &addr, 1, &pos, len, &started)) 00105 return str; 00106 00107 if (pos == len) 00108 return str; 00109 00110 *(str + pos) = 0; 00111 00112 return str; 00113 } 00114 00115 static int dnet_num(const char *src, uint16_t * dst) 00116 { 00117 int rv = 0; 00118 int tmp; 00119 *dst = 0; 00120 00121 while ((tmp = *src++) != 0) { 00122 tmp -= '0'; 00123 if ((tmp < 0) || (tmp > 9)) 00124 return rv; 00125 00126 rv++; 00127 (*dst) *= 10; 00128 (*dst) += tmp; 00129 } 00130 00131 return rv; 00132 } 00133 00134 static inline int dnet_pton(const char *src, char *addrbuf) 00135 { 00136 uint16_t area = 0; 00137 uint16_t node = 0; 00138 int pos; 00139 00140 pos = dnet_num(src, &area); 00141 if ((pos == 0) || (area > 63) || 00142 ((*(src + pos) != '.') && (*(src + pos) != ','))) 00143 return -EINVAL; 00144 00145 pos = dnet_num(src + pos + 1, &node); 00146 if ((pos == 0) || (node > 1023)) 00147 return -EINVAL; 00148 00149 *(uint16_t *)addrbuf = dn_ntohs((area << 10) | node); 00150 00151 return 1; 00152 } 00153 00154 /** 00155 * @name Creating Abstract Addresses 00156 * @{ 00157 */ 00158 00159 /** 00160 * Allocate new abstract address object. 00161 * @arg maxsize Maximum size of the binary address. 00162 * @return Newly allocated address object or NULL 00163 */ 00164 struct nl_addr *nl_addr_alloc(size_t maxsize) 00165 { 00166 struct nl_addr *addr; 00167 00168 addr = calloc(1, sizeof(*addr) + maxsize); 00169 if (!addr) { 00170 nl_errno(ENOMEM); 00171 return NULL; 00172 } 00173 00174 addr->a_refcnt = 1; 00175 addr->a_maxsize = maxsize; 00176 00177 return addr; 00178 } 00179 00180 /** 00181 * Allocate new abstract address object based on a binary address. 00182 * @arg family Address family. 00183 * @arg buf Buffer containing the binary address. 00184 * @arg size Length of binary address buffer. 00185 * @return Newly allocated address handle or NULL 00186 */ 00187 struct nl_addr *nl_addr_build(int family, void *buf, size_t size) 00188 { 00189 struct nl_addr *addr; 00190 00191 addr = nl_addr_alloc(size); 00192 if (!addr) 00193 return NULL; 00194 00195 addr->a_family = family; 00196 addr->a_len = size; 00197 addr->a_prefixlen = size*8; 00198 00199 if (size) 00200 memcpy(addr->a_addr, buf, size); 00201 00202 return addr; 00203 } 00204 00205 /** 00206 * Allocate abstract address object based on a character string 00207 * @arg addrstr Address represented as character string. 00208 * @arg hint Address family hint or AF_UNSPEC. 00209 * 00210 * Regognizes the following address formats: 00211 *@code 00212 * Format Len Family 00213 * ---------------------------------------------------------------- 00214 * IPv6 address format 16 AF_INET6 00215 * ddd.ddd.ddd.ddd 4 AF_INET 00216 * HH:HH:HH:HH:HH:HH 6 AF_LLC 00217 * AA{.|,}NNNN 2 AF_DECnet 00218 * HH:HH:HH:... variable AF_UNSPEC 00219 * @endcode 00220 * 00221 * Special values: 00222 * - none: All bits and length set to 0. 00223 * - {default|all|any}: All bits set to 0, length based on hint or 00224 * AF_INET if no hint is given. 00225 * 00226 * The prefix length may be appened at the end prefixed with a 00227 * slash, e.g. 10.0.0.0/8. 00228 * 00229 * @return Newly allocated abstract address object or NULL. 00230 */ 00231 struct nl_addr *nl_addr_parse(const char *addrstr, int hint) 00232 { 00233 int err, copy = 0, len = 0, family = AF_UNSPEC; 00234 char *str, *prefix, buf[32]; 00235 struct nl_addr *addr = NULL; /* gcc ain't that smart */ 00236 00237 str = strdup(addrstr); 00238 if (!str) { 00239 err = nl_errno(ENOMEM); 00240 goto errout; 00241 } 00242 00243 prefix = strchr(str, '/'); 00244 if (prefix) 00245 *prefix = '\0'; 00246 00247 if (!strcasecmp(str, "none")) { 00248 family = hint; 00249 goto prefix; 00250 } 00251 00252 if (!strcasecmp(str, "default") || 00253 !strcasecmp(str, "all") || 00254 !strcasecmp(str, "any")) { 00255 00256 switch (hint) { 00257 case AF_INET: 00258 case AF_UNSPEC: 00259 /* Kind of a hack, we assume that if there is 00260 * no hint given the user wants to have a IPv4 00261 * address given back. */ 00262 family = AF_INET; 00263 len = 4; 00264 goto prefix; 00265 00266 case AF_INET6: 00267 family = AF_INET6; 00268 len = 16; 00269 goto prefix; 00270 00271 case AF_LLC: 00272 family = AF_LLC; 00273 len = 6; 00274 goto prefix; 00275 00276 default: 00277 err = nl_error(EINVAL, "Unsuported address" \ 00278 "family for default address"); 00279 goto errout; 00280 } 00281 } 00282 00283 copy = 1; 00284 00285 if (hint == AF_INET || hint == AF_UNSPEC) { 00286 if (inet_pton(AF_INET, str, buf) > 0) { 00287 family = AF_INET; 00288 len = 4; 00289 goto prefix; 00290 } 00291 if (hint == AF_INET) { 00292 err = nl_error(EINVAL, "Invalid IPv4 address"); 00293 goto errout; 00294 } 00295 } 00296 00297 if (hint == AF_INET6 || hint == AF_UNSPEC) { 00298 if (inet_pton(AF_INET6, str, buf) > 0) { 00299 family = AF_INET6; 00300 len = 16; 00301 goto prefix; 00302 } 00303 if (hint == AF_INET6) { 00304 err = nl_error(EINVAL, "Invalid IPv6 address"); 00305 goto errout; 00306 } 00307 } 00308 00309 if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str, ':')) { 00310 unsigned int a, b, c, d, e, f; 00311 00312 if (sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x", 00313 &a, &b, &c, &d, &e, &f) == 6) { 00314 family = AF_LLC; 00315 len = 6; 00316 buf[0] = (unsigned char) a; 00317 buf[1] = (unsigned char) b; 00318 buf[2] = (unsigned char) c; 00319 buf[3] = (unsigned char) d; 00320 buf[4] = (unsigned char) e; 00321 buf[5] = (unsigned char) f; 00322 goto prefix; 00323 } 00324 00325 if (hint == AF_LLC) { 00326 err = nl_error(EINVAL, "Invalid link layer address"); 00327 goto errout; 00328 } 00329 } 00330 00331 if ((hint == AF_DECnet || hint == AF_UNSPEC) && 00332 (strchr(str, '.') || strchr(str, ','))) { 00333 if (dnet_pton(str, buf) > 0) { 00334 family = AF_DECnet; 00335 len = 2; 00336 goto prefix; 00337 } 00338 if (hint == AF_DECnet) { 00339 err = nl_error(EINVAL, "Invalid DECnet address"); 00340 goto errout; 00341 } 00342 } 00343 00344 if (hint == AF_UNSPEC && strchr(str, ':')) { 00345 int i = 0; 00346 char *s = str, *p; 00347 for (;;) { 00348 long l = strtol(s, &p, 16); 00349 00350 if (s == p || l > 0xff || i >= sizeof(buf)) { 00351 err = -EINVAL; 00352 goto errout; 00353 } 00354 00355 buf[i++] = (unsigned char) l; 00356 if (*p == '\0') 00357 break; 00358 s = ++p; 00359 } 00360 00361 len = i; 00362 family = AF_UNSPEC; 00363 goto prefix; 00364 } 00365 00366 err = nl_error(EINVAL, "Invalid address"); 00367 goto errout; 00368 00369 prefix: 00370 addr = nl_addr_alloc(len); 00371 if (!addr) { 00372 err = nl_errno(ENOMEM); 00373 goto errout; 00374 } 00375 00376 nl_addr_set_family(addr, family); 00377 00378 if (copy) 00379 nl_addr_set_binary_addr(addr, buf, len); 00380 00381 if (prefix) { 00382 char *p; 00383 long pl = strtol(++prefix, &p, 0); 00384 if (p == prefix) { 00385 nl_addr_destroy(addr); 00386 err = -EINVAL; 00387 goto errout; 00388 } 00389 nl_addr_set_prefixlen(addr, pl); 00390 } else 00391 nl_addr_set_prefixlen(addr, len * 8); 00392 00393 err = 0; 00394 errout: 00395 free(str); 00396 00397 return err ? NULL : addr; 00398 } 00399 00400 /** 00401 * Clone existing abstract address object. 00402 * @arg addr Abstract address object. 00403 * @return Newly allocated abstract address object being a duplicate of the 00404 * specified address object or NULL if a failure occured. 00405 */ 00406 struct nl_addr *nl_addr_clone(struct nl_addr *addr) 00407 { 00408 struct nl_addr *new; 00409 00410 new = nl_addr_build(addr->a_family, addr->a_addr, addr->a_len); 00411 if (new) 00412 new->a_prefixlen = addr->a_prefixlen; 00413 00414 return new; 00415 } 00416 00417 /** @} */ 00418 00419 /** 00420 * @name Destroying Abstract Addresses 00421 * @{ 00422 */ 00423 00424 /** 00425 * Destroy abstract address object. 00426 * @arg addr Abstract address object. 00427 */ 00428 void nl_addr_destroy(struct nl_addr *addr) 00429 { 00430 if (!addr) 00431 return; 00432 00433 if (addr->a_refcnt != 1) 00434 BUG(); 00435 00436 free(addr); 00437 } 00438 00439 /** @} */ 00440 00441 /** 00442 * @name Managing Usage References 00443 * @{ 00444 */ 00445 00446 struct nl_addr *nl_addr_get(struct nl_addr *addr) 00447 { 00448 addr->a_refcnt++; 00449 00450 return addr; 00451 } 00452 00453 void nl_addr_put(struct nl_addr *addr) 00454 { 00455 if (!addr) 00456 return; 00457 00458 if (addr->a_refcnt == 1) 00459 nl_addr_destroy(addr); 00460 else 00461 addr->a_refcnt--; 00462 } 00463 00464 /** 00465 * Check whether an abstract address object is shared. 00466 * @arg addr Abstract address object. 00467 * @return Non-zero if the abstract address object is shared, otherwise 0. 00468 */ 00469 int nl_addr_shared(struct nl_addr *addr) 00470 { 00471 return addr->a_refcnt > 1; 00472 } 00473 00474 /** @} */ 00475 00476 /** 00477 * @name Miscellaneous 00478 * @{ 00479 */ 00480 00481 /** 00482 * Compares two abstract address objects. 00483 * @arg a A abstract address object. 00484 * @arg b Another abstract address object. 00485 * 00486 * @return Integer less than, equal to or greather than zero if \c is found, 00487 * respectively to be less than, to, or be greater than \c b. 00488 */ 00489 int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b) 00490 { 00491 int d = a->a_family - b->a_family; 00492 00493 if (d == 0) { 00494 d = a->a_len - b->a_len; 00495 00496 if (a->a_len && d == 0) 00497 return memcmp(a->a_addr, b->a_addr, a->a_len); 00498 } 00499 00500 return d; 00501 } 00502 00503 /** 00504 * Compares the prefix of two abstract address objects. 00505 * @arg a A abstract address object. 00506 * @arg b Another abstract address object. 00507 * 00508 * @return Integer less than, equal to or greather than zero if \c is found, 00509 * respectively to be less than, to, or be greater than \c b. 00510 */ 00511 int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b) 00512 { 00513 int d = a->a_family - b->a_family; 00514 00515 if (d == 0) { 00516 int len = min(a->a_prefixlen, b->a_prefixlen); 00517 int bytes = len / 8; 00518 00519 d = memcmp(a->a_addr, b->a_addr, bytes); 00520 if (d == 0) { 00521 int mask = (1UL << (len % 8)) - 1UL; 00522 00523 d = (a->a_addr[bytes] & mask) - 00524 (b->a_addr[bytes] & mask); 00525 } 00526 } 00527 00528 return d; 00529 } 00530 00531 /** 00532 * Returns true if the address consists of all zeros 00533 * @arg addr Address to look at. 00534 */ 00535 int nl_addr_iszero(struct nl_addr *addr) 00536 { 00537 int i; 00538 00539 for (i = 0; i < addr->a_len; i++) 00540 if (addr->a_addr[i]) 00541 return 0; 00542 00543 return 1; 00544 } 00545 00546 /** 00547 * Check if an address matches a certain family. 00548 * @arg addr Address represented as character string. 00549 * @arg family Desired address family. 00550 * 00551 * @return 1 if the address is of the desired address family, 00552 * otherwise 0 is returned. 00553 */ 00554 int nl_addr_valid(char *addr, int family) 00555 { 00556 int ret; 00557 char buf[32]; 00558 00559 switch (family) { 00560 case AF_INET: 00561 case AF_INET6: 00562 ret = inet_pton(family, addr, buf); 00563 if (ret <= 0) 00564 return 0; 00565 break; 00566 00567 case AF_DECnet: 00568 ret = dnet_pton(addr, buf); 00569 if (ret <= 0) 00570 return 0; 00571 break; 00572 00573 case AF_LLC: 00574 if (sscanf(addr, "%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6) 00575 return 0; 00576 break; 00577 } 00578 00579 return 1; 00580 } 00581 00582 /** 00583 * Guess address family of an abstract address object based on address size. 00584 * @arg addr Abstract address object. 00585 * @return Address family or AF_UNSPEC if guessing wasn't successful. 00586 */ 00587 int nl_addr_guess_family(struct nl_addr *addr) 00588 { 00589 switch (addr->a_len) { 00590 case 4: 00591 return AF_INET; 00592 case 6: 00593 return AF_LLC; 00594 case 16: 00595 return AF_INET6; 00596 default: 00597 return AF_UNSPEC; 00598 } 00599 } 00600 00601 /** 00602 * Fill out sockaddr structure with values from abstract address object. 00603 * @arg addr Abstract address object. 00604 * @arg sa Destination sockaddr structure buffer. 00605 * @arg salen Length of sockaddr structure buffer. 00606 * 00607 * Fills out the specified sockaddr structure with the data found in the 00608 * specified abstract address. The salen argument needs to be set to the 00609 * size of sa but will be modified to the actual size used during before 00610 * the function exits. 00611 * 00612 * @return 0 on success or a negative error code 00613 */ 00614 int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa, 00615 socklen_t *salen) 00616 { 00617 switch (addr->a_family) { 00618 case AF_INET: { 00619 struct sockaddr_in *sai = (struct sockaddr_in *) sa; 00620 00621 if (*salen < sizeof(*sai)) 00622 return -EINVAL; 00623 00624 sai->sin_family = addr->a_family; 00625 memcpy(&sai->sin_addr, addr->a_addr, 4); 00626 *salen = sizeof(*sai); 00627 } 00628 break; 00629 00630 case AF_INET6: { 00631 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa; 00632 00633 if (*salen < sizeof(*sa6)) 00634 return -EINVAL; 00635 00636 sa6->sin6_family = addr->a_family; 00637 memcpy(&sa6->sin6_addr, addr->a_addr, 16); 00638 *salen = sizeof(*sa6); 00639 } 00640 break; 00641 00642 default: 00643 return -EINVAL; 00644 } 00645 00646 return 0; 00647 } 00648 00649 00650 /** @} */ 00651 00652 /** 00653 * @name Getting Information About Addresses 00654 * @{ 00655 */ 00656 00657 /** 00658 * Call getaddrinfo() for an abstract address object. 00659 * @arg addr Abstract address object. 00660 * 00661 * Calls getaddrinfo() for the specified abstract address in AI_NUMERICHOST 00662 * mode. 00663 * 00664 * @note The caller is responsible for freeing the linked list using the 00665 * interface provided by getaddrinfo(3). 00666 * 00667 * @return A linked list of addrinfo handles or NULL with an error message 00668 * associated. 00669 */ 00670 struct addrinfo *nl_addr_info(struct nl_addr *addr) 00671 { 00672 int err; 00673 struct addrinfo *res; 00674 char buf[INET6_ADDRSTRLEN+5]; 00675 struct addrinfo hint = { 00676 .ai_flags = AI_NUMERICHOST, 00677 .ai_family = addr->a_family, 00678 }; 00679 00680 nl_addr2str(addr, buf, sizeof(buf)); 00681 00682 err = getaddrinfo(buf, NULL, &hint, &res); 00683 if (err != 0) { 00684 nl_error(err, gai_strerror(err)); 00685 return NULL; 00686 } 00687 00688 return res; 00689 } 00690 00691 /** 00692 * Resolve abstract address object to a name using getnameinfo(). 00693 * @arg addr Abstract address object. 00694 * @arg host Destination buffer for host name. 00695 * @arg hostlen Length of destination buffer. 00696 * 00697 * Resolves the abstract address to a name and writes the looked up result 00698 * into the host buffer. getnameinfo() is used to perform the lookup and 00699 * is put into NI_NAMEREQD mode so the function will fail if the lookup 00700 * couldn't be performed. 00701 * 00702 * @return 0 on success or a negative error code. 00703 */ 00704 int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen) 00705 { 00706 int err; 00707 struct sockaddr_in6 buf; 00708 socklen_t salen = sizeof(buf); 00709 00710 err = nl_addr_fill_sockaddr(addr, (struct sockaddr *) &buf, &salen); 00711 if (err < 0) 00712 return err; 00713 00714 return getnameinfo((struct sockaddr *) &buf, salen, 00715 host, hostlen, NULL, 0, NI_NAMEREQD); 00716 } 00717 00718 /** @} */ 00719 00720 /** 00721 * @name Attributes 00722 * @{ 00723 */ 00724 00725 void nl_addr_set_family(struct nl_addr *addr, int family) 00726 { 00727 addr->a_family = family; 00728 } 00729 00730 int nl_addr_get_family(struct nl_addr *addr) 00731 { 00732 return addr->a_family; 00733 } 00734 00735 /** 00736 * Set binary address of abstract address object. 00737 * @arg addr Abstract address object. 00738 * @arg buf Buffer containing binary address. 00739 * @arg len Length of buffer containing binary address. 00740 */ 00741 int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len) 00742 { 00743 if (len > addr->a_maxsize) 00744 return -ERANGE; 00745 00746 addr->a_len = len; 00747 memcpy(addr->a_addr, buf, len); 00748 00749 return 0; 00750 } 00751 00752 /** 00753 * Get binary address of abstract address object. 00754 * @arg addr Abstract address object. 00755 */ 00756 void *nl_addr_get_binary_addr(struct nl_addr *addr) 00757 { 00758 return addr->a_addr; 00759 } 00760 00761 /** 00762 * Get length of binary address of abstract address object. 00763 * @arg addr Abstract address object. 00764 */ 00765 unsigned int nl_addr_get_len(struct nl_addr *addr) 00766 { 00767 return addr->a_len; 00768 } 00769 00770 void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen) 00771 { 00772 addr->a_prefixlen = prefixlen; 00773 } 00774 00775 /** 00776 * Get prefix length of abstract address object. 00777 * @arg addr Abstract address object. 00778 */ 00779 unsigned int nl_addr_get_prefixlen(struct nl_addr *addr) 00780 { 00781 return addr->a_prefixlen; 00782 } 00783 00784 /** @} */ 00785 00786 /** 00787 * @name Translations to Strings 00788 * @{ 00789 */ 00790 00791 /** 00792 * Convert abstract address object to character string. 00793 * @arg addr Abstract address object. 00794 * @arg buf Destination buffer. 00795 * @arg size Size of destination buffer. 00796 * 00797 * Converts an abstract address to a character string and stores 00798 * the result in the specified destination buffer. 00799 * 00800 * @return Address represented in ASCII stored in destination buffer. 00801 */ 00802 char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size) 00803 { 00804 int i; 00805 char tmp[16]; 00806 00807 if (!addr->a_len) { 00808 snprintf(buf, size, "none"); 00809 goto prefix; 00810 } 00811 00812 switch (addr->a_family) { 00813 case AF_INET: 00814 inet_ntop(AF_INET, addr->a_addr, buf, size); 00815 break; 00816 00817 case AF_INET6: 00818 inet_ntop(AF_INET6, addr->a_addr, buf, size); 00819 break; 00820 00821 case AF_DECnet: 00822 dnet_ntop(addr->a_addr, addr->a_len, buf, size); 00823 break; 00824 00825 case AF_LLC: 00826 default: 00827 snprintf(buf, size, "%02x", 00828 (unsigned char) addr->a_addr[0]); 00829 for (i = 1; i < addr->a_len; i++) { 00830 snprintf(tmp, sizeof(tmp), ":%02x", 00831 (unsigned char) addr->a_addr[i]); 00832 strncat(buf, tmp, size - strlen(buf) - 1); 00833 } 00834 break; 00835 } 00836 00837 prefix: 00838 if (addr->a_prefixlen != (8 * addr->a_len)) { 00839 snprintf(tmp, sizeof(tmp), "/%u", addr->a_prefixlen); 00840 strncat(buf, tmp, size - strlen(buf) - 1); 00841 } 00842 00843 return buf; 00844 } 00845 00846 /** @} */ 00847 00848 /** 00849 * @name Address Family Transformations 00850 * @{ 00851 */ 00852 00853 static struct trans_tbl afs[] = { 00854 __ADD(AF_UNSPEC,unspec) 00855 __ADD(AF_UNIX,unix) 00856 __ADD(AF_LOCAL,local) 00857 __ADD(AF_INET,inet) 00858 __ADD(AF_AX25,ax25) 00859 __ADD(AF_IPX,ipx) 00860 __ADD(AF_APPLETALK,appletalk) 00861 __ADD(AF_NETROM,netrom) 00862 __ADD(AF_BRIDGE,bridge) 00863 __ADD(AF_ATMPVC,atmpvc) 00864 __ADD(AF_X25,x25) 00865 __ADD(AF_INET6,inet6) 00866 __ADD(AF_ROSE,rose) 00867 __ADD(AF_DECnet,decnet) 00868 __ADD(AF_NETBEUI,netbeui) 00869 __ADD(AF_SECURITY,security) 00870 __ADD(AF_KEY,key) 00871 __ADD(AF_NETLINK,netlink) 00872 __ADD(AF_ROUTE,route) 00873 __ADD(AF_PACKET,packet) 00874 __ADD(AF_ASH,ash) 00875 __ADD(AF_ECONET,econet) 00876 __ADD(AF_ATMSVC,atmsvc) 00877 __ADD(AF_SNA,sna) 00878 __ADD(AF_IRDA,irda) 00879 __ADD(AF_PPPOX,pppox) 00880 __ADD(AF_WANPIPE,wanpipe) 00881 __ADD(AF_LLC,llc) 00882 __ADD(AF_BLUETOOTH,bluetooth) 00883 }; 00884 00885 char *nl_af2str(int family, char *buf, size_t size) 00886 { 00887 return __type2str(family, buf, size, afs, ARRAY_SIZE(afs)); 00888 } 00889 00890 int nl_str2af(const char *name) 00891 { 00892 int fam = __str2type(name, afs, ARRAY_SIZE(afs)); 00893 return fam >= 0 ? fam : AF_UNSPEC; 00894 } 00895 00896 /** @} */ 00897 00898 /** @} */