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