libnl 3.2.7
|
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 d = memcmp(a->a_addr, b->a_addr, a->a_len); 00501 00502 if (d == 0) 00503 return (a->a_prefixlen - b->a_prefixlen); 00504 } 00505 00506 return d; 00507 } 00508 00509 /** 00510 * Compares the prefix of two abstract address objects. 00511 * @arg a A abstract address object. 00512 * @arg b Another abstract address object. 00513 * 00514 * @return Integer less than, equal to or greather than zero if \c is found, 00515 * respectively to be less than, to, or be greater than \c b. 00516 */ 00517 int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b) 00518 { 00519 int d = a->a_family - b->a_family; 00520 00521 if (d == 0) { 00522 int len = min(a->a_prefixlen, b->a_prefixlen); 00523 int bytes = len / 8; 00524 00525 d = memcmp(a->a_addr, b->a_addr, bytes); 00526 if (d == 0) { 00527 int mask = (1UL << (len % 8)) - 1UL; 00528 00529 d = (a->a_addr[bytes] & mask) - 00530 (b->a_addr[bytes] & mask); 00531 } 00532 } 00533 00534 return d; 00535 } 00536 00537 /** 00538 * Returns true if the address consists of all zeros 00539 * @arg addr Address to look at. 00540 */ 00541 int nl_addr_iszero(struct nl_addr *addr) 00542 { 00543 int i; 00544 00545 for (i = 0; i < addr->a_len; i++) 00546 if (addr->a_addr[i]) 00547 return 0; 00548 00549 return 1; 00550 } 00551 00552 /** 00553 * Check if an address matches a certain family. 00554 * @arg addr Address represented as character string. 00555 * @arg family Desired address family. 00556 * 00557 * @return 1 if the address is of the desired address family, 00558 * otherwise 0 is returned. 00559 */ 00560 int nl_addr_valid(char *addr, int family) 00561 { 00562 int ret; 00563 char buf[32]; 00564 00565 switch (family) { 00566 case AF_INET: 00567 case AF_INET6: 00568 ret = inet_pton(family, addr, buf); 00569 if (ret <= 0) 00570 return 0; 00571 break; 00572 00573 case AF_DECnet: 00574 ret = dnet_pton(addr, buf); 00575 if (ret <= 0) 00576 return 0; 00577 break; 00578 00579 case AF_LLC: 00580 if (sscanf(addr, "%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6) 00581 return 0; 00582 break; 00583 } 00584 00585 return 1; 00586 } 00587 00588 /** 00589 * Guess address family of an abstract address object based on address size. 00590 * @arg addr Abstract address object. 00591 * @return Address family or AF_UNSPEC if guessing wasn't successful. 00592 */ 00593 int nl_addr_guess_family(struct nl_addr *addr) 00594 { 00595 switch (addr->a_len) { 00596 case 4: 00597 return AF_INET; 00598 case 6: 00599 return AF_LLC; 00600 case 16: 00601 return AF_INET6; 00602 default: 00603 return AF_UNSPEC; 00604 } 00605 } 00606 00607 /** 00608 * Fill out sockaddr structure with values from abstract address object. 00609 * @arg addr Abstract address object. 00610 * @arg sa Destination sockaddr structure buffer. 00611 * @arg salen Length of sockaddr structure buffer. 00612 * 00613 * Fills out the specified sockaddr structure with the data found in the 00614 * specified abstract address. The salen argument needs to be set to the 00615 * size of sa but will be modified to the actual size used during before 00616 * the function exits. 00617 * 00618 * @return 0 on success or a negative error code 00619 */ 00620 int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa, 00621 socklen_t *salen) 00622 { 00623 switch (addr->a_family) { 00624 case AF_INET: { 00625 struct sockaddr_in *sai = (struct sockaddr_in *) sa; 00626 00627 if (*salen < sizeof(*sai)) 00628 return -NLE_INVAL; 00629 00630 sai->sin_family = addr->a_family; 00631 memcpy(&sai->sin_addr, addr->a_addr, 4); 00632 *salen = sizeof(*sai); 00633 } 00634 break; 00635 00636 case AF_INET6: { 00637 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa; 00638 00639 if (*salen < sizeof(*sa6)) 00640 return -NLE_INVAL; 00641 00642 sa6->sin6_family = addr->a_family; 00643 memcpy(&sa6->sin6_addr, addr->a_addr, 16); 00644 *salen = sizeof(*sa6); 00645 } 00646 break; 00647 00648 default: 00649 return -NLE_INVAL; 00650 } 00651 00652 return 0; 00653 } 00654 00655 00656 /** @} */ 00657 00658 /** 00659 * @name Getting Information About Addresses 00660 * @{ 00661 */ 00662 00663 /** 00664 * Call getaddrinfo() for an abstract address object. 00665 * @arg addr Abstract address object. 00666 * @arg result Pointer to store resulting address list. 00667 * 00668 * Calls getaddrinfo() for the specified abstract address in AI_NUMERICHOST 00669 * mode. 00670 * 00671 * @note The caller is responsible for freeing the linked list using the 00672 * interface provided by getaddrinfo(3). 00673 * 00674 * @return 0 on success or a negative error code. 00675 */ 00676 int nl_addr_info(struct nl_addr *addr, struct addrinfo **result) 00677 { 00678 int err; 00679 char buf[INET6_ADDRSTRLEN+5]; 00680 struct addrinfo hint = { 00681 .ai_flags = AI_NUMERICHOST, 00682 .ai_family = addr->a_family, 00683 }; 00684 00685 nl_addr2str(addr, buf, sizeof(buf)); 00686 00687 err = getaddrinfo(buf, NULL, &hint, result); 00688 if (err != 0) { 00689 switch (err) { 00690 case EAI_ADDRFAMILY: return -NLE_AF_NOSUPPORT; 00691 case EAI_AGAIN: return -NLE_AGAIN; 00692 case EAI_BADFLAGS: return -NLE_INVAL; 00693 case EAI_FAIL: return -NLE_NOADDR; 00694 case EAI_FAMILY: return -NLE_AF_NOSUPPORT; 00695 case EAI_MEMORY: return -NLE_NOMEM; 00696 case EAI_NODATA: return -NLE_NOADDR; 00697 case EAI_NONAME: return -NLE_OBJ_NOTFOUND; 00698 case EAI_SERVICE: return -NLE_OPNOTSUPP; 00699 case EAI_SOCKTYPE: return -NLE_BAD_SOCK; 00700 default: return -NLE_FAILURE; 00701 } 00702 } 00703 00704 return 0; 00705 } 00706 00707 /** 00708 * Resolve abstract address object to a name using getnameinfo(). 00709 * @arg addr Abstract address object. 00710 * @arg host Destination buffer for host name. 00711 * @arg hostlen Length of destination buffer. 00712 * 00713 * Resolves the abstract address to a name and writes the looked up result 00714 * into the host buffer. getnameinfo() is used to perform the lookup and 00715 * is put into NI_NAMEREQD mode so the function will fail if the lookup 00716 * couldn't be performed. 00717 * 00718 * @return 0 on success or a negative error code. 00719 */ 00720 int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen) 00721 { 00722 int err; 00723 struct sockaddr_in6 buf; 00724 socklen_t salen = sizeof(buf); 00725 00726 err = nl_addr_fill_sockaddr(addr, (struct sockaddr *) &buf, &salen); 00727 if (err < 0) 00728 return err; 00729 00730 err = getnameinfo((struct sockaddr *) &buf, salen, host, hostlen, 00731 NULL, 0, NI_NAMEREQD); 00732 if (err < 0) 00733 return nl_syserr2nlerr(err); 00734 00735 return 0; 00736 } 00737 00738 /** @} */ 00739 00740 /** 00741 * @name Attributes 00742 * @{ 00743 */ 00744 00745 void nl_addr_set_family(struct nl_addr *addr, int family) 00746 { 00747 addr->a_family = family; 00748 } 00749 00750 int nl_addr_get_family(struct nl_addr *addr) 00751 { 00752 return addr->a_family; 00753 } 00754 00755 /** 00756 * Set binary address of abstract address object. 00757 * @arg addr Abstract address object. 00758 * @arg buf Buffer containing binary address. 00759 * @arg len Length of buffer containing binary address. 00760 */ 00761 int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len) 00762 { 00763 if (len > addr->a_maxsize) 00764 return -NLE_RANGE; 00765 00766 addr->a_len = len; 00767 memcpy(addr->a_addr, buf, len); 00768 00769 return 0; 00770 } 00771 00772 /** 00773 * Get binary address of abstract address object. 00774 * @arg addr Abstract address object. 00775 */ 00776 void *nl_addr_get_binary_addr(struct nl_addr *addr) 00777 { 00778 return addr->a_addr; 00779 } 00780 00781 /** 00782 * Get length of binary address of abstract address object. 00783 * @arg addr Abstract address object. 00784 */ 00785 unsigned int nl_addr_get_len(struct nl_addr *addr) 00786 { 00787 return addr->a_len; 00788 } 00789 00790 void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen) 00791 { 00792 addr->a_prefixlen = prefixlen; 00793 } 00794 00795 /** 00796 * Get prefix length of abstract address object. 00797 * @arg addr Abstract address object. 00798 */ 00799 unsigned int nl_addr_get_prefixlen(struct nl_addr *addr) 00800 { 00801 return addr->a_prefixlen; 00802 } 00803 00804 /** @} */ 00805 00806 /** 00807 * @name Translations to Strings 00808 * @{ 00809 */ 00810 00811 /** 00812 * Convert abstract address object to character string. 00813 * @arg addr Abstract address object. 00814 * @arg buf Destination buffer. 00815 * @arg size Size of destination buffer. 00816 * 00817 * Converts an abstract address to a character string and stores 00818 * the result in the specified destination buffer. 00819 * 00820 * @return Address represented in ASCII stored in destination buffer. 00821 */ 00822 char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size) 00823 { 00824 int i; 00825 char tmp[16]; 00826 00827 if (!addr || !addr->a_len) { 00828 snprintf(buf, size, "none"); 00829 if (addr) 00830 goto prefix; 00831 else 00832 return buf; 00833 } 00834 00835 switch (addr->a_family) { 00836 case AF_INET: 00837 inet_ntop(AF_INET, addr->a_addr, buf, size); 00838 break; 00839 00840 case AF_INET6: 00841 inet_ntop(AF_INET6, addr->a_addr, buf, size); 00842 break; 00843 00844 case AF_DECnet: 00845 dnet_ntop(addr->a_addr, addr->a_len, buf, size); 00846 break; 00847 00848 case AF_LLC: 00849 default: 00850 snprintf(buf, size, "%02x", 00851 (unsigned char) addr->a_addr[0]); 00852 for (i = 1; i < addr->a_len; i++) { 00853 snprintf(tmp, sizeof(tmp), ":%02x", 00854 (unsigned char) addr->a_addr[i]); 00855 strncat(buf, tmp, size - strlen(buf) - 1); 00856 } 00857 break; 00858 } 00859 00860 prefix: 00861 if (addr->a_prefixlen != (8 * addr->a_len)) { 00862 snprintf(tmp, sizeof(tmp), "/%u", addr->a_prefixlen); 00863 strncat(buf, tmp, size - strlen(buf) - 1); 00864 } 00865 00866 return buf; 00867 } 00868 00869 /** @} */ 00870 00871 /** 00872 * @name Address Family Transformations 00873 * @{ 00874 */ 00875 00876 static const struct trans_tbl afs[] = { 00877 __ADD(AF_UNSPEC,unspec) 00878 __ADD(AF_UNIX,unix) 00879 __ADD(AF_LOCAL,local) 00880 __ADD(AF_INET,inet) 00881 __ADD(AF_AX25,ax25) 00882 __ADD(AF_IPX,ipx) 00883 __ADD(AF_APPLETALK,appletalk) 00884 __ADD(AF_NETROM,netrom) 00885 __ADD(AF_BRIDGE,bridge) 00886 __ADD(AF_ATMPVC,atmpvc) 00887 __ADD(AF_X25,x25) 00888 __ADD(AF_INET6,inet6) 00889 __ADD(AF_ROSE,rose) 00890 __ADD(AF_DECnet,decnet) 00891 __ADD(AF_NETBEUI,netbeui) 00892 __ADD(AF_SECURITY,security) 00893 __ADD(AF_KEY,key) 00894 __ADD(AF_NETLINK,netlink) 00895 __ADD(AF_ROUTE,route) 00896 __ADD(AF_PACKET,packet) 00897 __ADD(AF_ASH,ash) 00898 __ADD(AF_ECONET,econet) 00899 __ADD(AF_ATMSVC,atmsvc) 00900 __ADD(AF_SNA,sna) 00901 __ADD(AF_IRDA,irda) 00902 __ADD(AF_PPPOX,pppox) 00903 __ADD(AF_WANPIPE,wanpipe) 00904 __ADD(AF_LLC,llc) 00905 __ADD(AF_BLUETOOTH,bluetooth) 00906 }; 00907 00908 char *nl_af2str(int family, char *buf, size_t size) 00909 { 00910 return __type2str(family, buf, size, afs, ARRAY_SIZE(afs)); 00911 } 00912 00913 int nl_str2af(const char *name) 00914 { 00915 int fam = __str2type(name, afs, ARRAY_SIZE(afs)); 00916 return fam >= 0 ? fam : -EINVAL; 00917 } 00918 00919 /** @} */ 00920 00921 /** @} */