libnl 3.9.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 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
447prefix:
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;
477errout:
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 */
495struct 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 */
525struct 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 */
541void 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 */
558int 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 */
587int 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 */
626int 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 */
652int 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 */
671int 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 */
711int 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 */
738int 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 */
806int 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 */
850int 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 */
882void 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 */
895int 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 */
920int 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 */
943void *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 */
955unsigned 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 */
967void 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 */
978unsigned 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 */
1001char *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
1043prefix:
1044 if (addr->a_family != AF_MPLS &&
1045 addr->a_prefixlen != (8 * addr->a_len)) {
1046 snprintf(tmp, sizeof(tmp), "/%u", 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
1060static 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
1127char *nl_af2str(int family, char *buf, size_t size)
1128{
1129 return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
1130}
1131
1132int 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/** @} */
int nl_addr_info(const struct nl_addr *addr, struct addrinfo **result)
Call getaddrinfo() for an abstract address object.
Definition addr.c:806
int nl_addr_iszero(const struct nl_addr *addr)
Returns true if the address consists of all zeros.
Definition addr.c:652
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:738
void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
Set the prefix length of an abstract address.
Definition addr.c:967
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
Definition addr.c:525
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:850
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
Definition addr.c:943
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
Definition addr.c:587
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:495
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:920
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.
Definition addr.c:895
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:626
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition addr.c:1001
int nl_addr_valid(const char *addr, int family)
Check if address string is parseable for a specific address family.
Definition addr.c:671
unsigned int nl_addr_get_prefixlen(const struct nl_addr *addr)
Return prefix length of abstract address object.
Definition addr.c:978
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
Definition addr.c:955
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition addr.c:541
void nl_addr_set_family(struct nl_addr *addr, int family)
Set address family.
Definition addr.c:882
int nl_addr_shared(const struct nl_addr *addr)
Check whether an abstract address is shared.
Definition addr.c:558
int nl_addr_guess_family(const struct nl_addr *addr)
Guess address family of abstract address based on address size.
Definition addr.c:711
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