All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
missing.c
Go to the documentation of this file.
1 /*
2  * missing.c Replacements for functions that are or can be
3  * missing on some platforms.
4  *
5  * Version: $Id: 85f5f81147491e1804e70bc00d64f096cb6e15de $
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; 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: 85f5f81147491e1804e70bc00d64f096cb6e15de $")
25 
26 #include <freeradius-devel/libradius.h>
27 
28 #include <ctype.h>
29 
30 #if !defined(HAVE_CLOCK_GETTIME) && defined(__MACH__)
31 # include <mach/mach_time.h>
32 #endif
33 
34 #ifndef HAVE_CRYPT
35 char *crypt(UNUSED char *key, char *salt)
36 {
37  /*log(L_ERR, "crypt() called but not implemented");*/
38  return salt;
39 }
40 #endif
41 
42 #ifndef HAVE_STRNCASECMP
43 int strncasecmp(char *s1, char *s2, int n)
44 {
45  int dif;
46  unsigned char *p1, *p2;
47  int c1, c2;
48 
49  p1 = (unsigned char *)s1;
50  p2 = (unsigned char *)s2;
51  dif = 0;
52 
53  while (n != 0) {
54  if (*p1 == 0 && *p2 == 0)
55  break;
56  c1 = *p1;
57  c2 = *p2;
58 
59  if (islower(c1)) c1 = toupper(c1);
60  if (islower(c2)) c2 = toupper(c2);
61 
62  if ((dif = c1 - c2) != 0)
63  break;
64  p1++;
65  p2++;
66  n--;
67  }
68  return dif;
69 }
70 #endif
71 
72 #ifndef HAVE_STRCASECMP
73 int strcasecmp(char *s1, char *s2)
74 {
75  int l1, l2;
76 
77  l1 = strlen(s1);
78  l2 = strlen(s2);
79  if (l2 > l1) l1 = l2;
80 
81  return strncasecmp(s1, s2, l1);
82 }
83 #endif
84 
85 #ifndef HAVE_INET_ATON
86 int inet_aton(char const *cp, struct in_addr *inp)
87 {
88  int a1, a2, a3, a4;
89 
90  if (sscanf(cp, "%d.%d.%d.%d", &a1, &a2, &a3, &a4) != 4)
91  return 0;
92 
93  inp->s_addr = htonl((a1 << 24) + (a2 << 16) + (a3 << 8) + a4);
94  return 1;
95 }
96 #endif
97 
98 #ifndef HAVE_STRSEP
99 /*
100  * Get next token from string *stringp, where tokens are
101  * possibly-empty strings separated by characters from delim.
102  *
103  * Writes NULs into the string at *stringp to end tokens.
104  * delim need not remain constant from call to call. On
105  * return, *stringp points past the last NUL written (if there
106  * might be further tokens), or is NULL (if there are
107  * definitely no more tokens).
108  *
109  * If *stringp is NULL, strsep returns NULL.
110  */
111 char *
112 strsep(char **stringp, char const *delim)
113 {
114  char *s;
115  char const *spanp;
116  int c, sc;
117  char *tok;
118 
119  if ((s = *stringp) == NULL)
120  return (NULL);
121 
122  for (tok = s;;) {
123  c = *s++;
124  spanp = delim;
125  do {
126  if ((sc = *spanp++) == c) {
127  if (c == 0)
128  s = NULL;
129  else
130  s[-1] = 0;
131  *stringp = s;
132  return (tok);
133  }
134  } while (sc != 0);
135  }
136 
137  return NULL; /* NOTREACHED, but the compiler complains */
138 }
139 #endif
140 
141 #ifndef HAVE_LOCALTIME_R
142 /*
143  * We use localtime_r() by default in the server.
144  *
145  * For systems which do NOT have localtime_r(), we make the
146  * assumption that localtime() is re-entrant, and returns a
147  * per-thread data structure.
148  *
149  * Even if localtime is NOT re-entrant, this function will
150  * lower the possibility of race conditions.
151  */
152 struct tm *localtime_r(time_t const *l_clock, struct tm *result)
153 {
154  memcpy(result, localtime(l_clock), sizeof(*result));
155 
156  return result;
157 }
158 #endif
159 
160 #ifndef HAVE_CTIME_R
161 /*
162  * We use ctime_r() by default in the server.
163  *
164  * For systems which do NOT have ctime_r(), we make the
165  * assumption that ctime() is re-entrant, and returns a
166  * per-thread data structure.
167  *
168  * Even if ctime is NOT re-entrant, this function will
169  * lower the possibility of race conditions.
170  */
171 char *ctime_r(time_t const *l_clock, char *l_buf)
172 {
173  strcpy(l_buf, ctime(l_clock));
174 
175  return l_buf;
176 }
177 #endif
178 
179 #ifndef HAVE_GMTIME_R
180 /*
181  * We use gmtime_r() by default in the server.
182  *
183  * For systems which do NOT have gmtime_r(), we make the
184  * assumption that gmtime() is re-entrant, and returns a
185  * per-thread data structure.
186  *
187  * Even if gmtime is NOT re-entrant, this function will
188  * lower the possibility of race conditions.
189  */
190 struct tm *gmtime_r(time_t const *l_clock, struct tm *result)
191 {
192  memcpy(result, gmtime(l_clock), sizeof(*result));
193 
194  return result;
195 }
196 #endif
197 
198 #ifndef HAVE_VDPRINTF
199 int vdprintf (int fd, char const *format, va_list args)
200 {
201  int ret;
202  FILE *fp;
203  int dup_fd;
204 
205  dup_fd = dup(fd);
206  if (dup_fd < 0) return -1;
207 
208  fp = fdopen(fd, "w");
209  if (!fp) {
210  close(dup_fd);
211  return -1;
212  }
213 
214  ret = vfprintf(fp, format, args);
215  fclose(fp); /* Also closes dup_fd */
216 
217  return ret;
218 }
219 #endif
220 
221 #ifndef HAVE_GETTIMEOFDAY
222 #ifdef WIN32
223 /*
224  * Number of micro-seconds between the beginning of the Windows epoch
225  * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970).
226  *
227  * This assumes all Win32 compilers have 64-bit support.
228  */
229 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) || defined(__WATCOMC__)
230 #define DELTA_EPOCH_IN_USEC 11644473600000000Ui64
231 #else
232 #define DELTA_EPOCH_IN_USEC 11644473600000000ULL
233 #endif
234 
235 static uint64_t filetime_to_unix_epoch (FILETIME const *ft)
236 {
237  uint64_t res = (uint64_t) ft->dwHighDateTime << 32;
238 
239  res |= ft->dwLowDateTime;
240  res /= 10; /* from 100 nano-sec periods to usec */
241  res -= DELTA_EPOCH_IN_USEC; /* from Win epoch to Unix epoch */
242  return (res);
243 }
244 
245 int gettimeofday (struct timeval *tv, UNUSED void *tz)
246 {
247  FILETIME ft;
248  uint64_t tim;
249 
250  if (!tv) {
251  errno = EINVAL;
252  return (-1);
253  }
254  GetSystemTimeAsFileTime (&ft);
255  tim = filetime_to_unix_epoch (&ft);
256  tv->tv_sec = (long) (tim / 1000000L);
257  tv->tv_usec = (long) (tim % 1000000L);
258  return (0);
259 }
260 #endif
261 #endif
262 
263 #if !defined(HAVE_CLOCK_GETTIME) && defined(__MACH__)
264 int clock_gettime(int clk_id, struct timespec *t)
265 {
266  static mach_timebase_info_data_t timebase;
267  static bool done_init = false;
268 
269 #ifdef HAVE_PTHREAD_H
270  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
271 #endif
272 
273  if (!done_init) {
274 #ifdef HAVE_PTHREAD_H
275  pthread_mutex_lock(&mutex);
276  if (!done_init) {
277 #endif
278  mach_timebase_info(&timebase);
279 #ifdef HAVE_PTHREAD_H
280  done_init = true;
281  }
282  pthread_mutex_unlock(&mutex);
283 #endif
284  }
285 
286  switch (clk_id) {
287  case CLOCK_REALTIME:
288  return -1;
289 
290  case CLOCK_MONOTONIC:
291  {
292  uint64_t time;
293  time = mach_absolute_time();
294  double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
295  double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
296  t->tv_sec = seconds;
297  t->tv_nsec = nseconds;
298  }
299  return 0;
300 
301  default:
302  errno = EINVAL;
303  return -1;
304  }
305 }
306 #endif
307 
308 #define NTP_EPOCH_OFFSET 2208988800ULL
309 
310 /*
311  * Convert 'struct timeval' into NTP format (32-bit integer
312  * of seconds, 32-bit integer of fractional seconds)
313  */
314 void
315 timeval2ntp(struct timeval const *tv, uint8_t *ntp)
316 {
317  uint32_t sec, usec;
318 
319  sec = tv->tv_sec + NTP_EPOCH_OFFSET;
320  usec = tv->tv_usec * 4295; /* close enough to 2^32 / USEC */
321  usec -= ((tv->tv_usec * 2143) >> 16); /* */
322 
323  sec = htonl(sec);
324  usec = htonl(usec);
325 
326  memcpy(ntp, &sec, sizeof(sec));
327  memcpy(ntp + sizeof(sec), &usec, sizeof(usec));
328 }
329 
330 /*
331  * Inverse of timeval2ntp
332  */
333 void
334 ntp2timeval(struct timeval *tv, char const *ntp)
335 {
336  uint32_t sec, usec;
337 
338  memcpy(&sec, ntp, sizeof(sec));
339  memcpy(&usec, ntp + sizeof(sec), sizeof(usec));
340 
341  sec = ntohl(sec);
342  usec = ntohl(usec);
343 
344  tv->tv_sec = sec - NTP_EPOCH_OFFSET;
345  tv->tv_usec = usec / 4295; /* close enough */
346 }
347 
348 #if !defined(HAVE_128BIT_INTEGERS) && !defined(WORDS_BIGENDIAN)
349 /** Swap byte order of 128 bit integer
350  *
351  * @param num 128bit integer to swap.
352  * @return 128bit integer reversed.
353  */
354 uint128_t ntohlll(uint128_t const num)
355 {
356  uint64_t const *p = (uint64_t const *) &num;
357  uint64_t ret[2];
358 
359  /* swapsies */
360  ret[1] = ntohll(p[0]);
361  ret[0] = ntohll(p[1]);
362 
363  return *(uint128_t *)ret;
364 }
365 #endif
366 
367 /*
368  * Replacements in case we don't have inet_pton
369  */
370 #ifndef HAVE_INET_PTON
371 static int inet_pton4(char const *src, struct in_addr *dst)
372 {
373  int octet;
374  unsigned int num;
375  char const *p, *off;
376  uint8_t tmp[4];
377  static char const digits[] = "0123456789";
378 
379  octet = 0;
380  p = src;
381  while (1) {
382  num = 0;
383  while (*p && ((off = strchr(digits, *p)) != NULL)) {
384  num *= 10;
385  num += (off - digits);
386 
387  if (num > 255) return 0;
388 
389  p++;
390  }
391  if (!*p) break;
392 
393  /*
394  * Not a digit, MUST be a dot, else we
395  * die.
396  */
397  if (*p != '.') {
398  return 0;
399  }
400 
401  tmp[octet++] = num;
402  p++;
403  }
404 
405  /*
406  * End of the string. At the fourth
407  * octet is OK, anything else is an
408  * error.
409  */
410  if (octet != 3) {
411  return 0;
412  }
413  tmp[3] = num;
414 
415  memcpy(dst, &tmp, sizeof(tmp));
416  return 1;
417 }
418 
419 
420 # ifdef HAVE_STRUCT_SOCKADDR_IN6
421 /** Convert presentation level address to network order binary form
422  *
423  * @note Does not touch dst unless it's returning 1.
424  * @note :: in a full address is silently ignored.
425  * @note Inspired by Mark Andrews.
426  * @author Paul Vixie, 1996.
427  *
428  * @param src presentation level address.
429  * @param dst where to write output address.
430  * @return
431  * - 1 if `src' is a valid [RFC1884 2.2] address.
432  * - 0 if `src' in not a valid [RFC1884 2.2] address.
433  */
434 static int inet_pton6(char const *src, unsigned char *dst)
435 {
436  static char const xdigits_l[] = "0123456789abcdef",
437  xdigits_u[] = "0123456789ABCDEF";
438  uint8_t tmp[IN6ADDRSZ], *tp, *endp, *colonp;
439  char const *xdigits, *curtok;
440  int ch, saw_xdigit;
441  u_int val;
442 
443  memset((tp = tmp), 0, IN6ADDRSZ);
444  endp = tp + IN6ADDRSZ;
445  colonp = NULL;
446  /* Leading :: requires some special handling. */
447  if (*src == ':')
448  if (*++src != ':')
449  return (0);
450  curtok = src;
451  saw_xdigit = 0;
452  val = 0;
453  while ((ch = *src++) != '\0') {
454  char const *pch;
455 
456  if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
457  pch = strchr((xdigits = xdigits_u), ch);
458  if (pch != NULL) {
459  val <<= 4;
460  val |= (pch - xdigits);
461  if (val > 0xffff)
462  return (0);
463  saw_xdigit = 1;
464  continue;
465  }
466  if (ch == ':') {
467  curtok = src;
468  if (!saw_xdigit) {
469  if (colonp)
470  return (0);
471  colonp = tp;
472  continue;
473  }
474  if (tp + INT16SZ > endp)
475  return (0);
476  *tp++ = (uint8_t) (val >> 8) & 0xff;
477  *tp++ = (uint8_t) val & 0xff;
478  saw_xdigit = 0;
479  val = 0;
480  continue;
481  }
482  if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
483  inet_pton4(curtok, (struct in_addr *) tp) > 0) {
484  tp += INADDRSZ;
485  saw_xdigit = 0;
486  break; /* '\0' was seen by inet_pton4(). */
487  }
488  return (0);
489  }
490  if (saw_xdigit) {
491  if (tp + INT16SZ > endp)
492  return (0);
493  *tp++ = (uint8_t) (val >> 8) & 0xff;
494  *tp++ = (uint8_t) val & 0xff;
495  }
496  if (colonp != NULL) {
497  /*
498  * Since some memmove()'s erroneously fail to handle
499  * overlapping regions, we'll do the shift by hand.
500  */
501  int const n = tp - colonp;
502  int i;
503 
504  for (i = 1; i <= n; i++) {
505  endp[- i] = colonp[n - i];
506  colonp[n - i] = 0;
507  }
508  tp = endp;
509  }
510  if (tp != endp)
511  return (0);
512  /* bcopy(tmp, dst, IN6ADDRSZ); */
513  memcpy(dst, tmp, IN6ADDRSZ);
514  return (1);
515 }
516 # endif
517 
518 /*
519  * Utility function, so that the rest of the server doesn't
520  * have ifdef's around IPv6 support
521  */
522 int inet_pton(int af, char const *src, void *dst)
523 {
524  if (af == AF_INET) return inet_pton4(src, dst);
525 
526 # ifdef HAVE_STRUCT_SOCKADDR_IN6
527  if (af == AF_INET6) return inet_pton6(src, dst);
528 # endif
529  return -1;
530 }
531 #endif /* HAVE_INET_PTON */
532 
533 #ifndef HAVE_INET_NTOP
534 /*
535  * Utility function, so that the rest of the server doesn't
536  * have ifdef's around IPv6 support
537  */
538 char const *inet_ntop(int af, void const *src, char *dst, size_t cnt)
539 {
540  if (af == AF_INET) {
541  uint8_t const *ipaddr = src;
542 
543  if (cnt <= INET_ADDRSTRLEN) return NULL;
544 
545  snprintf(dst, cnt, "%d.%d.%d.%d",
546  ipaddr[0], ipaddr[1],
547  ipaddr[2], ipaddr[3]);
548  return dst;
549  }
550 
551  /*
552  * If the system doesn't define this, we define it
553  * in missing.h
554  */
555  if (af == AF_INET6) {
556  struct in6_addr const *ipaddr = src;
557 
558  if (cnt <= INET6_ADDRSTRLEN) return NULL;
559 
560  snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
561  (ipaddr->s6_addr[0] << 8) | ipaddr->s6_addr[1],
562  (ipaddr->s6_addr[2] << 8) | ipaddr->s6_addr[3],
563  (ipaddr->s6_addr[4] << 8) | ipaddr->s6_addr[5],
564  (ipaddr->s6_addr[6] << 8) | ipaddr->s6_addr[7],
565  (ipaddr->s6_addr[8] << 8) | ipaddr->s6_addr[9],
566  (ipaddr->s6_addr[10] << 8) | ipaddr->s6_addr[11],
567  (ipaddr->s6_addr[12] << 8) | ipaddr->s6_addr[13],
568  (ipaddr->s6_addr[14] << 8) | ipaddr->s6_addr[15]);
569  return dst;
570  }
571 
572  return NULL; /* don't support IPv6 */
573 }
574 #endif
575 
576 /** Call talloc strdup, setting the type on the new chunk correctly
577  *
578  * For some bizarre reason the talloc string functions don't set the
579  * memory chunk type to char, which causes all kinds of issues with
580  * verifying VALUE_PAIRs.
581  *
582  * @param[in] t The talloc context to hang the result off.
583  * @param[in] p The string you want to duplicate.
584  * @return
585  * - Duplicated string.
586  * - NULL on error.
587  */
588 char *talloc_typed_strdup(void const *t, char const *p)
589 {
590  char *n;
591 
592  n = talloc_strdup(t, p);
593  if (!n) return NULL;
594  talloc_set_type(n, char);
595 
596  return n;
597 }
598 
599 /** Call talloc vasprintf, setting the type on the new chunk correctly
600  *
601  * For some bizarre reason the talloc string functions don't set the
602  * memory chunk type to char, which causes all kinds of issues with
603  * verifying VALUE_PAIRs.
604  *
605  * @param[in] t The talloc context to hang the result off.
606  * @param[in] fmt The format string.
607  * @return
608  * - Formatted string.
609  * - NULL on error.
610  */
611 char *talloc_typed_asprintf(void const *t, char const *fmt, ...)
612 {
613  char *n;
614  va_list ap;
615 
616  va_start(ap, fmt);
617  n = talloc_vasprintf(t, fmt, ap);
618  va_end(ap);
619  if (!n) return NULL;
620  talloc_set_type(n, char);
621 
622  return n;
623 }
624 
625 /** Binary safe strndup function
626  *
627  * @param[in] t The talloc context o allocate new buffer in.
628  * @param[in] in String to dup, may contain embedded '\0'.
629  * @param[in] inlen Number of bytes to dup.
630  * @return duped string.
631  */
632 char *talloc_bstrndup(void const *t, char const *in, size_t inlen)
633 {
634  char *p;
635 
636  p = talloc_array(t, char, inlen + 1);
637  if (!p) return NULL;
638  memcpy(p, in, inlen);
639  p[inlen] = '\0';
640 
641  return p;
642 }
643 
uint128_t ntohlll(uint128_t const num)
Swap byte order of 128 bit integer.
Definition: missing.c:354
#define UNUSED
Definition: libradius.h:134
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
Definition: missing.c:538
static int inet_pton4(char const *src, struct in_addr *dst)
Definition: missing.c:371
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:686
#define NTP_EPOCH_OFFSET
Definition: missing.c:308
int inet_aton(char const *cp, struct in_addr *inp)
Definition: missing.c:86
char * crypt(UNUSED char *key, char *salt)
Definition: missing.c:35
#define pthread_mutex_unlock(_x)
Definition: rlm_eap.h:78
void ntp2timeval(struct timeval *tv, char const *ntp)
Definition: missing.c:334
int vdprintf(int fd, char const *format, va_list args)
Definition: missing.c:199
char * talloc_typed_asprintf(void const *t, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition: missing.c:611
int inet_pton(int af, char const *src, void *dst)
Definition: missing.c:522
int strcasecmp(char *s1, char *s2)
Definition: missing.c:73
#define val(x)
Definition: timestr.c:37
char * talloc_bstrndup(void const *t, char const *in, size_t inlen)
Binary safe strndup function.
Definition: missing.c:632
char * ctime_r(time_t const *l_clock, char *l_buf)
Definition: missing.c:171
int strncasecmp(char *s1, char *s2, int n)
Definition: missing.c:43
void timeval2ntp(struct timeval const *tv, uint8_t *ntp)
Definition: missing.c:315
#define pthread_mutex_lock(_x)
Definition: rlm_eap.h:77
char * strsep(char **stringp, char const *delim)
Definition: missing.c:112
struct tm * localtime_r(time_t const *l_clock, struct tm *result)
Definition: missing.c:152
#define RCSID(id)
Definition: build.h:135
char * talloc_typed_strdup(void const *t, char const *p)
Call talloc strdup, setting the type on the new chunk correctly.
Definition: missing.c:588
static const uchar sc[16]
Definition: smbdes.c:112
struct tm * gmtime_r(time_t const *l_clock, struct tm *result)
Definition: missing.c:190