/build/buildd/libnl-1.0~pre6/lib/addr.c

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

Generated on Fri Apr 27 14:14:07 2007 for libnl by  doxygen 1.5.1