Typo
[freeradius.git] / src / lib / misc.c
1 /*
2  * misc.c       Various miscellaneous functions.
3  *
4  * Version:     $Id$
5  *
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.
10  *
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.
15  *
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
19  *
20  * Copyright 2000,2006  The FreeRADIUS server project
21  */
22
23 RCSID("$Id$")
24
25 #include        <freeradius-devel/libradius.h>
26
27 #include        <ctype.h>
28 #include        <sys/file.h>
29 #include        <fcntl.h>
30
31 #define FR_PUT_LE16(a, val)\
32         do {\
33                 a[1] = ((uint16_t) (val)) >> 8;\
34                 a[0] = ((uint16_t) (val)) & 0xff;\
35         } while (0)
36
37 #ifdef HAVE_PTHREAD_H
38 #  define PTHREAD_MUTEX_LOCK pthread_mutex_lock
39 #  define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
40 #else
41 #  define PTHREAD_MUTEX_LOCK(_x)
42 #  define PTHREAD_MUTEX_UNLOCK(_x)
43 #endif
44
45 bool    fr_dns_lookups = false;     /* IP -> hostname lookups? */
46 bool    fr_hostname_lookups = true; /* hostname -> IP lookups? */
47 int     fr_debug_flag = 0;
48
49 static char const *months[] = {
50         "jan", "feb", "mar", "apr", "may", "jun",
51         "jul", "aug", "sep", "oct", "nov", "dec" };
52
53 fr_thread_local_setup(char *, fr_inet_ntop_buffer);     /* macro */
54
55 typedef struct fr_talloc_link {
56         bool armed;
57         TALLOC_CTX *child;
58 } fr_talloc_link_t;
59
60 /** Sets a signal handler using sigaction if available, else signal
61  *
62  * @param sig to set handler for.
63  * @param func handler to set.
64  */
65 int fr_set_signal(int sig, sig_t func)
66 {
67 #ifdef HAVE_SIGACTION
68         struct sigaction act;
69
70         memset(&act, 0, sizeof(act));
71         act.sa_flags = 0;
72         sigemptyset(&act.sa_mask);
73         act.sa_handler = func;
74
75         if (sigaction(sig, &act, NULL) < 0) {
76                 fr_strerror_printf("Failed setting signal %i handler via sigaction(): %s", sig, fr_syserror(errno));
77                 return -1;
78         }
79 #else
80         if (signal(sig, func) < 0) {
81                 fr_strerror_printf("Failed setting signal %i handler via signal(): %s", sig, fr_syserror(errno));
82                 return -1;
83         }
84 #endif
85         return 0;
86 }
87
88 static int _fr_trigger_talloc_ctx_free(fr_talloc_link_t *trigger)
89 {
90         if (trigger->armed) talloc_free(trigger->child);
91
92         return 0;
93 }
94
95 static int _fr_disarm_talloc_ctx_free(bool **armed)
96 {
97         **armed = false;
98         return 0;
99 }
100
101 /** Link a parent and a child context, so the child is freed before the parent
102  *
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.
105  *
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.
109  */
110 int fr_link_talloc_ctx_free(TALLOC_CTX *parent, TALLOC_CTX *child)
111 {
112         fr_talloc_link_t *trigger;
113         bool **disarm;
114
115         trigger = talloc(parent, fr_talloc_link_t);
116         if (!trigger) return -1;
117
118         disarm = talloc(child, bool *);
119         if (!disarm) {
120                 talloc_free(trigger);
121                 return -1;
122         }
123
124         trigger->child = child;
125         trigger->armed = true;
126         *disarm = &trigger->armed;
127
128         talloc_set_destructor(trigger, _fr_trigger_talloc_ctx_free);
129         talloc_set_destructor(disarm, _fr_disarm_talloc_ctx_free);
130
131         return 0;
132 }
133
134 /*
135  *      Explicitly cleanup the memory allocated to the error inet_ntop
136  *      buffer.
137  */
138 static void _fr_inet_ntop_free(void *arg)
139 {
140         free(arg);
141 }
142
143 /** Wrapper around inet_ntop, prints IPv4/IPv6 addresses
144  *
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.
148  *
149  * So as with lib/log.c use TLS to allocate thread specific buffers, and
150  * write the IP address there instead.
151  *
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.
155  */
156 char const *fr_inet_ntop(int af, void const *src)
157 {
158         char *buffer;
159
160         if (!src) {
161                 return NULL;
162         }
163
164         buffer = fr_thread_local_init(fr_inet_ntop_buffer, _fr_inet_ntop_free);
165         if (!buffer) {
166                 int ret;
167
168                 /*
169                  *      malloc is thread safe, talloc is not
170                  */
171                 buffer = malloc(sizeof(char) * INET6_ADDRSTRLEN);
172                 if (!buffer) {
173                         fr_perror("Failed allocating memory for inet_ntop buffer");
174                         return NULL;
175                 }
176
177                 ret = fr_thread_local_set(fr_inet_ntop_buffer, buffer);
178                 if (ret != 0) {
179                         fr_perror("Failed setting up TLS for inet_ntop buffer: %s", fr_syserror(ret));
180                         free(buffer);
181                         return NULL;
182                 }
183         }
184         buffer[0] = '\0';
185
186         return inet_ntop(af, src, buffer, INET6_ADDRSTRLEN);
187 }
188
189 /*
190  *      Return an IP address in standard dot notation
191  *
192  *      FIXME: DELETE THIS
193  */
194 char const *ip_ntoa(char *buffer, uint32_t ipaddr)
195 {
196         ipaddr = ntohl(ipaddr);
197
198         sprintf(buffer, "%d.%d.%d.%d",
199                 (ipaddr >> 24) & 0xff,
200                 (ipaddr >> 16) & 0xff,
201                 (ipaddr >>  8) & 0xff,
202                 (ipaddr      ) & 0xff);
203         return buffer;
204 }
205
206 /** Parse an IPv4 address or IPv4 prefix in presentation format (and others)
207  *
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 -1.
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.
214  */
215 int fr_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback)
216 {
217         char *p;
218         unsigned int prefix;
219         char *eptr;
220
221         /* Dotted quad + / + [0-9]{1,2} */
222         char buffer[INET_ADDRSTRLEN + 3];
223
224         /*
225          *      Copy to intermediary buffer if we were given a length
226          */
227         if (inlen >= 0) {
228                 if (inlen >= (ssize_t)sizeof(buffer)) {
229                         fr_strerror_printf("Invalid IPv4 address string \"%s\"", value);
230                         return -1;
231                 }
232                 memcpy(buffer, value, inlen);
233                 buffer[inlen] = '\0';
234         }
235
236         p = strchr(value, '/');
237         /*
238          *      192.0.2.2 is parsed as if it was /32
239          */
240         if (!p) {
241                 /*
242                  *      Allow '*' as the wildcard address usually 0.0.0.0
243                  */
244                 if ((value[0] == '*') && (value[1] == '\0')) {
245                         out->ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
246                 /*
247                  *      Convert things which are obviously integers to IP addresses
248                  *
249                  *      We assume the number is the bigendian representation of the
250                  *      IP address.
251                  */
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);
257                                 return -1;
258                         }
259                 } else if (ip_hton(out, AF_INET, value, fallback) < 0) return -1;
260
261                 out->prefix = 32;
262                 out->af = AF_INET;
263
264                 return 0;
265         }
266
267         /*
268          *      Otherwise parse the prefix
269          */
270         if ((size_t)(p - value) >= INET_ADDRSTRLEN) {
271                 fr_strerror_printf("Invalid IPv4 address string \"%s\"", value);
272                 return -1;
273         }
274
275         /*
276          *      Copy the IP portion into a temporary buffer if we haven't already.
277          */
278         if (inlen < 0) memcpy(buffer, value, p - value);
279         buffer[p - value] = '\0';
280
281         if (!resolve) {
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);
284                         return -1;
285                 }
286         } else if (ip_hton(out, AF_INET, buffer, fallback) < 0) return -1;
287
288         prefix = strtoul(p + 1, &eptr, 10);
289         if (prefix > 32) {
290                 fr_strerror_printf("Invalid IPv4 mask length \"%s\".  Should be between 0-32", p);
291                 return -1;
292         }
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);
296                 return -1;
297         }
298
299         if (prefix < 32) {
300                 out->ipaddr.ip4addr = fr_inaddr_mask(&out->ipaddr.ip4addr, prefix);
301         }
302
303         out->prefix = (uint8_t) prefix;
304         out->af = AF_INET;
305
306         return 0;
307 }
308
309 /** Parse an IPv6 address or IPv6 prefix in presentation format (and others)
310  *
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 -1.
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.
317  */
318 int fr_pton6(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback)
319 {
320         char const *p;
321         unsigned int prefix;
322         char *eptr;
323
324         /* IPv6  + / + [0-9]{1,3} */
325         char buffer[INET6_ADDRSTRLEN + 4];
326
327         /*
328          *      Copy to intermediary buffer if we were given a length
329          */
330         if (inlen >= 0) {
331                 if (inlen >= (ssize_t)sizeof(buffer)) {
332                         fr_strerror_printf("Invalid IPv6 address string \"%s\"", value);
333                         return -1;
334                 }
335                 memcpy(buffer, value, inlen);
336                 buffer[inlen] = '\0';
337         }
338
339         p = strchr(value, '/');
340         if (!p) {
341                 /*
342                  *      Allow '*' as the wildcard address
343                  */
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);
349                                 return -1;
350                         }
351                 } else if (ip_hton(out, AF_INET6, value, fallback) < 0) return -1;
352
353                 out->prefix = 128;
354                 out->af = AF_INET6;
355
356                 return 0;
357         }
358
359         if ((p - value) >= INET6_ADDRSTRLEN) {
360                 fr_strerror_printf("Invalid IPv6 address string \"%s\"", value);
361                 return -1;
362         }
363
364         /*
365          *      Copy string to temporary buffer if we didn't do it earlier
366          */
367         if (inlen < 0) memcpy(buffer, value, p - value);
368         buffer[p - value] = '\0';
369
370         if (!resolve) {
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);
373                         return -1;
374                 }
375         } else if (ip_hton(out, AF_INET6, buffer, fallback) < 0) return -1;
376
377         prefix = strtoul(p + 1, &eptr, 10);
378         if (prefix > 128) {
379                 fr_strerror_printf("Invalid IPv6 mask length \"%s\".  Should be between 0-128", p);
380                 return -1;
381         }
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);
385                 return -1;
386         }
387
388         if (prefix < 128) {
389                 struct in6_addr addr;
390
391                 addr = fr_in6addr_mask(&out->ipaddr.ip6addr, prefix);
392                 memcpy(out->ipaddr.ip6addr.s6_addr, addr.s6_addr, sizeof(out->ipaddr.ip6addr.s6_addr));
393         }
394
395         out->prefix = (uint8_t) prefix;
396         out->af = AF_INET6;
397
398         return 0;
399 }
400
401 /** Simple wrapper to decide whether an IP value is v4 or v6 and call the appropriate parser.
402  *
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 -1.
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.
408  */
409 int fr_pton(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve)
410 {
411         size_t len, i;
412
413         len = (inlen >= 0) ? (size_t)inlen : strlen(value);
414         for (i = 0; i < len; i++) switch (value[i]) {
415         /*
416          *      Chars illegal in domain names and IPv4 addresses.
417          *      Must be v6 and cannot be a domain.
418          */
419         case ':':
420         case '[':
421         case ']':
422                 return fr_pton6(out, value, inlen, false, false);
423
424         /*
425          *      Chars which don't really tell us anything
426          */
427         case '.':
428         case '/':
429                 continue;
430
431         default:
432                 /*
433                  *      Outside the range of IPv4 chars, must be a domain
434                  *      Use A record in preference to AAAA record.
435                  */
436                 if ((value[i] < '0') || (value[i] > '9')) {
437                         if (!resolve) return -1;
438                         return fr_pton4(out, value, inlen, true, true);
439                 }
440                 break;
441         }
442
443         /*
444          *      All chars were in the IPv4 set [0-9/.], must be an IPv4
445          *      address.
446          */
447         return fr_pton4(out, value, inlen, false, false);
448 }
449
450 int fr_ntop(char *out, size_t outlen, fr_ipaddr_t *addr)
451 {
452         char buffer[INET6_ADDRSTRLEN];
453
454         if (inet_ntop(addr->af, &(addr->ipaddr), buffer, sizeof(buffer)) == NULL) return -1;
455
456         return snprintf(out, outlen, "%s/%i", buffer, addr->prefix);
457 }
458
459 /*
460  *      Internal wrapper for locking, to minimize the number of ifdef's
461  *
462  *      Use fcntl or error
463  */
464 int rad_lockfd(int fd, int lock_len)
465 {
466 #ifdef F_WRLCK
467         struct flock fl;
468
469         fl.l_start = 0;
470         fl.l_len = lock_len;
471         fl.l_pid = getpid();
472         fl.l_type = F_WRLCK;
473         fl.l_whence = SEEK_CUR;
474
475         return fcntl(fd, F_SETLKW, (void *)&fl);
476 #else
477 #error "missing definition for F_WRLCK, all file locks will fail"
478
479         return -1;
480 #endif
481 }
482
483 /*
484  *      Internal wrapper for locking, to minimize the number of ifdef's
485  *
486  *      Lock an fd, prefer lockf() over flock()
487  *      Nonblocking version.
488  */
489 int rad_lockfd_nonblock(int fd, int lock_len)
490 {
491 #ifdef F_WRLCK
492         struct flock fl;
493
494         fl.l_start = 0;
495         fl.l_len = lock_len;
496         fl.l_pid = getpid();
497         fl.l_type = F_WRLCK;
498         fl.l_whence = SEEK_CUR;
499
500         return fcntl(fd, F_SETLK, (void *)&fl);
501 #else
502 #error "missing definition for F_WRLCK, all file locks will fail"
503
504         return -1;
505 #endif
506 }
507
508 /*
509  *      Internal wrapper for unlocking, to minimize the number of ifdef's
510  *      in the source.
511  *
512  *      Unlock an fd, prefer lockf() over flock()
513  */
514 int rad_unlockfd(int fd, int lock_len)
515 {
516 #ifdef F_WRLCK
517         struct flock fl;
518
519         fl.l_start = 0;
520         fl.l_len = lock_len;
521         fl.l_pid = getpid();
522         fl.l_type = F_WRLCK;
523         fl.l_whence = SEEK_CUR;
524
525         return fcntl(fd, F_UNLCK, (void *)&fl);
526 #else
527 #error "missing definition for F_WRLCK, all file locks will fail"
528
529         return -1;
530 #endif
531 }
532
533 /*
534  *      Return an interface-id in standard colon notation
535  */
536 char *ifid_ntoa(char *buffer, size_t size, uint8_t const *ifid)
537 {
538         snprintf(buffer, size, "%x:%x:%x:%x",
539                  (ifid[0] << 8) + ifid[1], (ifid[2] << 8) + ifid[3],
540                  (ifid[4] << 8) + ifid[5], (ifid[6] << 8) + ifid[7]);
541         return buffer;
542 }
543
544
545 /*
546  *      Return an interface-id from
547  *      one supplied in standard colon notation.
548  */
549 uint8_t *ifid_aton(char const *ifid_str, uint8_t *ifid)
550 {
551         static char const xdigits[] = "0123456789abcdef";
552         char const *p, *pch;
553         int num_id = 0, val = 0, idx = 0;
554
555         for (p = ifid_str; ; ++p) {
556                 if (*p == ':' || *p == '\0') {
557                         if (num_id <= 0)
558                                 return NULL;
559
560                         /*
561                          *      Drop 'val' into the array.
562                          */
563                         ifid[idx] = (val >> 8) & 0xff;
564                         ifid[idx + 1] = val & 0xff;
565                         if (*p == '\0') {
566                                 /*
567                                  *      Must have all entries before
568                                  *      end of the string.
569                                  */
570                                 if (idx != 6)
571                                         return NULL;
572                                 break;
573                         }
574                         val = 0;
575                         num_id = 0;
576                         if ((idx += 2) > 6)
577                                 return NULL;
578                 } else if ((pch = strchr(xdigits, tolower(*p))) != NULL) {
579                         if (++num_id > 4)
580                                 return NULL;
581                         /*
582                          *      Dumb version of 'scanf'
583                          */
584                         val <<= 4;
585                         val |= (pch - xdigits);
586                 } else
587                         return NULL;
588         }
589         return ifid;
590 }
591
592
593 #ifndef HAVE_INET_PTON
594 static int inet_pton4(char const *src, struct in_addr *dst)
595 {
596         int octet;
597         unsigned int num;
598         char const *p, *off;
599         uint8_t tmp[4];
600         static char const digits[] = "0123456789";
601
602         octet = 0;
603         p = src;
604         while (1) {
605                 num = 0;
606                 while (*p && ((off = strchr(digits, *p)) != NULL)) {
607                         num *= 10;
608                         num += (off - digits);
609
610                         if (num > 255) return 0;
611
612                         p++;
613                 }
614                 if (!*p) break;
615
616                 /*
617                  *      Not a digit, MUST be a dot, else we
618                  *      die.
619                  */
620                 if (*p != '.') {
621                         return 0;
622                 }
623
624                 tmp[octet++] = num;
625                 p++;
626         }
627
628         /*
629          *      End of the string.  At the fourth
630          *      octet is OK, anything else is an
631          *      error.
632          */
633         if (octet != 3) {
634                 return 0;
635         }
636         tmp[3] = num;
637
638         memcpy(dst, &tmp, sizeof(tmp));
639         return 1;
640 }
641
642
643 #ifdef HAVE_STRUCT_SOCKADDR_IN6
644 /* int
645  * inet_pton6(src, dst)
646  *      convert presentation level address to network order binary form.
647  * return:
648  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
649  * notice:
650  *      (1) does not touch `dst' unless it's returning 1.
651  *      (2) :: in a full address is silently ignored.
652  * credit:
653  *      inspired by Mark Andrews.
654  * author:
655  *      Paul Vixie, 1996.
656  */
657 static int inet_pton6(char const *src, unsigned char *dst)
658 {
659         static char const xdigits_l[] = "0123456789abcdef",
660                           xdigits_u[] = "0123456789ABCDEF";
661         u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
662         char const *xdigits, *curtok;
663         int ch, saw_xdigit;
664         u_int val;
665
666         memset((tp = tmp), 0, IN6ADDRSZ);
667         endp = tp + IN6ADDRSZ;
668         colonp = NULL;
669         /* Leading :: requires some special handling. */
670         if (*src == ':')
671                 if (*++src != ':')
672                         return (0);
673         curtok = src;
674         saw_xdigit = 0;
675         val = 0;
676         while ((ch = *src++) != '\0') {
677                 char const *pch;
678
679                 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
680                         pch = strchr((xdigits = xdigits_u), ch);
681                 if (pch != NULL) {
682                         val <<= 4;
683                         val |= (pch - xdigits);
684                         if (val > 0xffff)
685                                 return (0);
686                         saw_xdigit = 1;
687                         continue;
688                 }
689                 if (ch == ':') {
690                         curtok = src;
691                         if (!saw_xdigit) {
692                                 if (colonp)
693                                         return (0);
694                                 colonp = tp;
695                                 continue;
696                         }
697                         if (tp + INT16SZ > endp)
698                                 return (0);
699                         *tp++ = (u_char) (val >> 8) & 0xff;
700                         *tp++ = (u_char) val & 0xff;
701                         saw_xdigit = 0;
702                         val = 0;
703                         continue;
704                 }
705                 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
706                     inet_pton4(curtok, (struct in_addr *) tp) > 0) {
707                         tp += INADDRSZ;
708                         saw_xdigit = 0;
709                         break;  /* '\0' was seen by inet_pton4(). */
710                 }
711                 return (0);
712         }
713         if (saw_xdigit) {
714                 if (tp + INT16SZ > endp)
715                         return (0);
716                 *tp++ = (u_char) (val >> 8) & 0xff;
717                 *tp++ = (u_char) val & 0xff;
718         }
719         if (colonp != NULL) {
720                 /*
721                  * Since some memmove()'s erroneously fail to handle
722                  * overlapping regions, we'll do the shift by hand.
723                  */
724                 int const n = tp - colonp;
725                 int i;
726
727                 for (i = 1; i <= n; i++) {
728                         endp[- i] = colonp[n - i];
729                         colonp[n - i] = 0;
730                 }
731                 tp = endp;
732         }
733         if (tp != endp)
734                 return (0);
735         /* bcopy(tmp, dst, IN6ADDRSZ); */
736         memcpy(dst, tmp, IN6ADDRSZ);
737         return (1);
738 }
739 #endif
740
741 /*
742  *      Utility function, so that the rest of the server doesn't
743  *      have ifdef's around IPv6 support
744  */
745 int inet_pton(int af, char const *src, void *dst)
746 {
747         if (af == AF_INET) {
748                 return inet_pton4(src, dst);
749         }
750 #ifdef HAVE_STRUCT_SOCKADDR_IN6
751
752         if (af == AF_INET6) {
753                 return inet_pton6(src, dst);
754         }
755 #endif
756
757         return -1;
758 }
759 #endif
760
761 #ifndef HAVE_INET_NTOP
762 /*
763  *      Utility function, so that the rest of the server doesn't
764  *      have ifdef's around IPv6 support
765  */
766 char const *inet_ntop(int af, void const *src, char *dst, size_t cnt)
767 {
768         if (af == AF_INET) {
769                 uint8_t const *ipaddr = src;
770
771                 if (cnt <= INET_ADDRSTRLEN) return NULL;
772
773                 snprintf(dst, cnt, "%d.%d.%d.%d",
774                          ipaddr[0], ipaddr[1],
775                          ipaddr[2], ipaddr[3]);
776                 return dst;
777         }
778
779         /*
780          *      If the system doesn't define this, we define it
781          *      in missing.h
782          */
783         if (af == AF_INET6) {
784                 struct in6_addr const *ipaddr = src;
785
786                 if (cnt <= INET6_ADDRSTRLEN) return NULL;
787
788                 snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
789                          (ipaddr->s6_addr[0] << 8) | ipaddr->s6_addr[1],
790                          (ipaddr->s6_addr[2] << 8) | ipaddr->s6_addr[3],
791                          (ipaddr->s6_addr[4] << 8) | ipaddr->s6_addr[5],
792                          (ipaddr->s6_addr[6] << 8) | ipaddr->s6_addr[7],
793                          (ipaddr->s6_addr[8] << 8) | ipaddr->s6_addr[9],
794                          (ipaddr->s6_addr[10] << 8) | ipaddr->s6_addr[11],
795                          (ipaddr->s6_addr[12] << 8) | ipaddr->s6_addr[13],
796                          (ipaddr->s6_addr[14] << 8) | ipaddr->s6_addr[15]);
797                 return dst;
798         }
799
800         return NULL;            /* don't support IPv6 */
801 }
802 #endif
803
804 /** Wrappers for IPv4/IPv6 host to IP address lookup
805  *
806  * This function returns only one IP address, of the specified address family,
807  * or the first address (of whatever family), if AF_UNSPEC is used.
808  *
809  * If fallback is specified and af is AF_INET, but no AF_INET records were
810  * found and a record for AF_INET6 exists that record will be returned.
811  *
812  * If fallback is specified and af is AF_INET6, and a record with AF_INET4 exists
813  * that record will be returned instead.
814  *
815  * @param out Where to write result.
816  * @param af To search for in preference.
817  * @param hostname to search for.
818  * @param fallback to the other adress family, if no records matching af, found.
819  * @return 0 on success, else -1 on failure.
820  */
821 int ip_hton(fr_ipaddr_t *out, int af, char const *hostname, bool fallback)
822 {
823         int rcode;
824         struct addrinfo hints, *ai = NULL, *alt = NULL, *res = NULL;
825
826         /*
827          *      Avoid malloc for IP addresses.  This helps us debug
828          *      memory errors when using talloc.
829          */
830 #ifdef TALLOC_DEBUG
831         if (true) {
832 #else
833         if (!fr_hostname_lookups) {
834 #endif
835 #ifdef HAVE_STRUCT_SOCKADDR_IN6
836                 if (af == AF_UNSPEC) {
837                         char const *p;
838
839                         for (p = hostname; *p != '\0'; p++) {
840                                 if ((*p == ':') ||
841                                     (*p == '[') ||
842                                     (*p == ']')) {
843                                         af = AF_INET6;
844                                         break;
845                                 }
846                         }
847                 }
848 #endif
849
850                 if (af == AF_UNSPEC) af = AF_INET;
851
852                 if (!inet_pton(af, hostname, &(out->ipaddr))) return -1;
853
854                 out->af = af;
855                 return 0;
856         }
857
858         memset(&hints, 0, sizeof(hints));
859
860         /*
861          *      If we're falling back we need both IPv4 and IPv6 records
862          */
863         if (fallback) {
864                 hints.ai_family = AF_UNSPEC;
865         } else {
866                 hints.ai_family = af;
867         }
868
869         if ((rcode = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
870                 switch (af) {
871                 default:
872                 case AF_UNSPEC:
873                         fr_strerror_printf("Failed resolving \"%s\" to IP address: %s",
874                                            hostname, gai_strerror(rcode));
875                         return -1;
876
877                 case AF_INET:
878                         fr_strerror_printf("Failed resolving \"%s\" to IPv4 address: %s",
879                                            hostname, gai_strerror(rcode));
880                         return -1;
881
882                 case AF_INET6:
883                         fr_strerror_printf("Failed resolving \"%s\" to IPv6 address: %s",
884                                            hostname, gai_strerror(rcode));
885                         return -1;
886                 }
887         }
888
889         for (ai = res; ai; ai = ai->ai_next) {
890                 if ((af == ai->ai_family) || (af == AF_UNSPEC)) break;
891                 if (!alt && fallback && ((ai->ai_family == AF_INET) || (ai->ai_family == AF_INET6))) alt = ai;
892         }
893
894         if (!ai) ai = alt;
895         if (!ai) {
896                 fr_strerror_printf("ip_hton failed to find requested information for host %.100s", hostname);
897                 freeaddrinfo(res);
898                 return -1;
899         }
900
901         rcode = fr_sockaddr2ipaddr((struct sockaddr_storage *)ai->ai_addr,
902                                    ai->ai_addrlen, out, NULL);
903         freeaddrinfo(res);
904         if (!rcode) return -1;
905
906         return 0;
907 }
908
909 /*
910  *      Look IP addresses up, and print names (depending on DNS config)
911  */
912 char const *ip_ntoh(fr_ipaddr_t const *src, char *dst, size_t cnt)
913 {
914         struct sockaddr_storage ss;
915         int error;
916         socklen_t salen;
917
918         /*
919          *      No DNS lookups
920          */
921         if (!fr_dns_lookups) {
922                 return inet_ntop(src->af, &(src->ipaddr), dst, cnt);
923         }
924
925         if (!fr_ipaddr2sockaddr(src, 0, &ss, &salen)) {
926                 return NULL;
927         }
928
929         if ((error = getnameinfo((struct sockaddr *)&ss, salen, dst, cnt, NULL, 0,
930                                  NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
931                 fr_strerror_printf("ip_ntoh: %s", gai_strerror(error));
932                 return NULL;
933         }
934         return dst;
935 }
936
937 /** Mask off a portion of an IPv4 address
938  *
939  * @param ipaddr to mask.
940  * @param prefix Number of contiguous bits to mask.
941  * @return an ipv4 address with the host portion zeroed out.
942  */
943 struct in_addr fr_inaddr_mask(struct in_addr const *ipaddr, uint8_t prefix)
944 {
945         uint32_t ret;
946
947         if (prefix > 32) {
948                 prefix = 32;
949         }
950
951         /* Short circuit */
952         if (prefix == 32) {
953                 return *ipaddr;
954         }
955
956         if (prefix == 0)
957                 ret = 0;
958         else ret = htonl(~((0x00000001UL << (32 - prefix)) - 1)) & ipaddr->s_addr;
959         return (*(struct in_addr *)&ret);
960 }
961
962 /** Mask off a portion of an IPv6 address
963  *
964  * @param ipaddr to mask.
965  * @param prefix Number of contiguous bits to mask.
966  * @return an ipv6 address with the host portion zeroed out.
967  */
968 struct in6_addr fr_in6addr_mask(struct in6_addr const *ipaddr, uint8_t prefix)
969 {
970         uint64_t const *p = (uint64_t const *) ipaddr;
971         uint64_t ret[2], *o = ret;
972
973         if (prefix > 128) {
974                 prefix = 128;
975         }
976
977         /* Short circuit */
978         if (prefix == 128) {
979                 return *ipaddr;
980         }
981
982         if (prefix >= 64) {
983                 prefix -= 64;
984                 *o++ = 0xffffffffffffffffULL & *p++;
985         } else {
986                 ret[1] = 0;
987         }
988
989         *o = htonll(~((0x0000000000000001ULL << (64 - prefix)) - 1)) & *p;
990
991         return *(struct in6_addr *) &ret;
992 }
993
994 /** Zeroes out the host portion of an fr_ipaddr_t
995  *
996  * @param[in,out] addr to mask
997  * @param[in] prefix Length of the network portion.
998  */
999 void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
1000 {
1001
1002         switch (addr->af) {
1003         case AF_INET:
1004                 addr->ipaddr.ip4addr = fr_inaddr_mask(&addr->ipaddr.ip4addr, prefix);
1005                 break;
1006
1007         case AF_INET6:
1008                 addr->ipaddr.ip6addr = fr_in6addr_mask(&addr->ipaddr.ip6addr, prefix);
1009                 break;
1010
1011         default:
1012                 return;
1013         }
1014         addr->prefix = prefix;
1015 }
1016
1017 static char const hextab[] = "0123456789abcdef";
1018
1019 /** Convert hex strings to binary data
1020  *
1021  * @param bin Buffer to write output to.
1022  * @param outlen length of output buffer (or length of input string / 2).
1023  * @param hex input string.
1024  * @param inlen length of the input string
1025  * @return length of data written to buffer.
1026  */
1027 size_t fr_hex2bin(uint8_t *bin, size_t outlen, char const *hex, size_t inlen)
1028 {
1029         size_t i;
1030         size_t len;
1031         char *c1, *c2;
1032
1033         /*
1034          *      Smartly truncate output, caller should check number of bytes
1035          *      written.
1036          */
1037         len = inlen >> 1;
1038         if (len > outlen) len = outlen;
1039
1040         for (i = 0; i < len; i++) {
1041                 if(!(c1 = memchr(hextab, tolower((int) hex[i << 1]), sizeof(hextab))) ||
1042                    !(c2 = memchr(hextab, tolower((int) hex[(i << 1) + 1]), sizeof(hextab))))
1043                         break;
1044                 bin[i] = ((c1-hextab)<<4) + (c2-hextab);
1045         }
1046
1047         return i;
1048 }
1049
1050 /** Convert binary data to a hex string
1051  *
1052  * Ascii encoded hex string will not be prefixed with '0x'
1053  *
1054  * @warning If the output buffer isn't long enough, we have a buffer overflow.
1055  *
1056  * @param[out] hex Buffer to write hex output.
1057  * @param[in] bin input.
1058  * @param[in] inlen of bin input.
1059  * @return length of data written to buffer.
1060  */
1061 size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen)
1062 {
1063         size_t i;
1064
1065         for (i = 0; i < inlen; i++) {
1066                 hex[0] = hextab[((*bin) >> 4) & 0x0f];
1067                 hex[1] = hextab[*bin & 0x0f];
1068                 hex += 2;
1069                 bin++;
1070         }
1071
1072         *hex = '\0';
1073         return inlen * 2;
1074 }
1075
1076 /** Convert binary data to a hex string
1077  *
1078  * Ascii encoded hex string will not be prefixed with '0x'
1079  *
1080  * @param[in] ctx to alloc buffer in.
1081  * @param[in] bin input.
1082  * @param[in] inlen of bin input.
1083  * @return length of data written to buffer.
1084  */
1085 char *fr_abin2hex(TALLOC_CTX *ctx, uint8_t const *bin, size_t inlen)
1086 {
1087         char *buff;
1088
1089         buff = talloc_array(ctx, char, (inlen << 2));
1090         if (!buff) return NULL;
1091
1092         fr_bin2hex(buff, bin, inlen);
1093
1094         return buff;
1095 }
1096
1097 /** Consume the integer (or hex) portion of a value string
1098  *
1099  * @param value string to parse.
1100  * @param end pointer to the first non numeric char.
1101  * @return integer value.
1102  */
1103 uint32_t fr_strtoul(char const *value, char **end)
1104 {
1105         if ((value[0] == '0') && (value[1] == 'x')) {
1106                 return strtoul(value, end, 16);
1107         }
1108
1109         return strtoul(value, end, 10);
1110 }
1111
1112 /** Check whether the string is all whitespace
1113  *
1114  * @return true if the entirety of the string is whitespace, else false.
1115  */
1116 bool is_whitespace(char const *value)
1117 {
1118         do {
1119                 if (!isspace(*value)) return false;
1120         } while (*++value);
1121
1122         return true;
1123 }
1124
1125 /** Check whether the string is all numbers
1126  *
1127  * @return true if the entirety of the string is are numebrs, else false.
1128  */
1129 bool is_integer(char const *value)
1130 {
1131         do {
1132                 if (!isdigit(*value)) return false;
1133         } while (*++value);
1134
1135         return true;
1136 }
1137
1138 /** Check whether the string is allzeros
1139  *
1140  * @return true if the entirety of the string is are numebrs, else false.
1141  */
1142 bool is_zero(char const *value)
1143 {
1144         do {
1145                 if (*value != '0') return false;
1146         } while (*++value);
1147
1148         return true;
1149 }
1150
1151 /*
1152  *      So we don't have ifdef's in the rest of the code
1153  */
1154 #ifndef HAVE_CLOSEFROM
1155 int closefrom(int fd)
1156 {
1157         int i;
1158         int maxfd = 256;
1159
1160 #ifdef _SC_OPEN_MAX
1161         maxfd = sysconf(_SC_OPEN_MAX);
1162         if (maxfd < 0) {
1163           maxfd = 256;
1164         }
1165 #endif
1166
1167         if (fd > maxfd) return 0;
1168
1169         /*
1170          *      FIXME: return EINTR?
1171          *
1172          *      Use F_CLOSEM?
1173          */
1174         for (i = fd; i < maxfd; i++) {
1175                 close(i);
1176         }
1177
1178         return 0;
1179 }
1180 #endif
1181
1182 int fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
1183 {
1184         if (a->af < b->af) return -1;
1185         if (a->af > b->af) return +1;
1186
1187         if (a->prefix < b->prefix) return -1;
1188         if (a->prefix > b->prefix) return +1;
1189
1190         switch (a->af) {
1191         case AF_INET:
1192                 return memcmp(&a->ipaddr.ip4addr,
1193                               &b->ipaddr.ip4addr,
1194                               sizeof(a->ipaddr.ip4addr));
1195                 break;
1196
1197 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1198         case AF_INET6:
1199                 if (a->scope < b->scope) return -1;
1200                 if (a->scope > b->scope) return +1;
1201
1202                 return memcmp(&a->ipaddr.ip6addr,
1203                               &b->ipaddr.ip6addr,
1204                               sizeof(a->ipaddr.ip6addr));
1205                 break;
1206 #endif
1207
1208         default:
1209                 break;
1210         }
1211
1212         return -1;
1213 }
1214
1215 int fr_ipaddr2sockaddr(fr_ipaddr_t const *ipaddr, uint16_t port,
1216                        struct sockaddr_storage *sa, socklen_t *salen)
1217 {
1218         memset(sa, 0, sizeof(*sa));
1219
1220         if (ipaddr->af == AF_INET) {
1221                 struct sockaddr_in s4;
1222
1223                 *salen = sizeof(s4);
1224
1225                 memset(&s4, 0, sizeof(s4));
1226                 s4.sin_family = AF_INET;
1227                 s4.sin_addr = ipaddr->ipaddr.ip4addr;
1228                 s4.sin_port = htons(port);
1229                 memset(sa, 0, sizeof(*sa));
1230                 memcpy(sa, &s4, sizeof(s4));
1231
1232 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1233         } else if (ipaddr->af == AF_INET6) {
1234                 struct sockaddr_in6 s6;
1235
1236                 *salen = sizeof(s6);
1237
1238                 memset(&s6, 0, sizeof(s6));
1239                 s6.sin6_family = AF_INET6;
1240                 s6.sin6_addr = ipaddr->ipaddr.ip6addr;
1241                 s6.sin6_port = htons(port);
1242                 s6.sin6_scope_id = ipaddr->scope;
1243                 memset(sa, 0, sizeof(*sa));
1244                 memcpy(sa, &s6, sizeof(s6));
1245 #endif
1246         } else {
1247                 return 0;
1248         }
1249
1250         return 1;
1251 }
1252
1253
1254 int fr_sockaddr2ipaddr(struct sockaddr_storage const *sa, socklen_t salen,
1255                        fr_ipaddr_t *ipaddr, uint16_t *port)
1256 {
1257         memset(ipaddr, 0, sizeof(*ipaddr));
1258
1259         if (sa->ss_family == AF_INET) {
1260                 struct sockaddr_in      s4;
1261
1262                 if (salen < sizeof(s4)) {
1263                         fr_strerror_printf("IPv4 address is too small");
1264                         return 0;
1265                 }
1266
1267                 memcpy(&s4, sa, sizeof(s4));
1268                 ipaddr->af = AF_INET;
1269                 ipaddr->prefix = 32;
1270                 ipaddr->ipaddr.ip4addr = s4.sin_addr;
1271                 if (port) *port = ntohs(s4.sin_port);
1272
1273 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1274         } else if (sa->ss_family == AF_INET6) {
1275                 struct sockaddr_in6     s6;
1276
1277                 if (salen < sizeof(s6)) {
1278                         fr_strerror_printf("IPv6 address is too small");
1279                         return 0;
1280                 }
1281
1282                 memcpy(&s6, sa, sizeof(s6));
1283                 ipaddr->af = AF_INET6;
1284                 ipaddr->prefix = 128;
1285                 ipaddr->ipaddr.ip6addr = s6.sin6_addr;
1286                 if (port) *port = ntohs(s6.sin6_port);
1287                 ipaddr->scope = s6.sin6_scope_id;
1288 #endif
1289
1290         } else {
1291                 fr_strerror_printf("Unsupported address famility %d",
1292                                    sa->ss_family);
1293                 return 0;
1294         }
1295
1296         return 1;
1297 }
1298
1299 /** Convert UTF8 string to UCS2 encoding
1300  *
1301  * @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
1302  *
1303  * @param[out] out Where to write the ucs2 string.
1304  * @param[in] outlen Size of output buffer.
1305  * @param[in] in UTF8 string to convert.
1306  * @param[in] inlen length of UTF8 string.
1307  * @return the size of the UCS2 string written to the output buffer (in bytes).
1308  */
1309 ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
1310 {
1311         size_t i;
1312         uint8_t *start = out;
1313
1314         for (i = 0; i < inlen; i++) {
1315                 uint8_t c, c2, c3;
1316
1317                 c = in[i];
1318                 if ((size_t)(out - start) >= outlen) {
1319                         /* input too long */
1320                         return -1;
1321                 }
1322
1323                 /* One-byte encoding */
1324                 if (c <= 0x7f) {
1325                         FR_PUT_LE16(out, c);
1326                         out += 2;
1327                         continue;
1328                 } else if ((i == (inlen - 1)) || ((size_t)(out - start) >= (outlen - 1))) {
1329                         /* Incomplete surrogate */
1330                         return -1;
1331                 }
1332
1333                 c2 = in[++i];
1334                 /* Two-byte encoding */
1335                 if ((c & 0xe0) == 0xc0) {
1336                         FR_PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
1337                         out += 2;
1338                         continue;
1339                 }
1340                 if ((i == inlen) || ((size_t)(out - start) >= (outlen - 1))) {
1341                         /* Incomplete surrogate */
1342                         return -1;
1343                 }
1344
1345                 /* Three-byte encoding */
1346                 c3 = in[++i];
1347                 FR_PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
1348                 out += 2;
1349         }
1350
1351         return out - start;
1352 }
1353
1354 /** Write 128bit unsigned integer to buffer
1355  *
1356  * @author Alexey Frunze
1357  *
1358  * @param out where to write result to.
1359  * @param outlen size of out.
1360  * @param num 128 bit integer.
1361  */
1362 size_t fr_prints_uint128(char *out, size_t outlen, uint128_t const num)
1363 {
1364         char buff[128 / 3 + 1 + 1];
1365         uint64_t n[2];
1366         char *p = buff;
1367         int i;
1368 #ifdef RADIUS_LITTLE_ENDIAN
1369         const size_t l = 0;
1370         const size_t h = 1;
1371 #else
1372         const size_t l = 1;
1373         const size_t h = 0;
1374 #endif
1375
1376         memset(buff, '0', sizeof(buff) - 1);
1377         buff[sizeof(buff) - 1] = '\0';
1378
1379         memcpy(n, &num, sizeof(n));
1380
1381         for (i = 0; i < 128; i++) {
1382                 ssize_t j;
1383                 int carry;
1384
1385                 carry = (n[h] >= 0x8000000000000000);
1386
1387                 // Shift n[] left, doubling it
1388                 n[h] = ((n[h] << 1) & 0xffffffffffffffff) + (n[l] >= 0x8000000000000000);
1389                 n[l] = ((n[l] << 1) & 0xffffffffffffffff);
1390
1391                 // Add s[] to itself in decimal, doubling it
1392                 for (j = sizeof(buff) - 2; j >= 0; j--) {
1393                         buff[j] += buff[j] - '0' + carry;
1394                         carry = (buff[j] > '9');
1395                         if (carry) {
1396                                 buff[j] -= 10;
1397                         }
1398                 }
1399         }
1400
1401         while ((*p == '0') && (p < &buff[sizeof(buff) - 2])) {
1402                 p++;
1403         }
1404
1405         return strlcpy(out, p, outlen);
1406 }
1407
1408 /*
1409  *      Sort of strtok/strsep function.
1410  */
1411 static char *mystrtok(char **ptr, char const *sep)
1412 {
1413         char    *res;
1414
1415         if (**ptr == 0) {
1416                 return NULL;
1417         }
1418
1419         while (**ptr && strchr(sep, **ptr)) {
1420                 (*ptr)++;
1421         }
1422         if (**ptr == 0) {
1423                 return NULL;
1424         }
1425
1426         res = *ptr;
1427         while (**ptr && strchr(sep, **ptr) == NULL) {
1428                 (*ptr)++;
1429         }
1430
1431         if (**ptr != 0) {
1432                 *(*ptr)++ = 0;
1433         }
1434         return res;
1435 }
1436
1437 /** Convert string in various formats to a time_t
1438  *
1439  * @param date_str input date string.
1440  * @param date time_t to write result to.
1441  * @return 0 on success or -1 on error.
1442  */
1443 int fr_get_time(char const *date_str, time_t *date)
1444 {
1445         int             i;
1446         time_t          t;
1447         struct tm       *tm, s_tm;
1448         char            buf[64];
1449         char            *p;
1450         char            *f[4];
1451         char            *tail = NULL;
1452
1453         /*
1454          * Test for unix timestamp date
1455          */
1456         *date = strtoul(date_str, &tail, 10);
1457         if (*tail == '\0') {
1458                 return 0;
1459         }
1460
1461         tm = &s_tm;
1462         memset(tm, 0, sizeof(*tm));
1463         tm->tm_isdst = -1;      /* don't know, and don't care about DST */
1464
1465         strlcpy(buf, date_str, sizeof(buf));
1466
1467         p = buf;
1468         f[0] = mystrtok(&p, " \t");
1469         f[1] = mystrtok(&p, " \t");
1470         f[2] = mystrtok(&p, " \t");
1471         f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
1472         if (!f[0] || !f[1] || !f[2]) return -1;
1473
1474         /*
1475          *      The time has a colon, where nothing else does.
1476          *      So if we find it, bubble it to the back of the list.
1477          */
1478         if (f[3]) {
1479                 for (i = 0; i < 3; i++) {
1480                         if (strchr(f[i], ':')) {
1481                                 p = f[3];
1482                                 f[3] = f[i];
1483                                 f[i] = p;
1484                                 break;
1485                         }
1486                 }
1487         }
1488
1489         /*
1490          *  The month is text, which allows us to find it easily.
1491          */
1492         tm->tm_mon = 12;
1493         for (i = 0; i < 3; i++) {
1494                 if (isalpha( (int) *f[i])) {
1495                         /*
1496                          *  Bubble the month to the front of the list
1497                          */
1498                         p = f[0];
1499                         f[0] = f[i];
1500                         f[i] = p;
1501
1502                         for (i = 0; i < 12; i++) {
1503                                 if (strncasecmp(months[i], f[0], 3) == 0) {
1504                                         tm->tm_mon = i;
1505                                         break;
1506                                 }
1507                         }
1508                 }
1509         }
1510
1511         /* month not found? */
1512         if (tm->tm_mon == 12) return -1;
1513
1514         /*
1515          *  The year may be in f[1], or in f[2]
1516          */
1517         tm->tm_year = atoi(f[1]);
1518         tm->tm_mday = atoi(f[2]);
1519
1520         if (tm->tm_year >= 1900) {
1521                 tm->tm_year -= 1900;
1522
1523         } else {
1524                 /*
1525                  *  We can't use 2-digit years any more, they make it
1526                  *  impossible to tell what's the day, and what's the year.
1527                  */
1528                 if (tm->tm_mday < 1900) return -1;
1529
1530                 /*
1531                  *  Swap the year and the day.
1532                  */
1533                 i = tm->tm_year;
1534                 tm->tm_year = tm->tm_mday - 1900;
1535                 tm->tm_mday = i;
1536         }
1537
1538         /*
1539          *  If the day is out of range, die.
1540          */
1541         if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
1542                 return -1;
1543         }
1544
1545         /*
1546          *      There may be %H:%M:%S.  Parse it in a hacky way.
1547          */
1548         if (f[3]) {
1549                 f[0] = f[3];    /* HH */
1550                 f[1] = strchr(f[0], ':'); /* find : separator */
1551                 if (!f[1]) return -1;
1552
1553                 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
1554
1555                 f[2] = strchr(f[1], ':'); /* find : separator */
1556                 if (f[2]) {
1557                   *(f[2]++) = '\0';     /* nuke it, and point to SS */
1558                   tm->tm_sec = atoi(f[2]);
1559                 }                       /* else leave it as zero */
1560
1561                 tm->tm_hour = atoi(f[0]);
1562                 tm->tm_min = atoi(f[1]);
1563         }
1564
1565         /*
1566          *  Returns -1 on error.
1567          */
1568         t = mktime(tm);
1569         if (t == (time_t) -1) return -1;
1570
1571         *date = t;
1572
1573         return 0;
1574 }
1575
1576 /** Compares two pointers
1577  *
1578  * @param a first pointer to compare.
1579  * @param b second pointer to compare.
1580  * @return -1 if a < b, +1 if b > a, or 0 if both equal.
1581  */
1582 int8_t fr_pointer_cmp(void const *a, void const *b)
1583 {
1584         if (a < b) return -1;
1585         if (a == b) return 0;
1586
1587         return 1;
1588 }
1589
1590 static int _quick_partition(void const *to_sort[], int min, int max, fr_cmp_t cmp) {
1591         void const *pivot = to_sort[min];
1592         int i = min;
1593         int j = max + 1;
1594         void const *tmp;
1595
1596         for (;;) {
1597                 do ++i; while((cmp(to_sort[i], pivot) <= 0) && i <= max);
1598                 do --j; while(cmp(to_sort[j], pivot) > 0);
1599
1600                 if (i >= j) break;
1601
1602                 tmp = to_sort[i];
1603                 to_sort[i] = to_sort[j];
1604                 to_sort[j] = tmp;
1605         }
1606
1607         tmp = to_sort[min];
1608         to_sort[min] = to_sort[j];
1609         to_sort[j] = tmp;
1610
1611         return j;
1612 }
1613
1614 /** Quick sort an array of pointers using a comparator
1615  *
1616  * @param to_sort array of pointers to sort.
1617  * @param min_idx the lowest index (usually 0).
1618  * @param max_idx the highest index (usually length of array - 1).
1619  * @param cmp the comparison function to use to sort the array elements.
1620  */
1621 void fr_quick_sort(void const *to_sort[], int min_idx, int max_idx, fr_cmp_t cmp)
1622 {
1623         int part;
1624
1625         if (min_idx >= max_idx) return;
1626
1627         part = _quick_partition(to_sort, min_idx, max_idx, cmp);
1628         fr_quick_sort(to_sort, min_idx, part - 1, cmp);
1629         fr_quick_sort(to_sort, part + 1, max_idx, cmp);
1630 }
1631
1632 #ifdef TALLOC_DEBUG
1633 void fr_talloc_verify_cb(UNUSED const void *ptr, UNUSED int depth,
1634                          UNUSED int max_depth, UNUSED int is_ref,
1635                          UNUSED void *private_data)
1636 {
1637         /* do nothing */
1638 }
1639 #endif