libnl  3.2.24-rc1
addr.c
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. */
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 
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 
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 
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 
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 
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 
1068 char *nl_af2str(int family, char *buf, size_t size)
1069 {
1070  return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
1071 }
1072 
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 /** @} */