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