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