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