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)
384 len = (inlen == 0) ? strlen(value) : inlen;
385 for (i = 0; i < len; i++) switch (value[i]) {
387 * Chars illegal in domain names and IPv4 addresses.
388 * Must be v6 and cannot be a domain.
393 return fr_pton6(out, value, inlen, false, false);
396 * Chars which don't really tell us anything
404 * Outside the range of IPv4 chars, must be a domain
405 * Use A record in preference to AAAA record.
407 if ((value[i] < '0') || (value[i] > '9')) {
408 if (!resolve) return -1;
409 return fr_pton4(out, value, inlen, true, true);
415 * All chars were in the IPv4 set [0-9/.], must be an IPv4
418 return fr_pton4(out, value, inlen, false, false);
421 /** Check if the IP address is equivalent to INADDR_ANY
423 * @param addr to chec.
424 * @return true if IP address matches INADDR_ANY or INADDR6_ANY (assumed to be 0), else false.
426 bool is_wildcard(fr_ipaddr_t *addr)
428 static struct in6_addr in6_addr;
432 return (addr->ipaddr.ip4addr.s_addr == htons(INADDR_ANY));
435 return (memcmp(addr->ipaddr.ip6addr.s6_addr, in6_addr.s6_addr, sizeof(in6_addr.s6_addr)) == 0) ? true :false;
443 int fr_ntop(char *out, size_t outlen, fr_ipaddr_t *addr)
445 char buffer[INET6_ADDRSTRLEN];
447 if (inet_ntop(addr->af, &(addr->ipaddr), buffer, sizeof(buffer)) == NULL) return -1;
449 return snprintf(out, outlen, "%s/%i", buffer, addr->prefix);
453 * Internal wrapper for locking, to minimize the number of ifdef's
457 int rad_lockfd(int fd, int lock_len)
466 fl.l_whence = SEEK_CUR;
468 return fcntl(fd, F_SETLKW, (void *)&fl);
470 #error "missing definition for F_WRLCK, all file locks will fail"
477 * Internal wrapper for locking, to minimize the number of ifdef's
479 * Lock an fd, prefer lockf() over flock()
480 * Nonblocking version.
482 int rad_lockfd_nonblock(int fd, int lock_len)
491 fl.l_whence = SEEK_CUR;
493 return fcntl(fd, F_SETLK, (void *)&fl);
495 #error "missing definition for F_WRLCK, all file locks will fail"
502 * Internal wrapper for unlocking, to minimize the number of ifdef's
505 * Unlock an fd, prefer lockf() over flock()
507 int rad_unlockfd(int fd, int lock_len)
516 fl.l_whence = SEEK_CUR;
518 return fcntl(fd, F_UNLCK, (void *)&fl);
520 #error "missing definition for F_WRLCK, all file locks will fail"
527 * Return an interface-id in standard colon notation
529 char *ifid_ntoa(char *buffer, size_t size, uint8_t const *ifid)
531 snprintf(buffer, size, "%x:%x:%x:%x",
532 (ifid[0] << 8) + ifid[1], (ifid[2] << 8) + ifid[3],
533 (ifid[4] << 8) + ifid[5], (ifid[6] << 8) + ifid[7]);
539 * Return an interface-id from
540 * one supplied in standard colon notation.
542 uint8_t *ifid_aton(char const *ifid_str, uint8_t *ifid)
544 static char const xdigits[] = "0123456789abcdef";
546 int num_id = 0, val = 0, idx = 0;
548 for (p = ifid_str; ; ++p) {
549 if (*p == ':' || *p == '\0') {
554 * Drop 'val' into the array.
556 ifid[idx] = (val >> 8) & 0xff;
557 ifid[idx + 1] = val & 0xff;
560 * Must have all entries before
571 } else if ((pch = strchr(xdigits, tolower(*p))) != NULL) {
575 * Dumb version of 'scanf'
578 val |= (pch - xdigits);
586 #ifndef HAVE_INET_PTON
587 static int inet_pton4(char const *src, struct in_addr *dst)
593 static char const digits[] = "0123456789";
599 while (*p && ((off = strchr(digits, *p)) != NULL)) {
601 num += (off - digits);
603 if (num > 255) return 0;
610 * Not a digit, MUST be a dot, else we
622 * End of the string. At the fourth
623 * octet is OK, anything else is an
631 memcpy(dst, &tmp, sizeof(tmp));
636 #ifdef HAVE_STRUCT_SOCKADDR_IN6
638 * inet_pton6(src, dst)
639 * convert presentation level address to network order binary form.
641 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
643 * (1) does not touch `dst' unless it's returning 1.
644 * (2) :: in a full address is silently ignored.
646 * inspired by Mark Andrews.
650 static int inet_pton6(char const *src, unsigned char *dst)
652 static char const xdigits_l[] = "0123456789abcdef",
653 xdigits_u[] = "0123456789ABCDEF";
654 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
655 char const *xdigits, *curtok;
659 memset((tp = tmp), 0, IN6ADDRSZ);
660 endp = tp + IN6ADDRSZ;
662 /* Leading :: requires some special handling. */
669 while ((ch = *src++) != '\0') {
672 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
673 pch = strchr((xdigits = xdigits_u), ch);
676 val |= (pch - xdigits);
690 if (tp + INT16SZ > endp)
692 *tp++ = (u_char) (val >> 8) & 0xff;
693 *tp++ = (u_char) val & 0xff;
698 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
699 inet_pton4(curtok, (struct in_addr *) tp) > 0) {
702 break; /* '\0' was seen by inet_pton4(). */
707 if (tp + INT16SZ > endp)
709 *tp++ = (u_char) (val >> 8) & 0xff;
710 *tp++ = (u_char) val & 0xff;
712 if (colonp != NULL) {
714 * Since some memmove()'s erroneously fail to handle
715 * overlapping regions, we'll do the shift by hand.
717 int const n = tp - colonp;
720 for (i = 1; i <= n; i++) {
721 endp[- i] = colonp[n - i];
728 /* bcopy(tmp, dst, IN6ADDRSZ); */
729 memcpy(dst, tmp, IN6ADDRSZ);
735 * Utility function, so that the rest of the server doesn't
736 * have ifdef's around IPv6 support
738 int inet_pton(int af, char const *src, void *dst)
741 return inet_pton4(src, dst);
743 #ifdef HAVE_STRUCT_SOCKADDR_IN6
745 if (af == AF_INET6) {
746 return inet_pton6(src, dst);
754 #ifndef HAVE_INET_NTOP
756 * Utility function, so that the rest of the server doesn't
757 * have ifdef's around IPv6 support
759 char const *inet_ntop(int af, void const *src, char *dst, size_t cnt)
762 uint8_t const *ipaddr = src;
764 if (cnt <= INET_ADDRSTRLEN) return NULL;
766 snprintf(dst, cnt, "%d.%d.%d.%d",
767 ipaddr[0], ipaddr[1],
768 ipaddr[2], ipaddr[3]);
773 * If the system doesn't define this, we define it
776 if (af == AF_INET6) {
777 struct in6_addr const *ipaddr = src;
779 if (cnt <= INET6_ADDRSTRLEN) return NULL;
781 snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
782 (ipaddr->s6_addr[0] << 8) | ipaddr->s6_addr[1],
783 (ipaddr->s6_addr[2] << 8) | ipaddr->s6_addr[3],
784 (ipaddr->s6_addr[4] << 8) | ipaddr->s6_addr[5],
785 (ipaddr->s6_addr[6] << 8) | ipaddr->s6_addr[7],
786 (ipaddr->s6_addr[8] << 8) | ipaddr->s6_addr[9],
787 (ipaddr->s6_addr[10] << 8) | ipaddr->s6_addr[11],
788 (ipaddr->s6_addr[12] << 8) | ipaddr->s6_addr[13],
789 (ipaddr->s6_addr[14] << 8) | ipaddr->s6_addr[15]);
793 return NULL; /* don't support IPv6 */
797 /** Wrappers for IPv4/IPv6 host to IP address lookup
799 * This function returns only one IP address, of the specified address family,
800 * or the first address (of whatever family), if AF_UNSPEC is used.
802 * If fallback is specified and af is AF_INET, but no AF_INET records were
803 * found and a record for AF_INET6 exists that record will be returned.
805 * If fallback is specified and af is AF_INET6, and a record with AF_INET4 exists
806 * that record will be returned instead.
808 * @param out Where to write result.
809 * @param af To search for in preference.
810 * @param hostname to search for.
811 * @param fallback to the other adress family, if no records matching af, found.
812 * @return 0 on success, else -1 on failure.
814 int ip_hton(fr_ipaddr_t *out, int af, char const *hostname, bool fallback)
817 struct addrinfo hints, *ai = NULL, *alt = NULL, *res = NULL;
819 if (!fr_hostname_lookups) {
820 #ifdef HAVE_STRUCT_SOCKADDR_IN6
821 if (af == AF_UNSPEC) {
824 for (p = hostname; *p != '\0'; p++) {
835 if (af == AF_UNSPEC) af = AF_INET;
837 if (!inet_pton(af, hostname, &(out->ipaddr))) {
845 memset(&hints, 0, sizeof(hints));
846 hints.ai_family = af;
850 * Avoid malloc for IP addresses. This helps us debug
851 * memory errors when using talloc.
855 * If it's all numeric, avoid getaddrinfo()
857 if (inet_pton(af, hostname, &out->ipaddr.ip4addr) == 1) {
863 if ((rcode = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
864 fr_strerror_printf("ip_hton: %s", gai_strerror(rcode));
868 for (ai = res; ai; ai = ai->ai_next) {
869 if ((af == ai->ai_family) || (af == AF_UNSPEC)) break;
870 if (!alt && fallback && ((ai->ai_family == AF_INET) || (ai->ai_family == AF_INET6))) alt = ai;
875 fr_strerror_printf("ip_hton failed to find requested information for host %.100s", hostname);
880 rcode = fr_sockaddr2ipaddr((struct sockaddr_storage *)ai->ai_addr,
881 ai->ai_addrlen, out, NULL);
883 if (!rcode) return -1;
889 * Look IP addresses up, and print names (depending on DNS config)
891 char const *ip_ntoh(fr_ipaddr_t const *src, char *dst, size_t cnt)
893 struct sockaddr_storage ss;
900 if (!fr_dns_lookups) {
901 return inet_ntop(src->af, &(src->ipaddr), dst, cnt);
904 if (!fr_ipaddr2sockaddr(src, 0, &ss, &salen)) {
908 if ((error = getnameinfo((struct sockaddr *)&ss, salen, dst, cnt, NULL, 0,
909 NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
910 fr_strerror_printf("ip_ntoh: %s", gai_strerror(error));
916 /** Mask off a portion of an IPv4 address
918 * @param ipaddr to mask.
919 * @param prefix Number of contiguous bits to mask.
920 * @return an ipv6 address with the host portion zeroed out.
922 struct in_addr fr_inaddr_mask(struct in_addr const *ipaddr, uint8_t prefix)
935 ret = htonl(~((0x00000001UL << (32 - prefix)) - 1)) & ipaddr->s_addr;
936 return (*(struct in_addr *)&ret);
939 /** Mask off a portion of an IPv6 address
941 * @param ipaddr to mask.
942 * @param prefix Number of contiguous bits to mask.
943 * @return an ipv6 address with the host portion zeroed out.
945 struct in6_addr fr_in6addr_mask(struct in6_addr const *ipaddr, uint8_t prefix)
947 uint64_t const *p = (uint64_t const *) ipaddr;
948 uint64_t ret[2], *o = ret;
961 *o++ = 0xffffffffffffffffULL & *p++;
966 *o = htonll(~((0x0000000000000001ULL << (64 - prefix)) - 1)) & *p;
968 return *(struct in6_addr *) &ret;
971 /** Zeroes out the host portion of an fr_ipaddr_t
973 * @param[in,out] addr to mask
974 * @param[in] prefix Length of the network portion.
976 void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
981 addr->ipaddr.ip4addr = fr_inaddr_mask(&addr->ipaddr.ip4addr, prefix);
985 addr->ipaddr.ip6addr = fr_in6addr_mask(&addr->ipaddr.ip6addr, prefix);
991 addr->prefix = prefix;
994 static char const *hextab = "0123456789abcdef";
996 /** Convert hex strings to binary data
998 * @param bin Buffer to write output to.
999 * @param hex input string.
1000 * @param outlen length of output buffer (or length of input string / 2).
1001 * @return length of data written to buffer.
1003 size_t fr_hex2bin(uint8_t *bin, char const *hex, size_t outlen)
1008 for (i = 0; i < outlen; i++) {
1009 if(!(c1 = memchr(hextab, tolower((int) hex[i << 1]), 16)) ||
1010 !(c2 = memchr(hextab, tolower((int) hex[(i << 1) + 1]), 16)))
1012 bin[i] = ((c1-hextab)<<4) + (c2-hextab);
1019 /** Convert binary data to a hex string
1021 * Ascii encoded hex string will not be prefixed with '0x'
1023 * @warning If the output buffer isn't long enough, we have a buffer overflow.
1025 * @param[out] hex Buffer to write hex output.
1026 * @param[in] bin input.
1027 * @param[in] inlen of bin input.
1028 * @return length of data written to buffer.
1030 size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen)
1034 for (i = 0; i < inlen; i++) {
1035 hex[0] = hextab[((*bin) >> 4) & 0x0f];
1036 hex[1] = hextab[*bin & 0x0f];
1047 /** Consume the integer (or hex) portion of a value string
1049 * @param value string to parse.
1050 * @param end pointer to the first non numeric char.
1051 * @return integer value.
1053 uint32_t fr_strtoul(char const *value, char **end)
1055 if ((value[0] == '0') && (value[1] == 'x')) {
1056 return strtoul(value, end, 16);
1059 return strtoul(value, end, 10);
1062 /** Check whether the string is all whitespace
1064 * @return true if the entirety of the string is whitespace, else false.
1066 bool is_whitespace(char const *value)
1069 if (!isspace(*value)) return false;
1075 /** Check whether the string is all numbers
1077 * @return true if the entirety of the string is are numebrs, else false.
1079 bool is_integer(char const *value)
1082 if (!isdigit(*value)) return false;
1088 /** Check whether the string is allzeros
1090 * @return true if the entirety of the string is are numebrs, else false.
1092 bool is_zero(char const *value)
1095 if (*value != '0') return false;
1102 * So we don't have ifdef's in the rest of the code
1104 #ifndef HAVE_CLOSEFROM
1105 int closefrom(int fd)
1111 maxfd = sysconf(_SC_OPEN_MAX);
1117 if (fd > maxfd) return 0;
1120 * FIXME: return EINTR?
1124 for (i = fd; i < maxfd; i++) {
1132 int fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
1134 if (a->af < b->af) return -1;
1135 if (a->af > b->af) return +1;
1139 return memcmp(&a->ipaddr.ip4addr,
1141 sizeof(a->ipaddr.ip4addr));
1144 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1146 if (a->scope < b->scope) return -1;
1147 if (a->scope > b->scope) return +1;
1149 return memcmp(&a->ipaddr.ip6addr,
1151 sizeof(a->ipaddr.ip6addr));
1162 int fr_ipaddr2sockaddr(fr_ipaddr_t const *ipaddr, uint16_t port,
1163 struct sockaddr_storage *sa, socklen_t *salen)
1165 if (ipaddr->af == AF_INET) {
1166 struct sockaddr_in s4;
1168 *salen = sizeof(s4);
1170 memset(&s4, 0, sizeof(s4));
1171 s4.sin_family = AF_INET;
1172 s4.sin_addr = ipaddr->ipaddr.ip4addr;
1173 s4.sin_port = htons(port);
1174 memset(sa, 0, sizeof(*sa));
1175 memcpy(sa, &s4, sizeof(s4));
1177 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1178 } else if (ipaddr->af == AF_INET6) {
1179 struct sockaddr_in6 s6;
1181 *salen = sizeof(s6);
1183 memset(&s6, 0, sizeof(s6));
1184 s6.sin6_family = AF_INET6;
1185 s6.sin6_addr = ipaddr->ipaddr.ip6addr;
1186 s6.sin6_port = htons(port);
1187 s6.sin6_scope_id = ipaddr->scope;
1188 memset(sa, 0, sizeof(*sa));
1189 memcpy(sa, &s6, sizeof(s6));
1199 int fr_sockaddr2ipaddr(struct sockaddr_storage const *sa, socklen_t salen,
1200 fr_ipaddr_t *ipaddr, uint16_t *port)
1202 if (sa->ss_family == AF_INET) {
1203 struct sockaddr_in s4;
1205 if (salen < sizeof(s4)) {
1206 fr_strerror_printf("IPv4 address is too small");
1210 memcpy(&s4, sa, sizeof(s4));
1211 ipaddr->af = AF_INET;
1212 ipaddr->prefix = 32;
1213 ipaddr->ipaddr.ip4addr = s4.sin_addr;
1214 if (port) *port = ntohs(s4.sin_port);
1216 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1217 } else if (sa->ss_family == AF_INET6) {
1218 struct sockaddr_in6 s6;
1220 if (salen < sizeof(s6)) {
1221 fr_strerror_printf("IPv6 address is too small");
1225 memcpy(&s6, sa, sizeof(s6));
1226 ipaddr->af = AF_INET6;
1227 ipaddr->prefix = 128;
1228 ipaddr->ipaddr.ip6addr = s6.sin6_addr;
1229 if (port) *port = ntohs(s6.sin6_port);
1230 ipaddr->scope = s6.sin6_scope_id;
1234 fr_strerror_printf("Unsupported address famility %d",
1242 /** Convert UTF8 string to UCS2 encoding
1244 * @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
1246 * @param[out] out Where to write the ucs2 string.
1247 * @param[in] outlen Size of output buffer.
1248 * @param[in] in UTF8 string to convert.
1249 * @param[in] inlen length of UTF8 string.
1250 * @return the size of the UCS2 string written to the output buffer (in bytes).
1252 ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
1255 uint8_t *start = out;
1257 for (i = 0; i < inlen; i++) {
1261 if ((size_t)(out - start) >= outlen) {
1262 /* input too long */
1266 /* One-byte encoding */
1268 FR_PUT_LE16(out, c);
1271 } else if ((i == (inlen - 1)) || ((size_t)(out - start) >= (outlen - 1))) {
1272 /* Incomplete surrogate */
1277 /* Two-byte encoding */
1278 if ((c & 0xe0) == 0xc0) {
1279 FR_PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
1283 if ((i == inlen) || ((size_t)(out - start) >= (outlen - 1))) {
1284 /* Incomplete surrogate */
1288 /* Three-byte encoding */
1290 FR_PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
1297 /** Write 128bit unsigned integer to buffer
1299 * @author Alexey Frunze
1301 * @param out where to write result to.
1302 * @param outlen size of out.
1303 * @param num 128 bit integer.
1305 size_t fr_prints_uint128(char *out, size_t outlen, uint128_t const num)
1307 char buff[128 / 3 + 1 + 1];
1312 memset(buff, '0', sizeof(buff) - 1);
1313 buff[sizeof(buff) - 1] = '\0';
1315 memcpy(n, &num, sizeof(n));
1317 for (i = 0; i < 128; i++) {
1321 carry = (n[1] >= 0x8000000000000000);
1323 // Shift n[] left, doubling it
1324 n[1] = ((n[1] << 1) & 0xffffffffffffffff) + (n[0] >= 0x8000000000000000);
1325 n[0] = ((n[0] << 1) & 0xffffffffffffffff);
1327 // Add s[] to itself in decimal, doubling it
1328 for (j = sizeof(buff) - 2; j >= 0; j--) {
1329 buff[j] += buff[j] - '0' + carry;
1330 carry = (buff[j] > '9');
1337 while ((*p == '0') && (p < &buff[sizeof(buff) - 2])) {
1341 return strlcpy(out, p, outlen);
1344 /** Calculate powers
1346 * @author Orson Peters
1347 * @note Borrowed from the gist here: https://gist.github.com/nightcracker/3551590.
1349 * @param base a 32bit signed integer.
1350 * @param exp amount to raise base by.
1351 * @return base ^ pow, or 0 on underflow/overflow.
1353 int64_t fr_pow(int32_t base, uint8_t exp) {
1354 static const uint8_t highest_bit_set[] = {
1355 0, 1, 2, 2, 3, 3, 3, 3,
1356 4, 4, 4, 4, 4, 4, 4, 4,
1357 5, 5, 5, 5, 5, 5, 5, 5,
1358 5, 5, 5, 5, 5, 5, 5, 5,
1359 6, 6, 6, 6, 6, 6, 6, 6,
1360 6, 6, 6, 6, 6, 6, 6, 6,
1361 6, 6, 6, 6, 6, 6, 6, 6,
1362 6, 6, 6, 6, 6, 6, 6, 255, // anything past 63 is a guaranteed overflow with base > 1
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,
1376 255, 255, 255, 255, 255, 255, 255, 255,
1377 255, 255, 255, 255, 255, 255, 255, 255,
1378 255, 255, 255, 255, 255, 255, 255, 255,
1379 255, 255, 255, 255, 255, 255, 255, 255,
1380 255, 255, 255, 255, 255, 255, 255, 255,
1381 255, 255, 255, 255, 255, 255, 255, 255,
1382 255, 255, 255, 255, 255, 255, 255, 255,
1383 255, 255, 255, 255, 255, 255, 255, 255,
1384 255, 255, 255, 255, 255, 255, 255, 255,
1385 255, 255, 255, 255, 255, 255, 255, 255,
1386 255, 255, 255, 255, 255, 255, 255, 255,
1389 uint64_t result = 1;
1391 switch (highest_bit_set[exp]) {
1392 case 255: // we use 255 as an overflow marker and return 0 on overflow/underflow
1398 return 1 - 2 * (exp & 1);
1402 if (exp & 1) result *= base;
1406 if (exp & 1) result *= base;
1410 if (exp & 1) result *= base;
1414 if (exp & 1) result *= base;
1418 if (exp & 1) result *= base;
1422 if (exp & 1) result *= base;
1429 * Sort of strtok/strsep function.
1431 static char *mystrtok(char **ptr, char const *sep)
1439 while (**ptr && strchr(sep, **ptr)) {
1447 while (**ptr && strchr(sep, **ptr) == NULL) {
1457 /** Convert string in various formats to a time_t
1459 * @param date_str input date string.
1460 * @param date time_t to write result to.
1461 * @return 0 on success or -1 on error.
1463 int fr_get_time(char const *date_str, time_t *date)
1467 struct tm *tm, s_tm;
1474 * Test for unix timestamp date
1476 *date = strtoul(date_str, &tail, 10);
1477 if (*tail == '\0') {
1482 memset(tm, 0, sizeof(*tm));
1483 tm->tm_isdst = -1; /* don't know, and don't care about DST */
1485 strlcpy(buf, date_str, sizeof(buf));
1488 f[0] = mystrtok(&p, " \t");
1489 f[1] = mystrtok(&p, " \t");
1490 f[2] = mystrtok(&p, " \t");
1491 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
1492 if (!f[0] || !f[1] || !f[2]) return -1;
1495 * The time has a colon, where nothing else does.
1496 * So if we find it, bubble it to the back of the list.
1499 for (i = 0; i < 3; i++) {
1500 if (strchr(f[i], ':')) {
1510 * The month is text, which allows us to find it easily.
1513 for (i = 0; i < 3; i++) {
1514 if (isalpha( (int) *f[i])) {
1516 * Bubble the month to the front of the list
1522 for (i = 0; i < 12; i++) {
1523 if (strncasecmp(months[i], f[0], 3) == 0) {
1531 /* month not found? */
1532 if (tm->tm_mon == 12) return -1;
1535 * The year may be in f[1], or in f[2]
1537 tm->tm_year = atoi(f[1]);
1538 tm->tm_mday = atoi(f[2]);
1540 if (tm->tm_year >= 1900) {
1541 tm->tm_year -= 1900;
1545 * We can't use 2-digit years any more, they make it
1546 * impossible to tell what's the day, and what's the year.
1548 if (tm->tm_mday < 1900) return -1;
1551 * Swap the year and the day.
1554 tm->tm_year = tm->tm_mday - 1900;
1559 * If the day is out of range, die.
1561 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
1566 * There may be %H:%M:%S. Parse it in a hacky way.
1569 f[0] = f[3]; /* HH */
1570 f[1] = strchr(f[0], ':'); /* find : separator */
1571 if (!f[1]) return -1;
1573 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
1575 f[2] = strchr(f[1], ':'); /* find : separator */
1577 *(f[2]++) = '\0'; /* nuke it, and point to SS */
1578 tm->tm_sec = atoi(f[2]);
1579 } /* else leave it as zero */
1581 tm->tm_hour = atoi(f[0]);
1582 tm->tm_min = atoi(f[1]);
1586 * Returns -1 on error.
1589 if (t == (time_t) -1) return -1;
1596 /** Compares two pointers
1598 * @param a first pointer to compare.
1599 * @param b second pointer to compare.
1600 * @return -1 if a < b, +1 if b > a, or 0 if both equal.
1602 int8_t fr_pointer_cmp(void const *a, void const *b)
1604 if (a < b) return -1;
1605 if (a == b) return 0;
1610 static int _quick_partition(void const *to_sort[], int min, int max, fr_cmp_t cmp) {
1611 void const *pivot = to_sort[min];
1617 do ++i; while((cmp(to_sort[i], pivot) <= 0) && i <= max);
1618 do --j; while(cmp(to_sort[j], pivot) > 0);
1623 to_sort[i] = to_sort[j];
1628 to_sort[min] = to_sort[j];
1634 /** Quick sort an array of pointers using a comparator
1636 * @param to_sort array of pointers to sort.
1637 * @param min_idx the lowest index (usually 0).
1638 * @param max_idx the highest index (usually length of array - 1).
1639 * @param cmp the comparison function to use to sort the array elements.
1641 void fr_quick_sort(void const *to_sort[], int min_idx, int max_idx, fr_cmp_t cmp)
1645 if (min_idx >= max_idx) return;
1647 part = _quick_partition(to_sort, min_idx, max_idx, cmp);
1648 fr_quick_sort(to_sort, min_idx, part - 1, cmp);
1649 fr_quick_sort(to_sort, part + 1, max_idx, cmp);
1653 void fr_talloc_verify_cb(UNUSED const void *ptr, UNUSED int depth,
1654 UNUSED int max_depth, UNUSED int is_ref,
1655 UNUSED void *private_data)