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 fr_thread_local_setup(char *, fr_inet_ntop_buffer); /* macro */
45 /** Allocates a new talloc context from the root autofree context
47 * @param signum signal raised.
49 static void _sigtrap_handler(UNUSED int signum)
51 fr_debugger_present = 0;
52 signal(SIGTRAP, SIG_DFL);
55 /** Break in GDB (if were running under GDB)
57 * If the server is running under GDB this will raise a SIGTRAP which
58 * will pause the running process.
60 * If the server is not running under GDB then this will do nothing.
62 void fr_debug_break(void)
64 if (fr_debugger_present == -1) {
65 fr_debugger_present = 0;
66 signal(SIGTRAP, _sigtrap_handler);
68 } else if (fr_debugger_present == 1) {
74 * Return an IP address in standard dot notation
78 char const *ip_ntoa(char *buffer, uint32_t ipaddr)
80 ipaddr = ntohl(ipaddr);
82 sprintf(buffer, "%d.%d.%d.%d",
83 (ipaddr >> 24) & 0xff,
84 (ipaddr >> 16) & 0xff,
91 * Internal wrapper for locking, to minimize the number of ifdef's
95 int rad_lockfd(int fd, int lock_len)
104 fl.l_whence = SEEK_CUR;
106 return fcntl(fd, F_SETLKW, (void *)&fl);
108 #error "missing definition for F_WRLCK, all file locks will fail"
115 * Internal wrapper for locking, to minimize the number of ifdef's
117 * Lock an fd, prefer lockf() over flock()
118 * Nonblocking version.
120 int rad_lockfd_nonblock(int fd, int lock_len)
129 fl.l_whence = SEEK_CUR;
131 return fcntl(fd, F_SETLK, (void *)&fl);
133 #error "missing definition for F_WRLCK, all file locks will fail"
140 * Internal wrapper for unlocking, to minimize the number of ifdef's
143 * Unlock an fd, prefer lockf() over flock()
145 int rad_unlockfd(int fd, int lock_len)
154 fl.l_whence = SEEK_CUR;
156 return fcntl(fd, F_UNLCK, (void *)&fl);
158 #error "missing definition for F_WRLCK, all file locks will fail"
165 * Return an interface-id in standard colon notation
167 char *ifid_ntoa(char *buffer, size_t size, uint8_t const *ifid)
169 snprintf(buffer, size, "%x:%x:%x:%x",
170 (ifid[0] << 8) + ifid[1], (ifid[2] << 8) + ifid[3],
171 (ifid[4] << 8) + ifid[5], (ifid[6] << 8) + ifid[7]);
177 * Return an interface-id from
178 * one supplied in standard colon notation.
180 uint8_t *ifid_aton(char const *ifid_str, uint8_t *ifid)
182 static char const xdigits[] = "0123456789abcdef";
184 int num_id = 0, val = 0, idx = 0;
186 for (p = ifid_str; ; ++p) {
187 if (*p == ':' || *p == '\0') {
192 * Drop 'val' into the array.
194 ifid[idx] = (val >> 8) & 0xff;
195 ifid[idx + 1] = val & 0xff;
198 * Must have all entries before
209 } else if ((pch = strchr(xdigits, tolower(*p))) != NULL) {
213 * Dumb version of 'scanf'
216 val |= (pch - xdigits);
224 #ifndef HAVE_INET_PTON
225 static int inet_pton4(char const *src, struct in_addr *dst)
231 static char const digits[] = "0123456789";
237 while (*p && ((off = strchr(digits, *p)) != NULL)) {
239 num += (off - digits);
241 if (num > 255) return 0;
248 * Not a digit, MUST be a dot, else we
260 * End of the string. At the fourth
261 * octet is OK, anything else is an
269 memcpy(dst, &tmp, sizeof(tmp));
274 #ifdef HAVE_STRUCT_SOCKADDR_IN6
276 * inet_pton6(src, dst)
277 * convert presentation level address to network order binary form.
279 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
281 * (1) does not touch `dst' unless it's returning 1.
282 * (2) :: in a full address is silently ignored.
284 * inspired by Mark Andrews.
289 inet_pton6(char const *src, unsigned char *dst)
291 static char const xdigits_l[] = "0123456789abcdef",
292 xdigits_u[] = "0123456789ABCDEF";
293 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
294 char const *xdigits, *curtok;
298 memset((tp = tmp), 0, IN6ADDRSZ);
299 endp = tp + IN6ADDRSZ;
301 /* Leading :: requires some special handling. */
308 while ((ch = *src++) != '\0') {
311 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
312 pch = strchr((xdigits = xdigits_u), ch);
315 val |= (pch - xdigits);
329 if (tp + INT16SZ > endp)
331 *tp++ = (u_char) (val >> 8) & 0xff;
332 *tp++ = (u_char) val & 0xff;
337 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
338 inet_pton4(curtok, (struct in_addr *) tp) > 0) {
341 break; /* '\0' was seen by inet_pton4(). */
346 if (tp + INT16SZ > endp)
348 *tp++ = (u_char) (val >> 8) & 0xff;
349 *tp++ = (u_char) val & 0xff;
351 if (colonp != NULL) {
353 * Since some memmove()'s erroneously fail to handle
354 * overlapping regions, we'll do the shift by hand.
356 int const n = tp - colonp;
359 for (i = 1; i <= n; i++) {
360 endp[- i] = colonp[n - i];
367 /* bcopy(tmp, dst, IN6ADDRSZ); */
368 memcpy(dst, tmp, IN6ADDRSZ);
374 * Utility function, so that the rest of the server doesn't
375 * have ifdef's around IPv6 support
377 int inet_pton(int af, char const *src, void *dst)
380 return inet_pton4(src, dst);
382 #ifdef HAVE_STRUCT_SOCKADDR_IN6
384 if (af == AF_INET6) {
385 return inet_pton6(src, dst);
394 #ifndef HAVE_INET_NTOP
396 * Utility function, so that the rest of the server doesn't
397 * have ifdef's around IPv6 support
399 char const *inet_ntop(int af, void const *src, char *dst, size_t cnt)
402 uint8_t const *ipaddr = src;
404 if (cnt <= INET_ADDRSTRLEN) return NULL;
406 snprintf(dst, cnt, "%d.%d.%d.%d",
407 ipaddr[0], ipaddr[1],
408 ipaddr[2], ipaddr[3]);
413 * If the system doesn't define this, we define it
416 if (af == AF_INET6) {
417 struct const in6_addr *ipaddr = src;
419 if (cnt <= INET6_ADDRSTRLEN) return NULL;
421 snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
422 (ipaddr->s6_addr[0] << 8) | ipaddr->s6_addr[1],
423 (ipaddr->s6_addr[2] << 8) | ipaddr->s6_addr[3],
424 (ipaddr->s6_addr[4] << 8) | ipaddr->s6_addr[5],
425 (ipaddr->s6_addr[6] << 8) | ipaddr->s6_addr[7],
426 (ipaddr->s6_addr[8] << 8) | ipaddr->s6_addr[9],
427 (ipaddr->s6_addr[10] << 8) | ipaddr->s6_addr[11],
428 (ipaddr->s6_addr[12] << 8) | ipaddr->s6_addr[13],
429 (ipaddr->s6_addr[14] << 8) | ipaddr->s6_addr[15]);
433 return NULL; /* don't support IPv6 */
439 * Wrappers for IPv4/IPv6 host to IP address lookup.
440 * This API returns only one IP address, of the specified
441 * address family, or the first address (of whatever family),
442 * if AF_UNSPEC is used.
444 int ip_hton(char const *src, int af, fr_ipaddr_t *dst)
447 struct addrinfo hints, *ai = NULL, *res = NULL;
449 memset(&hints, 0, sizeof(hints));
450 hints.ai_family = af;
452 if ((rcode = getaddrinfo(src, NULL, &hints, &res)) != 0) {
453 fr_strerror_printf("ip_hton: %s", gai_strerror(rcode));
457 for (ai = res; ai; ai = ai->ai_next) {
458 if ((af == ai->ai_family) || (af == AF_UNSPEC))
463 fr_strerror_printf("ip_hton failed to find requested information for host %.100s", src);
468 rcode = fr_sockaddr2ipaddr((struct sockaddr_storage *)ai->ai_addr,
469 ai->ai_addrlen, dst, NULL);
471 if (!rcode) return -1;
477 * Look IP addresses up, and print names (depending on DNS config)
479 char const *ip_ntoh(fr_ipaddr_t const *src, char *dst, size_t cnt)
481 struct sockaddr_storage ss;
488 if (!fr_dns_lookups) {
489 return inet_ntop(src->af, &(src->ipaddr), dst, cnt);
492 if (!fr_ipaddr2sockaddr(src, 0, &ss, &salen)) {
496 if ((error = getnameinfo((struct sockaddr *)&ss, salen, dst, cnt, NULL, 0,
497 NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
498 fr_strerror_printf("ip_ntoh: %s", gai_strerror(error));
505 static char const *hextab = "0123456789abcdef";
507 /** Convert hex strings to binary data
509 * @param bin Buffer to write output to.
510 * @param hex input string.
511 * @param outlen length of output buffer (or length of input string / 2).
512 * @return length of data written to buffer.
514 size_t fr_hex2bin(uint8_t *bin, char const *hex, size_t outlen)
519 for (i = 0; i < outlen; i++) {
520 if(!(c1 = memchr(hextab, tolower((int) hex[i << 1]), 16)) ||
521 !(c2 = memchr(hextab, tolower((int) hex[(i << 1) + 1]), 16)))
523 bin[i] = ((c1-hextab)<<4) + (c2-hextab);
530 /** Convert binary data to a hex string
532 * Ascii encoded hex string will not be prefixed with '0x'
534 * @warning If the output buffer isn't long enough, we have a buffer overflow.
536 * @param[out] hex Buffer to write hex output.
537 * @param[in] bin input.
538 * @param[in] inlen of bin input.
539 * @return length of data written to buffer.
541 size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen)
545 for (i = 0; i < inlen; i++) {
546 hex[0] = hextab[((*bin) >> 4) & 0x0f];
547 hex[1] = hextab[*bin & 0x0f];
558 * So we don't have ifdef's in the rest of the code
560 #ifndef HAVE_CLOSEFROM
561 int closefrom(int fd)
567 maxfd = sysconf(_SC_OPEN_MAX);
573 if (fd > maxfd) return 0;
576 * FIXME: return EINTR?
580 for (i = fd; i < maxfd; i++) {
588 int fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
590 if (a->af < b->af) return -1;
591 if (a->af > b->af) return +1;
595 return memcmp(&a->ipaddr.ip4addr,
597 sizeof(a->ipaddr.ip4addr));
600 #ifdef HAVE_STRUCT_SOCKADDR_IN6
602 if (a->scope < b->scope) return -1;
603 if (a->scope > b->scope) return +1;
605 return memcmp(&a->ipaddr.ip6addr,
607 sizeof(a->ipaddr.ip6addr));
618 int fr_ipaddr2sockaddr(fr_ipaddr_t const *ipaddr, int port,
619 struct sockaddr_storage *sa, socklen_t *salen)
621 if (ipaddr->af == AF_INET) {
622 struct sockaddr_in s4;
626 memset(&s4, 0, sizeof(s4));
627 s4.sin_family = AF_INET;
628 s4.sin_addr = ipaddr->ipaddr.ip4addr;
629 s4.sin_port = htons(port);
630 memset(sa, 0, sizeof(*sa));
631 memcpy(sa, &s4, sizeof(s4));
633 #ifdef HAVE_STRUCT_SOCKADDR_IN6
634 } else if (ipaddr->af == AF_INET6) {
635 struct sockaddr_in6 s6;
639 memset(&s6, 0, sizeof(s6));
640 s6.sin6_family = AF_INET6;
641 s6.sin6_addr = ipaddr->ipaddr.ip6addr;
642 s6.sin6_port = htons(port);
643 s6.sin6_scope_id = ipaddr->scope;
644 memset(sa, 0, sizeof(*sa));
645 memcpy(sa, &s6, sizeof(s6));
655 int fr_sockaddr2ipaddr(struct sockaddr_storage const *sa, socklen_t salen,
656 fr_ipaddr_t *ipaddr, int *port)
658 if (sa->ss_family == AF_INET) {
659 struct sockaddr_in s4;
661 if (salen < sizeof(s4)) {
662 fr_strerror_printf("IPv4 address is too small");
666 memcpy(&s4, sa, sizeof(s4));
667 ipaddr->af = AF_INET;
668 ipaddr->ipaddr.ip4addr = s4.sin_addr;
669 if (port) *port = ntohs(s4.sin_port);
671 #ifdef HAVE_STRUCT_SOCKADDR_IN6
672 } else if (sa->ss_family == AF_INET6) {
673 struct sockaddr_in6 s6;
675 if (salen < sizeof(s6)) {
676 fr_strerror_printf("IPv6 address is too small");
680 memcpy(&s6, sa, sizeof(s6));
681 ipaddr->af = AF_INET6;
682 ipaddr->ipaddr.ip6addr = s6.sin6_addr;
683 if (port) *port = ntohs(s6.sin6_port);
684 ipaddr->scope = s6.sin6_scope_id;
688 fr_strerror_printf("Unsupported address famility %d",
696 /** Convert UTF8 string to UCS2 encoding
698 * @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
700 * @param[out] out Where to write the ucs2 string.
701 * @param[in] outlen Size of output buffer.
702 * @param[in] in UTF8 string to convert.
703 * @param[in] inlen length of UTF8 string.
704 * @return the size of the UCS2 string written to the output buffer (in bytes).
706 ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
709 uint8_t *start = out;
711 for (i = 0; i < inlen; i++) {
715 if ((size_t)(out - start) >= outlen) {
720 /* One-byte encoding */
725 } else if ((i == (inlen - 1)) || ((size_t)(out - start) >= (outlen - 1))) {
726 /* Incomplete surrogate */
731 /* Two-byte encoding */
732 if ((c & 0xe0) == 0xc0) {
733 FR_PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
737 if ((i == inlen) || ((size_t)(out - start) >= (outlen - 1))) {
738 /* Incomplete surrogate */
742 /* Three-byte encoding */
744 FR_PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));