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 # define PTHREAD_MUTEX_LOCK pthread_mutex_lock
39 # define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
41 # define PTHREAD_MUTEX_LOCK(_x)
42 # define PTHREAD_MUTEX_UNLOCK(_x)
45 bool fr_dns_lookups = false; /* IP -> hostname lookups? */
46 bool fr_hostname_lookups = true; /* hostname -> IP lookups? */
47 int fr_debug_flag = 0;
49 static char const *months[] = {
50 "jan", "feb", "mar", "apr", "may", "jun",
51 "jul", "aug", "sep", "oct", "nov", "dec" };
53 fr_thread_local_setup(char *, fr_inet_ntop_buffer); /* macro */
55 typedef struct fr_talloc_link {
60 /** Sets a signal handler using sigaction if available, else signal
62 * @param sig to set handler for.
63 * @param func handler to set.
65 int fr_set_signal(int sig, sig_t func)
70 memset(&act, 0, sizeof(act));
72 sigemptyset(&act.sa_mask);
73 act.sa_handler = func;
75 if (sigaction(sig, &act, NULL) < 0) {
76 fr_strerror_printf("Failed setting signal %i handler via sigaction(): %s", sig, fr_syserror(errno));
80 if (signal(sig, func) < 0) {
81 fr_strerror_printf("Failed setting signal %i handler via signal(): %s", sig, fr_syserror(errno));
88 static int _fr_trigger_talloc_ctx_free(fr_talloc_link_t *trigger)
90 if (trigger->armed) talloc_free(trigger->child);
95 static int _fr_disarm_talloc_ctx_free(bool **armed)
101 /** Link a parent and a child context, so the child is freed before the parent
103 * @note This is not thread safe. Do not free parent before threads are joined, do not call from a child thread.
104 * @note It's OK to free the child before threads are joined, but this will leak memory until the parent is freed.
106 * @param parent who's fate the child should share.
107 * @param child bound to parent's lifecycle.
108 * @return 0 on success -1 on failure.
110 int fr_link_talloc_ctx_free(TALLOC_CTX *parent, TALLOC_CTX *child)
112 fr_talloc_link_t *trigger;
115 trigger = talloc(parent, fr_talloc_link_t);
116 if (!trigger) return -1;
118 disarm = talloc(child, bool *);
120 talloc_free(trigger);
124 trigger->child = child;
125 trigger->armed = true;
126 *disarm = &trigger->armed;
128 talloc_set_destructor(trigger, _fr_trigger_talloc_ctx_free);
129 talloc_set_destructor(disarm, _fr_disarm_talloc_ctx_free);
135 * Explicitly cleanup the memory allocated to the error inet_ntop
138 static void _fr_inet_ntop_free(void *arg)
143 /** Wrapper around inet_ntop, prints IPv4/IPv6 addresses
145 * inet_ntop requires the caller pass in a buffer for the address.
146 * This would be annoying and cumbersome, seeing as quite often the ASCII
147 * address is only used for logging output.
149 * So as with lib/log.c use TLS to allocate thread specific buffers, and
150 * write the IP address there instead.
152 * @param af address family, either AF_INET or AF_INET6.
153 * @param src pointer to network address structure.
154 * @return NULL on error, else pointer to ASCII buffer containing text version of address.
156 char const *fr_inet_ntop(int af, void const *src)
164 buffer = fr_thread_local_init(fr_inet_ntop_buffer, _fr_inet_ntop_free);
169 * malloc is thread safe, talloc is not
171 buffer = malloc(sizeof(char) * INET6_ADDRSTRLEN);
173 fr_perror("Failed allocating memory for inet_ntop buffer");
177 ret = fr_thread_local_set(fr_inet_ntop_buffer, buffer);
179 fr_perror("Failed setting up TLS for inet_ntop buffer: %s", fr_syserror(ret));
186 return inet_ntop(af, src, buffer, INET6_ADDRSTRLEN);
190 * Return an IP address in standard dot notation
194 char const *ip_ntoa(char *buffer, uint32_t ipaddr)
196 ipaddr = ntohl(ipaddr);
198 sprintf(buffer, "%d.%d.%d.%d",
199 (ipaddr >> 24) & 0xff,
200 (ipaddr >> 16) & 0xff,
201 (ipaddr >> 8) & 0xff,
206 /** Parse an IPv4 address or IPv4 prefix in presentation format (and others)
208 * @param out Where to write the ip address value.
209 * @param value to parse, may be dotted quad [+ prefix], or integer, or octal number, or '*' (INADDR_ANY).
210 * @param inlen Length of value, if value is \0 terminated inlen may be 0.
211 * @param resolve If true and value doesn't look like an IP address, try and resolve value as a hostname.
212 * @param fallback to IPv4 resolution if no A records can be found.
213 * @return 0 if ip address was parsed successfully, else -1 on error.
215 int fr_pton4(fr_ipaddr_t *out, char const *value, size_t inlen, bool resolve, bool fallback)
221 /* Dotted quad + / + [0-9]{1,2} */
222 char buffer[INET_ADDRSTRLEN + 3];
225 * Copy to intermediary buffer if we were given a length
228 if (inlen >= sizeof(buffer)) {
229 fr_strerror_printf("Invalid IPv4 address string \"%s\"", value);
232 memcpy(buffer, value, inlen);
233 buffer[inlen] = '\0';
236 p = strchr(value, '/');
238 * 192.0.2.2 is parsed as if it was /32
242 * Allow '*' as the wildcard address usually 0.0.0.0
244 if ((value[0] == '*') && (value[1] == '\0')) {
245 out->ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
247 * Convert things which are obviously integers to IP addresses
249 * We assume the number is the bigendian representation of the
252 } else if (is_integer(value) || ((value[0] == '0') && (value[1] == 'x'))) {
253 out->ipaddr.ip4addr.s_addr = htonl(strtoul(value, NULL, 0));
254 } else if (!resolve) {
255 if (inet_pton(AF_INET, value, &(out->ipaddr.ip4addr.s_addr)) <= 0) {
256 fr_strerror_printf("Failed to parse IPv4 address string \"%s\"", value);
259 } else if (ip_hton(out, AF_INET, value, fallback) < 0) return -1;
268 * Otherwise parse the prefix
270 if ((size_t)(p - value) >= INET_ADDRSTRLEN) {
271 fr_strerror_printf("Invalid IPv4 address string \"%s\"", value);
276 * Copy the IP portion into a temporary buffer if we haven't already.
278 if (inlen == 0) memcpy(buffer, value, p - value);
279 buffer[p - value] = '\0';
282 if (inet_pton(AF_INET, buffer, &(out->ipaddr.ip4addr.s_addr)) <= 0) {
283 fr_strerror_printf("Failed to parse IPv4 address string \"%s\"", value);
286 } else if (ip_hton(out, AF_INET, buffer, fallback) < 0) return -1;
288 prefix = strtoul(p + 1, &eptr, 10);
290 fr_strerror_printf("Invalid IPv4 mask length \"%s\". Should be between 0-32", p);
293 if (eptr[0] != '\0') {
294 fr_strerror_printf("Failed to parse IPv4 address string \"%s\", "
295 "got garbage after mask length \"%s\"", value, eptr);
300 out->ipaddr.ip4addr = fr_inaddr_mask(&(out->ipaddr.ip4addr), prefix);
303 out->prefix = (uint8_t) prefix;
309 /** Parse an IPv6 address or IPv6 prefix in presentation format (and others)
311 * @param out Where to write the ip address value.
312 * @param value to parse.
313 * @param inlen Length of value, if value is \0 terminated inlen may be 0.
314 * @param resolve If true and value doesn't look like an IP address, try and resolve value as a hostname.
315 * @param fallback to IPv4 resolution if no AAAA records can be found.
316 * @return 0 if ip address was parsed successfully, else -1 on error.
318 int fr_pton6(fr_ipaddr_t *out, char const *value, size_t inlen, bool resolve, bool fallback)
324 /* IPv6 + / + [0-9]{1,3} */
325 char buffer[INET6_ADDRSTRLEN + 4];
328 * Copy to intermediary buffer if we were given a length
331 if (inlen >= sizeof(buffer)) {
332 fr_strerror_printf("Invalid IPv6 address string \"%s\"", value);
335 memcpy(buffer, value, inlen);
336 buffer[inlen] = '\0';
339 p = strchr(value, '/');
342 * Allow '*' as the wildcard address
344 if ((value[0] == '*') && (value[1] == '\0')) {
345 memset(&out->ipaddr.ip6addr.s6_addr, 0, sizeof(out->ipaddr.ip6addr.s6_addr));
346 } else if (!resolve) {
347 if (inet_pton(AF_INET6, value, &(out->ipaddr.ip6addr.s6_addr)) <= 0) {
348 fr_strerror_printf("Failed to parse IPv6 address string \"%s\"", value);
351 } else if (ip_hton(out, AF_INET6, value, fallback) < 0) return -1;
359 if ((p - value) >= INET6_ADDRSTRLEN) {
360 fr_strerror_printf("Invalid IPv6 address string \"%s\"", value);
365 * Copy string to temporary buffer if we didn't do it earlier
367 if (inlen == 0) memcpy(buffer, value, p - value);
368 buffer[p - value] = '\0';
371 if (inet_pton(AF_INET6, buffer, &(out->ipaddr.ip6addr.s6_addr)) <= 0) {
372 fr_strerror_printf("Failed to parse IPv6 address string \"%s\"", value);
375 } else if (ip_hton(out, AF_INET6, buffer, fallback) < 0) return -1;
377 prefix = strtoul(p + 1, &eptr, 10);
379 fr_strerror_printf("Invalid IPv6 mask length \"%s\". Should be between 0-128", p);
382 if (eptr[0] != '\0') {
383 fr_strerror_printf("Failed to parse IPv6 address string \"%s\", "
384 "got garbage after mask length \"%s\"", value, eptr);
389 struct in6_addr addr;
391 addr = fr_in6addr_mask(&(out->ipaddr.ip6addr), prefix);
392 memcpy(&(out->ipaddr.ip6addr.s6_addr), &addr, sizeof(addr));
395 out->prefix = (uint8_t) prefix;
401 /** Simple wrapper to decide whether an IP value is v4 or v6 and call the appropriate parser.
403 * @param out Where to write the ip address value.
404 * @param value to parse.
405 * @param inlen Length of value, if value is \0 terminated inlen may be 0.
406 * @param resolve If true and value doesn't look like an IP address, try and resolve value as a hostname.
407 * @return 0 if ip address was parsed successfully, else -1 on error.
409 int fr_pton(fr_ipaddr_t *out, char const *value, size_t inlen, bool resolve)
413 len = (inlen == 0) ? strlen(value) : inlen;
414 for (i = 0; i < len; i++) switch (value[i]) {
416 * Chars illegal in domain names and IPv4 addresses.
417 * Must be v6 and cannot be a domain.
422 return fr_pton6(out, value, inlen, false, false);
425 * Chars which don't really tell us anything
433 * Outside the range of IPv4 chars, must be a domain
434 * Use A record in preference to AAAA record.
436 if ((value[i] < '0') || (value[i] > '9')) {
437 if (!resolve) return -1;
438 return fr_pton4(out, value, inlen, true, true);
444 * All chars were in the IPv4 set [0-9/.], must be an IPv4
447 return fr_pton4(out, value, inlen, false, false);
450 /** Check if the IP address is equivalent to INADDR_ANY
452 * @param addr to chec.
453 * @return true if IP address matches INADDR_ANY or INADDR6_ANY (assumed to be 0), else false.
455 bool is_wildcard(fr_ipaddr_t *addr)
457 static struct in6_addr in6_addr;
461 return (addr->ipaddr.ip4addr.s_addr == htons(INADDR_ANY));
464 return (memcmp(addr->ipaddr.ip6addr.s6_addr, in6_addr.s6_addr, sizeof(in6_addr.s6_addr)) == 0) ? true :false;
472 int fr_ntop(char *out, size_t outlen, fr_ipaddr_t *addr)
474 char buffer[INET6_ADDRSTRLEN];
476 if (inet_ntop(addr->af, &(addr->ipaddr), buffer, sizeof(buffer)) == NULL) return -1;
478 return snprintf(out, outlen, "%s/%i", buffer, addr->prefix);
482 * Internal wrapper for locking, to minimize the number of ifdef's
486 int rad_lockfd(int fd, int lock_len)
495 fl.l_whence = SEEK_CUR;
497 return fcntl(fd, F_SETLKW, (void *)&fl);
499 #error "missing definition for F_WRLCK, all file locks will fail"
506 * Internal wrapper for locking, to minimize the number of ifdef's
508 * Lock an fd, prefer lockf() over flock()
509 * Nonblocking version.
511 int rad_lockfd_nonblock(int fd, int lock_len)
520 fl.l_whence = SEEK_CUR;
522 return fcntl(fd, F_SETLK, (void *)&fl);
524 #error "missing definition for F_WRLCK, all file locks will fail"
531 * Internal wrapper for unlocking, to minimize the number of ifdef's
534 * Unlock an fd, prefer lockf() over flock()
536 int rad_unlockfd(int fd, int lock_len)
545 fl.l_whence = SEEK_CUR;
547 return fcntl(fd, F_UNLCK, (void *)&fl);
549 #error "missing definition for F_WRLCK, all file locks will fail"
556 * Return an interface-id in standard colon notation
558 char *ifid_ntoa(char *buffer, size_t size, uint8_t const *ifid)
560 snprintf(buffer, size, "%x:%x:%x:%x",
561 (ifid[0] << 8) + ifid[1], (ifid[2] << 8) + ifid[3],
562 (ifid[4] << 8) + ifid[5], (ifid[6] << 8) + ifid[7]);
568 * Return an interface-id from
569 * one supplied in standard colon notation.
571 uint8_t *ifid_aton(char const *ifid_str, uint8_t *ifid)
573 static char const xdigits[] = "0123456789abcdef";
575 int num_id = 0, val = 0, idx = 0;
577 for (p = ifid_str; ; ++p) {
578 if (*p == ':' || *p == '\0') {
583 * Drop 'val' into the array.
585 ifid[idx] = (val >> 8) & 0xff;
586 ifid[idx + 1] = val & 0xff;
589 * Must have all entries before
600 } else if ((pch = strchr(xdigits, tolower(*p))) != NULL) {
604 * Dumb version of 'scanf'
607 val |= (pch - xdigits);
615 #ifndef HAVE_INET_PTON
616 static int inet_pton4(char const *src, struct in_addr *dst)
622 static char const digits[] = "0123456789";
628 while (*p && ((off = strchr(digits, *p)) != NULL)) {
630 num += (off - digits);
632 if (num > 255) return 0;
639 * Not a digit, MUST be a dot, else we
651 * End of the string. At the fourth
652 * octet is OK, anything else is an
660 memcpy(dst, &tmp, sizeof(tmp));
665 #ifdef HAVE_STRUCT_SOCKADDR_IN6
667 * inet_pton6(src, dst)
668 * convert presentation level address to network order binary form.
670 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
672 * (1) does not touch `dst' unless it's returning 1.
673 * (2) :: in a full address is silently ignored.
675 * inspired by Mark Andrews.
679 static int inet_pton6(char const *src, unsigned char *dst)
681 static char const xdigits_l[] = "0123456789abcdef",
682 xdigits_u[] = "0123456789ABCDEF";
683 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
684 char const *xdigits, *curtok;
688 memset((tp = tmp), 0, IN6ADDRSZ);
689 endp = tp + IN6ADDRSZ;
691 /* Leading :: requires some special handling. */
698 while ((ch = *src++) != '\0') {
701 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
702 pch = strchr((xdigits = xdigits_u), ch);
705 val |= (pch - xdigits);
719 if (tp + INT16SZ > endp)
721 *tp++ = (u_char) (val >> 8) & 0xff;
722 *tp++ = (u_char) val & 0xff;
727 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
728 inet_pton4(curtok, (struct in_addr *) tp) > 0) {
731 break; /* '\0' was seen by inet_pton4(). */
736 if (tp + INT16SZ > endp)
738 *tp++ = (u_char) (val >> 8) & 0xff;
739 *tp++ = (u_char) val & 0xff;
741 if (colonp != NULL) {
743 * Since some memmove()'s erroneously fail to handle
744 * overlapping regions, we'll do the shift by hand.
746 int const n = tp - colonp;
749 for (i = 1; i <= n; i++) {
750 endp[- i] = colonp[n - i];
757 /* bcopy(tmp, dst, IN6ADDRSZ); */
758 memcpy(dst, tmp, IN6ADDRSZ);
764 * Utility function, so that the rest of the server doesn't
765 * have ifdef's around IPv6 support
767 int inet_pton(int af, char const *src, void *dst)
770 return inet_pton4(src, dst);
772 #ifdef HAVE_STRUCT_SOCKADDR_IN6
774 if (af == AF_INET6) {
775 return inet_pton6(src, dst);
783 #ifndef HAVE_INET_NTOP
785 * Utility function, so that the rest of the server doesn't
786 * have ifdef's around IPv6 support
788 char const *inet_ntop(int af, void const *src, char *dst, size_t cnt)
791 uint8_t const *ipaddr = src;
793 if (cnt <= INET_ADDRSTRLEN) return NULL;
795 snprintf(dst, cnt, "%d.%d.%d.%d",
796 ipaddr[0], ipaddr[1],
797 ipaddr[2], ipaddr[3]);
802 * If the system doesn't define this, we define it
805 if (af == AF_INET6) {
806 struct in6_addr const *ipaddr = src;
808 if (cnt <= INET6_ADDRSTRLEN) return NULL;
810 snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
811 (ipaddr->s6_addr[0] << 8) | ipaddr->s6_addr[1],
812 (ipaddr->s6_addr[2] << 8) | ipaddr->s6_addr[3],
813 (ipaddr->s6_addr[4] << 8) | ipaddr->s6_addr[5],
814 (ipaddr->s6_addr[6] << 8) | ipaddr->s6_addr[7],
815 (ipaddr->s6_addr[8] << 8) | ipaddr->s6_addr[9],
816 (ipaddr->s6_addr[10] << 8) | ipaddr->s6_addr[11],
817 (ipaddr->s6_addr[12] << 8) | ipaddr->s6_addr[13],
818 (ipaddr->s6_addr[14] << 8) | ipaddr->s6_addr[15]);
822 return NULL; /* don't support IPv6 */
826 /** Wrappers for IPv4/IPv6 host to IP address lookup
828 * This function returns only one IP address, of the specified address family,
829 * or the first address (of whatever family), if AF_UNSPEC is used.
831 * If fallback is specified and af is AF_INET, but no AF_INET records were
832 * found and a record for AF_INET6 exists that record will be returned.
834 * If fallback is specified and af is AF_INET6, and a record with AF_INET4 exists
835 * that record will be returned instead.
837 * @param out Where to write result.
838 * @param af To search for in preference.
839 * @param hostname to search for.
840 * @param fallback to the other adress family, if no records matching af, found.
841 * @return 0 on success, else -1 on failure.
843 int ip_hton(fr_ipaddr_t *out, int af, char const *hostname, bool fallback)
846 struct addrinfo hints, *ai = NULL, *alt = NULL, *res = NULL;
848 if (!fr_hostname_lookups) {
849 #ifdef HAVE_STRUCT_SOCKADDR_IN6
850 if (af == AF_UNSPEC) {
853 for (p = hostname; *p != '\0'; p++) {
864 if (af == AF_UNSPEC) af = AF_INET;
866 if (!inet_pton(af, hostname, &(out->ipaddr))) {
874 memset(&hints, 0, sizeof(hints));
875 hints.ai_family = af;
879 * Avoid malloc for IP addresses. This helps us debug
880 * memory errors when using talloc.
884 * If it's all numeric, avoid getaddrinfo()
886 if (inet_pton(af, hostname, &out->ipaddr.ip4addr) == 1) {
892 if ((rcode = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
893 fr_strerror_printf("ip_hton: %s", gai_strerror(rcode));
897 for (ai = res; ai; ai = ai->ai_next) {
898 if ((af == ai->ai_family) || (af == AF_UNSPEC)) break;
899 if (!alt && fallback && ((ai->ai_family == AF_INET) || (ai->ai_family == AF_INET6))) alt = ai;
904 fr_strerror_printf("ip_hton failed to find requested information for host %.100s", hostname);
909 rcode = fr_sockaddr2ipaddr((struct sockaddr_storage *)ai->ai_addr,
910 ai->ai_addrlen, out, NULL);
912 if (!rcode) return -1;
918 * Look IP addresses up, and print names (depending on DNS config)
920 char const *ip_ntoh(fr_ipaddr_t const *src, char *dst, size_t cnt)
922 struct sockaddr_storage ss;
929 if (!fr_dns_lookups) {
930 return inet_ntop(src->af, &(src->ipaddr), dst, cnt);
933 if (!fr_ipaddr2sockaddr(src, 0, &ss, &salen)) {
937 if ((error = getnameinfo((struct sockaddr *)&ss, salen, dst, cnt, NULL, 0,
938 NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
939 fr_strerror_printf("ip_ntoh: %s", gai_strerror(error));
945 /** Mask off a portion of an IPv4 address
947 * @param ipaddr to mask.
948 * @param prefix Number of contiguous bits to mask.
949 * @return an ipv6 address with the host portion zeroed out.
951 struct in_addr fr_inaddr_mask(struct in_addr const *ipaddr, uint8_t prefix)
964 ret = htonl(~((0x00000001UL << (32 - prefix)) - 1)) & ipaddr->s_addr;
965 return (*(struct in_addr *)&ret);
968 /** Mask off a portion of an IPv6 address
970 * @param ipaddr to mask.
971 * @param prefix Number of contiguous bits to mask.
972 * @return an ipv6 address with the host portion zeroed out.
974 struct in6_addr fr_in6addr_mask(struct in6_addr const *ipaddr, uint8_t prefix)
976 uint64_t const *p = (uint64_t const *) ipaddr;
977 uint64_t ret[2], *o = ret;
990 *o++ = 0xffffffffffffffffULL & *p++;
995 *o = htonll(~((0x0000000000000001ULL << (64 - prefix)) - 1)) & *p;
997 return *(struct in6_addr *) &ret;
1000 /** Zeroes out the host portion of an fr_ipaddr_t
1002 * @param[in,out] addr to mask
1003 * @param[in] prefix Length of the network portion.
1005 void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
1010 addr->ipaddr.ip4addr = fr_inaddr_mask(&addr->ipaddr.ip4addr, prefix);
1014 addr->ipaddr.ip6addr = fr_in6addr_mask(&addr->ipaddr.ip6addr, prefix);
1020 addr->prefix = prefix;
1023 static char const hextab[] = "0123456789abcdef";
1025 /** Convert hex strings to binary data
1027 * @param bin Buffer to write output to.
1028 * @param outlen length of output buffer (or length of input string / 2).
1029 * @param hex input string.
1030 * @param inlen length of the input string
1031 * @return length of data written to buffer.
1033 size_t fr_hex2bin(uint8_t *bin, size_t outlen, char const *hex, size_t inlen)
1040 * Smartly truncate output, caller should check number of bytes
1044 if (len > outlen) len = outlen;
1046 for (i = 0; i < len; i++) {
1047 if(!(c1 = memchr(hextab, tolower((int) hex[i << 1]), sizeof(hextab))) ||
1048 !(c2 = memchr(hextab, tolower((int) hex[(i << 1) + 1]), sizeof(hextab))))
1050 bin[i] = ((c1-hextab)<<4) + (c2-hextab);
1057 /** Convert binary data to a hex string
1059 * Ascii encoded hex string will not be prefixed with '0x'
1061 * @warning If the output buffer isn't long enough, we have a buffer overflow.
1063 * @param[out] hex Buffer to write hex output.
1064 * @param[in] bin input.
1065 * @param[in] inlen of bin input.
1066 * @return length of data written to buffer.
1068 size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen)
1072 for (i = 0; i < inlen; i++) {
1073 hex[0] = hextab[((*bin) >> 4) & 0x0f];
1074 hex[1] = hextab[*bin & 0x0f];
1085 /** Consume the integer (or hex) portion of a value string
1087 * @param value string to parse.
1088 * @param end pointer to the first non numeric char.
1089 * @return integer value.
1091 uint32_t fr_strtoul(char const *value, char **end)
1093 if ((value[0] == '0') && (value[1] == 'x')) {
1094 return strtoul(value, end, 16);
1097 return strtoul(value, end, 10);
1100 /** Check whether the string is all whitespace
1102 * @return true if the entirety of the string is whitespace, else false.
1104 bool is_whitespace(char const *value)
1107 if (!isspace(*value)) return false;
1113 /** Check whether the string is all numbers
1115 * @return true if the entirety of the string is are numebrs, else false.
1117 bool is_integer(char const *value)
1120 if (!isdigit(*value)) return false;
1126 /** Check whether the string is allzeros
1128 * @return true if the entirety of the string is are numebrs, else false.
1130 bool is_zero(char const *value)
1133 if (*value != '0') return false;
1140 * So we don't have ifdef's in the rest of the code
1142 #ifndef HAVE_CLOSEFROM
1143 int closefrom(int fd)
1149 maxfd = sysconf(_SC_OPEN_MAX);
1155 if (fd > maxfd) return 0;
1158 * FIXME: return EINTR?
1162 for (i = fd; i < maxfd; i++) {
1170 int fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
1172 if (a->af < b->af) return -1;
1173 if (a->af > b->af) return +1;
1177 return memcmp(&a->ipaddr.ip4addr,
1179 sizeof(a->ipaddr.ip4addr));
1182 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1184 if (a->scope < b->scope) return -1;
1185 if (a->scope > b->scope) return +1;
1187 return memcmp(&a->ipaddr.ip6addr,
1189 sizeof(a->ipaddr.ip6addr));
1200 int fr_ipaddr2sockaddr(fr_ipaddr_t const *ipaddr, uint16_t port,
1201 struct sockaddr_storage *sa, socklen_t *salen)
1203 if (ipaddr->af == AF_INET) {
1204 struct sockaddr_in s4;
1206 *salen = sizeof(s4);
1208 memset(&s4, 0, sizeof(s4));
1209 s4.sin_family = AF_INET;
1210 s4.sin_addr = ipaddr->ipaddr.ip4addr;
1211 s4.sin_port = htons(port);
1212 memset(sa, 0, sizeof(*sa));
1213 memcpy(sa, &s4, sizeof(s4));
1215 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1216 } else if (ipaddr->af == AF_INET6) {
1217 struct sockaddr_in6 s6;
1219 *salen = sizeof(s6);
1221 memset(&s6, 0, sizeof(s6));
1222 s6.sin6_family = AF_INET6;
1223 s6.sin6_addr = ipaddr->ipaddr.ip6addr;
1224 s6.sin6_port = htons(port);
1225 s6.sin6_scope_id = ipaddr->scope;
1226 memset(sa, 0, sizeof(*sa));
1227 memcpy(sa, &s6, sizeof(s6));
1237 int fr_sockaddr2ipaddr(struct sockaddr_storage const *sa, socklen_t salen,
1238 fr_ipaddr_t *ipaddr, uint16_t *port)
1240 if (sa->ss_family == AF_INET) {
1241 struct sockaddr_in s4;
1243 if (salen < sizeof(s4)) {
1244 fr_strerror_printf("IPv4 address is too small");
1248 memcpy(&s4, sa, sizeof(s4));
1249 ipaddr->af = AF_INET;
1250 ipaddr->prefix = 32;
1251 ipaddr->ipaddr.ip4addr = s4.sin_addr;
1252 if (port) *port = ntohs(s4.sin_port);
1254 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1255 } else if (sa->ss_family == AF_INET6) {
1256 struct sockaddr_in6 s6;
1258 if (salen < sizeof(s6)) {
1259 fr_strerror_printf("IPv6 address is too small");
1263 memcpy(&s6, sa, sizeof(s6));
1264 ipaddr->af = AF_INET6;
1265 ipaddr->prefix = 128;
1266 ipaddr->ipaddr.ip6addr = s6.sin6_addr;
1267 if (port) *port = ntohs(s6.sin6_port);
1268 ipaddr->scope = s6.sin6_scope_id;
1272 fr_strerror_printf("Unsupported address famility %d",
1280 /** Convert UTF8 string to UCS2 encoding
1282 * @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
1284 * @param[out] out Where to write the ucs2 string.
1285 * @param[in] outlen Size of output buffer.
1286 * @param[in] in UTF8 string to convert.
1287 * @param[in] inlen length of UTF8 string.
1288 * @return the size of the UCS2 string written to the output buffer (in bytes).
1290 ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
1293 uint8_t *start = out;
1295 for (i = 0; i < inlen; i++) {
1299 if ((size_t)(out - start) >= outlen) {
1300 /* input too long */
1304 /* One-byte encoding */
1306 FR_PUT_LE16(out, c);
1309 } else if ((i == (inlen - 1)) || ((size_t)(out - start) >= (outlen - 1))) {
1310 /* Incomplete surrogate */
1315 /* Two-byte encoding */
1316 if ((c & 0xe0) == 0xc0) {
1317 FR_PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
1321 if ((i == inlen) || ((size_t)(out - start) >= (outlen - 1))) {
1322 /* Incomplete surrogate */
1326 /* Three-byte encoding */
1328 FR_PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
1335 /** Write 128bit unsigned integer to buffer
1337 * @author Alexey Frunze
1339 * @param out where to write result to.
1340 * @param outlen size of out.
1341 * @param num 128 bit integer.
1343 size_t fr_prints_uint128(char *out, size_t outlen, uint128_t const num)
1345 char buff[128 / 3 + 1 + 1];
1350 memset(buff, '0', sizeof(buff) - 1);
1351 buff[sizeof(buff) - 1] = '\0';
1353 memcpy(n, &num, sizeof(n));
1355 for (i = 0; i < 128; i++) {
1359 carry = (n[1] >= 0x8000000000000000);
1361 // Shift n[] left, doubling it
1362 n[1] = ((n[1] << 1) & 0xffffffffffffffff) + (n[0] >= 0x8000000000000000);
1363 n[0] = ((n[0] << 1) & 0xffffffffffffffff);
1365 // Add s[] to itself in decimal, doubling it
1366 for (j = sizeof(buff) - 2; j >= 0; j--) {
1367 buff[j] += buff[j] - '0' + carry;
1368 carry = (buff[j] > '9');
1375 while ((*p == '0') && (p < &buff[sizeof(buff) - 2])) {
1379 return strlcpy(out, p, outlen);
1382 /** Calculate powers
1384 * @author Orson Peters
1385 * @note Borrowed from the gist here: https://gist.github.com/nightcracker/3551590.
1387 * @param base a 32bit signed integer.
1388 * @param exp amount to raise base by.
1389 * @return base ^ pow, or 0 on underflow/overflow.
1391 int64_t fr_pow(int32_t base, uint8_t exp) {
1392 static const uint8_t highest_bit_set[] = {
1393 0, 1, 2, 2, 3, 3, 3, 3,
1394 4, 4, 4, 4, 4, 4, 4, 4,
1395 5, 5, 5, 5, 5, 5, 5, 5,
1396 5, 5, 5, 5, 5, 5, 5, 5,
1397 6, 6, 6, 6, 6, 6, 6, 6,
1398 6, 6, 6, 6, 6, 6, 6, 6,
1399 6, 6, 6, 6, 6, 6, 6, 6,
1400 6, 6, 6, 6, 6, 6, 6, 255, // anything past 63 is a guaranteed overflow with base > 1
1401 255, 255, 255, 255, 255, 255, 255, 255,
1402 255, 255, 255, 255, 255, 255, 255, 255,
1403 255, 255, 255, 255, 255, 255, 255, 255,
1404 255, 255, 255, 255, 255, 255, 255, 255,
1405 255, 255, 255, 255, 255, 255, 255, 255,
1406 255, 255, 255, 255, 255, 255, 255, 255,
1407 255, 255, 255, 255, 255, 255, 255, 255,
1408 255, 255, 255, 255, 255, 255, 255, 255,
1409 255, 255, 255, 255, 255, 255, 255, 255,
1410 255, 255, 255, 255, 255, 255, 255, 255,
1411 255, 255, 255, 255, 255, 255, 255, 255,
1412 255, 255, 255, 255, 255, 255, 255, 255,
1413 255, 255, 255, 255, 255, 255, 255, 255,
1414 255, 255, 255, 255, 255, 255, 255, 255,
1415 255, 255, 255, 255, 255, 255, 255, 255,
1416 255, 255, 255, 255, 255, 255, 255, 255,
1417 255, 255, 255, 255, 255, 255, 255, 255,
1418 255, 255, 255, 255, 255, 255, 255, 255,
1419 255, 255, 255, 255, 255, 255, 255, 255,
1420 255, 255, 255, 255, 255, 255, 255, 255,
1421 255, 255, 255, 255, 255, 255, 255, 255,
1422 255, 255, 255, 255, 255, 255, 255, 255,
1423 255, 255, 255, 255, 255, 255, 255, 255,
1424 255, 255, 255, 255, 255, 255, 255, 255,
1427 uint64_t result = 1;
1429 switch (highest_bit_set[exp]) {
1430 case 255: // we use 255 as an overflow marker and return 0 on overflow/underflow
1436 return 1 - 2 * (exp & 1);
1440 if (exp & 1) result *= base;
1444 if (exp & 1) result *= base;
1448 if (exp & 1) result *= base;
1452 if (exp & 1) result *= base;
1456 if (exp & 1) result *= base;
1460 if (exp & 1) result *= base;
1467 * Sort of strtok/strsep function.
1469 static char *mystrtok(char **ptr, char const *sep)
1477 while (**ptr && strchr(sep, **ptr)) {
1485 while (**ptr && strchr(sep, **ptr) == NULL) {
1495 /** Convert string in various formats to a time_t
1497 * @param date_str input date string.
1498 * @param date time_t to write result to.
1499 * @return 0 on success or -1 on error.
1501 int fr_get_time(char const *date_str, time_t *date)
1505 struct tm *tm, s_tm;
1512 * Test for unix timestamp date
1514 *date = strtoul(date_str, &tail, 10);
1515 if (*tail == '\0') {
1520 memset(tm, 0, sizeof(*tm));
1521 tm->tm_isdst = -1; /* don't know, and don't care about DST */
1523 strlcpy(buf, date_str, sizeof(buf));
1526 f[0] = mystrtok(&p, " \t");
1527 f[1] = mystrtok(&p, " \t");
1528 f[2] = mystrtok(&p, " \t");
1529 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
1530 if (!f[0] || !f[1] || !f[2]) return -1;
1533 * The time has a colon, where nothing else does.
1534 * So if we find it, bubble it to the back of the list.
1537 for (i = 0; i < 3; i++) {
1538 if (strchr(f[i], ':')) {
1548 * The month is text, which allows us to find it easily.
1551 for (i = 0; i < 3; i++) {
1552 if (isalpha( (int) *f[i])) {
1554 * Bubble the month to the front of the list
1560 for (i = 0; i < 12; i++) {
1561 if (strncasecmp(months[i], f[0], 3) == 0) {
1569 /* month not found? */
1570 if (tm->tm_mon == 12) return -1;
1573 * The year may be in f[1], or in f[2]
1575 tm->tm_year = atoi(f[1]);
1576 tm->tm_mday = atoi(f[2]);
1578 if (tm->tm_year >= 1900) {
1579 tm->tm_year -= 1900;
1583 * We can't use 2-digit years any more, they make it
1584 * impossible to tell what's the day, and what's the year.
1586 if (tm->tm_mday < 1900) return -1;
1589 * Swap the year and the day.
1592 tm->tm_year = tm->tm_mday - 1900;
1597 * If the day is out of range, die.
1599 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
1604 * There may be %H:%M:%S. Parse it in a hacky way.
1607 f[0] = f[3]; /* HH */
1608 f[1] = strchr(f[0], ':'); /* find : separator */
1609 if (!f[1]) return -1;
1611 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
1613 f[2] = strchr(f[1], ':'); /* find : separator */
1615 *(f[2]++) = '\0'; /* nuke it, and point to SS */
1616 tm->tm_sec = atoi(f[2]);
1617 } /* else leave it as zero */
1619 tm->tm_hour = atoi(f[0]);
1620 tm->tm_min = atoi(f[1]);
1624 * Returns -1 on error.
1627 if (t == (time_t) -1) return -1;
1634 /** Compares two pointers
1636 * @param a first pointer to compare.
1637 * @param b second pointer to compare.
1638 * @return -1 if a < b, +1 if b > a, or 0 if both equal.
1640 int8_t fr_pointer_cmp(void const *a, void const *b)
1642 if (a < b) return -1;
1643 if (a == b) return 0;
1648 static int _quick_partition(void const *to_sort[], int min, int max, fr_cmp_t cmp) {
1649 void const *pivot = to_sort[min];
1655 do ++i; while((cmp(to_sort[i], pivot) <= 0) && i <= max);
1656 do --j; while(cmp(to_sort[j], pivot) > 0);
1661 to_sort[i] = to_sort[j];
1666 to_sort[min] = to_sort[j];
1672 /** Quick sort an array of pointers using a comparator
1674 * @param to_sort array of pointers to sort.
1675 * @param min_idx the lowest index (usually 0).
1676 * @param max_idx the highest index (usually length of array - 1).
1677 * @param cmp the comparison function to use to sort the array elements.
1679 void fr_quick_sort(void const *to_sort[], int min_idx, int max_idx, fr_cmp_t cmp)
1683 if (min_idx >= max_idx) return;
1685 part = _quick_partition(to_sort, min_idx, max_idx, cmp);
1686 fr_quick_sort(to_sort, min_idx, part - 1, cmp);
1687 fr_quick_sort(to_sort, part + 1, max_idx, cmp);
1691 void fr_talloc_verify_cb(UNUSED const void *ptr, UNUSED int depth,
1692 UNUSED int max_depth, UNUSED int is_ref,
1693 UNUSED void *private_data)