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