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>
32 #define FR_PUT_LE16(a, val)\
34 a[1] = ((uint16_t) (val)) >> 8;\
35 a[0] = ((uint16_t) (val)) & 0xff;\
38 static int fr_debugger_present = -1;
40 int fr_dns_lookups = 0;
41 int fr_debug_flag = 0;
43 /** Allocates a new talloc context from the root autofree context
45 * @param signum signal raised.
47 static void _sigtrap_handler(UNUSED int signum)
49 fr_debugger_present = 0;
50 signal(SIGTRAP, SIG_DFL);
53 /** Break in GDB (if were running under GDB)
55 * If the server is running under GDB this will raise a SIGTRAP which
56 * will pause the running process.
58 * If the server is not running under GDB then this will do nothing.
60 void fr_debug_break(void)
62 if (fr_debugger_present == -1) {
63 fr_debugger_present = 0;
64 signal(SIGTRAP, _sigtrap_handler);
66 } else if (fr_debugger_present == 1) {
72 * Return an IP address in standard dot notation
76 char const *ip_ntoa(char *buffer, uint32_t ipaddr)
78 ipaddr = ntohl(ipaddr);
80 sprintf(buffer, "%d.%d.%d.%d",
81 (ipaddr >> 24) & 0xff,
82 (ipaddr >> 16) & 0xff,
89 * Internal wrapper for locking, to minimize the number of ifdef's
93 int rad_lockfd(int fd, int lock_len)
102 fl.l_whence = SEEK_CUR;
104 return fcntl(fd, F_SETLKW, (void *)&fl);
106 #error "missing definition for F_WRLCK, all file locks will fail"
113 * Internal wrapper for locking, to minimize the number of ifdef's
115 * Lock an fd, prefer lockf() over flock()
116 * Nonblocking version.
118 int rad_lockfd_nonblock(int fd, int lock_len)
127 fl.l_whence = SEEK_CUR;
129 return fcntl(fd, F_SETLK, (void *)&fl);
131 #error "missing definition for F_WRLCK, all file locks will fail"
138 * Internal wrapper for unlocking, to minimize the number of ifdef's
141 * Unlock an fd, prefer lockf() over flock()
143 int rad_unlockfd(int fd, int lock_len)
152 fl.l_whence = SEEK_CUR;
154 return fcntl(fd, F_UNLCK, (void *)&fl);
156 #error "missing definition for F_WRLCK, all file locks will fail"
163 * Return an interface-id in standard colon notation
165 char *ifid_ntoa(char *buffer, size_t size, uint8_t const *ifid)
167 snprintf(buffer, size, "%x:%x:%x:%x",
168 (ifid[0] << 8) + ifid[1], (ifid[2] << 8) + ifid[3],
169 (ifid[4] << 8) + ifid[5], (ifid[6] << 8) + ifid[7]);
175 * Return an interface-id from
176 * one supplied in standard colon notation.
178 uint8_t *ifid_aton(char const *ifid_str, uint8_t *ifid)
180 static char const xdigits[] = "0123456789abcdef";
182 int num_id = 0, val = 0, idx = 0;
184 for (p = ifid_str; ; ++p) {
185 if (*p == ':' || *p == '\0') {
190 * Drop 'val' into the array.
192 ifid[idx] = (val >> 8) & 0xff;
193 ifid[idx + 1] = val & 0xff;
196 * Must have all entries before
207 } else if ((pch = strchr(xdigits, tolower(*p))) != NULL) {
211 * Dumb version of 'scanf'
214 val |= (pch - xdigits);
222 #ifndef HAVE_INET_PTON
223 static int inet_pton4(char const *src, struct in_addr *dst)
229 static char const digits[] = "0123456789";
235 while (*p && ((off = strchr(digits, *p)) != NULL)) {
237 num += (off - digits);
239 if (num > 255) return 0;
246 * Not a digit, MUST be a dot, else we
258 * End of the string. At the fourth
259 * octet is OK, anything else is an
267 memcpy(dst, &tmp, sizeof(tmp));
272 #ifdef HAVE_STRUCT_SOCKADDR_IN6
274 * inet_pton6(src, dst)
275 * convert presentation level address to network order binary form.
277 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
279 * (1) does not touch `dst' unless it's returning 1.
280 * (2) :: in a full address is silently ignored.
282 * inspired by Mark Andrews.
286 static int inet_pton6(char const *src, unsigned char *dst)
288 static char const xdigits_l[] = "0123456789abcdef",
289 xdigits_u[] = "0123456789ABCDEF";
290 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
291 char const *xdigits, *curtok;
295 memset((tp = tmp), 0, IN6ADDRSZ);
296 endp = tp + IN6ADDRSZ;
298 /* Leading :: requires some special handling. */
305 while ((ch = *src++) != '\0') {
308 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
309 pch = strchr((xdigits = xdigits_u), ch);
312 val |= (pch - xdigits);
326 if (tp + INT16SZ > endp)
328 *tp++ = (u_char) (val >> 8) & 0xff;
329 *tp++ = (u_char) val & 0xff;
334 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
335 inet_pton4(curtok, (struct in_addr *) tp) > 0) {
338 break; /* '\0' was seen by inet_pton4(). */
343 if (tp + INT16SZ > endp)
345 *tp++ = (u_char) (val >> 8) & 0xff;
346 *tp++ = (u_char) val & 0xff;
348 if (colonp != NULL) {
350 * Since some memmove()'s erroneously fail to handle
351 * overlapping regions, we'll do the shift by hand.
353 int const n = tp - colonp;
356 for (i = 1; i <= n; i++) {
357 endp[- i] = colonp[n - i];
364 /* bcopy(tmp, dst, IN6ADDRSZ); */
365 memcpy(dst, tmp, IN6ADDRSZ);
371 * Utility function, so that the rest of the server doesn't
372 * have ifdef's around IPv6 support
374 int inet_pton(int af, char const *src, void *dst)
377 return inet_pton4(src, dst);
379 #ifdef HAVE_STRUCT_SOCKADDR_IN6
381 if (af == AF_INET6) {
382 return inet_pton6(src, dst);
390 #ifndef HAVE_INET_NTOP
392 * Utility function, so that the rest of the server doesn't
393 * have ifdef's around IPv6 support
395 char const *inet_ntop(int af, void const *src, char *dst, size_t cnt)
398 uint8_t const *ipaddr = src;
400 if (cnt <= INET_ADDRSTRLEN) return NULL;
402 snprintf(dst, cnt, "%d.%d.%d.%d",
403 ipaddr[0], ipaddr[1],
404 ipaddr[2], ipaddr[3]);
409 * If the system doesn't define this, we define it
412 if (af == AF_INET6) {
413 struct const in6_addr *ipaddr = src;
415 if (cnt <= INET6_ADDRSTRLEN) return NULL;
417 snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
418 (ipaddr->s6_addr[0] << 8) | ipaddr->s6_addr[1],
419 (ipaddr->s6_addr[2] << 8) | ipaddr->s6_addr[3],
420 (ipaddr->s6_addr[4] << 8) | ipaddr->s6_addr[5],
421 (ipaddr->s6_addr[6] << 8) | ipaddr->s6_addr[7],
422 (ipaddr->s6_addr[8] << 8) | ipaddr->s6_addr[9],
423 (ipaddr->s6_addr[10] << 8) | ipaddr->s6_addr[11],
424 (ipaddr->s6_addr[12] << 8) | ipaddr->s6_addr[13],
425 (ipaddr->s6_addr[14] << 8) | ipaddr->s6_addr[15]);
429 return NULL; /* don't support IPv6 */
435 * Try to convert the address to v4 then v6
437 int ip_ptonx(char const *src, fr_ipaddr_t *dst)
439 if (inet_pton(AF_INET, src, &dst->ipaddr.ip4addr) == 1) {
444 #ifdef HAVE_STRUCT_SOCKADDR_IN6
445 if (inet_pton(AF_INET6, src, &dst->ipaddr.ip6addr) == 1) {
455 * Wrappers for IPv4/IPv6 host to IP address lookup.
456 * This API returns only one IP address, of the specified
457 * address family, or the first address (of whatever family),
458 * if AF_UNSPEC is used.
460 int ip_hton(char const *src, int af, fr_ipaddr_t *dst)
463 struct addrinfo hints, *ai = NULL, *res = NULL;
465 memset(&hints, 0, sizeof(hints));
466 hints.ai_family = af;
470 * Avoid malloc for IP addresses. This helps us debug
471 * memory errors when using talloc.
475 * If it's all numeric, avoid getaddrinfo()
477 if (inet_pton(af, src, &dst->ipaddr.ip4addr) == 1) {
483 if ((rcode = getaddrinfo(src, NULL, &hints, &res)) != 0) {
484 fr_strerror_printf("ip_hton: %s", gai_strerror(rcode));
488 for (ai = res; ai; ai = ai->ai_next) {
489 if ((af == ai->ai_family) || (af == AF_UNSPEC))
494 fr_strerror_printf("ip_hton failed to find requested information for host %.100s", src);
499 rcode = fr_sockaddr2ipaddr((struct sockaddr_storage *)ai->ai_addr,
500 ai->ai_addrlen, dst, NULL);
502 if (!rcode) return -1;
508 * Look IP addresses up, and print names (depending on DNS config)
510 char const *ip_ntoh(fr_ipaddr_t const *src, char *dst, size_t cnt)
512 struct sockaddr_storage ss;
519 if (!fr_dns_lookups) {
520 return inet_ntop(src->af, &(src->ipaddr), dst, cnt);
523 if (!fr_ipaddr2sockaddr(src, 0, &ss, &salen)) {
527 if ((error = getnameinfo((struct sockaddr *)&ss, salen, dst, cnt, NULL, 0,
528 NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
529 fr_strerror_printf("ip_ntoh: %s", gai_strerror(error));
536 static char const *hextab = "0123456789abcdef";
538 /** Convert hex strings to binary data
540 * @param bin Buffer to write output to.
541 * @param hex input string.
542 * @param outlen length of output buffer (or length of input string / 2).
543 * @return length of data written to buffer.
545 size_t fr_hex2bin(uint8_t *bin, char const *hex, size_t outlen)
550 for (i = 0; i < outlen; i++) {
551 if(!(c1 = memchr(hextab, tolower((int) hex[i << 1]), 16)) ||
552 !(c2 = memchr(hextab, tolower((int) hex[(i << 1) + 1]), 16)))
554 bin[i] = ((c1-hextab)<<4) + (c2-hextab);
561 /** Convert binary data to a hex string
563 * Ascii encoded hex string will not be prefixed with '0x'
565 * @warning If the output buffer isn't long enough, we have a buffer overflow.
567 * @param[out] hex Buffer to write hex output.
568 * @param[in] bin input.
569 * @param[in] inlen of bin input.
570 * @return length of data written to buffer.
572 size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen)
576 for (i = 0; i < inlen; i++) {
577 hex[0] = hextab[((*bin) >> 4) & 0x0f];
578 hex[1] = hextab[*bin & 0x0f];
589 * So we don't have ifdef's in the rest of the code
591 #ifndef HAVE_CLOSEFROM
592 int closefrom(int fd)
598 maxfd = sysconf(_SC_OPEN_MAX);
604 if (fd > maxfd) return 0;
607 * FIXME: return EINTR?
611 for (i = fd; i < maxfd; i++) {
619 int fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
621 if (a->af < b->af) return -1;
622 if (a->af > b->af) return +1;
626 return memcmp(&a->ipaddr.ip4addr,
628 sizeof(a->ipaddr.ip4addr));
631 #ifdef HAVE_STRUCT_SOCKADDR_IN6
633 if (a->scope < b->scope) return -1;
634 if (a->scope > b->scope) return +1;
636 return memcmp(&a->ipaddr.ip6addr,
638 sizeof(a->ipaddr.ip6addr));
649 int fr_ipaddr2sockaddr(fr_ipaddr_t const *ipaddr, int port,
650 struct sockaddr_storage *sa, socklen_t *salen)
652 if (ipaddr->af == AF_INET) {
653 struct sockaddr_in s4;
657 memset(&s4, 0, sizeof(s4));
658 s4.sin_family = AF_INET;
659 s4.sin_addr = ipaddr->ipaddr.ip4addr;
660 s4.sin_port = htons(port);
661 memset(sa, 0, sizeof(*sa));
662 memcpy(sa, &s4, sizeof(s4));
664 #ifdef HAVE_STRUCT_SOCKADDR_IN6
665 } else if (ipaddr->af == AF_INET6) {
666 struct sockaddr_in6 s6;
670 memset(&s6, 0, sizeof(s6));
671 s6.sin6_family = AF_INET6;
672 s6.sin6_addr = ipaddr->ipaddr.ip6addr;
673 s6.sin6_port = htons(port);
674 s6.sin6_scope_id = ipaddr->scope;
675 memset(sa, 0, sizeof(*sa));
676 memcpy(sa, &s6, sizeof(s6));
686 int fr_sockaddr2ipaddr(struct sockaddr_storage const *sa, socklen_t salen,
687 fr_ipaddr_t *ipaddr, int *port)
689 if (sa->ss_family == AF_INET) {
690 struct sockaddr_in s4;
692 if (salen < sizeof(s4)) {
693 fr_strerror_printf("IPv4 address is too small");
697 memcpy(&s4, sa, sizeof(s4));
698 ipaddr->af = AF_INET;
699 ipaddr->ipaddr.ip4addr = s4.sin_addr;
700 if (port) *port = ntohs(s4.sin_port);
702 #ifdef HAVE_STRUCT_SOCKADDR_IN6
703 } else if (sa->ss_family == AF_INET6) {
704 struct sockaddr_in6 s6;
706 if (salen < sizeof(s6)) {
707 fr_strerror_printf("IPv6 address is too small");
711 memcpy(&s6, sa, sizeof(s6));
712 ipaddr->af = AF_INET6;
713 ipaddr->ipaddr.ip6addr = s6.sin6_addr;
714 if (port) *port = ntohs(s6.sin6_port);
715 ipaddr->scope = s6.sin6_scope_id;
719 fr_strerror_printf("Unsupported address famility %d",
727 /** Convert UTF8 string to UCS2 encoding
729 * @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
731 * @param[out] out Where to write the ucs2 string.
732 * @param[in] outlen Size of output buffer.
733 * @param[in] in UTF8 string to convert.
734 * @param[in] inlen length of UTF8 string.
735 * @return the size of the UCS2 string written to the output buffer (in bytes).
737 ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
740 uint8_t *start = out;
742 for (i = 0; i < inlen; i++) {
746 if ((size_t)(out - start) >= outlen) {
751 /* One-byte encoding */
756 } else if ((i == (inlen - 1)) || ((size_t)(out - start) >= (outlen - 1))) {
757 /* Incomplete surrogate */
762 /* Two-byte encoding */
763 if ((c & 0xe0) == 0xc0) {
764 FR_PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
768 if ((i == inlen) || ((size_t)(out - start) >= (outlen - 1))) {
769 /* Incomplete surrogate */
773 /* Three-byte encoding */
775 FR_PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
783 void fr_talloc_verify_cb(UNUSED const void *ptr, UNUSED int depth,
784 UNUSED int max_depth, UNUSED int is_ref,
785 UNUSED void *private_data)