2 * misc.c Various miscellaneous functions.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2000,2006 The FreeRADIUS server project
25 #include <freeradius-devel/libradius.h>
31 #define FR_PUT_LE16(a, val)\
33 a[1] = ((uint16_t) (val)) >> 8;\
34 a[0] = ((uint16_t) (val)) & 0xff;\
38 static pthread_mutex_t autofree_context = PTHREAD_MUTEX_INITIALIZER;
39 # define PTHREAD_MUTEX_LOCK pthread_mutex_lock
40 # define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
42 # define PTHREAD_MUTEX_LOCK(_x)
43 # define PTHREAD_MUTEX_UNLOCK(_x)
46 bool fr_dns_lookups = false; /* IP -> hostname lookups? */
47 bool fr_hostname_lookups = true; /* hostname -> IP lookups? */
48 int fr_debug_flag = 0;
50 static char const *months[] = {
51 "jan", "feb", "mar", "apr", "may", "jun",
52 "jul", "aug", "sep", "oct", "nov", "dec" };
54 fr_thread_local_setup(char *, fr_inet_ntop_buffer); /* macro */
56 /** Sets a signal handler using sigaction if available, else signal
58 * @param sig to set handler for.
59 * @param func handler to set.
61 int fr_set_signal(int sig, sig_t func)
66 memset(&act, 0, sizeof(act));
68 sigemptyset(&act.sa_mask);
69 act.sa_handler = func;
71 if (sigaction(sig, &act, NULL) < 0) {
72 fr_strerror_printf("Failed setting signal %i handler via sigaction(): %s", sig, fr_syserror(errno));
76 if (signal(sig, func) < 0) {
77 fr_strerror_printf("Failed setting signal %i handler via signal(): %s", sig, fr_syserror(errno));
84 /** Allocates a new talloc context from the root autofree context
86 * This function is threadsafe, whereas using the NULL context is not.
88 * @note The returned context must be freed by the caller.
89 * @returns a new talloc context parented by the root autofree context.
91 TALLOC_CTX *fr_autofree_ctx(void)
93 static TALLOC_CTX *ctx = NULL, *child;
94 PTHREAD_MUTEX_LOCK(&autofree_context);
96 ctx = talloc_autofree_context();
99 child = talloc_new(ctx);
100 PTHREAD_MUTEX_UNLOCK(&autofree_context);
106 * Explicitly cleanup the memory allocated to the error inet_ntop
109 static void _fr_inet_ntop_free(void *arg)
114 /** Wrapper around inet_ntop, prints IPv4/IPv6 addresses
116 * inet_ntop requires the caller pass in a buffer for the address.
117 * This would be annoying and cumbersome, seeing as quite often the ASCII
118 * address is only used for logging output.
120 * So as with lib/log.c use TLS to allocate thread specific buffers, and
121 * write the IP address there instead.
123 * @param af address family, either AF_INET or AF_INET6.
124 * @param src pointer to network address structure.
125 * @return NULL on error, else pointer to ASCII buffer containing text version of address.
127 char const *fr_inet_ntop(int af, void const *src)
135 buffer = fr_thread_local_init(fr_inet_ntop_buffer, _fr_inet_ntop_free);
140 * malloc is thread safe, talloc is not
142 buffer = malloc(sizeof(char) * INET6_ADDRSTRLEN);
144 fr_perror("Failed allocating memory for inet_ntop buffer");
148 ret = fr_thread_local_set(fr_inet_ntop_buffer, buffer);
150 fr_perror("Failed setting up TLS for inet_ntop buffer: %s", fr_syserror(ret));
157 return inet_ntop(af, src, buffer, INET6_ADDRSTRLEN);
161 * Return an IP address in standard dot notation
165 char const *ip_ntoa(char *buffer, uint32_t ipaddr)
167 ipaddr = ntohl(ipaddr);
169 sprintf(buffer, "%d.%d.%d.%d",
170 (ipaddr >> 24) & 0xff,
171 (ipaddr >> 16) & 0xff,
172 (ipaddr >> 8) & 0xff,
177 /** Parse an IPv4 address or IPv4 prefix in presentation format (and others)
179 * @param out Where to write the ip address value.
180 * @param value to parse, may be dotted quad [+ prefix], or integer, or octal number, or '*' (INADDR_ANY).
181 * @param inlen Length of value, if value is \0 terminated inlen may be 0.
182 * @param resolve If true and value doesn't look like an IP address, try and resolve value as a hostname.
183 * @param fallback to IPv4 resolution if no A records can be found.
184 * @return 0 if ip address was parsed successfully, else -1 on error.
186 int fr_pton4(fr_ipaddr_t *out, char const *value, size_t inlen, bool resolve, bool fallback)
192 /* Dotted quad + / + [0-9]{1,2} */
193 char buffer[INET_ADDRSTRLEN + 3];
196 * Copy to intermediary buffer if we were given a length
199 if (inlen >= sizeof(buffer)) {
200 fr_strerror_printf("Invalid IPv4 address string \"%s\"", value);
203 memcpy(buffer, value, inlen);
204 buffer[inlen] = '\0';
207 p = strchr(value, '/');
209 * 192.0.2.2 is parsed as if it was /32
213 * Allow '*' as the wildcard address usually 0.0.0.0
215 if ((value[0] == '*') && (value[1] == '\0')) {
216 out->ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
218 * Convert things which are obviously integers to IP addresses
220 * We assume the number is the bigendian representation of the
223 } else if (is_integer(value)) {
224 out->ipaddr.ip4addr.s_addr = htonl(strtoul(value, NULL, 0));
225 } else if (!resolve) {
226 if (inet_pton(AF_INET, value, &(out->ipaddr.ip4addr.s_addr)) <= 0) {
227 fr_strerror_printf("Failed to parse IPv4 address string \"%s\"", value);
230 } else if (ip_hton(out, AF_INET, value, fallback) < 0) return -1;
239 * Otherwise parse the prefix
241 if ((size_t)(p - value) >= INET_ADDRSTRLEN) {
242 fr_strerror_printf("Invalid IPv4 address string \"%s\"", value);
247 * Copy the IP portion into a temporary buffer if we haven't already.
249 if (inlen == 0) memcpy(buffer, value, p - value);
250 buffer[p - value] = '\0';
253 if (inet_pton(AF_INET, buffer, &(out->ipaddr.ip4addr.s_addr)) <= 0) {
254 fr_strerror_printf("Failed to parse IPv4 address string \"%s\"", value);
257 } else if (ip_hton(out, AF_INET, buffer, fallback) < 0) return -1;
259 prefix = strtoul(p + 1, &eptr, 10);
261 fr_strerror_printf("Invalid IPv4 mask length \"%s\". Should be between 0-32", p);
264 if (eptr[0] != '\0') {
265 fr_strerror_printf("Failed to parse IPv4 address string \"%s\", "
266 "got garbage after mask length \"%s\"", value, eptr);
271 out->ipaddr.ip4addr = fr_inaddr_mask(&(out->ipaddr.ip4addr), prefix);
274 out->prefix = (uint8_t) prefix;
280 /** Parse an IPv6 address or IPv6 prefix in presentation format (and others)
282 * @param out Where to write the ip address value.
283 * @param value to parse.
284 * @param inlen Length of value, if value is \0 terminated inlen may be 0.
285 * @param resolve If true and value doesn't look like an IP address, try and resolve value as a hostname.
286 * @param fallback to IPv4 resolution if no AAAA records can be found.
287 * @return 0 if ip address was parsed successfully, else -1 on error.
289 int fr_pton6(fr_ipaddr_t *out, char const *value, size_t inlen, bool resolve, bool fallback)
295 /* IPv6 + / + [0-9]{1,3} */
296 char buffer[INET6_ADDRSTRLEN + 4];
299 * Copy to intermediary buffer if we were given a length
302 if (inlen >= sizeof(buffer)) {
303 fr_strerror_printf("Invalid IPv6 address string \"%s\"", value);
306 memcpy(buffer, value, inlen);
307 buffer[inlen] = '\0';
310 p = strchr(value, '/');
313 * Allow '*' as the wildcard address
315 if ((value[0] == '*') && (value[1] == '\0')) {
316 memset(&out->ipaddr.ip6addr.s6_addr, 0, sizeof(out->ipaddr.ip6addr.s6_addr));
317 } else if (!resolve) {
318 if (inet_pton(AF_INET6, value, &(out->ipaddr.ip6addr.s6_addr)) <= 0) {
319 fr_strerror_printf("Failed to parse IPv6 address string \"%s\"", value);
322 } else if (ip_hton(out, AF_INET6, value, fallback) < 0) return -1;
330 if ((p - value) >= INET6_ADDRSTRLEN) {
331 fr_strerror_printf("Invalid IPv6 address string \"%s\"", value);
336 * Copy string to temporary buffer if we didn't do it earlier
338 if (inlen == 0) memcpy(buffer, value, p - value);
339 buffer[p - value] = '\0';
342 if (inet_pton(AF_INET6, buffer, &(out->ipaddr.ip6addr.s6_addr)) <= 0) {
343 fr_strerror_printf("Failed to parse IPv6 address string \"%s\"", value);
346 } else if (ip_hton(out, AF_INET6, buffer, fallback) < 0) return -1;
348 prefix = strtoul(p + 1, &eptr, 10);
350 fr_strerror_printf("Invalid IPv6 mask length \"%s\". Should be between 0-128", p);
353 if (eptr[0] != '\0') {
354 fr_strerror_printf("Failed to parse IPv6 address string \"%s\", "
355 "got garbage after mask length \"%s\"", value, eptr);
360 struct in6_addr addr;
362 addr = fr_in6addr_mask(&(out->ipaddr.ip6addr), prefix);
363 memcpy(&(out->ipaddr.ip6addr.s6_addr), &addr, sizeof(addr));
366 out->prefix = (uint8_t) prefix;
372 /** Simple wrapper to decide whether an IP value is v4 or v6 and call the appropriate parser.
374 * @param out Where to write the ip address value.
375 * @param value to parse.
376 * @param inlen Length of value, if value is \0 terminated inlen may be 0.
377 * @param resolve If true and value doesn't look like an IP address, try and resolve value as a hostname.
378 * @return 0 if ip address was parsed successfully, else -1 on error.
380 int fr_pton(fr_ipaddr_t *out, char const *value, size_t inlen, bool resolve)
385 for (p = value; *p != '\0'; p++) {
396 return fr_pton4(out, value, inlen, resolve, true);
399 * If we found ':' or '[' or ']' in the above string, there's
400 * no way this can be a hostname, so don't try to resolve.
403 return fr_pton6(out, value, inlen, false, false);
410 /** Check if the IP address is equivalent to INADDR_ANY
412 * @param addr to chec.
413 * @return true if IP address matches INADDR_ANY or INADDR6_ANY (assumed to be 0), else false.
415 bool is_wildcard(fr_ipaddr_t *addr)
417 static struct in6_addr in6_addr;
421 return (addr->ipaddr.ip4addr.s_addr == htons(INADDR_ANY));
424 return (memcmp(addr->ipaddr.ip6addr.s6_addr, in6_addr.s6_addr, sizeof(in6_addr.s6_addr)) == 0) ? true :false;
432 int fr_ntop(char *out, size_t outlen, fr_ipaddr_t *addr)
434 char buffer[INET6_ADDRSTRLEN];
436 if (inet_ntop(addr->af, &(addr->ipaddr), buffer, sizeof(buffer)) == NULL) return -1;
438 return snprintf(out, outlen, "%s/%i", buffer, addr->prefix);
442 * Internal wrapper for locking, to minimize the number of ifdef's
446 int rad_lockfd(int fd, int lock_len)
455 fl.l_whence = SEEK_CUR;
457 return fcntl(fd, F_SETLKW, (void *)&fl);
459 #error "missing definition for F_WRLCK, all file locks will fail"
466 * Internal wrapper for locking, to minimize the number of ifdef's
468 * Lock an fd, prefer lockf() over flock()
469 * Nonblocking version.
471 int rad_lockfd_nonblock(int fd, int lock_len)
480 fl.l_whence = SEEK_CUR;
482 return fcntl(fd, F_SETLK, (void *)&fl);
484 #error "missing definition for F_WRLCK, all file locks will fail"
491 * Internal wrapper for unlocking, to minimize the number of ifdef's
494 * Unlock an fd, prefer lockf() over flock()
496 int rad_unlockfd(int fd, int lock_len)
505 fl.l_whence = SEEK_CUR;
507 return fcntl(fd, F_UNLCK, (void *)&fl);
509 #error "missing definition for F_WRLCK, all file locks will fail"
516 * Return an interface-id in standard colon notation
518 char *ifid_ntoa(char *buffer, size_t size, uint8_t const *ifid)
520 snprintf(buffer, size, "%x:%x:%x:%x",
521 (ifid[0] << 8) + ifid[1], (ifid[2] << 8) + ifid[3],
522 (ifid[4] << 8) + ifid[5], (ifid[6] << 8) + ifid[7]);
528 * Return an interface-id from
529 * one supplied in standard colon notation.
531 uint8_t *ifid_aton(char const *ifid_str, uint8_t *ifid)
533 static char const xdigits[] = "0123456789abcdef";
535 int num_id = 0, val = 0, idx = 0;
537 for (p = ifid_str; ; ++p) {
538 if (*p == ':' || *p == '\0') {
543 * Drop 'val' into the array.
545 ifid[idx] = (val >> 8) & 0xff;
546 ifid[idx + 1] = val & 0xff;
549 * Must have all entries before
560 } else if ((pch = strchr(xdigits, tolower(*p))) != NULL) {
564 * Dumb version of 'scanf'
567 val |= (pch - xdigits);
575 #ifndef HAVE_INET_PTON
576 static int inet_pton4(char const *src, struct in_addr *dst)
582 static char const digits[] = "0123456789";
588 while (*p && ((off = strchr(digits, *p)) != NULL)) {
590 num += (off - digits);
592 if (num > 255) return 0;
599 * Not a digit, MUST be a dot, else we
611 * End of the string. At the fourth
612 * octet is OK, anything else is an
620 memcpy(dst, &tmp, sizeof(tmp));
625 #ifdef HAVE_STRUCT_SOCKADDR_IN6
627 * inet_pton6(src, dst)
628 * convert presentation level address to network order binary form.
630 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
632 * (1) does not touch `dst' unless it's returning 1.
633 * (2) :: in a full address is silently ignored.
635 * inspired by Mark Andrews.
639 static int inet_pton6(char const *src, unsigned char *dst)
641 static char const xdigits_l[] = "0123456789abcdef",
642 xdigits_u[] = "0123456789ABCDEF";
643 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
644 char const *xdigits, *curtok;
648 memset((tp = tmp), 0, IN6ADDRSZ);
649 endp = tp + IN6ADDRSZ;
651 /* Leading :: requires some special handling. */
658 while ((ch = *src++) != '\0') {
661 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
662 pch = strchr((xdigits = xdigits_u), ch);
665 val |= (pch - xdigits);
679 if (tp + INT16SZ > endp)
681 *tp++ = (u_char) (val >> 8) & 0xff;
682 *tp++ = (u_char) val & 0xff;
687 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
688 inet_pton4(curtok, (struct in_addr *) tp) > 0) {
691 break; /* '\0' was seen by inet_pton4(). */
696 if (tp + INT16SZ > endp)
698 *tp++ = (u_char) (val >> 8) & 0xff;
699 *tp++ = (u_char) val & 0xff;
701 if (colonp != NULL) {
703 * Since some memmove()'s erroneously fail to handle
704 * overlapping regions, we'll do the shift by hand.
706 int const n = tp - colonp;
709 for (i = 1; i <= n; i++) {
710 endp[- i] = colonp[n - i];
717 /* bcopy(tmp, dst, IN6ADDRSZ); */
718 memcpy(dst, tmp, IN6ADDRSZ);
724 * Utility function, so that the rest of the server doesn't
725 * have ifdef's around IPv6 support
727 int inet_pton(int af, char const *src, void *dst)
730 return inet_pton4(src, dst);
732 #ifdef HAVE_STRUCT_SOCKADDR_IN6
734 if (af == AF_INET6) {
735 return inet_pton6(src, dst);
743 #ifndef HAVE_INET_NTOP
745 * Utility function, so that the rest of the server doesn't
746 * have ifdef's around IPv6 support
748 char const *inet_ntop(int af, void const *src, char *dst, size_t cnt)
751 uint8_t const *ipaddr = src;
753 if (cnt <= INET_ADDRSTRLEN) return NULL;
755 snprintf(dst, cnt, "%d.%d.%d.%d",
756 ipaddr[0], ipaddr[1],
757 ipaddr[2], ipaddr[3]);
762 * If the system doesn't define this, we define it
765 if (af == AF_INET6) {
766 struct in6_addr const *ipaddr = src;
768 if (cnt <= INET6_ADDRSTRLEN) return NULL;
770 snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
771 (ipaddr->s6_addr[0] << 8) | ipaddr->s6_addr[1],
772 (ipaddr->s6_addr[2] << 8) | ipaddr->s6_addr[3],
773 (ipaddr->s6_addr[4] << 8) | ipaddr->s6_addr[5],
774 (ipaddr->s6_addr[6] << 8) | ipaddr->s6_addr[7],
775 (ipaddr->s6_addr[8] << 8) | ipaddr->s6_addr[9],
776 (ipaddr->s6_addr[10] << 8) | ipaddr->s6_addr[11],
777 (ipaddr->s6_addr[12] << 8) | ipaddr->s6_addr[13],
778 (ipaddr->s6_addr[14] << 8) | ipaddr->s6_addr[15]);
782 return NULL; /* don't support IPv6 */
786 /** Wrappers for IPv4/IPv6 host to IP address lookup
788 * This function returns only one IP address, of the specified address family,
789 * or the first address (of whatever family), if AF_UNSPEC is used.
791 * If fallback is specified and af is AF_INET, but no AF_INET records were
792 * found and a record for AF_INET6 exists that record will be returned.
794 * If fallback is specified and af is AF_INET6, and a record with AF_INET4 exists
795 * that record will be returned instead.
797 * @param out Where to write result.
798 * @param af To search for in preference.
799 * @param hostname to search for.
800 * @param fallback to the other adress family, if no records matching af, found.
801 * @return 0 on success, else -1 on failure.
803 int ip_hton(fr_ipaddr_t *out, int af, char const *hostname, bool fallback)
806 struct addrinfo hints, *ai = NULL, *alt = NULL, *res = NULL;
808 if (!fr_hostname_lookups) {
809 #ifdef HAVE_STRUCT_SOCKADDR_IN6
810 if (af == AF_UNSPEC) {
813 for (p = hostname; *p != '\0'; p++) {
824 if (af == AF_UNSPEC) af = AF_INET;
826 if (!inet_pton(af, hostname, &(out->ipaddr))) {
834 memset(&hints, 0, sizeof(hints));
835 hints.ai_family = af;
839 * Avoid malloc for IP addresses. This helps us debug
840 * memory errors when using talloc.
844 * If it's all numeric, avoid getaddrinfo()
846 if (inet_pton(af, hostname, &out->ipaddr.ip4addr) == 1) {
852 if ((rcode = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
853 fr_strerror_printf("ip_hton: %s", gai_strerror(rcode));
857 for (ai = res; ai; ai = ai->ai_next) {
858 if ((af == ai->ai_family) || (af == AF_UNSPEC)) break;
859 if (!alt && fallback && ((ai->ai_family == AF_INET) || (ai->ai_family == AF_INET6))) alt = ai;
864 fr_strerror_printf("ip_hton failed to find requested information for host %.100s", hostname);
869 rcode = fr_sockaddr2ipaddr((struct sockaddr_storage *)ai->ai_addr,
870 ai->ai_addrlen, out, NULL);
872 if (!rcode) return -1;
878 * Look IP addresses up, and print names (depending on DNS config)
880 char const *ip_ntoh(fr_ipaddr_t const *src, char *dst, size_t cnt)
882 struct sockaddr_storage ss;
889 if (!fr_dns_lookups) {
890 return inet_ntop(src->af, &(src->ipaddr), dst, cnt);
893 if (!fr_ipaddr2sockaddr(src, 0, &ss, &salen)) {
897 if ((error = getnameinfo((struct sockaddr *)&ss, salen, dst, cnt, NULL, 0,
898 NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
899 fr_strerror_printf("ip_ntoh: %s", gai_strerror(error));
905 /** Mask off a portion of an IPv4 address
907 * @param ipaddr to mask.
908 * @param prefix Number of contiguous bits to mask.
909 * @return an ipv6 address with the host portion zeroed out.
911 struct in_addr fr_inaddr_mask(struct in_addr const *ipaddr, uint8_t prefix)
924 ret = htonl(~((0x00000001UL << (32 - prefix)) - 1)) & ipaddr->s_addr;
925 return (*(struct in_addr *)&ret);
928 /** Mask off a portion of an IPv6 address
930 * @param ipaddr to mask.
931 * @param prefix Number of contiguous bits to mask.
932 * @return an ipv6 address with the host portion zeroed out.
934 struct in6_addr fr_in6addr_mask(struct in6_addr const *ipaddr, uint8_t prefix)
936 uint64_t const *p = (uint64_t const *) ipaddr;
937 uint64_t ret[2], *o = ret;
950 *o++ = 0xffffffffffffffffULL & *p++;
955 *o = htonll(~((0x0000000000000001ULL << (64 - prefix)) - 1)) & *p;
957 return *(struct in6_addr *) &ret;
960 /** Zeroes out the host portion of an fr_ipaddr_t
962 * @param[in,out] addr to mask
963 * @param[in] prefix Length of the network portion.
965 void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
970 addr->ipaddr.ip4addr = fr_inaddr_mask(&addr->ipaddr.ip4addr, prefix);
974 addr->ipaddr.ip6addr = fr_in6addr_mask(&addr->ipaddr.ip6addr, prefix);
980 addr->prefix = prefix;
983 static char const *hextab = "0123456789abcdef";
985 /** Convert hex strings to binary data
987 * @param bin Buffer to write output to.
988 * @param hex input string.
989 * @param outlen length of output buffer (or length of input string / 2).
990 * @return length of data written to buffer.
992 size_t fr_hex2bin(uint8_t *bin, char const *hex, size_t outlen)
997 for (i = 0; i < outlen; i++) {
998 if(!(c1 = memchr(hextab, tolower((int) hex[i << 1]), 16)) ||
999 !(c2 = memchr(hextab, tolower((int) hex[(i << 1) + 1]), 16)))
1001 bin[i] = ((c1-hextab)<<4) + (c2-hextab);
1008 /** Convert binary data to a hex string
1010 * Ascii encoded hex string will not be prefixed with '0x'
1012 * @warning If the output buffer isn't long enough, we have a buffer overflow.
1014 * @param[out] hex Buffer to write hex output.
1015 * @param[in] bin input.
1016 * @param[in] inlen of bin input.
1017 * @return length of data written to buffer.
1019 size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen)
1023 for (i = 0; i < inlen; i++) {
1024 hex[0] = hextab[((*bin) >> 4) & 0x0f];
1025 hex[1] = hextab[*bin & 0x0f];
1036 /** Consume the integer (or hex) portion of a value string
1038 * @param value string to parse.
1039 * @param end pointer to the first non numeric char.
1040 * @return integer value.
1042 uint32_t fr_strtoul(char const *value, char **end)
1044 if ((value[0] == '0') && (value[1] == 'x')) {
1045 return strtoul(value, end, 16);
1048 return strtoul(value, end, 10);
1051 /** Check whether the string is all whitespace
1053 * @return true if the entirety of the string is whitespace, else false.
1055 bool is_whitespace(char const *value)
1058 if (!isspace(*value)) return false;
1064 /** Check whether the string is all numbers
1066 * @return true if the entirety of the string is are numebrs, else false.
1068 bool is_integer(char const *value)
1071 if (!isdigit(*value)) return false;
1077 /** Check whether the string is allzeros
1079 * @return true if the entirety of the string is are numebrs, else false.
1081 bool is_zero(char const *value)
1084 if (*value != '0') return false;
1091 * So we don't have ifdef's in the rest of the code
1093 #ifndef HAVE_CLOSEFROM
1094 int closefrom(int fd)
1100 maxfd = sysconf(_SC_OPEN_MAX);
1106 if (fd > maxfd) return 0;
1109 * FIXME: return EINTR?
1113 for (i = fd; i < maxfd; i++) {
1121 int fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
1123 if (a->af < b->af) return -1;
1124 if (a->af > b->af) return +1;
1128 return memcmp(&a->ipaddr.ip4addr,
1130 sizeof(a->ipaddr.ip4addr));
1133 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1135 if (a->scope < b->scope) return -1;
1136 if (a->scope > b->scope) return +1;
1138 return memcmp(&a->ipaddr.ip6addr,
1140 sizeof(a->ipaddr.ip6addr));
1151 int fr_ipaddr2sockaddr(fr_ipaddr_t const *ipaddr, uint16_t port,
1152 struct sockaddr_storage *sa, socklen_t *salen)
1154 if (ipaddr->af == AF_INET) {
1155 struct sockaddr_in s4;
1157 *salen = sizeof(s4);
1159 memset(&s4, 0, sizeof(s4));
1160 s4.sin_family = AF_INET;
1161 s4.sin_addr = ipaddr->ipaddr.ip4addr;
1162 s4.sin_port = htons(port);
1163 memset(sa, 0, sizeof(*sa));
1164 memcpy(sa, &s4, sizeof(s4));
1166 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1167 } else if (ipaddr->af == AF_INET6) {
1168 struct sockaddr_in6 s6;
1170 *salen = sizeof(s6);
1172 memset(&s6, 0, sizeof(s6));
1173 s6.sin6_family = AF_INET6;
1174 s6.sin6_addr = ipaddr->ipaddr.ip6addr;
1175 s6.sin6_port = htons(port);
1176 s6.sin6_scope_id = ipaddr->scope;
1177 memset(sa, 0, sizeof(*sa));
1178 memcpy(sa, &s6, sizeof(s6));
1188 int fr_sockaddr2ipaddr(struct sockaddr_storage const *sa, socklen_t salen,
1189 fr_ipaddr_t *ipaddr, uint16_t *port)
1191 if (sa->ss_family == AF_INET) {
1192 struct sockaddr_in s4;
1194 if (salen < sizeof(s4)) {
1195 fr_strerror_printf("IPv4 address is too small");
1199 memcpy(&s4, sa, sizeof(s4));
1200 ipaddr->af = AF_INET;
1201 ipaddr->prefix = 32;
1202 ipaddr->ipaddr.ip4addr = s4.sin_addr;
1203 if (port) *port = ntohs(s4.sin_port);
1205 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1206 } else if (sa->ss_family == AF_INET6) {
1207 struct sockaddr_in6 s6;
1209 if (salen < sizeof(s6)) {
1210 fr_strerror_printf("IPv6 address is too small");
1214 memcpy(&s6, sa, sizeof(s6));
1215 ipaddr->af = AF_INET6;
1216 ipaddr->prefix = 128;
1217 ipaddr->ipaddr.ip6addr = s6.sin6_addr;
1218 if (port) *port = ntohs(s6.sin6_port);
1219 ipaddr->scope = s6.sin6_scope_id;
1223 fr_strerror_printf("Unsupported address famility %d",
1231 /** Convert UTF8 string to UCS2 encoding
1233 * @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
1235 * @param[out] out Where to write the ucs2 string.
1236 * @param[in] outlen Size of output buffer.
1237 * @param[in] in UTF8 string to convert.
1238 * @param[in] inlen length of UTF8 string.
1239 * @return the size of the UCS2 string written to the output buffer (in bytes).
1241 ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
1244 uint8_t *start = out;
1246 for (i = 0; i < inlen; i++) {
1250 if ((size_t)(out - start) >= outlen) {
1251 /* input too long */
1255 /* One-byte encoding */
1257 FR_PUT_LE16(out, c);
1260 } else if ((i == (inlen - 1)) || ((size_t)(out - start) >= (outlen - 1))) {
1261 /* Incomplete surrogate */
1266 /* Two-byte encoding */
1267 if ((c & 0xe0) == 0xc0) {
1268 FR_PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
1272 if ((i == inlen) || ((size_t)(out - start) >= (outlen - 1))) {
1273 /* Incomplete surrogate */
1277 /* Three-byte encoding */
1279 FR_PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
1286 /** Write 128bit unsigned integer to buffer
1288 * @author Alexey Frunze
1290 * @param out where to write result to.
1291 * @param outlen size of out.
1292 * @param num 128 bit integer.
1294 size_t fr_prints_uint128(char *out, size_t outlen, uint128_t const num)
1296 char buff[128 / 3 + 1 + 1];
1301 memset(buff, '0', sizeof(buff) - 1);
1302 buff[sizeof(buff) - 1] = '\0';
1304 memcpy(n, &num, sizeof(n));
1306 for (i = 0; i < 128; i++) {
1310 carry = (n[1] >= 0x8000000000000000);
1312 // Shift n[] left, doubling it
1313 n[1] = ((n[1] << 1) & 0xffffffffffffffff) + (n[0] >= 0x8000000000000000);
1314 n[0] = ((n[0] << 1) & 0xffffffffffffffff);
1316 // Add s[] to itself in decimal, doubling it
1317 for (j = sizeof(buff) - 2; j >= 0; j--) {
1318 buff[j] += buff[j] - '0' + carry;
1319 carry = (buff[j] > '9');
1326 while ((*p == '0') && (p < &buff[sizeof(buff) - 2])) {
1330 return strlcpy(out, p, outlen);
1333 /** Calculate powers
1335 * @author Orson Peters
1336 * @note Borrowed from the gist here: https://gist.github.com/nightcracker/3551590.
1338 * @param base a 32bit signed integer.
1339 * @param exp amount to raise base by.
1340 * @return base ^ pow, or 0 on underflow/overflow.
1342 int64_t fr_pow(int32_t base, uint8_t exp) {
1343 static const uint8_t highest_bit_set[] = {
1344 0, 1, 2, 2, 3, 3, 3, 3,
1345 4, 4, 4, 4, 4, 4, 4, 4,
1346 5, 5, 5, 5, 5, 5, 5, 5,
1347 5, 5, 5, 5, 5, 5, 5, 5,
1348 6, 6, 6, 6, 6, 6, 6, 6,
1349 6, 6, 6, 6, 6, 6, 6, 6,
1350 6, 6, 6, 6, 6, 6, 6, 6,
1351 6, 6, 6, 6, 6, 6, 6, 255, // anything past 63 is a guaranteed overflow with base > 1
1352 255, 255, 255, 255, 255, 255, 255, 255,
1353 255, 255, 255, 255, 255, 255, 255, 255,
1354 255, 255, 255, 255, 255, 255, 255, 255,
1355 255, 255, 255, 255, 255, 255, 255, 255,
1356 255, 255, 255, 255, 255, 255, 255, 255,
1357 255, 255, 255, 255, 255, 255, 255, 255,
1358 255, 255, 255, 255, 255, 255, 255, 255,
1359 255, 255, 255, 255, 255, 255, 255, 255,
1360 255, 255, 255, 255, 255, 255, 255, 255,
1361 255, 255, 255, 255, 255, 255, 255, 255,
1362 255, 255, 255, 255, 255, 255, 255, 255,
1363 255, 255, 255, 255, 255, 255, 255, 255,
1364 255, 255, 255, 255, 255, 255, 255, 255,
1365 255, 255, 255, 255, 255, 255, 255, 255,
1366 255, 255, 255, 255, 255, 255, 255, 255,
1367 255, 255, 255, 255, 255, 255, 255, 255,
1368 255, 255, 255, 255, 255, 255, 255, 255,
1369 255, 255, 255, 255, 255, 255, 255, 255,
1370 255, 255, 255, 255, 255, 255, 255, 255,
1371 255, 255, 255, 255, 255, 255, 255, 255,
1372 255, 255, 255, 255, 255, 255, 255, 255,
1373 255, 255, 255, 255, 255, 255, 255, 255,
1374 255, 255, 255, 255, 255, 255, 255, 255,
1375 255, 255, 255, 255, 255, 255, 255, 255,
1378 uint64_t result = 1;
1380 switch (highest_bit_set[exp]) {
1381 case 255: // we use 255 as an overflow marker and return 0 on overflow/underflow
1387 return 1 - 2 * (exp & 1);
1391 if (exp & 1) result *= base;
1395 if (exp & 1) result *= base;
1399 if (exp & 1) result *= base;
1403 if (exp & 1) result *= base;
1407 if (exp & 1) result *= base;
1411 if (exp & 1) result *= base;
1418 * Sort of strtok/strsep function.
1420 static char *mystrtok(char **ptr, char const *sep)
1428 while (**ptr && strchr(sep, **ptr)) {
1436 while (**ptr && strchr(sep, **ptr) == NULL) {
1446 /** Convert string in various formats to a time_t
1448 * @param date_str input date string.
1449 * @param date time_t to write result to.
1450 * @return 0 on success or -1 on error.
1452 int fr_get_time(char const *date_str, time_t *date)
1456 struct tm *tm, s_tm;
1463 * Test for unix timestamp date
1465 *date = strtoul(date_str, &tail, 10);
1466 if (*tail == '\0') {
1471 memset(tm, 0, sizeof(*tm));
1472 tm->tm_isdst = -1; /* don't know, and don't care about DST */
1474 strlcpy(buf, date_str, sizeof(buf));
1477 f[0] = mystrtok(&p, " \t");
1478 f[1] = mystrtok(&p, " \t");
1479 f[2] = mystrtok(&p, " \t");
1480 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
1481 if (!f[0] || !f[1] || !f[2]) return -1;
1484 * The time has a colon, where nothing else does.
1485 * So if we find it, bubble it to the back of the list.
1488 for (i = 0; i < 3; i++) {
1489 if (strchr(f[i], ':')) {
1499 * The month is text, which allows us to find it easily.
1502 for (i = 0; i < 3; i++) {
1503 if (isalpha( (int) *f[i])) {
1505 * Bubble the month to the front of the list
1511 for (i = 0; i < 12; i++) {
1512 if (strncasecmp(months[i], f[0], 3) == 0) {
1520 /* month not found? */
1521 if (tm->tm_mon == 12) return -1;
1524 * The year may be in f[1], or in f[2]
1526 tm->tm_year = atoi(f[1]);
1527 tm->tm_mday = atoi(f[2]);
1529 if (tm->tm_year >= 1900) {
1530 tm->tm_year -= 1900;
1534 * We can't use 2-digit years any more, they make it
1535 * impossible to tell what's the day, and what's the year.
1537 if (tm->tm_mday < 1900) return -1;
1540 * Swap the year and the day.
1543 tm->tm_year = tm->tm_mday - 1900;
1548 * If the day is out of range, die.
1550 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
1555 * There may be %H:%M:%S. Parse it in a hacky way.
1558 f[0] = f[3]; /* HH */
1559 f[1] = strchr(f[0], ':'); /* find : separator */
1560 if (!f[1]) return -1;
1562 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
1564 f[2] = strchr(f[1], ':'); /* find : separator */
1566 *(f[2]++) = '\0'; /* nuke it, and point to SS */
1567 tm->tm_sec = atoi(f[2]);
1568 } /* else leave it as zero */
1570 tm->tm_hour = atoi(f[0]);
1571 tm->tm_min = atoi(f[1]);
1575 * Returns -1 on error.
1578 if (t == (time_t) -1) return -1;
1585 /** Compares two pointers
1587 * @param a first pointer to compare.
1588 * @param b second pointer to compare.
1589 * @return -1 if a < b, +1 if b > a, or 0 if both equal.
1591 int8_t fr_pointer_cmp(void const *a, void const *b)
1593 if (a < b) return -1;
1594 if (a == b) return 0;
1599 static int _quick_partition(void const *to_sort[], int min, int max, fr_cmp_t cmp) {
1600 void const *pivot = to_sort[min];
1606 do ++i; while((cmp(to_sort[i], pivot) <= 0) && i <= max);
1607 do --j; while(cmp(to_sort[j], pivot) > 0);
1612 to_sort[i] = to_sort[j];
1617 to_sort[min] = to_sort[j];
1623 /** Quick sort an array of pointers using a comparator
1625 * @param to_sort array of pointers to sort.
1626 * @param min_idx the lowest index (usually 0).
1627 * @param max_idx the highest index (usually length of array - 1).
1628 * @param cmp the comparison function to use to sort the array elements.
1630 void fr_quick_sort(void const *to_sort[], int min_idx, int max_idx, fr_cmp_t cmp)
1634 if (min_idx >= max_idx) return;
1636 part = _quick_partition(to_sort, min_idx, max_idx, cmp);
1637 fr_quick_sort(to_sort, min_idx, part - 1, cmp);
1638 fr_quick_sort(to_sort, part + 1, max_idx, cmp);
1642 void fr_talloc_verify_cb(UNUSED const void *ptr, UNUSED int depth,
1643 UNUSED int max_depth, UNUSED int is_ref,
1644 UNUSED void *private_data)