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