Home | History | Annotate | Download | only in lib
      1 /*
      2  * lib/addr.c		Network Address
      3  *
      4  *	This library is free software; you can redistribute it and/or
      5  *	modify it under the terms of the GNU Lesser General Public
      6  *	License as published by the Free Software Foundation version 2.1
      7  *	of the License.
      8  *
      9  * Copyright (c) 2003-2013 Thomas Graf <tgraf (at) suug.ch>
     10  */
     11 
     12 /**
     13  * @ingroup core_types
     14  * @defgroup addr Network Address
     15  *
     16  * Abstract data type representing any kind of network address
     17  *
     18  * Related sections in the development guide:
     19  * - @core_doc{_abstract_address, Network Addresses}
     20  *
     21  * @{
     22  *
     23  * Header
     24  * ------
     25  * ~~~~{.c}
     26  * #include <netlink/addr.h>
     27  * ~~~~
     28  */
     29 
     30 #include <netlink-private/netlink.h>
     31 #include <netlink/netlink.h>
     32 #include <netlink/utils.h>
     33 #include <netlink/addr.h>
     34 #include <linux/socket.h>
     35 
     36 /* All this DECnet stuff is stolen from iproute2, thanks to whoever wrote
     37  * this, probably Alexey. */
     38 static inline uint16_t dn_ntohs(uint16_t addr)
     39 {
     40 	union {
     41 		uint8_t byte[2];
     42 		uint16_t word;
     43 	} u = {
     44 		.word = addr,
     45 	};
     46 
     47 	return ((uint16_t) u.byte[0]) | (((uint16_t) u.byte[1]) << 8);
     48 }
     49 
     50 static inline int do_digit(char *str, uint16_t *addr, uint16_t scale,
     51 			   size_t *pos, size_t len, int *started)
     52 {
     53 	uint16_t tmp = *addr / scale;
     54 
     55 	if (*pos == len)
     56 		return 1;
     57 
     58 	if (((tmp) > 0) || *started || (scale == 1)) {
     59 		*str = tmp + '0';
     60 		*started = 1;
     61 		(*pos)++;
     62 		*addr -= (tmp * scale);
     63 	}
     64 
     65 	return 0;
     66 }
     67 
     68 static const char *dnet_ntop(char *addrbuf, size_t addrlen, char *str,
     69 			     size_t len)
     70 {
     71 	uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf);
     72 	uint16_t area = addr >> 10;
     73 	size_t pos = 0;
     74 	int started = 0;
     75 
     76 	if (addrlen != 2)
     77 		return NULL;
     78 
     79 	addr &= 0x03ff;
     80 
     81 	if (len == 0)
     82 		return str;
     83 
     84 	if (do_digit(str + pos, &area, 10, &pos, len, &started))
     85 		return str;
     86 
     87 	if (do_digit(str + pos, &area, 1, &pos, len, &started))
     88 		return str;
     89 
     90 	if (pos == len)
     91 		return str;
     92 
     93 	*(str + pos) = '.';
     94 	pos++;
     95 	started = 0;
     96 
     97 	if (do_digit(str + pos, &addr, 1000, &pos, len, &started))
     98 		return str;
     99 
    100 	if (do_digit(str + pos, &addr, 100, &pos, len, &started))
    101 		return str;
    102 
    103 	if (do_digit(str + pos, &addr, 10, &pos, len, &started))
    104 		return str;
    105 
    106 	if (do_digit(str + pos, &addr, 1, &pos, len, &started))
    107 		return str;
    108 
    109 	if (pos == len)
    110 		return str;
    111 
    112 	*(str + pos) = 0;
    113 
    114 	return str;
    115 }
    116 
    117 static int dnet_num(const char *src, uint16_t * dst)
    118 {
    119 	int rv = 0;
    120 	int tmp;
    121 	*dst = 0;
    122 
    123 	while ((tmp = *src++) != 0) {
    124 		tmp -= '0';
    125 		if ((tmp < 0) || (tmp > 9))
    126 			return rv;
    127 
    128 		rv++;
    129 		(*dst) *= 10;
    130 		(*dst) += tmp;
    131 	}
    132 
    133 	return rv;
    134 }
    135 
    136 static inline int dnet_pton(const char *src, char *addrbuf)
    137 {
    138 	uint16_t area = 0;
    139 	uint16_t node = 0;
    140 	int pos;
    141 
    142 	pos = dnet_num(src, &area);
    143 	if ((pos == 0) || (area > 63) ||
    144 	    ((*(src + pos) != '.') && (*(src + pos) != ',')))
    145 		return -NLE_INVAL;
    146 
    147 	pos = dnet_num(src + pos + 1, &node);
    148 	if ((pos == 0) || (node > 1023))
    149 		return -NLE_INVAL;
    150 
    151 	*(uint16_t *)addrbuf = dn_ntohs((area << 10) | node);
    152 
    153 	return 1;
    154 }
    155 
    156 static void addr_destroy(struct nl_addr *addr)
    157 {
    158 	if (!addr)
    159 		return;
    160 
    161 	if (addr->a_refcnt != 1)
    162 		BUG();
    163 
    164 	free(addr);
    165 }
    166 
    167 /**
    168  * @name Creating Abstract Network Addresses
    169  * @{
    170  */
    171 
    172 /**
    173  * Allocate empty abstract address
    174  * @arg maxsize		Upper limit of the binary address to be stored
    175  *
    176  * The new address object will be empty with a prefix length of 0 and will
    177  * be capable of holding binary addresses up to the specified limit.
    178  *
    179  * @see nl_addr_build()
    180  * @see nl_addr_parse()
    181  * @see nl_addr_put()
    182  *
    183  * @return Allocated address object or NULL upon failure.
    184  */
    185 struct nl_addr *nl_addr_alloc(size_t maxsize)
    186 {
    187 	struct nl_addr *addr;
    188 
    189 	addr = calloc(1, sizeof(*addr) + maxsize);
    190 	if (!addr)
    191 		return NULL;
    192 
    193 	addr->a_refcnt = 1;
    194 	addr->a_maxsize = maxsize;
    195 
    196 	return addr;
    197 }
    198 
    199 /**
    200  * Allocate abstract address based on a binary address.
    201  * @arg family		Address family
    202  * @arg buf		Binary address
    203  * @arg size		Length of binary address
    204  *
    205  * This function will allocate an abstract address capable of holding the
    206  * binary address specified. The prefix length will be set to the full
    207  * length of the binary address provided.
    208  *
    209  * @see nl_addr_alloc()
    210  * @see nl_addr_alloc_attr()
    211  * @see nl_addr_parse()
    212  * @see nl_addr_put()
    213  *
    214  * @return Allocated address object or NULL upon failure.
    215  */
    216 struct nl_addr *nl_addr_build(int family, void *buf, size_t size)
    217 {
    218 	struct nl_addr *addr;
    219 
    220 	addr = nl_addr_alloc(size);
    221 	if (!addr)
    222 		return NULL;
    223 
    224 	addr->a_family = family;
    225 	addr->a_len = size;
    226 	addr->a_prefixlen = size*8;
    227 
    228 	if (size)
    229 		memcpy(addr->a_addr, buf, size);
    230 
    231 	return addr;
    232 }
    233 
    234 /**
    235  * Allocate abstract address based on Netlink attribute.
    236  * @arg nla		Netlink attribute
    237  * @arg family		Address family.
    238  *
    239  * Allocates an abstract address based on the specified Netlink attribute
    240  * by interpreting the payload of the Netlink attribute as the binary
    241  * address.
    242  *
    243  * This function is identical to:
    244  * @code
    245  * nl_addr_build(family, nla_data(nla), nla_len(nla));
    246  * @endcode
    247  *
    248  * @see nl_addr_alloc()
    249  * @see nl_addr_build()
    250  * @see nl_addr_parse()
    251  * @see nl_addr_put()
    252  *
    253  * @return Allocated address object or NULL upon failure.
    254  */
    255 struct nl_addr *nl_addr_alloc_attr(struct nlattr *nla, int family)
    256 {
    257 	return nl_addr_build(family, nla_data(nla), nla_len(nla));
    258 }
    259 
    260 /**
    261  * Allocate abstract address based on character string
    262  * @arg addrstr		Address represented as character string.
    263  * @arg hint		Address family hint or AF_UNSPEC.
    264  * @arg result		Pointer to store resulting address.
    265  *
    266  * Regognizes the following address formats:
    267  * @code
    268  *  Format                      Len                Family
    269  *  ----------------------------------------------------------------
    270  *  IPv6 address format         16                 AF_INET6
    271  *  ddd.ddd.ddd.ddd             4                  AF_INET
    272  *  HH:HH:HH:HH:HH:HH           6                  AF_LLC
    273  *  AA{.|,}NNNN                 2                  AF_DECnet
    274  *  HH:HH:HH:...                variable           AF_UNSPEC
    275  * @endcode
    276  *
    277  *  Special values:
    278  *    - none: All bits and length set to 0.
    279  *    - {default|all|any}: All bits set to 0, length based on hint or
    280  *                         AF_INET if no hint is given.
    281  *
    282  * The prefix length may be appened at the end prefixed with a
    283  * slash, e.g. 10.0.0.0/8.
    284  *
    285  * @see nl_addr_alloc()
    286  * @see nl_addr_build()
    287  * @see nl_addr_put()
    288  *
    289  * @return 0 on success or a negative error code.
    290  */
    291 int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result)
    292 {
    293 	int err, copy = 0, len = 0, family = AF_UNSPEC;
    294 	char *str, *prefix, buf[32];
    295 	struct nl_addr *addr = NULL; /* gcc ain't that smart */
    296 
    297 	str = strdup(addrstr);
    298 	if (!str) {
    299 		err = -NLE_NOMEM;
    300 		goto errout;
    301 	}
    302 
    303 	prefix = strchr(str, '/');
    304 	if (prefix)
    305 		*prefix = '\0';
    306 
    307 	if (!strcasecmp(str, "none")) {
    308 		family = hint;
    309 		goto prefix;
    310 	}
    311 
    312 	if (!strcasecmp(str, "default") ||
    313 	    !strcasecmp(str, "all") ||
    314 	    !strcasecmp(str, "any")) {
    315 
    316 		len = 0;
    317 
    318 		switch (hint) {
    319 			case AF_INET:
    320 			case AF_UNSPEC:
    321 				/* Kind of a hack, we assume that if there is
    322 				 * no hint given the user wants to have a IPv4
    323 				 * address given back. */
    324 				family = AF_INET;
    325 				goto prefix;
    326 
    327 			case AF_INET6:
    328 				family = AF_INET6;
    329 				goto prefix;
    330 
    331 			case AF_LLC:
    332 				family = AF_LLC;
    333 				goto prefix;
    334 
    335 			default:
    336 				err = -NLE_AF_NOSUPPORT;
    337 				goto errout;
    338 		}
    339 	}
    340 
    341 	copy = 1;
    342 
    343 	if (hint == AF_INET || hint == AF_UNSPEC) {
    344 		if (inet_pton(AF_INET, str, buf) > 0) {
    345 			family = AF_INET;
    346 			len = 4;
    347 			goto prefix;
    348 		}
    349 		if (hint == AF_INET) {
    350 			err = -NLE_NOADDR;
    351 			goto errout;
    352 		}
    353 	}
    354 
    355 	if (hint == AF_INET6 || hint == AF_UNSPEC) {
    356 		if (inet_pton(AF_INET6, str, buf) > 0) {
    357 			family = AF_INET6;
    358 			len = 16;
    359 			goto prefix;
    360 		}
    361 		if (hint == AF_INET6) {
    362 			err = -NLE_NOADDR;
    363 			goto errout;
    364 		}
    365 	}
    366 
    367 	if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str, ':')) {
    368 		unsigned int a, b, c, d, e, f;
    369 
    370 		if (sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
    371 		    &a, &b, &c, &d, &e, &f) == 6) {
    372 			family = AF_LLC;
    373 			len = 6;
    374 			buf[0] = (unsigned char) a;
    375 			buf[1] = (unsigned char) b;
    376 			buf[2] = (unsigned char) c;
    377 			buf[3] = (unsigned char) d;
    378 			buf[4] = (unsigned char) e;
    379 			buf[5] = (unsigned char) f;
    380 			goto prefix;
    381 		}
    382 
    383 		if (hint == AF_LLC) {
    384 			err = -NLE_NOADDR;
    385 			goto errout;
    386 		}
    387 	}
    388 
    389 	if ((hint == AF_DECnet || hint == AF_UNSPEC) &&
    390 	    (strchr(str, '.') || strchr(str, ','))) {
    391 		if (dnet_pton(str, buf) > 0) {
    392 			family = AF_DECnet;
    393 			len = 2;
    394 			goto prefix;
    395 		}
    396 		if (hint == AF_DECnet) {
    397 			err = -NLE_NOADDR;
    398 			goto errout;
    399 		}
    400 	}
    401 
    402 	if (hint == AF_UNSPEC && strchr(str, ':')) {
    403 		size_t i = 0;
    404 		char *s = str, *p;
    405 		for (;;) {
    406 			long l = strtol(s, &p, 16);
    407 
    408 			if (s == p || l > 0xff || i >= sizeof(buf)) {
    409 				err = -NLE_INVAL;
    410 				goto errout;
    411 			}
    412 
    413 			buf[i++] = (unsigned char) l;
    414 			if (*p == '\0')
    415 				break;
    416 			s = ++p;
    417 		}
    418 
    419 		len = i;
    420 		family = AF_UNSPEC;
    421 		goto prefix;
    422 	}
    423 
    424 	err = -NLE_NOADDR;
    425 	goto errout;
    426 
    427 prefix:
    428 	addr = nl_addr_alloc(len);
    429 	if (!addr) {
    430 		err = -NLE_NOMEM;
    431 		goto errout;
    432 	}
    433 
    434 	nl_addr_set_family(addr, family);
    435 
    436 	if (copy)
    437 		nl_addr_set_binary_addr(addr, buf, len);
    438 
    439 	if (prefix) {
    440 		char *p;
    441 		long pl = strtol(++prefix, &p, 0);
    442 		if (p == prefix) {
    443 			addr_destroy(addr);
    444 			err = -NLE_INVAL;
    445 			goto errout;
    446 		}
    447 		nl_addr_set_prefixlen(addr, pl);
    448 	} else
    449 		nl_addr_set_prefixlen(addr, len * 8);
    450 
    451 	*result = addr;
    452 	err = 0;
    453 errout:
    454 	free(str);
    455 
    456 	return err;
    457 }
    458 
    459 /**
    460  * Clone existing abstract address object
    461  * @arg addr		Abstract address object
    462  *
    463  * Allocates new abstract address representing an identical clone of an
    464  * existing address.
    465  *
    466  * @see nl_addr_alloc()
    467  * @see nl_addr_put()
    468  *
    469  * @return Allocated abstract address or NULL upon failure.
    470  */
    471 struct nl_addr *nl_addr_clone(struct nl_addr *addr)
    472 {
    473 	struct nl_addr *new;
    474 
    475 	new = nl_addr_build(addr->a_family, addr->a_addr, addr->a_len);
    476 	if (new)
    477 		new->a_prefixlen = addr->a_prefixlen;
    478 
    479 	return new;
    480 }
    481 
    482 /** @} */
    483 
    484 /**
    485  * @name Managing Usage References
    486  * @{
    487  */
    488 
    489 /**
    490  * Increase the reference counter of an abstract address
    491  * @arg addr		Abstract address
    492  *
    493  * Increases the reference counter of the address and thus prevents the
    494  * release of the memory resources until the reference is given back
    495  * using the function nl_addr_put().
    496  *
    497  * @see nl_addr_put()
    498  *
    499  * @return Pointer to the existing abstract address
    500  */
    501 struct nl_addr *nl_addr_get(struct nl_addr *addr)
    502 {
    503 	addr->a_refcnt++;
    504 
    505 	return addr;
    506 }
    507 
    508 /**
    509  * Decrease the reference counter of an abstract address
    510  * @arg addr		Abstract addr
    511  *
    512  * @note The resources of the abstract address will be freed after the
    513  *       last reference to the address has been returned.
    514  *
    515  * @see nl_addr_get()
    516  */
    517 void nl_addr_put(struct nl_addr *addr)
    518 {
    519 	if (!addr)
    520 		return;
    521 
    522 	if (addr->a_refcnt == 1)
    523 		addr_destroy(addr);
    524 	else
    525 		addr->a_refcnt--;
    526 }
    527 
    528 /**
    529  * Check whether an abstract address is shared.
    530  * @arg addr		Abstract address object.
    531  *
    532  * @return Non-zero if the abstract address is shared, otherwise 0.
    533  */
    534 int nl_addr_shared(struct nl_addr *addr)
    535 {
    536 	return addr->a_refcnt > 1;
    537 }
    538 
    539 /** @} */
    540 
    541 /**
    542  * @name Miscellaneous
    543  * @{
    544  */
    545 
    546 /**
    547  * Compare abstract addresses
    548  * @arg a		An abstract address
    549  * @arg b		Another abstract address
    550  *
    551  * Verifies whether the address family, address length, prefix length, and
    552  * binary addresses of two abstract addresses matches.
    553  *
    554  * @note This function will *not* respect the prefix length in the sense
    555  *       that only the actual prefix will be compared. Please refer to the
    556  *       nl_addr_cmp_prefix() function if you require this functionality.
    557  *
    558  * @see nl_addr_cmp_prefix()
    559  *
    560  * @return Integer less than, equal to or greather than zero if the two
    561  *         addresses match.
    562  */
    563 int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
    564 {
    565 	int d = a->a_family - b->a_family;
    566 
    567 	if (d == 0) {
    568 		d = a->a_len - b->a_len;
    569 
    570 		if (a->a_len && d == 0) {
    571 			d = memcmp(a->a_addr, b->a_addr, a->a_len);
    572 
    573 			if (d == 0)
    574 				return (a->a_prefixlen - b->a_prefixlen);
    575 		}
    576 	}
    577 
    578 	return d;
    579 }
    580 
    581 /**
    582  * Compare the prefix of two abstract addresses
    583  * @arg a		An abstract address
    584  * @arg b		Another abstract address
    585  *
    586  * Verifies whether the address family and the binary address covered by
    587  * the smaller prefix length of the two abstract addresses matches.
    588  *
    589  * @see nl_addr_cmp()
    590  *
    591  * @return Integer less than, equal to or greather than zero if the two
    592  *         addresses match.
    593  */
    594 int nl_addr_cmp_prefix(struct nl_addr *a, struct nl_addr *b)
    595 {
    596 	int d = a->a_family - b->a_family;
    597 
    598 	if (d == 0) {
    599 		int len = min(a->a_prefixlen, b->a_prefixlen);
    600 		int bytes = len / 8;
    601 
    602 		d = memcmp(a->a_addr, b->a_addr, bytes);
    603 		if (d == 0 && (len % 8) != 0) {
    604 			int mask = (0xFF00 >> (len % 8)) & 0xFF;
    605 
    606 			d = (a->a_addr[bytes] & mask) -
    607 			    (b->a_addr[bytes] & mask);
    608 		}
    609 	}
    610 
    611 	return d;
    612 }
    613 
    614 /**
    615  * Returns true if the address consists of all zeros
    616  * @arg addr		Abstract address
    617  *
    618  * @return 1 if the binary address consists of all zeros, 0 otherwise.
    619  */
    620 int nl_addr_iszero(struct nl_addr *addr)
    621 {
    622 	unsigned int i;
    623 
    624 	for (i = 0; i < addr->a_len; i++)
    625 		if (addr->a_addr[i])
    626 			return 0;
    627 
    628 	return 1;
    629 }
    630 
    631 /**
    632  * Check if address string is parseable for a specific address family
    633  * @arg addr		Address represented as character string.
    634  * @arg family		Desired address family.
    635  *
    636  * @return 1 if the address is parseable assuming the specified address family,
    637  *         otherwise 0 is returned.
    638  */
    639 int nl_addr_valid(char *addr, int family)
    640 {
    641 	int ret;
    642 	char buf[32];
    643 
    644 	switch (family) {
    645 	case AF_INET:
    646 	case AF_INET6:
    647 		ret = inet_pton(family, addr, buf);
    648 		if (ret <= 0)
    649 			return 0;
    650 		break;
    651 
    652 	case AF_DECnet:
    653 		ret = dnet_pton(addr, buf);
    654 		if (ret <= 0)
    655 			return 0;
    656 		break;
    657 
    658 	case AF_LLC:
    659 		if (sscanf(addr, "%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6)
    660 			return 0;
    661 		break;
    662 	}
    663 
    664 	return 1;
    665 }
    666 
    667 /**
    668  * Guess address family of abstract address based on address size
    669  * @arg addr		Abstract address object.
    670  *
    671  * @return Numeric address family or AF_UNSPEC
    672  */
    673 int nl_addr_guess_family(struct nl_addr *addr)
    674 {
    675 	switch (addr->a_len) {
    676 		case 4:
    677 			return AF_INET;
    678 		case 6:
    679 			return AF_LLC;
    680 		case 16:
    681 			return AF_INET6;
    682 		default:
    683 			return AF_UNSPEC;
    684 	}
    685 }
    686 
    687 /**
    688  * Fill out sockaddr structure with values from abstract address object.
    689  * @arg addr		Abstract address object.
    690  * @arg sa		Destination sockaddr structure buffer.
    691  * @arg salen		Length of sockaddr structure buffer.
    692  *
    693  * Fills out the specified sockaddr structure with the data found in the
    694  * specified abstract address. The salen argument needs to be set to the
    695  * size of sa but will be modified to the actual size used during before
    696  * the function exits.
    697  *
    698  * @return 0 on success or a negative error code
    699  */
    700 int nl_addr_fill_sockaddr(struct nl_addr *addr, struct sockaddr *sa,
    701 			  socklen_t *salen)
    702 {
    703 	switch (addr->a_family) {
    704 	case AF_INET: {
    705 		struct sockaddr_in *sai = (struct sockaddr_in *) sa;
    706 
    707 		if (*salen < sizeof(*sai))
    708 			return -NLE_INVAL;
    709 
    710 		sai->sin_family = addr->a_family;
    711 		memcpy(&sai->sin_addr, addr->a_addr, 4);
    712 		*salen = sizeof(*sai);
    713 	}
    714 		break;
    715 
    716 	case AF_INET6: {
    717 		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa;
    718 
    719 		if (*salen < sizeof(*sa6))
    720 			return -NLE_INVAL;
    721 
    722 		sa6->sin6_family = addr->a_family;
    723 		memcpy(&sa6->sin6_addr, addr->a_addr, 16);
    724 		*salen = sizeof(*sa6);
    725 	}
    726 		break;
    727 
    728 	default:
    729 		return -NLE_INVAL;
    730 	}
    731 
    732 	return 0;
    733 }
    734 
    735 
    736 /** @} */
    737 
    738 /**
    739  * @name Getting Information About Addresses
    740  * @{
    741  */
    742 
    743 /**
    744  * Call getaddrinfo() for an abstract address object.
    745  * @arg addr		Abstract address object.
    746  * @arg result		Pointer to store resulting address list.
    747  *
    748  * Calls getaddrinfo() for the specified abstract address in AI_NUMERICHOST
    749  * mode.
    750  *
    751  * @note The caller is responsible for freeing the linked list using the
    752  *       interface provided by getaddrinfo(3).
    753  *
    754  * @return 0 on success or a negative error code.
    755  */
    756 int nl_addr_info(struct nl_addr *addr, struct addrinfo **result)
    757 {
    758 	int err;
    759 	char buf[INET6_ADDRSTRLEN+5];
    760 	struct addrinfo hint = {
    761 		.ai_flags = AI_NUMERICHOST,
    762 		.ai_family = addr->a_family,
    763 	};
    764 
    765 	nl_addr2str(addr, buf, sizeof(buf));
    766 
    767 	err = getaddrinfo(buf, NULL, &hint, result);
    768 	if (err != 0) {
    769 		switch (err) {
    770 		case EAI_ADDRFAMILY: return -NLE_AF_NOSUPPORT;
    771 		case EAI_AGAIN: return -NLE_AGAIN;
    772 		case EAI_BADFLAGS: return -NLE_INVAL;
    773 		case EAI_FAIL: return -NLE_NOADDR;
    774 		case EAI_FAMILY: return -NLE_AF_NOSUPPORT;
    775 		case EAI_MEMORY: return -NLE_NOMEM;
    776 		case EAI_NODATA: return -NLE_NOADDR;
    777 		case EAI_NONAME: return -NLE_OBJ_NOTFOUND;
    778 		case EAI_SERVICE: return -NLE_OPNOTSUPP;
    779 		case EAI_SOCKTYPE: return -NLE_BAD_SOCK;
    780 		default: return -NLE_FAILURE;
    781 		}
    782 	}
    783 
    784 	return 0;
    785 }
    786 
    787 /**
    788  * Resolve abstract address object to a name using getnameinfo().
    789  * @arg addr		Abstract address object.
    790  * @arg host		Destination buffer for host name.
    791  * @arg hostlen		Length of destination buffer.
    792  *
    793  * Resolves the abstract address to a name and writes the looked up result
    794  * into the host buffer. getnameinfo() is used to perform the lookup and
    795  * is put into NI_NAMEREQD mode so the function will fail if the lookup
    796  * couldn't be performed.
    797  *
    798  * @return 0 on success or a negative error code.
    799  */
    800 int nl_addr_resolve(struct nl_addr *addr, char *host, size_t hostlen)
    801 {
    802 	int err;
    803 	struct sockaddr_in6 buf;
    804 	socklen_t salen = sizeof(buf);
    805 
    806 	err = nl_addr_fill_sockaddr(addr, (struct sockaddr *) &buf, &salen);
    807 	if (err < 0)
    808 		return err;
    809 
    810 	err = getnameinfo((struct sockaddr *) &buf, salen, host, hostlen,
    811 			  NULL, 0, NI_NAMEREQD);
    812 	if (err < 0)
    813 		return nl_syserr2nlerr(err);
    814 
    815 	return 0;
    816 }
    817 
    818 /** @} */
    819 
    820 /**
    821  * @name Attributes
    822  * @{
    823  */
    824 
    825 /**
    826  * Set address family
    827  * @arg addr		Abstract address object
    828  * @arg family		Address family
    829  *
    830  * @see nl_addr_get_family()
    831  */
    832 void nl_addr_set_family(struct nl_addr *addr, int family)
    833 {
    834 	addr->a_family = family;
    835 }
    836 
    837 /**
    838  * Return address family
    839  * @arg addr		Abstract address object
    840  *
    841  * @see nl_addr_set_family()
    842  *
    843  * @return The numeric address family or `AF_UNSPEC`
    844  */
    845 int nl_addr_get_family(struct nl_addr *addr)
    846 {
    847 	return addr->a_family;
    848 }
    849 
    850 /**
    851  * Set binary address of abstract address object.
    852  * @arg addr		Abstract address object.
    853  * @arg buf		Buffer containing binary address.
    854  * @arg len		Length of buffer containing binary address.
    855  *
    856  * Modifies the binary address portion of the abstract address. The
    857  * abstract address must be capable of holding the required amount
    858  * or this function will fail.
    859  *
    860  * @note This function will *not* modify the prefix length. It is within
    861  *       the responsibility of the caller to set the prefix length to the
    862  *       desirable length.
    863  *
    864  * @see nl_addr_alloc()
    865  * @see nl_addr_get_binary_addr()
    866  * @see nl_addr_get_len()
    867  *
    868  * @return 0 on success or a negative error code.
    869  */
    870 int nl_addr_set_binary_addr(struct nl_addr *addr, void *buf, size_t len)
    871 {
    872 	if (len > addr->a_maxsize)
    873 		return -NLE_RANGE;
    874 
    875 	addr->a_len = len;
    876 	memset(addr->a_addr, 0, addr->a_maxsize);
    877 
    878 	if (len)
    879 		memcpy(addr->a_addr, buf, len);
    880 
    881 	return 0;
    882 }
    883 
    884 /**
    885  * Get binary address of abstract address object.
    886  * @arg addr		Abstract address object.
    887  *
    888  * @see nl_addr_set_binary_addr()
    889  * @see nl_addr_get_len()
    890  *
    891  * @return Pointer to binary address of length nl_addr_get_len()
    892  */
    893 void *nl_addr_get_binary_addr(struct nl_addr *addr)
    894 {
    895 	return addr->a_addr;
    896 }
    897 
    898 /**
    899  * Get length of binary address of abstract address object.
    900  * @arg addr		Abstract address object.
    901  *
    902  * @see nl_addr_get_binary_addr()
    903  * @see nl_addr_set_binary_addr()
    904  */
    905 unsigned int nl_addr_get_len(struct nl_addr *addr)
    906 {
    907 	return addr->a_len;
    908 }
    909 
    910 /**
    911  * Set the prefix length of an abstract address
    912  * @arg addr		Abstract address object
    913  * @arg prefixlen	New prefix length
    914  *
    915  * @see nl_addr_get_prefixlen()
    916  */
    917 void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
    918 {
    919 	addr->a_prefixlen = prefixlen;
    920 }
    921 
    922 /**
    923  * Return prefix length of abstract address object.
    924  * @arg addr		Abstract address object
    925  *
    926  * @see nl_addr_set_prefixlen()
    927  */
    928 unsigned int nl_addr_get_prefixlen(struct nl_addr *addr)
    929 {
    930 	return addr->a_prefixlen;
    931 }
    932 
    933 /** @} */
    934 
    935 /**
    936  * @name Translations to Strings
    937  * @{
    938  */
    939 
    940 /**
    941  * Convert abstract address object to character string.
    942  * @arg addr		Abstract address object.
    943  * @arg buf		Destination buffer.
    944  * @arg size		Size of destination buffer.
    945  *
    946  * Converts an abstract address to a character string and stores
    947  * the result in the specified destination buffer.
    948  *
    949  * @return Address represented in ASCII stored in destination buffer.
    950  */
    951 char *nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
    952 {
    953 	unsigned int i;
    954 	char tmp[16];
    955 
    956 	if (!addr || !addr->a_len) {
    957 		snprintf(buf, size, "none");
    958 		if (addr)
    959 			goto prefix;
    960 		else
    961 			return buf;
    962 	}
    963 
    964 	switch (addr->a_family) {
    965 		case AF_INET:
    966 			inet_ntop(AF_INET, addr->a_addr, buf, size);
    967 			break;
    968 
    969 		case AF_INET6:
    970 			inet_ntop(AF_INET6, addr->a_addr, buf, size);
    971 			break;
    972 
    973 		case AF_DECnet:
    974 			dnet_ntop(addr->a_addr, addr->a_len, buf, size);
    975 			break;
    976 
    977 		case AF_LLC:
    978 		default:
    979 			snprintf(buf, size, "%02x",
    980 				 (unsigned char) addr->a_addr[0]);
    981 			for (i = 1; i < addr->a_len; i++) {
    982 				snprintf(tmp, sizeof(tmp), ":%02x",
    983 					 (unsigned char) addr->a_addr[i]);
    984 				strncat(buf, tmp, size - strlen(buf) - 1);
    985 			}
    986 			break;
    987 	}
    988 
    989 prefix:
    990 	if (addr->a_prefixlen != (8 * addr->a_len)) {
    991 		snprintf(tmp, sizeof(tmp), "/%u", addr->a_prefixlen);
    992 		strncat(buf, tmp, size - strlen(buf) - 1);
    993 	}
    994 
    995 	return buf;
    996 }
    997 
    998 /** @} */
    999 
   1000 /**
   1001  * @name Address Family Transformations
   1002  * @{
   1003  */
   1004 
   1005 static const struct trans_tbl afs[] = {
   1006 	__ADD(AF_UNSPEC,unspec)
   1007 	__ADD(AF_UNIX,unix)
   1008 	__ADD(AF_INET,inet)
   1009 	__ADD(AF_AX25,ax25)
   1010 	__ADD(AF_IPX,ipx)
   1011 	__ADD(AF_APPLETALK,appletalk)
   1012 	__ADD(AF_NETROM,netrom)
   1013 	__ADD(AF_BRIDGE,bridge)
   1014 	__ADD(AF_ATMPVC,atmpvc)
   1015 	__ADD(AF_X25,x25)
   1016 	__ADD(AF_INET6,inet6)
   1017 	__ADD(AF_ROSE,rose)
   1018 	__ADD(AF_DECnet,decnet)
   1019 	__ADD(AF_NETBEUI,netbeui)
   1020 	__ADD(AF_SECURITY,security)
   1021 	__ADD(AF_KEY,key)
   1022 	__ADD(AF_NETLINK,netlink)
   1023 	__ADD(AF_PACKET,packet)
   1024 	__ADD(AF_ASH,ash)
   1025 	__ADD(AF_ECONET,econet)
   1026 	__ADD(AF_ATMSVC,atmsvc)
   1027 #ifdef AF_RDS
   1028 	__ADD(AF_RDS,rds)
   1029 #endif
   1030 	__ADD(AF_SNA,sna)
   1031 	__ADD(AF_IRDA,irda)
   1032 	__ADD(AF_PPPOX,pppox)
   1033 	__ADD(AF_WANPIPE,wanpipe)
   1034 	__ADD(AF_LLC,llc)
   1035 #ifdef AF_CAN
   1036 	__ADD(AF_CAN,can)
   1037 #endif
   1038 #ifdef AF_TIPC
   1039 	__ADD(AF_TIPC,tipc)
   1040 #endif
   1041 	__ADD(AF_BLUETOOTH,bluetooth)
   1042 #ifdef AF_IUCV
   1043 	__ADD(AF_IUCV,iucv)
   1044 #endif
   1045 #ifdef AF_RXRPC
   1046 	__ADD(AF_RXRPC,rxrpc)
   1047 #endif
   1048 #ifdef AF_ISDN
   1049 	__ADD(AF_ISDN,isdn)
   1050 #endif
   1051 #ifdef AF_PHONET
   1052 	__ADD(AF_PHONET,phonet)
   1053 #endif
   1054 #ifdef AF_IEEE802154
   1055 	__ADD(AF_IEEE802154,ieee802154)
   1056 #endif
   1057 #ifdef AF_CAIF
   1058 	__ADD(AF_CAIF,caif)
   1059 #endif
   1060 #ifdef AF_ALG
   1061 	__ADD(AF_ALG,alg)
   1062 #endif
   1063 #ifdef AF_NFC
   1064 	__ADD(AF_NFC,nfc)
   1065 #endif
   1066 };
   1067 
   1068 char *nl_af2str(int family, char *buf, size_t size)
   1069 {
   1070 	return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
   1071 }
   1072 
   1073 int nl_str2af(const char *name)
   1074 {
   1075 	int fam = __str2type(name, afs, ARRAY_SIZE(afs));
   1076 	return fam >= 0 ? fam : -EINVAL;
   1077 }
   1078 
   1079 /** @} */
   1080 
   1081 /** @} */
   1082