• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

/libnl3-3.2.7/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-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 /** @} */

Generated on Tue May 29 2012 08:28:39 for libnl by  doxygen 1.7.1