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