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