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) || ((value[0] == '0') && (value[1] == 'x'))) {
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 outlen length of output buffer (or length of input string / 2).
1000 * @param hex input string.
1001 * @param inlen length of the input string
1002 * @return length of data written to buffer.
1004 size_t fr_hex2bin(uint8_t *bin, size_t outlen, char const *hex, size_t inlen)
1011 * Smartly truncate output, caller should check number of bytes
1015 if (len > outlen) len = outlen;
1017 for (i = 0; i < len; i++) {
1018 if(!(c1 = memchr(hextab, tolower((int) hex[i << 1]), sizeof(hextab))) ||
1019 !(c2 = memchr(hextab, tolower((int) hex[(i << 1) + 1]), sizeof(hextab))))
1021 bin[i] = ((c1-hextab)<<4) + (c2-hextab);
1028 /** Convert binary data to a hex string
1030 * Ascii encoded hex string will not be prefixed with '0x'
1032 * @warning If the output buffer isn't long enough, we have a buffer overflow.
1034 * @param[out] hex Buffer to write hex output.
1035 * @param[in] bin input.
1036 * @param[in] inlen of bin input.
1037 * @return length of data written to buffer.
1039 size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen)
1043 for (i = 0; i < inlen; i++) {
1044 hex[0] = hextab[((*bin) >> 4) & 0x0f];
1045 hex[1] = hextab[*bin & 0x0f];
1056 /** Consume the integer (or hex) portion of a value string
1058 * @param value string to parse.
1059 * @param end pointer to the first non numeric char.
1060 * @return integer value.
1062 uint32_t fr_strtoul(char const *value, char **end)
1064 if ((value[0] == '0') && (value[1] == 'x')) {
1065 return strtoul(value, end, 16);
1068 return strtoul(value, end, 10);
1071 /** Check whether the string is all whitespace
1073 * @return true if the entirety of the string is whitespace, else false.
1075 bool is_whitespace(char const *value)
1078 if (!isspace(*value)) return false;
1084 /** Check whether the string is all numbers
1086 * @return true if the entirety of the string is are numebrs, else false.
1088 bool is_integer(char const *value)
1091 if (!isdigit(*value)) return false;
1097 /** Check whether the string is allzeros
1099 * @return true if the entirety of the string is are numebrs, else false.
1101 bool is_zero(char const *value)
1104 if (*value != '0') return false;
1111 * So we don't have ifdef's in the rest of the code
1113 #ifndef HAVE_CLOSEFROM
1114 int closefrom(int fd)
1120 maxfd = sysconf(_SC_OPEN_MAX);
1126 if (fd > maxfd) return 0;
1129 * FIXME: return EINTR?
1133 for (i = fd; i < maxfd; i++) {
1141 int fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
1143 if (a->af < b->af) return -1;
1144 if (a->af > b->af) return +1;
1148 return memcmp(&a->ipaddr.ip4addr,
1150 sizeof(a->ipaddr.ip4addr));
1153 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1155 if (a->scope < b->scope) return -1;
1156 if (a->scope > b->scope) return +1;
1158 return memcmp(&a->ipaddr.ip6addr,
1160 sizeof(a->ipaddr.ip6addr));
1171 int fr_ipaddr2sockaddr(fr_ipaddr_t const *ipaddr, uint16_t port,
1172 struct sockaddr_storage *sa, socklen_t *salen)
1174 if (ipaddr->af == AF_INET) {
1175 struct sockaddr_in s4;
1177 *salen = sizeof(s4);
1179 memset(&s4, 0, sizeof(s4));
1180 s4.sin_family = AF_INET;
1181 s4.sin_addr = ipaddr->ipaddr.ip4addr;
1182 s4.sin_port = htons(port);
1183 memset(sa, 0, sizeof(*sa));
1184 memcpy(sa, &s4, sizeof(s4));
1186 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1187 } else if (ipaddr->af == AF_INET6) {
1188 struct sockaddr_in6 s6;
1190 *salen = sizeof(s6);
1192 memset(&s6, 0, sizeof(s6));
1193 s6.sin6_family = AF_INET6;
1194 s6.sin6_addr = ipaddr->ipaddr.ip6addr;
1195 s6.sin6_port = htons(port);
1196 s6.sin6_scope_id = ipaddr->scope;
1197 memset(sa, 0, sizeof(*sa));
1198 memcpy(sa, &s6, sizeof(s6));
1208 int fr_sockaddr2ipaddr(struct sockaddr_storage const *sa, socklen_t salen,
1209 fr_ipaddr_t *ipaddr, uint16_t *port)
1211 if (sa->ss_family == AF_INET) {
1212 struct sockaddr_in s4;
1214 if (salen < sizeof(s4)) {
1215 fr_strerror_printf("IPv4 address is too small");
1219 memcpy(&s4, sa, sizeof(s4));
1220 ipaddr->af = AF_INET;
1221 ipaddr->prefix = 32;
1222 ipaddr->ipaddr.ip4addr = s4.sin_addr;
1223 if (port) *port = ntohs(s4.sin_port);
1225 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1226 } else if (sa->ss_family == AF_INET6) {
1227 struct sockaddr_in6 s6;
1229 if (salen < sizeof(s6)) {
1230 fr_strerror_printf("IPv6 address is too small");
1234 memcpy(&s6, sa, sizeof(s6));
1235 ipaddr->af = AF_INET6;
1236 ipaddr->prefix = 128;
1237 ipaddr->ipaddr.ip6addr = s6.sin6_addr;
1238 if (port) *port = ntohs(s6.sin6_port);
1239 ipaddr->scope = s6.sin6_scope_id;
1243 fr_strerror_printf("Unsupported address famility %d",
1251 /** Convert UTF8 string to UCS2 encoding
1253 * @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
1255 * @param[out] out Where to write the ucs2 string.
1256 * @param[in] outlen Size of output buffer.
1257 * @param[in] in UTF8 string to convert.
1258 * @param[in] inlen length of UTF8 string.
1259 * @return the size of the UCS2 string written to the output buffer (in bytes).
1261 ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
1264 uint8_t *start = out;
1266 for (i = 0; i < inlen; i++) {
1270 if ((size_t)(out - start) >= outlen) {
1271 /* input too long */
1275 /* One-byte encoding */
1277 FR_PUT_LE16(out, c);
1280 } else if ((i == (inlen - 1)) || ((size_t)(out - start) >= (outlen - 1))) {
1281 /* Incomplete surrogate */
1286 /* Two-byte encoding */
1287 if ((c & 0xe0) == 0xc0) {
1288 FR_PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
1292 if ((i == inlen) || ((size_t)(out - start) >= (outlen - 1))) {
1293 /* Incomplete surrogate */
1297 /* Three-byte encoding */
1299 FR_PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
1306 /** Write 128bit unsigned integer to buffer
1308 * @author Alexey Frunze
1310 * @param out where to write result to.
1311 * @param outlen size of out.
1312 * @param num 128 bit integer.
1314 size_t fr_prints_uint128(char *out, size_t outlen, uint128_t const num)
1316 char buff[128 / 3 + 1 + 1];
1321 memset(buff, '0', sizeof(buff) - 1);
1322 buff[sizeof(buff) - 1] = '\0';
1324 memcpy(n, &num, sizeof(n));
1326 for (i = 0; i < 128; i++) {
1330 carry = (n[1] >= 0x8000000000000000);
1332 // Shift n[] left, doubling it
1333 n[1] = ((n[1] << 1) & 0xffffffffffffffff) + (n[0] >= 0x8000000000000000);
1334 n[0] = ((n[0] << 1) & 0xffffffffffffffff);
1336 // Add s[] to itself in decimal, doubling it
1337 for (j = sizeof(buff) - 2; j >= 0; j--) {
1338 buff[j] += buff[j] - '0' + carry;
1339 carry = (buff[j] > '9');
1346 while ((*p == '0') && (p < &buff[sizeof(buff) - 2])) {
1350 return strlcpy(out, p, outlen);
1353 /** Calculate powers
1355 * @author Orson Peters
1356 * @note Borrowed from the gist here: https://gist.github.com/nightcracker/3551590.
1358 * @param base a 32bit signed integer.
1359 * @param exp amount to raise base by.
1360 * @return base ^ pow, or 0 on underflow/overflow.
1362 int64_t fr_pow(int32_t base, uint8_t exp) {
1363 static const uint8_t highest_bit_set[] = {
1364 0, 1, 2, 2, 3, 3, 3, 3,
1365 4, 4, 4, 4, 4, 4, 4, 4,
1366 5, 5, 5, 5, 5, 5, 5, 5,
1367 5, 5, 5, 5, 5, 5, 5, 5,
1368 6, 6, 6, 6, 6, 6, 6, 6,
1369 6, 6, 6, 6, 6, 6, 6, 6,
1370 6, 6, 6, 6, 6, 6, 6, 6,
1371 6, 6, 6, 6, 6, 6, 6, 255, // anything past 63 is a guaranteed overflow with base > 1
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,
1387 255, 255, 255, 255, 255, 255, 255, 255,
1388 255, 255, 255, 255, 255, 255, 255, 255,
1389 255, 255, 255, 255, 255, 255, 255, 255,
1390 255, 255, 255, 255, 255, 255, 255, 255,
1391 255, 255, 255, 255, 255, 255, 255, 255,
1392 255, 255, 255, 255, 255, 255, 255, 255,
1393 255, 255, 255, 255, 255, 255, 255, 255,
1394 255, 255, 255, 255, 255, 255, 255, 255,
1395 255, 255, 255, 255, 255, 255, 255, 255,
1398 uint64_t result = 1;
1400 switch (highest_bit_set[exp]) {
1401 case 255: // we use 255 as an overflow marker and return 0 on overflow/underflow
1407 return 1 - 2 * (exp & 1);
1411 if (exp & 1) result *= base;
1415 if (exp & 1) result *= base;
1419 if (exp & 1) result *= base;
1423 if (exp & 1) result *= base;
1427 if (exp & 1) result *= base;
1431 if (exp & 1) result *= base;
1438 * Sort of strtok/strsep function.
1440 static char *mystrtok(char **ptr, char const *sep)
1448 while (**ptr && strchr(sep, **ptr)) {
1456 while (**ptr && strchr(sep, **ptr) == NULL) {
1466 /** Convert string in various formats to a time_t
1468 * @param date_str input date string.
1469 * @param date time_t to write result to.
1470 * @return 0 on success or -1 on error.
1472 int fr_get_time(char const *date_str, time_t *date)
1476 struct tm *tm, s_tm;
1483 * Test for unix timestamp date
1485 *date = strtoul(date_str, &tail, 10);
1486 if (*tail == '\0') {
1491 memset(tm, 0, sizeof(*tm));
1492 tm->tm_isdst = -1; /* don't know, and don't care about DST */
1494 strlcpy(buf, date_str, sizeof(buf));
1497 f[0] = mystrtok(&p, " \t");
1498 f[1] = mystrtok(&p, " \t");
1499 f[2] = mystrtok(&p, " \t");
1500 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
1501 if (!f[0] || !f[1] || !f[2]) return -1;
1504 * The time has a colon, where nothing else does.
1505 * So if we find it, bubble it to the back of the list.
1508 for (i = 0; i < 3; i++) {
1509 if (strchr(f[i], ':')) {
1519 * The month is text, which allows us to find it easily.
1522 for (i = 0; i < 3; i++) {
1523 if (isalpha( (int) *f[i])) {
1525 * Bubble the month to the front of the list
1531 for (i = 0; i < 12; i++) {
1532 if (strncasecmp(months[i], f[0], 3) == 0) {
1540 /* month not found? */
1541 if (tm->tm_mon == 12) return -1;
1544 * The year may be in f[1], or in f[2]
1546 tm->tm_year = atoi(f[1]);
1547 tm->tm_mday = atoi(f[2]);
1549 if (tm->tm_year >= 1900) {
1550 tm->tm_year -= 1900;
1554 * We can't use 2-digit years any more, they make it
1555 * impossible to tell what's the day, and what's the year.
1557 if (tm->tm_mday < 1900) return -1;
1560 * Swap the year and the day.
1563 tm->tm_year = tm->tm_mday - 1900;
1568 * If the day is out of range, die.
1570 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
1575 * There may be %H:%M:%S. Parse it in a hacky way.
1578 f[0] = f[3]; /* HH */
1579 f[1] = strchr(f[0], ':'); /* find : separator */
1580 if (!f[1]) return -1;
1582 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
1584 f[2] = strchr(f[1], ':'); /* find : separator */
1586 *(f[2]++) = '\0'; /* nuke it, and point to SS */
1587 tm->tm_sec = atoi(f[2]);
1588 } /* else leave it as zero */
1590 tm->tm_hour = atoi(f[0]);
1591 tm->tm_min = atoi(f[1]);
1595 * Returns -1 on error.
1598 if (t == (time_t) -1) return -1;
1605 /** Compares two pointers
1607 * @param a first pointer to compare.
1608 * @param b second pointer to compare.
1609 * @return -1 if a < b, +1 if b > a, or 0 if both equal.
1611 int8_t fr_pointer_cmp(void const *a, void const *b)
1613 if (a < b) return -1;
1614 if (a == b) return 0;
1619 static int _quick_partition(void const *to_sort[], int min, int max, fr_cmp_t cmp) {
1620 void const *pivot = to_sort[min];
1626 do ++i; while((cmp(to_sort[i], pivot) <= 0) && i <= max);
1627 do --j; while(cmp(to_sort[j], pivot) > 0);
1632 to_sort[i] = to_sort[j];
1637 to_sort[min] = to_sort[j];
1643 /** Quick sort an array of pointers using a comparator
1645 * @param to_sort array of pointers to sort.
1646 * @param min_idx the lowest index (usually 0).
1647 * @param max_idx the highest index (usually length of array - 1).
1648 * @param cmp the comparison function to use to sort the array elements.
1650 void fr_quick_sort(void const *to_sort[], int min_idx, int max_idx, fr_cmp_t cmp)
1654 if (min_idx >= max_idx) return;
1656 part = _quick_partition(to_sort, min_idx, max_idx, cmp);
1657 fr_quick_sort(to_sort, min_idx, part - 1, cmp);
1658 fr_quick_sort(to_sort, part + 1, max_idx, cmp);
1662 void fr_talloc_verify_cb(UNUSED const void *ptr, UNUSED int depth,
1663 UNUSED int max_depth, UNUSED int is_ref,
1664 UNUSED void *private_data)