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