The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
inet.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License, version 2 of the
4  * License as published by the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License
12  * along with this program; if not, write to the Free Software
13  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
14  */
15 
16 /** Functions for parsing, printing, masking and retrieving IP addresses
17  *
18  * @file src/lib/util/inet.c
19  *
20  * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
21  * @copyright 2015 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
22  */
23 #include <freeradius-devel/util/inet.h>
24 #include <freeradius-devel/util/misc.h>
25 #include <freeradius-devel/util/strerror.h>
26 #include <freeradius-devel/util/syserror.h>
27 #include <freeradius-devel/util/value.h>
28 
29 #include <stdlib.h>
30 #include <ifaddrs.h>
31 #include <net/if_arp.h>
32 
33 /*
34  * Linux
35  */
36 #if defined(HAVE_LINUX_IF_PACKET_H)
37 # include <linux/if_packet.h>
38 # include <linux/if_ether.h>
39 /*
40  * Apple, *BSD
41  */
42 #elif defined(HAVE_NET_IF_DL_H)
43 # include <net/if_dl.h> /* Needed for struct sockaddr_ll def */
44 /*
45  * emscripten/musl
46  */
47 #elif defined(HAVE_NETPACKET_PACKET_H)
48 # include <netpacket/packet.h> /* Needed for struct sockaddr_ll def */
49 #endif
50 
51 bool fr_reverse_lookups = false; //!< IP -> hostname lookups?
52 bool fr_hostname_lookups = true; //!< hostname -> IP lookups?
53 
54 /** Determine if an address is the INADDR_ANY address for its address family
55  *
56  * @param ipaddr to check.
57  * @return
58  * - 0 if it's not.
59  * - 1 if it is.
60  * - -1 on error.
61  */
63 {
64 
65  if (ipaddr->af == AF_INET) {
66  if (ipaddr->addr.v4.s_addr == htonl(INADDR_ANY)) {
67  return 1;
68  }
69 
70 #ifdef HAVE_STRUCT_SOCKADDR_IN6
71  } else if (ipaddr->af == AF_INET6) {
72  /* Unconst for emscripten/musl */
73  if (IN6_IS_ADDR_UNSPECIFIED(UNCONST(struct in6_addr *, &(ipaddr->addr.v6)))) {
74  return 1;
75  }
76 #endif
77 
78  } else {
79  fr_strerror_const("Unknown address family");
80  return -1;
81  }
82 
83  return 0;
84 }
85 
86 /** Determine if an address is a multicast address
87  *
88  * @param ipaddr to check.
89  * @return
90  * - 0 if it's not.
91  * - 1 if it is.
92  * - -1 on error.
93  */
95 {
96  if (ipaddr->af == AF_INET) {
97  /*
98  * 224.0.0.0 (3758096384) - 239.255.255.255 (4026531839)
99  */
100  if ((ipaddr->addr.v4.s_addr >= 3758096384) && (ipaddr->addr.v4.s_addr <= 4026531839)) return 1;
101 #ifdef HAVE_STRUCT_SOCKADDR_IN6
102  } else if (ipaddr->af == AF_INET6) {
103  /* Unconst for emscripten/musl */
104  if (IN6_IS_ADDR_MULTICAST(UNCONST(struct in6_addr *, &(ipaddr->addr.v6)))) {
105  return 1;
106  }
107 #endif
108 
109  } else {
110  fr_strerror_const("Unknown address family");
111  return -1;
112  }
113 
114  return 0;
115 }
116 
117 /** Determine if an address is a prefix
118  *
119  * @param ipaddr to check.
120  * @return
121  * - 0 if it's not.
122  * - 1 if it is.
123  * - -1 on error.
124  */
126 {
127  switch (ipaddr->af) {
128  case AF_INET:
129  return (ipaddr->prefix < 32);
130 
131  case AF_INET6:
132  return (ipaddr->prefix < 128);
133 
134  default:
135  fr_strerror_const("Unknown address family");
136  return -1;
137  }
138 }
139 
140 /** Mask off a portion of an IPv4 address
141  *
142  * @param ipaddr to mask.
143  * @param prefix Number of contiguous bits to mask.
144  * @return an ipv4 address with the host portion zeroed out.
145  */
146 static struct in_addr fr_inaddr_mask(struct in_addr const *ipaddr, uint8_t prefix)
147 {
148  uint32_t ret;
149 
150  if (prefix > 32) prefix = 32;
151 
152  /* Short circuit */
153  if (prefix == 32) return *ipaddr;
154 
155  if (prefix == 0) ret = 0;
156  else ret = htonl(~((0x00000001UL << (32 - prefix)) - 1)) & ipaddr->s_addr;
157 
158  return (*(struct in_addr *)&ret);
159 }
160 
161 /** Mask off a portion of an IPv6 address
162  *
163  * @param ipaddr to mask.
164  * @param prefix Number of contiguous bits to mask.
165  * @return an ipv6 address with the host portion zeroed out.
166  */
167 static struct in6_addr fr_in6addr_mask(struct in6_addr const *ipaddr, uint8_t prefix)
168 {
169  uint64_t const *p = (uint64_t const *) ipaddr;
170  uint64_t addr; /* Needed for alignment */
171  uint64_t ret[2], *o = ret;
172 
173  if (prefix > 128) prefix = 128;
174 
175  /* Short circuit */
176  if (prefix == 128) return *ipaddr;
177 
178  if (prefix >= 64) {
179  prefix -= 64;
180  memcpy(&addr, p, sizeof(addr)); /* Needed for aligned access (ubsan) */
181  *o++ = 0xffffffffffffffffULL & addr; /* lhs portion masked */
182  p++;
183  } else {
184  ret[1] = 0; /* rhs portion zeroed */
185  }
186 
187  /* Max left shift is 63 else we get overflow */
188  if (prefix > 0) {
189  memcpy(&addr, p, sizeof(addr)); /* Needed for aligned access (ubsan) */
190  *o = htonll(~((uint64_t)(0x0000000000000001ULL << (64 - prefix)) - 1)) & addr;
191  } else {
192  *o = 0;
193  }
194 
195  return *(struct in6_addr *) &ret;
196 }
197 
198 /** Zeroes out the host portion of an fr_ipaddr_t
199  *
200  * @param[in,out] addr to mask
201  * @param[in] prefix Length of the network portion.
202  */
203 void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
204 {
205 
206  switch (addr->af) {
207  case AF_INET:
208  addr->addr.v4 = fr_inaddr_mask(&addr->addr.v4, prefix);
209  break;
210 
211  case AF_INET6:
212  addr->addr.v6 = fr_in6addr_mask(&addr->addr.v6, prefix);
213  break;
214 
215  default:
216  return;
217  }
218  addr->prefix = prefix;
219 }
220 
221 /** Wrappers for IPv4/IPv6 host to IP address lookup
222  *
223  * This function returns only one IP address, of the specified address family,
224  * or the first address (of whatever family), if AF_UNSPEC is used.
225  *
226  * If fallback is specified and af is AF_INET, but not AF_INET records were
227  * found and a record for AF_INET6 exists that record will be returned.
228  *
229  * If fallback is specified and af is AF_INET6, and a record with AF_INET4 exists
230  * that record will be returned inserted.
231  *
232  * @param[out] out Where to write result.
233  * @param[in] af To search for in preference.
234  * @param[in] hostname to search for.
235  * @param[in] fallback to the other address family, if no records matching af, found.
236  * @return
237  * - 0 on success.
238  * - -1 on failure.
239  */
240 int fr_inet_hton(fr_ipaddr_t *out, int af, char const *hostname, bool fallback)
241 {
242  int ret;
243  struct addrinfo hints, *ai = NULL, *alt = NULL, *res = NULL;
244 
245  /*
246  * Avoid alloc for IP addresses. This helps us debug
247  * memory errors when using talloc.
248  */
249  if (!fr_hostname_lookups) {
250 #ifdef HAVE_STRUCT_SOCKADDR_IN6
251  if (af == AF_UNSPEC) {
252  char const *p;
253 
254  for (p = hostname; *p != '\0'; p++) {
255  if ((*p == ':') ||
256  (*p == '[') ||
257  (*p == ']')) {
258  af = AF_INET6;
259  break;
260  }
261  }
262  }
263 #endif
264 
265  if (af == AF_UNSPEC) af = AF_INET;
266 
267  if (inet_pton(af, hostname, &(out->addr)) == 0) {
268  fr_strerror_printf("\"%s\" is not a valid IP address and "
269  "hostname lookups are disabled", hostname);
270  return -1;
271  }
272  out->af = af;
273  out->prefix = 32;
274  out->scope_id = 0;
275 
276  return 0;
277  }
278 
279  memset(&hints, 0, sizeof(hints));
280 
281  /*
282  * If we're falling back we need both IPv4 and IPv6 records
283  */
284  if (fallback) {
285  hints.ai_family = AF_UNSPEC;
286  } else {
287  hints.ai_family = af;
288  }
289 
290  if ((ret = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
291  switch (af) {
292  default:
293  case AF_UNSPEC:
294  fr_strerror_printf("Failed resolving \"%s\" to IP address: %s",
295  hostname, gai_strerror(ret));
296  return -1;
297 
298  case AF_INET:
299  fr_strerror_printf("Failed resolving \"%s\" to IPv4 address: %s",
300  hostname, gai_strerror(ret));
301  return -1;
302 
303  case AF_INET6:
304  fr_strerror_printf("Failed resolving \"%s\" to IPv6 address: %s",
305  hostname, gai_strerror(ret));
306  return -1;
307  }
308  }
309 
310  for (ai = res; ai; ai = ai->ai_next) {
311  if ((af == ai->ai_family) || (af == AF_UNSPEC)) break;
312  if (!alt && fallback && ((ai->ai_family == AF_INET) || (ai->ai_family == AF_INET6))) alt = ai;
313  }
314 
315  if (!ai) ai = alt;
316  if (!ai) {
317  fr_strerror_printf("Failed resolving \"%s\": No records matching requested address family returned",
318  hostname);
319  freeaddrinfo(res);
320  return -1;
321  }
322 
323  ret = fr_ipaddr_from_sockaddr(out, NULL, (struct sockaddr_storage *)ai->ai_addr, ai->ai_addrlen);
324  freeaddrinfo(res);
325  if (ret < 0) {
326  fr_strerror_const("Failed converting sockaddr to ipaddr");
327  return -1;
328  }
329 
330  return 0;
331 }
332 
333 /** Perform reverse resolution of an IP address
334  *
335  * Attempt to resolve an IP address to a DNS record (if dns lookups are enabled).
336  *
337  * @param[in] src address to resolve.
338  * @param[out] out Where to write the resulting hostname.
339  * @param[in] outlen length of the output buffer.
340  */
341 char const *fr_inet_ntoh(fr_ipaddr_t const *src, char *out, size_t outlen)
342 {
343  struct sockaddr_storage ss;
344  int error;
345  socklen_t salen;
346 
347  /*
348  * No DNS lookups
349  */
350  if (!fr_reverse_lookups) {
351  return inet_ntop(src->af, &(src->addr), out, outlen);
352  }
353 
354  if (fr_ipaddr_to_sockaddr(&ss, &salen, src, 0) < 0) return NULL;
355 
356  if ((error = getnameinfo((struct sockaddr *)&ss, salen, out, outlen, NULL, 0,
357  NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
358  fr_strerror_printf("fr_inet_ntoh: %s", gai_strerror(error));
359  return NULL;
360  }
361  return out;
362 }
363 
364 
365 /** Parse a single octet of an IPv4 address string
366  *
367  * @param[out] out Where to write integer.
368  * @param[in] str to parse.
369  * @return
370  * - >= 0 on success (number of bytes parsed of in).
371  * - < 0 on error.
372  */
373 static int ip_octet_from_str(uint32_t *out, char const *str)
374 {
375  uint32_t octet;
376  char const *p = str;
377 
378  if ((*p < '0') || (*p > '9')) return -1;
379 
380  octet = 0;
381 
382  while ((*p >= '0') && (*p <= '9')) {
383  octet *= 10;
384  octet += *p - '0';
385  p++;
386 
387  if (octet > 255) return -1;
388  }
389 
390  *out = octet;
391  return p - str;
392 }
393 
394 /** Parses the network portion of an IPv4 prefix into an in_addr
395  *
396  * @note output is in network order.
397  *
398  * Parses address strings in dotted quad notation.
399  * Unlike inet_pton allows octets to be omitted, in which case their value is considered to be 0.
400  * Unlike inet_aton treats integers as representing the highest octet of an IPv4 address, and
401  * limits them to 255.
402  *
403  * Examples of acceptable strings:
404  * - 192.168.0.0
405  * - 192.168.0.0/24
406  * - 192.168/16
407  * - 192
408  * - 192/8
409  *
410  * @param[out] out Where to write parsed address.
411  * @param[in] str to parse.
412  * @return
413  * - >= 0 on success (number of bytes parsed of in).
414  * - < 0 on error.
415  */
416 static int ip_prefix_addr_from_str(struct in_addr *out, char const *str)
417 {
418  int shift, length;
419  uint32_t octet;
420  uint32_t addr;
421  char const *p = str;
422 
423  addr = 0;
424  out->s_addr = 0;
425 
426  for (shift = 24; shift >= 0; shift -= 8) {
427  length = ip_octet_from_str(&octet, p);
428  if (length <= 0) return -1;
429 
430  addr |= octet << shift;
431  p += length;
432 
433  /*
434  * EOS or / means we're done.
435  */
436  if (!*p || (*p == '/')) break;
437 
438  /*
439  * We require dots between octets.
440  */
441  if (*p != '.') return -1;
442  p++;
443  }
444 
445  out->s_addr = htonl(addr);
446  return p - str;
447 }
448 
449 /** Parse an IPv4 address or IPv4 prefix in presentation format (and others)
450  *
451  * @param[out] out Where to write the ip address value.
452  * @param[in] value to parse, may be:
453  * - dotted quad [+ prefix]
454  * - integer
455  * - octal number
456  * - '*' (INADDR_ANY)
457  * - FQDN if resolve is true.
458  * @param[in] inlen Length of value, if value is \0 terminated inlen may be -1.
459  * @param[in] resolve If true and value doesn't look like an IP address, try and resolve value as a hostname.
460  * @param[in] fallback to IPv6 resolution if no A records can be found.
461  * @param[in] mask_bits If true, set address bits to zero.
462  * @return
463  * - 0 if ip address was parsed successfully.
464  * - -1 on failure.
465  */
466 int fr_inet_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback, bool mask_bits)
467 {
468  char *p;
469  unsigned int mask;
470  char const *end;
471  char *eptr;
472  char buffer[256]; /* As per RFC1035 */
473  int ret;
474 
475  /*
476  * Zero out output so we don't have invalid fields
477  * like scope_id hanging around with garbage values.
478  */
479  memset(out, 0, sizeof(*out));
480 
481  end = value + inlen;
482  while ((value < end) && isspace((uint8_t) *value)) value++;
483  if (value == end) {
484  fr_strerror_const("Empty IPv4 address string is invalid");
485  return -1;
486  }
487  inlen = end - value;
488 
489  /*
490  * Copy to intermediary buffer if we were given a length
491  */
492  if (inlen >= 0) {
493  if (inlen >= (ssize_t)sizeof(buffer)) {
494  fr_strerror_printf("Invalid IPv4 address string \"%pV\"", fr_box_strvalue_len(value, inlen));
495  return -1;
496  }
497  memcpy(buffer, value, inlen);
498  buffer[inlen] = '\0';
499  value = buffer;
500  }
501 
502  p = strchr(value, '/');
503 
504  /*
505  * 192.0.2.2 is parsed as if it was /32
506  */
507  if (!p) {
508  out->prefix = 32;
509  out->af = AF_INET;
510 
511  /*
512  * Allow '*' as the wildcard address usually 0.0.0.0
513  */
514  if ((value[0] == '*') && (value[1] == '\0')) {
515  out->addr.v4.s_addr = htonl(INADDR_ANY);
516 
517  /*
518  * Convert things which are obviously integers to IP addresses
519  *
520  * We assume the number is the bigendian representation of the
521  * IP address.
522  */
523  } else if (is_integer(value) || ((value[0] == '0') && (value[1] == 'x'))) {
524  out->addr.v4.s_addr = htonl(strtoul(value, NULL, 0));
525 
526  } else if (!resolve) {
527  unsigned int a, b, c, d;
528  int num;
529  char rest;
530 
531  a = b = c = d = 0;
532 
533  num = sscanf(value, "%u.%u.%u.%u%c", &a, &b, &c, &d, &rest);
534  if ((num == 0) || (num == 5) ||
535  (a > 255) || (b > 255) || (c > 255) || (d > 255)) {
536  fr_strerror_printf("Failed to parse IPv4 address string \"%s\"", value);
537  return -1;
538  }
539 
540  out->addr.v4.s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d);
541 
542  } else if (fr_inet_hton(out, AF_INET, value, fallback) < 0) return -1;
543 
544  return 0;
545  }
546 
547  /*
548  * Otherwise parse the prefix
549  */
550  if ((size_t)(p - value) >= INET_ADDRSTRLEN) {
551  fr_strerror_printf("Invalid IPv4 address string \"%s\"", value);
552  return -1;
553  }
554 
555  /*
556  * Copy the IP portion into a temporary buffer if we haven't already.
557  */
558  if (inlen < 0) memcpy(buffer, value, p - value);
559 
560  /*
561  * We need a special function here, as inet_pton doesn't like
562  * address strings with octets omitted, and inet_aton treats
563  * 127 as an integer value, and sets the lowest octet of the
564  * prefix to 127 instead of the highest.
565  *
566  * @todo we should allow hostnames to be parsed as prefixes.
567  */
568  buffer[p - value] = '\0';
569  ret = ip_prefix_addr_from_str(&out->addr.v4, buffer);
570  buffer[p - value] = '/'; /* Set back to '/' to produce proper errors */
571 
572  if (ret <= 0) {
573  fr_strerror_printf("Failed to parse IPv4 prefix string \"%s\"", value);
574  return -1;
575  }
576 
577  mask = strtoul(p + 1, &eptr, 10);
578  if (mask > 32) {
579  fr_strerror_printf("Invalid IPv4 mask length \"%s\". Should be between 0-32", p);
580  return -1;
581  }
582 
583  if (eptr[0] != '\0') {
584  fr_strerror_printf("Failed to parse IPv4 prefix string \"%s\", "
585  "got garbage after mask length \"%s\"", value, eptr);
586  return -1;
587  }
588 
589  if (mask_bits && (mask < 32)) {
590  out->addr.v4 = fr_inaddr_mask(&out->addr.v4, mask);
591  }
592 
593  out->prefix = (uint8_t) mask;
594  out->af = AF_INET;
595 
596  return 0;
597 }
598 
599 /** Parse an IPv6 address or IPv6 prefix in presentation format (and others)
600  *
601  * @param[out] out Where to write the ip address value.
602  * @param[in] value to parse, may be:
603  * - IPv6 hexits [+ prefix].
604  * - '*' wildcard.
605  * - FQDN if resolve is true.
606  * @param[in] inlen Length of value, if value is \0 terminated inlen may be -1.
607  * @param[in] resolve If true and value doesn't look like an IP address,
608  * try and resolve value as a hostname.
609  * @param[in] fallback to IPv4 resolution if no AAAA records can be found.
610  * @param[in] mask If true, set address bits to zero.
611  * @return
612  * - 0 if ip address was parsed successfully.
613  * - -1 on failure.
614  */
615 int fr_inet_pton6(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback, bool mask)
616 {
617  char *p;
618  char const *end;
619  unsigned int prefix;
620  char *eptr;
621  char buffer[256]; /* As per RFC1035 */
622  int ret;
623 
624  /*
625  * Zero out output so we don't have fields
626  * like scope_id hanging around with garbage values.
627  */
628  memset(out, 0, sizeof(*out));
629 
630  if (inlen < 0) inlen = strlen(value);
631 
632  end = value + inlen;
633  while ((value < end) && isspace((uint8_t) *value)) value++;
634  if (value == end) {
635  fr_strerror_const("Empty IPv6 address string is invalid");
636  return -1;
637  }
638  inlen = end - value; /* always >0 due to the above check for value==end */
639 
640  /*
641  * Copy to intermediary buffer.
642  */
643  if (inlen >= (ssize_t)sizeof(buffer)) {
644  fr_strerror_printf("Invalid IPv6 address string \"%pV\"", fr_box_strvalue_len(value, inlen));
645  return -1;
646  }
647 
648  memcpy(buffer, value, inlen);
649  buffer[inlen] = '\0';
650  value = buffer;
651 
652  p = strchr(value, '/');
653  if (!p) {
654  out->prefix = 128;
655  out->af = AF_INET6;
656 
657  /*
658  * Allow scopes for non-prefix values.
659  */
660  p = strchr(value, '%');
661  if (p) *(p++) = '\0';
662 
663  /*
664  * Allow '*' as the wildcard address
665  */
666  if ((value[0] == '*') && (value[1] == '\0')) {
667  out->addr.v6 = (struct in6_addr)IN6ADDR_ANY_INIT;
668  } else if (!resolve) {
669  if (inet_pton(AF_INET6, value, out->addr.v6.s6_addr) <= 0) {
670  fr_strerror_printf("Failed to parse IPv6 address string \"%s\"", value);
671  return -1;
672  }
673  } else if (fr_inet_hton(out, AF_INET6, value, fallback) < 0) return -1;
674 
675  /*
676  * No scope, or just '%'. That's fine.
677  */
678  if (!p || !*p) return 0;
679 
680  /*
681  * Parse scope.
682  */
683  prefix = strtoul(p, &eptr, 10);
684  if (prefix > UINT32_MAX) {
685  fr_strerror_printf("Invalid scope ID \"%s\". Should be between 0-2^32-1", p);
686  return -1;
687  }
688  if (eptr[0] != '\0') {
689  fr_strerror_printf("Failed to parse scope \"%s\", "
690  "got garbage after numerical scope value \"%s\"", p, eptr);
691  return -1;
692  }
693 
694  return 0;
695  }
696 
697  if ((p - value) >= INET6_ADDRSTRLEN) {
698  fr_strerror_printf("Invalid IPv6 address string \"%s\"", value);
699  return -1;
700  }
701 
702  /*
703  * Copy string to temporary buffer if we didn't do it earlier
704  */
705  if (inlen < 0) memcpy(buffer, value, p - value);
706 
707  if (!resolve) {
708  buffer[p - value] = '\0';
709  ret = inet_pton(AF_INET6, buffer, out->addr.v6.s6_addr);
710  buffer[p - value] = '/';
711  if (ret <= 0) {
712  fr_strerror_printf("Failed to parse IPv6 address string \"%s\"", value);
713  return -1;
714  }
715  } else {
716  buffer[p - value] = '\0';
717  ret = fr_inet_hton(out, AF_INET6, buffer, fallback);
718  buffer[p - value] = '/';
719  if (ret < 0) return -1;
720  }
721 
722  prefix = strtoul(p + 1, &eptr, 10);
723  if (prefix > 128) {
724  fr_strerror_printf("Invalid IPv6 mask length \"%s\". Should be between 0-128", p);
725  return -1;
726  }
727  if (eptr[0] != '\0') {
728  fr_strerror_printf("Failed to parse IPv6 address string \"%s\", "
729  "got garbage after mask length \"%s\"", value, eptr);
730  return -1;
731  }
732 
733  if (mask && (prefix < 128)) {
734  struct in6_addr addr;
735 
736  addr = fr_in6addr_mask(&out->addr.v6, prefix);
737  memcpy(out->addr.v6.s6_addr, addr.s6_addr, sizeof(out->addr.v6.s6_addr));
738  }
739 
740  out->af = AF_INET6;
741  out->prefix = (uint8_t) prefix;
742 
743  return 0;
744 }
745 
746 /** Simple wrapper to decide whether an IP value is v4 or v6 and call the appropriate parser
747  *
748  * @param[out] out Where to write the ip address value.
749  * @param[in] value to parse.
750  * @param[in] inlen Length of value, if value is \0 terminated inlen may be -1.
751  * @param[in] resolve If true and value doesn't look like an IP address, try and resolve value
752  * as a hostname.
753  * @param[in] af If the address type is not obvious from the format, and resolve is true,
754  * the DNS record (A or AAAA) we require. Also controls which parser we pass
755  * the address to if we have no idea what it is.
756  * - AF_UNSPEC - Use the server default IP family.
757  * - AF_INET - Treat value as an IPv4 address.
758  * - AF_INET6 - Treat value as in IPv6 address.
759  * @param[in] mask If true, set address bits to zero.
760  * @return
761  * - 0 if ip address was parsed successfully.
762  * - -1 on failure.
763  */
764 int fr_inet_pton(fr_ipaddr_t *out, char const *value, ssize_t inlen, int af, bool resolve, bool mask)
765 {
766  size_t len, i;
767  bool hostname = true;
768  bool ipv4 = true;
769  bool ipv6 = true;
770  char const *end;
771 
772  end = value + inlen;
773  while ((value < end) && isspace((uint8_t) *value)) value++;
774  if (value == end) {
775  fr_strerror_const("Empty IPv4 address string is invalid");
776  return -1;
777  }
778  inlen = end - value;
779 
780  len = (inlen >= 0) ? (size_t)inlen : strlen(value);
781 
782  for (i = 0; i < len; i++) {
783  /*
784  * These are valid for IPv4, IPv6, and host names.
785  */
786  if ((value[i] >= '0') && (value[i] <= '9')) {
787  continue;
788  }
789 
790  /*
791  * These are invalid for IPv4, but OK for IPv6
792  * and host names.
793  */
794  if ((value[i] >= 'a') && (value[i] <= 'f')) {
795  ipv4 = false;
796  continue;
797  }
798 
799  /*
800  * These are invalid for IPv4, but OK for IPv6
801  * and host names.
802  */
803  if ((value[i] >= 'A') && (value[i] <= 'F')) {
804  ipv4 = false;
805  continue;
806  }
807 
808  /*
809  * This is only valid for IPv6 addresses.
810  */
811  if (value[i] == ':') {
812  ipv4 = false;
813  hostname = false;
814  continue;
815  }
816 
817  /*
818  * Valid for IPv4 and host names, not for IPv6.
819  */
820  if (value[i] == '.') {
821  ipv6 = false;
822  continue;
823  }
824 
825  /*
826  * Netmasks are allowed by us, and MUST come at
827  * the end of the address.
828  */
829  if (value[i] == '/') {
830  break;
831  }
832 
833  /*
834  * Any characters other than what are checked for
835  * above can't be IPv4 or IPv6 addresses.
836  */
837  ipv4 = false;
838  ipv6 = false;
839  }
840 
841  /*
842  * It's not an IPv4 or IPv6 address. It MUST be a host
843  * name.
844  */
845  if (!ipv4 && !ipv6) {
846  /*
847  * Not an IPv4 or IPv6 address, and we weren't
848  * asked to do DNS resolution, we can't do it.
849  */
850  if (!resolve) {
851  fr_strerror_const("Not IPv4/6 address, and asked not to resolve");
852  return -1;
853  }
854 
855  /*
856  * It's not a hostname, either, so bail out
857  * early.
858  */
859  if (!hostname) {
860  fr_strerror_const("Invalid address");
861  return -1;
862  }
863  }
864 
865  /*
866  * The name has a ':' in it. Therefore it must be an
867  * IPv6 address. Error out if the caller specified IPv4.
868  * Otherwise, force IPv6.
869  */
870  if (ipv6 && !hostname) {
871  if (af == AF_INET) {
872  fr_strerror_const("Invalid address");
873  return -1;
874  }
875 
876  af = AF_INET6;
877  }
878 
879  /*
880  * Use whatever the caller specified, OR what we
881  * insinuated above from looking at the name string.
882  */
883  switch (af) {
884  case AF_UNSPEC:
885  return fr_inet_pton4(out, value, inlen, resolve, true, mask);
886 
887  case AF_INET:
888  return fr_inet_pton4(out, value, inlen, resolve, false, mask);
889 
890  case AF_INET6:
891  return fr_inet_pton6(out, value, inlen, resolve, false, mask);
892 
893  default:
894  break;
895  }
896 
897  /*
898  * No idea what it is...
899  */
900  fr_strerror_printf("Invalid address family %i", af);
901  return -1;
902 }
903 
904 /** Parses IPv4/6 address + port, to fr_ipaddr_t and integer (port)
905  *
906  * @param[out] out Where to write the ip address value.
907  * @param[out] port_out Where to write the port (0 if no port found).
908  * @param[in] value to parse.
909  * @param[in] inlen Length of value, if value is \0 terminated inlen may be -1.
910  * @param[in] resolve If true and value doesn't look like an IP address, try and resolve value
911  * as a hostname.
912  * @param[in] af If the address type is not obvious from the format, and resolve is true,
913  * the DNS record (A or AAAA) we require. Also controls which parser we pass
914  * the address to if we have no idea what it is.
915  * - AF_UNSPEC - Use the server default IP family.
916  * - AF_INET - Treat value as an IPv4 address.
917  * - AF_INET6 - Treat value as in IPv6 address.
918  * @param[in] mask If true, set address bits to zero.
919  * @return
920  * - 0 if ip address was parsed successfully.
921  * - -1 on failure.
922  */
923 int fr_inet_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value,
924  ssize_t inlen, int af, bool resolve, bool mask)
925 {
926  char const *p = value, *q;
927  char *end;
928  unsigned long port;
929  char buffer[6];
930  size_t len;
931 
932  *port_out = 0;
933 
934  len = (inlen >= 0) ? (size_t)inlen : strlen(value);
935 
936  if (*p == '[') {
937  if (!(q = memchr(p + 1, ']', len - 1))) {
938  fr_strerror_const("Missing closing ']' for IPv6 address");
939  return -1;
940  }
941 
942  /*
943  * inet_pton doesn't like the address being wrapped in []
944  */
945  if (fr_inet_pton6(out, p + 1, (q - p) - 1, false, false, mask) < 0) return -1;
946 
947  if (q[1] == ':') {
948  q++;
949  goto do_port;
950  }
951 
952  return 0;
953  }
954 
955  /*
956  * Host, IPv4 or IPv6 with no port
957  */
958  q = memchr(p, ':', len);
959  if (!q) return fr_inet_pton(out, p, len, af, resolve, mask);
960 
961  /*
962  * IPv4 or host, with port
963  */
964  if (fr_inet_pton(out, p, (q - p), af, resolve, mask) < 0) return -1;
965 do_port:
966  /*
967  * Valid ports are a maximum of 5 digits, so if the
968  * input length indicates there are more than 5 chars
969  * after the ':' then there's an issue.
970  */
971  if (len > (size_t) ((q + sizeof(buffer)) - value)) {
972  error:
973  fr_strerror_const("IP string contains trailing garbage after port delimiter");
974  return -1;
975  }
976 
977  p = q + 1; /* Move to first digit */
978 
979  strlcpy(buffer, p, (len - (p - value)) + 1);
980  port = strtoul(buffer, &end, 10);
981  if (*end != '\0') goto error; /* Trailing garbage after integer */
982 
983  if ((port > UINT16_MAX) || (port == 0)) {
984  fr_strerror_printf("Port %lu outside valid port range 1-" STRINGIFY(UINT16_MAX), port);
985  return -1;
986  }
987  *port_out = port;
988 
989  return 0;
990 }
991 
992 /** Print the address portion of a #fr_ipaddr_t
993  *
994  * @note Includes the textual scope_id name (eth0, en0 etc...) if supported.
995  *
996  * @param[out] out Where to write the resulting IP string.
997  * Should be at least FR_IPADDR_STRLEN bytes.
998  * @param[in] outlen of output buffer.
999  * @param[in] addr to convert to presentation format.
1000  * @return
1001  * - NULL on error (use fr_syserror(errno)).
1002  * - a pointer to out on success.
1003  */
1004 char *fr_inet_ntop(char out[static FR_IPADDR_STRLEN], size_t outlen, fr_ipaddr_t const *addr)
1005 {
1006  char *p;
1007  size_t len;
1008 
1009  out[0] = '\0';
1010 
1011  if (inet_ntop(addr->af, &addr->addr, out, outlen) == NULL) {
1012  fr_strerror_printf("%s", fr_syserror(errno));
1013  return NULL;
1014  }
1015 
1016  if ((addr->af == AF_INET) || (addr->scope_id == 0)) return out;
1017 
1018  p = out + strlen(out);
1019 
1020 #ifdef WITH_IFINDEX_NAME_RESOLUTION
1021  {
1022  char buffer[IFNAMSIZ];
1023  char *ifname;
1024 
1025  ifname = fr_ifname_from_ifindex(buffer, addr->scope_id);
1026  if (ifname) {
1027  len = snprintf(p, outlen - (p - out), "%%%s", ifname);
1028  if (is_truncated(len + (p - out), outlen)) {
1029  fr_strerror_printf("Address buffer too small, needed %zu bytes, have %zu bytes",
1030  (p - out) + len, outlen);
1031  return NULL;
1032  }
1033  return out;
1034  }
1035 
1036  }
1037 #endif
1038 
1039  len = snprintf(p, outlen - (p - out), "%%%u", addr->scope_id);
1040  if (is_truncated(len + (p - out), outlen)) {
1041  fr_strerror_printf("Address buffer too small, needed %zu bytes, have %zu bytes",
1042  (p - out) + len, outlen);
1043  return NULL;
1044  }
1045 
1046  return out;
1047 }
1048 
1049 /** Print a #fr_ipaddr_t as a CIDR style network prefix
1050  *
1051  * @param[out] out Where to write the resulting prefix string.
1052  * Should be at least FR_IPADDR_PREFIX_STRLEN bytes.
1053  * @param[in] outlen of output buffer.
1054  * @param[in] addr to convert to presentation format.
1055  * @return
1056  * - NULL on error (use fr_syserror(errno)).
1057  * - a pointer to out on success.
1058  */
1059 char *fr_inet_ntop_prefix(char out[static FR_IPADDR_PREFIX_STRLEN], size_t outlen, fr_ipaddr_t const *addr)
1060 {
1061  char *p;
1062  size_t len;
1063 
1064  if (fr_inet_ntop(out, outlen, addr) == NULL) return NULL;
1065 
1066  p = out + strlen(out);
1067 
1068  len = snprintf(p, outlen - (p - out), "/%i", addr->prefix);
1069  if (is_truncated(len + (p - out), outlen)) {
1070  fr_strerror_printf("Address buffer too small, needed %zu bytes, have %zu bytes",
1071  (p - out) + len, outlen);
1072  return NULL;
1073  }
1074 
1075  return out;
1076 }
1077 
1078 /** Print an interface-id in standard colon notation
1079  *
1080  * @param[out] out Where to write the resulting interface-id string.
1081  * @param[in] outlen of output buffer.
1082  * @param[in] ifid to print.
1083  * @return a pointer to out.
1084  */
1085 char *fr_inet_ifid_ntop(char *out, size_t outlen, uint8_t const *ifid)
1086 {
1087  snprintf(out, outlen, "%x:%x:%x:%x",
1088  fr_nbo_to_uint16(ifid), fr_nbo_to_uint16(ifid + 2),
1089  fr_nbo_to_uint16(ifid + 4), fr_nbo_to_uint16(ifid + 6));
1090  return out;
1091 }
1092 
1093 /** Convert interface-id in colon notation to 8 byte binary form
1094  *
1095  * @param[out] out Where to write the binary interface-id.
1096  * @param[in] ifid_str to parse.
1097  * @return a pointer to out.
1098  */
1099 uint8_t *fr_inet_ifid_pton(uint8_t out[static 8], char const *ifid_str)
1100 {
1101  static char const xdigits[] = "0123456789abcdef";
1102  char const *p, *pch;
1103  int num_id = 0, val = 0, idx = 0;
1104 
1105  for (p = ifid_str; ; ++p) {
1106  if (*p == ':' || *p == '\0') {
1107  if (num_id <= 0)
1108  return NULL;
1109 
1110  /*
1111  * Drop 'val' into the array.
1112  */
1113  out[idx] = (val >> 8) & 0xff;
1114  out[idx + 1] = val & 0xff;
1115  if (*p == '\0') {
1116  /*
1117  * Must have all entries before
1118  * end of the string.
1119  */
1120  if (idx != 6)
1121  return NULL;
1122  break;
1123  }
1124  val = 0;
1125  num_id = 0;
1126  if ((idx += 2) > 6)
1127  return NULL;
1128  } else if ((pch = strchr(xdigits, tolower((uint8_t) *p))) != NULL) {
1129  if (++num_id > 4)
1130  return NULL;
1131  /*
1132  * Dumb version of 'scanf'
1133  */
1134  val <<= 4;
1135  val |= (pch - xdigits);
1136  } else
1137  return NULL;
1138  }
1139  return out;
1140 }
1141 
1142 #ifdef SIOCGIFADDR
1143 /** Retrieve the primary IP address associated with an interface
1144  *
1145  * @param[out] out The primary IP address associated with the named interface.
1146  * @param[in] af of IP address to retrieve (AF_INET or AF_INET6).
1147  * @param[in] name of interface.
1148  * @return
1149  * - 0 on success.
1150  * - -1 on failure.
1151  */
1152 int fr_ipaddr_from_ifname(fr_ipaddr_t *out, int af, char const *name)
1153 {
1154  int fd;
1155  struct ifreq if_req;
1156  fr_ipaddr_t ipaddr;
1157 
1158  memset(&if_req, 0, sizeof(if_req));
1159  memset(out, 0, sizeof(*out));
1160 
1161  /*
1162  * Set the interface we're resolving, and the address family.
1163  */
1164  if_req.ifr_addr.sa_family = af;
1165  strlcpy(if_req.ifr_name, name, sizeof(if_req.ifr_name));
1166 
1167  fd = socket(AF_INET, SOCK_DGRAM, 0);
1168  if (fd < 0) {
1169  fr_strerror_printf("Failed opening temporary socket for SIOCGIFADDR: %s", fr_syserror(errno));
1170  error:
1171  close(fd);
1172  return -1;
1173  }
1174  if (ioctl(fd, SIOCGIFADDR, &if_req) < 0) {
1175  fr_strerror_printf("Failed determining address for interface %s: %s", name, fr_syserror(errno));
1176  goto error;
1177  }
1178 
1179  /*
1180  * There's nothing in the ifreq struct that gives us the length
1181  * of the sockaddr struct, so we just use sizeof here.
1182  * sockaddr2ipaddr uses the address family anyway, so we should
1183  * be OK.
1184  */
1185  if (fr_ipaddr_from_sockaddr(&ipaddr, NULL,
1186  (struct sockaddr_storage *)&if_req.ifr_addr,
1187  sizeof(if_req.ifr_addr)) < 0) goto error;
1188  *out = ipaddr;
1189 
1190  close(fd);
1191 
1192  return 0;
1193 }
1194 #else
1196 {
1197  fr_strerror_printf("No support for SIOCGIFADDR, can't determine IP address of %s", name);
1198  return -1;
1199 }
1200 #endif
1201 
1202 #ifdef WITH_IFINDEX_NAME_RESOLUTION
1203 /** Resolve ifindex to interface name
1204  *
1205  * @param[out] out Buffer to use to store the name, must be at least IFNAMSIZ bytes.
1206  * @param[in] ifindex to resolve to name.
1207  * @return
1208  * - NULL on error.
1209  * - a pointer to out on success.
1210  */
1211 char *fr_ifname_from_ifindex(char out[static IFNAMSIZ], int ifindex)
1212 {
1213 #ifdef HAVE_IF_INDEXTONAME
1214  if (!if_indextoname(ifindex, out)) {
1215  fr_strerror_printf("Failed resolving interface index %i to name", ifindex);
1216  return NULL;
1217  }
1218 #else
1219  struct ifreq if_req;
1220  int fd;
1221 
1222  memset(&if_req, 0, sizeof(if_req));
1223  if_req.ifr_ifindex = ifindex;
1224 
1225  fd = socket(AF_INET, SOCK_DGRAM, 0);
1226  if (fd < 0) {
1227  fr_strerror_printf("Failed opening temporary socket for SIOCGIFADDR: %s", fr_syserror(errno));
1228  error:
1229  close(fd);
1230  return NULL;
1231  }
1232 
1233  /*
1234  * First we resolve the interface index to the interface name
1235  * Which is pretty inefficient, but it seems the only way to
1236  * identify interfaces for SIOCG* operations is with the interface
1237  * name.
1238  */
1239  if (ioctl(fd, SIOCGIFNAME, &if_req) < 0) {
1240  fr_strerror_printf("Failed resolving interface index %i to name: %s", ifindex, fr_syserror(errno));
1241  goto error;
1242  }
1243  strlcpy(out, if_req.ifr_name, IFNAMSIZ);
1244  close(fd);
1245 #endif
1246  return out;
1247 }
1248 #endif
1249 
1250 #ifdef WITH_IFINDEX_IPADDR_RESOLUTION
1251 /** Returns the primary IP address for a given interface index
1252  *
1253  * @note Intended to be used with udpfromto (recvfromto) to retrieve the
1254  * source IP address to use when responding to broadcast packets.
1255  *
1256  * @note Will likely be quite slow due to the number of system calls.
1257  *
1258  * @param[out] out Where to write the primary IP address.
1259  * @param[in] fd File descriptor of any datagram or raw socket.
1260  * @param[in] af to get interface for.
1261  * @param[in] ifindex of interface to get IP address for.
1262  * @return
1263  * - 0 on success.
1264  * - -1 on failure.
1265  */
1266 int fr_ipaddr_from_ifindex(fr_ipaddr_t *out, int fd, int af, int ifindex)
1267 {
1268  struct ifreq if_req;
1269  fr_ipaddr_t ipaddr;
1270 
1271  memset(&if_req, 0, sizeof(if_req));
1272  memset(out, 0, sizeof(*out));
1273 
1274 #ifdef SIOCGIFNAME
1275  if_req.ifr_ifindex = ifindex;
1276  /*
1277  * First we resolve the interface index to the interface name
1278  * Which is pretty inefficient, but it seems the only way to
1279  * identify interfaces for SIOCG* operations is with the interface
1280  * name.
1281  */
1282  if (ioctl(fd, SIOCGIFNAME, &if_req) < 0) {
1283  fr_strerror_printf("Failed resolving interface index %i to name: %s", ifindex, fr_syserror(errno));
1284  return -1;
1285  }
1286 #elif defined(HAVE_IF_INDEXTONAME)
1287  if (!if_indextoname(ifindex, if_req.ifr_name)) {
1288  fr_strerror_printf("Failed resolving interface index %i to name", ifindex);
1289  return -1;
1290  }
1291 #else
1292 # error Need SIOCGIFNAME or if_indextoname
1293 #endif
1294 
1295  /*
1296  * Name should now be present in if_req, so we just need to
1297  * set the address family.
1298  */
1299  if_req.ifr_addr.sa_family = af;
1300 
1301  if (ioctl(fd, SIOCGIFADDR, &if_req) < 0) {
1302  fr_strerror_printf("Failed determining address for interface %s: %s",
1303  if_req.ifr_name, fr_syserror(errno));
1304  return -1;
1305  }
1306 
1307  /*
1308  * There's nothing in the ifreq struct that gives us the length
1309  * of the sockaddr struct, so we just use sizeof here.
1310  * sockaddr2ipaddr uses the address family anyway, so we should
1311  * be OK.
1312  */
1313  if (fr_ipaddr_from_sockaddr(&ipaddr, NULL,
1314  (struct sockaddr_storage *)&if_req.ifr_addr,
1315  sizeof(if_req.ifr_addr)) < 0) return -1;
1316  *out = ipaddr;
1317 
1318  return 0;
1319 }
1320 #endif
1321 
1322 /** Compare two ip addresses
1323  *
1324  * @param[in] a First ip to compare.
1325  * @param[in] b Second ip to compare.
1326  * @return
1327  * - 1 if a > b
1328  * - 0 if a == b
1329  * - -1 if a < b
1330  * - -2 on error.
1331  */
1332 int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
1333 {
1334  int ret;
1335  size_t len;
1336 
1337  CMP_RETURN(a, b, af);
1338  CMP_RETURN(a, b, prefix);
1339 
1340  /*
1341  * We only care about prefix bytes.
1342  *
1343  * Host bytes should be masked on ingestion
1344  * for prefix types.
1345  */
1346  len = ((a->prefix + 7) & -8) >> 3;
1347  switch (a->af) {
1348  case AF_INET:
1349  ret = memcmp(&a->addr.v4, &b->addr.v4, len);
1350  return CMP(ret, 0);
1351 
1352 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1353  case AF_INET6:
1354  CMP_RETURN(a, b, scope_id);
1355  ret = memcmp(&a->addr.v6, &b->addr.v6, len);
1356  return CMP(ret, 0);
1357 #endif
1358 
1359  default:
1360  fr_strerror_printf("Invalid address family %u", a->af);
1361  return -2;
1362  }
1363 }
1364 
1365 /** Convert our internal ip address representation to a sockaddr
1366  *
1367  * @param[out] sa where to write out the sockaddr,
1368  * must be large enough to hold
1369  * sizeof(s6).
1370  * @param[out] salen Length of the sockaddr struct.
1371  * @param[in] ipaddr IP address to convert.
1372  * @param[in] port Port to convert.
1373 
1374  * @return
1375  * - 0 on success.
1376  * - -1 on failure.
1377  */
1378 int fr_ipaddr_to_sockaddr(struct sockaddr_storage *sa, socklen_t *salen,
1379  fr_ipaddr_t const *ipaddr, uint16_t port)
1380 {
1381  memset(sa, 0, sizeof(*sa));
1382 
1383  if (ipaddr->af == AF_INET) {
1384  struct sockaddr_in s4;
1385 
1386  *salen = sizeof(s4);
1387 
1388  memset(&s4, 0, sizeof(s4));
1389  s4.sin_family = AF_INET;
1390  s4.sin_addr = ipaddr->addr.v4;
1391  s4.sin_port = htons(port);
1392  memset(sa, 0, sizeof(*sa));
1393  memcpy(sa, &s4, sizeof(s4));
1394 
1395 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1396  } else if (ipaddr->af == AF_INET6) {
1397  struct sockaddr_in6 s6;
1398 
1399  *salen = sizeof(s6);
1400 
1401  memset(&s6, 0, sizeof(s6));
1402  s6.sin6_family = AF_INET6;
1403  s6.sin6_addr = ipaddr->addr.v6;
1404  s6.sin6_port = htons(port);
1405  s6.sin6_scope_id = ipaddr->scope_id;
1406  memset(sa, 0, sizeof(*sa));
1407  memcpy(sa, &s6, sizeof(s6));
1408 #endif
1409  } else {
1410  fr_strerror_printf("Unsupported address family %d", ipaddr->af);
1411  return -1;
1412  }
1413 
1414  return 0;
1415 }
1416 
1417 /** Convert sockaddr to our internal ip address representation
1418  *
1419  * @param[out] ipaddr Where to write the ipaddr.
1420  * @param[out] port Where to write the port.
1421  * @param[in] sa struct to convert.
1422  * @param[in] salen Length of the sockaddr struct.
1423  * @return
1424  * - 0 on success.
1425  * - -1 on failure.
1426  */
1428  struct sockaddr_storage const *sa, socklen_t salen)
1429 {
1430  memset(ipaddr, 0, sizeof(*ipaddr));
1431 
1432  if (sa->ss_family == AF_INET) {
1433  struct sockaddr_in s4;
1434 
1435  if (salen < sizeof(s4)) {
1436  fr_strerror_const("IPv4 address is too small");
1437  return 0;
1438  }
1439 
1440  memcpy(&s4, sa, sizeof(s4));
1441  ipaddr->af = AF_INET;
1442  ipaddr->prefix = 32;
1443  ipaddr->addr.v4 = s4.sin_addr;
1444  if (port) *port = ntohs(s4.sin_port);
1445  ipaddr->scope_id = 0;
1446 
1447 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1448  } else if (sa->ss_family == AF_INET6) {
1449  struct sockaddr_in6 s6;
1450 
1451  if (salen < sizeof(s6)) {
1452  fr_strerror_const("IPv6 address is too small");
1453  return 0;
1454  }
1455 
1456  memcpy(&s6, sa, sizeof(s6));
1457  ipaddr->af = AF_INET6;
1458  ipaddr->prefix = 128;
1459  ipaddr->addr.v6 = s6.sin6_addr;
1460  if (port) *port = ntohs(s6.sin6_port);
1461  ipaddr->scope_id = s6.sin6_scope_id;
1462 #endif
1463 
1464  } else {
1465  fr_strerror_printf("Unsupported address family %d", sa->ss_family);
1466  return -1;
1467  }
1468 
1469  return 0;
1470 }
1471 
1473 {
1474  struct ifaddrs *list = NULL;
1475  struct ifaddrs *i;
1476 
1477  /*
1478  * This should be set already for IPv6. We should only need to do this for IPv4.
1479  */
1480  if (ipaddr->scope_id != 0) return;
1481 
1482  /*
1483  * Bind manually to an IP used by the named interface.
1484  */
1485  if (getifaddrs(&list) < 0) return;
1486 
1487  for (i = list; i != NULL; i = i->ifa_next) {
1489 
1490  if (!i->ifa_addr || !i->ifa_name || (ipaddr->af != i->ifa_addr->sa_family)) continue;
1491 
1493  (struct sockaddr_storage *)i->ifa_addr, sizeof(struct sockaddr_in6));
1494  my_ipaddr.scope_id = 0;
1495 
1496  /*
1497  * my_ipaddr will have a scope_id, but the input
1498  * ipaddr won't have one. We therefore set the
1499  * local one to zero, so that we can do correct
1500  * IP address comparisons.
1501  *
1502  * If the comparison succeeds, then we return
1503  * both the interface name, and we update the
1504  * input ipaddr with the correct scope_id.
1505  */
1506  if (fr_ipaddr_cmp(ipaddr, &my_ipaddr) == 0) {
1507  ipaddr->scope_id = if_nametoindex(i->ifa_name);
1508  break;
1509  }
1510  }
1511 
1512  freeifaddrs(list);
1513 }
1514 
1515 
1516 char *fr_ipaddr_to_interface(TALLOC_CTX *ctx, fr_ipaddr_t *ipaddr)
1517 {
1518  struct ifaddrs *list = NULL;
1519  struct ifaddrs *i;
1520  char *interface = NULL;
1521 
1522  /*
1523  * Bind manually to an IP used by the named interface.
1524  */
1525  if (getifaddrs(&list) < 0) return NULL;
1526 
1527  for (i = list; i != NULL; i = i->ifa_next) {
1528  int scope_id;
1530 
1531  if (!i->ifa_addr || !i->ifa_name || (ipaddr->af != i->ifa_addr->sa_family)) continue;
1532 
1534  (struct sockaddr_storage *)i->ifa_addr, sizeof(struct sockaddr_in6));
1535 
1536  /*
1537  * my_ipaddr will have a scope_id, but the input
1538  * ipaddr won't have one. We therefore set the
1539  * local one to zero, so that we can do correct
1540  * IP address comparisons.
1541  *
1542  * If the comparison succeeds, then we return
1543  * both the interface name, and we update the
1544  * input ipaddr with the correct scope_id.
1545  */
1546  scope_id = my_ipaddr.scope_id;
1547  my_ipaddr.scope_id = 0;
1548  if (fr_ipaddr_cmp(ipaddr, &my_ipaddr) == 0) {
1549  interface = talloc_strdup(ctx, i->ifa_name);
1550  ipaddr->scope_id = scope_id;
1551  break;
1552  }
1553  }
1554 
1555  freeifaddrs(list);
1556  return interface;
1557 }
1558 
1559 int fr_interface_to_ipaddr(char const *interface, fr_ipaddr_t *ipaddr, int af, bool link_local)
1560 {
1561  struct ifaddrs *list = NULL;
1562  struct ifaddrs *i;
1563  int ret = -1;
1564 
1565  if (getifaddrs(&list) < 0) return -1;
1566 
1567  for (i = list; i != NULL; i = i->ifa_next) {
1569  struct sockaddr_storage sa;
1570 
1571  if (!i->ifa_addr || !i->ifa_name || ((af != AF_UNSPEC) && (af != i->ifa_addr->sa_family))) continue;
1572  if (strcmp(i->ifa_name, interface) != 0) continue;
1573 
1574  memcpy(&sa, i->ifa_addr, sizeof(struct sockaddr_in6)); /* ifa->ifa_addr may not be aligned properly */
1575 
1576  fr_ipaddr_from_sockaddr(&my_ipaddr, NULL, &sa, sizeof(struct sockaddr_in6));
1577 
1578  /*
1579  * If they ask for a link local address, then give
1580  * it to them.
1581  */
1582  if (link_local) {
1583  if (my_ipaddr.af != AF_INET6) continue;
1584  if (!IN6_IS_ADDR_LINKLOCAL(&my_ipaddr.addr.v6)) continue;
1585  }
1586 
1587  *ipaddr = my_ipaddr;
1588  ret = 0;
1589  break;
1590  }
1591 
1592  freeifaddrs(list);
1593  return ret;
1594 }
1595 
1596 /*
1597  * AF_PACKET on Linux
1598  * AF_LINK on BSD
1599  */
1600 #ifndef AF_LINK
1601 #define AF_LINK AF_PACKET
1602 #endif
1603 
1604 int fr_interface_to_ethernet(char const *interface, fr_ethernet_t *ethernet)
1605 {
1606  struct ifaddrs *list = NULL;
1607  struct ifaddrs *i;
1608  int ret = -1;
1609 
1610  if (getifaddrs(&list) < 0) return -1;
1611 
1612  for (i = list; i != NULL; i = i->ifa_next) {
1613  if (!i->ifa_addr || !i->ifa_name || (i->ifa_addr->sa_family != AF_LINK)) continue;
1614  if (strcmp(i->ifa_name, interface) != 0) continue;
1615 
1616 #if defined(__linux__) || defined(__EMSCRIPTEN__)
1617  {
1618  struct sockaddr_ll *ll;
1619 
1620  ll = (struct sockaddr_ll *) i->ifa_addr;
1621  if ((ll->sll_hatype != 1) || (ll->sll_halen != 6)) continue;
1622 
1623  memcpy(ethernet->addr, ll->sll_addr, 6);
1624  }
1625 #else
1626  {
1627  struct sockaddr_dl *ll;
1628 
1629  ll = (struct sockaddr_dl *) i->ifa_addr;
1630  if (ll->sdl_alen != 6) continue;
1631 
1632  memcpy(ethernet->addr, LLADDR(ll), 6);
1633  }
1634 #endif
1635  ret = 0;
1636  break;
1637  }
1638 
1639  freeifaddrs(list);
1640  return ret;
1641 }
static int const char char buffer[256]
Definition: acutest.h:574
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define STRINGIFY(x)
Definition: build.h:195
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
Definition: build.h:119
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition: build.h:110
#define UNUSED
Definition: build.h:313
Test enumeration values.
Definition: dict_test.h:92
int getaddrinfo(char const *hostname, char const *servname, struct addrinfo const *hints, struct addrinfo **res)
Definition: getaddrinfo.c:261
void freeaddrinfo(struct addrinfo *ai)
Definition: getaddrinfo.c:251
char const * gai_strerror(int ecode)
Definition: getaddrinfo.c:231
int getnameinfo(struct sockaddr const *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, unsigned int flags)
Definition: getaddrinfo.c:381
int fr_interface_to_ipaddr(char const *interface, fr_ipaddr_t *ipaddr, int af, bool link_local)
Definition: inet.c:1559
char * fr_inet_ifid_ntop(char *out, size_t outlen, uint8_t const *ifid)
Print an interface-id in standard colon notation.
Definition: inet.c:1085
int fr_ipaddr_is_prefix(fr_ipaddr_t const *ipaddr)
Determine if an address is a prefix.
Definition: inet.c:125
uint8_t * fr_inet_ifid_pton(uint8_t out[static 8], char const *ifid_str)
Convert interface-id in colon notation to 8 byte binary form.
Definition: inet.c:1099
int fr_ipaddr_is_multicast(fr_ipaddr_t const *ipaddr)
Determine if an address is a multicast address.
Definition: inet.c:94
void fr_ipaddr_get_scope_id(fr_ipaddr_t *ipaddr)
Definition: inet.c:1472
int fr_inet_pton6(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback, bool mask)
Parse an IPv6 address or IPv6 prefix in presentation format (and others)
Definition: inet.c:615
int fr_inet_hton(fr_ipaddr_t *out, int af, char const *hostname, bool fallback)
Wrappers for IPv4/IPv6 host to IP address lookup.
Definition: inet.c:240
char * fr_inet_ntop_prefix(char out[static FR_IPADDR_PREFIX_STRLEN], size_t outlen, fr_ipaddr_t const *addr)
Print a fr_ipaddr_t as a CIDR style network prefix.
Definition: inet.c:1059
static int ip_octet_from_str(uint32_t *out, char const *str)
Parse a single octet of an IPv4 address string.
Definition: inet.c:373
int fr_ipaddr_from_sockaddr(fr_ipaddr_t *ipaddr, uint16_t *port, struct sockaddr_storage const *sa, socklen_t salen)
Convert sockaddr to our internal ip address representation.
Definition: inet.c:1427
int fr_inet_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback, bool mask_bits)
Parse an IPv4 address or IPv4 prefix in presentation format (and others)
Definition: inet.c:466
char const * fr_inet_ntoh(fr_ipaddr_t const *src, char *out, size_t outlen)
Perform reverse resolution of an IP address.
Definition: inet.c:341
bool fr_hostname_lookups
hostname -> IP lookups?
Definition: inet.c:52
int fr_inet_pton(fr_ipaddr_t *out, char const *value, ssize_t inlen, int af, bool resolve, bool mask)
Simple wrapper to decide whether an IP value is v4 or v6 and call the appropriate parser.
Definition: inet.c:764
int fr_inet_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value, ssize_t inlen, int af, bool resolve, bool mask)
Parses IPv4/6 address + port, to fr_ipaddr_t and integer (port)
Definition: inet.c:923
int fr_ipaddr_is_inaddr_any(fr_ipaddr_t const *ipaddr)
Determine if an address is the INADDR_ANY address for its address family.
Definition: inet.c:62
#define AF_LINK
Definition: inet.c:1601
int fr_ipaddr_to_sockaddr(struct sockaddr_storage *sa, socklen_t *salen, fr_ipaddr_t const *ipaddr, uint16_t port)
Convert our internal ip address representation to a sockaddr.
Definition: inet.c:1378
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
Definition: inet.c:1332
static struct in6_addr fr_in6addr_mask(struct in6_addr const *ipaddr, uint8_t prefix)
Mask off a portion of an IPv6 address.
Definition: inet.c:167
void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
Zeroes out the host portion of an fr_ipaddr_t.
Definition: inet.c:203
int fr_interface_to_ethernet(char const *interface, fr_ethernet_t *ethernet)
Definition: inet.c:1604
char * fr_inet_ntop(char out[static FR_IPADDR_STRLEN], size_t outlen, fr_ipaddr_t const *addr)
Print the address portion of a fr_ipaddr_t.
Definition: inet.c:1004
int fr_ipaddr_from_ifname(UNUSED fr_ipaddr_t *out, UNUSED int af, char const *name)
Definition: inet.c:1195
static int ip_prefix_addr_from_str(struct in_addr *out, char const *str)
Parses the network portion of an IPv4 prefix into an in_addr.
Definition: inet.c:416
bool fr_reverse_lookups
IP -> hostname lookups?
Definition: inet.c:51
static struct in_addr fr_inaddr_mask(struct in_addr const *ipaddr, uint8_t prefix)
Mask off a portion of an IPv4 address.
Definition: inet.c:146
char * fr_ipaddr_to_interface(TALLOC_CTX *ctx, fr_ipaddr_t *ipaddr)
Definition: inet.c:1516
uint8_t prefix
Prefix length - Between 0-32 for IPv4 and 0-128 for IPv6.
Definition: inet.h:69
#define FR_IPADDR_STRLEN
Like INET6_ADDRSTRLEN but includes space for the textual Zone ID.
Definition: inet.h:89
int af
Address family.
Definition: inet.h:64
union fr_ipaddr_t::@121 addr
uint32_t scope_id
A host may have multiple link-local interfaces the scope ID allows the application to specify which o...
Definition: inet.h:70
uint8_t addr[6]
Ethernet address.
Definition: inet.h:46
#define FR_IPADDR_PREFIX_STRLEN
Like FR_IPADDR_STRLEN but with space for a prefix.
Definition: inet.h:93
Struct to represent an ethernet address.
Definition: inet.h:45
IPv4/6 prefix.
Definition: merged_model.c:272
unsigned short uint16_t
Definition: merged_model.c:31
unsigned int uint32_t
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
static bool is_integer(char const *value)
Check whether the string is all numbers.
Definition: misc.h:128
int inet_pton(int af, char const *src, void *dst)
Definition: missing.c:427
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
Definition: missing.c:443
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
Definition: nbo.h:137
#define is_truncated(_ret, _max)
Definition: print.h:48
static fr_ipaddr_t my_ipaddr
Definition: radius1_test.c:73
static char const * hostname(char *buf, size_t buflen, uint32_t ipaddr)
Definition: radwho.c:133
static uint32_t mask
Definition: rbmonkey.c:39
static char const * name
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:689
if(!subtype_vp) goto fail
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:34
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: syserror.c:243
close(uq->fd)
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
#define fr_box_strvalue_len(_val, _len)
Definition: value.h:279
static size_t char fr_sbuff_t size_t inlen
Definition: value.h:984
static size_t char ** out
Definition: value.h:984