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