• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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. */
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(char * addrbuf,size_t addrlen,char * str,size_t len)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 
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,void * buf,size_t size)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  */
nl_addr_alloc_attr(struct nlattr * nla,int family)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  */
nl_addr_parse(const char * addrstr,int hint,struct nl_addr ** result)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  */
nl_addr_clone(struct nl_addr * addr)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  */
nl_addr_get(struct nl_addr * addr)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  */
nl_addr_put(struct nl_addr * addr)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  */
nl_addr_shared(struct nl_addr * addr)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  */
nl_addr_cmp(struct nl_addr * a,struct nl_addr * b)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  */
nl_addr_cmp_prefix(struct nl_addr * a,struct nl_addr * b)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  */
nl_addr_iszero(struct nl_addr * addr)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  */
nl_addr_valid(char * addr,int family)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  */
nl_addr_guess_family(struct nl_addr * addr)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  */
nl_addr_fill_sockaddr(struct nl_addr * addr,struct sockaddr * sa,socklen_t * salen)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  */
nl_addr_info(struct nl_addr * addr,struct addrinfo ** result)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  */
nl_addr_resolve(struct nl_addr * addr,char * host,size_t hostlen)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  */
nl_addr_set_family(struct nl_addr * addr,int family)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  */
nl_addr_get_family(struct nl_addr * addr)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  */
nl_addr_set_binary_addr(struct nl_addr * addr,void * buf,size_t len)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  */
nl_addr_get_binary_addr(struct nl_addr * addr)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  */
nl_addr_get_len(struct nl_addr * addr)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  */
nl_addr_set_prefixlen(struct nl_addr * addr,int prefixlen)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  */
nl_addr_get_prefixlen(struct nl_addr * addr)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  */
nl_addr2str(struct nl_addr * addr,char * buf,size_t size)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 
nl_af2str(int family,char * buf,size_t size)1068 char *nl_af2str(int family, char *buf, size_t size)
1069 {
1070 	return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
1071 }
1072 
nl_str2af(const char * name)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