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