The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
missing.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Replacements for functions that are or can be missing on some platforms
18 *
19 * @file src/lib/util/missing.c
20 *
21 * @copyright 2000,2006 The FreeRADIUS server project
22 */
23RCSID("$Id: 65cd304c9cb8c036bd5195a8459ba4874c20ebde $")
24
25#include <freeradius-devel/missing.h>
26
27#include <ctype.h>
28#include <pthread.h>
29#include <stdbool.h>
30
31#if !defined(HAVE_CLOCK_GETTIME) && defined(__MACH__)
32# include <mach/mach_time.h>
33#endif
34
35#ifndef HAVE_STRNCASECMP
36int strncasecmp(char *s1, char *s2, int n)
37{
38 int dif;
39 unsigned char *p1, *p2;
40 int c1, c2;
41
42 p1 = (unsigned char *)s1;
43 p2 = (unsigned char *)s2;
44 dif = 0;
45
46 while (n != 0) {
47 if (*p1 == 0 && *p2 == 0)
48 break;
49 c1 = *p1;
50 c2 = *p2;
51
52 if (islower(c1)) c1 = toupper(c1);
53 if (islower(c2)) c2 = toupper(c2);
54
55 if ((dif = c1 - c2) != 0)
56 break;
57 p1++;
58 p2++;
59 n--;
60 }
61 return dif;
62}
63#endif
64
65#ifndef HAVE_STRCASECMP
66int strcasecmp(char *s1, char *s2)
67{
68 int l1, l2;
69
70 l1 = strlen(s1);
71 l2 = strlen(s2);
72 if (l2 > l1) l1 = l2;
73
74 return strncasecmp(s1, s2, l1);
75}
76#endif
77
78
79#ifndef HAVE_MEMRCHR
80/** GNU libc extension on some platforms
81 *
82 */
83void *memrchr(void const *s, int c, size_t n)
84{
85 uint8_t *p;
86
87 if (n == 0) return NULL;
88
89 memcpy(&p, &s, sizeof(p)); /* defeat const */
90 for (p += (n - 1); p >= (uint8_t const *)s; p--) if (*p == (uint8_t)c) return (void *)p;
91
92 return NULL;
93}
94#endif
95
96#ifndef HAVE_INET_ATON
97int inet_aton(char const *cp, struct in_addr *inp)
98{
99 int a1, a2, a3, a4;
100
101 if (sscanf(cp, "%d.%d.%d.%d", &a1, &a2, &a3, &a4) != 4)
102 return 0;
103
104 inp->s_addr = htonl((a1 << 24) + (a2 << 16) + (a3 << 8) + a4);
105 return 1;
106}
107#endif
108
109#ifndef HAVE_STRSEP
110/*
111 * Get next token from string *stringp, where tokens are
112 * possibly-empty strings separated by characters from delim.
113 *
114 * Writes NULs into the string at *stringp to end tokens.
115 * delim need not remain constant from call to call. On
116 * return, *stringp points past the last NUL written (if there
117 * might be further tokens), or is NULL (if there are
118 * definitely no more tokens).
119 *
120 * If *stringp is NULL, strsep returns NULL.
121 */
122char *
123strsep(char **stringp, char const *delim)
124{
125 char *s;
126 char const *spanp;
127 int c, sc;
128 char *tok;
129
130 if ((s = *stringp) == NULL)
131 return (NULL);
132
133 for (tok = s;;) {
134 c = *s++;
135 spanp = delim;
136 do {
137 if ((sc = *spanp++) == c) {
138 if (c == 0)
139 s = NULL;
140 else
141 s[-1] = 0;
142 *stringp = s;
143 return (tok);
144 }
145 } while (sc != 0);
146 }
147
148 return NULL; /* NOTREACHED, but the compiler complains */
149}
150#endif
151
152#ifndef HAVE_LOCALTIME_R
153/*
154 * We use localtime_r() by default in the server.
155 *
156 * For systems which do NOT have localtime_r(), we make the
157 * assumption that localtime() is re-entrant, and returns a
158 * per-thread data structure.
159 *
160 * Even if localtime is NOT re-entrant, this function will
161 * lower the possibility of race conditions.
162 */
163struct tm *localtime_r(time_t const *l_clock, struct tm *result)
164{
165 memcpy(result, localtime(l_clock), sizeof(*result));
166
167 return result;
168}
169#endif
170
171#ifndef HAVE_CTIME_R
172/*
173 * We use ctime_r() by default in the server.
174 *
175 * For systems which do NOT have ctime_r(), we make the
176 * assumption that ctime() is re-entrant, and returns a
177 * per-thread data structure.
178 *
179 * Even if ctime is NOT re-entrant, this function will
180 * lower the possibility of race conditions.
181 */
182char *ctime_r(time_t const *l_clock, char *l_buf)
183{
184 strcpy(l_buf, ctime(l_clock));
185
186 return l_buf;
187}
188#endif
189
190#ifndef HAVE_GMTIME_R
191/*
192 * We use gmtime_r() by default in the server.
193 *
194 * For systems which do NOT have gmtime_r(), we make the
195 * assumption that gmtime() is re-entrant, and returns a
196 * per-thread data structure.
197 *
198 * Even if gmtime is NOT re-entrant, this function will
199 * lower the possibility of race conditions.
200 */
201struct tm *gmtime_r(time_t const *l_clock, struct tm *result)
202{
203 memcpy(result, gmtime(l_clock), sizeof(*result));
204
205 return result;
206}
207#endif
208
209#ifndef HAVE_VDPRINTF
210int vdprintf (int fd, char const *format, va_list args)
211{
212 int ret;
213 FILE *fp;
214 int dup_fd;
215
216 dup_fd = dup(fd);
217 if (dup_fd < 0) return -1;
218
219 fp = fdopen(fd, "w");
220 if (!fp) {
221 close(dup_fd);
222 return -1;
223 }
224
225 ret = vfprintf(fp, format, args);
226 fclose(fp); /* Also closes dup_fd */
227
228 return ret;
229}
230#endif
231
232
233#if !defined(HAVE_CLOCK_GETTIME) && defined(__MACH__)
234int clock_gettime(int clk_id, struct timespec *t)
235{
236 static mach_timebase_info_data_t timebase;
237 static bool done_init = false;
238
239 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
240
241 if (!done_init) {
242 pthread_mutex_lock(&mutex);
243 if (!done_init) {
244 mach_timebase_info(&timebase);
245 done_init = true;
246 }
247 pthread_mutex_unlock(&mutex);
248 }
249
250 switch (clk_id) {
251 case CLOCK_REALTIME:
252 return -1;
253
254 case CLOCK_MONOTONIC:
255 {
256 uint64_t time;
257 time = mach_absolute_time();
258 double nanoseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
259 double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
260 t->tv_sec = seconds;
261 t->tv_nsec = nanoseconds;
262 }
263 return 0;
264
265 default:
266 errno = EINVAL;
267 return -1;
268 }
269}
270#endif
271
272/*
273 * Replacements in case we don't have inet_pton
274 */
275#ifndef HAVE_INET_PTON
276static int inet_pton4(char const *src, struct in_addr *dst)
277{
278 int octet;
279 unsigned int num;
280 char const *p, *off;
281 uint8_t tmp[4];
282 static char const digits[] = "0123456789";
283
284 octet = 0;
285 p = src;
286 while (1) {
287 num = 0;
288 while (*p && ((off = strchr(digits, *p)) != NULL)) {
289 num *= 10;
290 num += (off - digits);
291
292 if (num > 255) return 0;
293
294 p++;
295 }
296 if (!*p) break;
297
298 /*
299 * Not a digit, MUST be a dot, else we
300 * die.
301 */
302 if (*p != '.') {
303 return 0;
304 }
305
306 tmp[octet++] = num;
307 p++;
308 }
309
310 /*
311 * End of the string. At the fourth
312 * octet is OK, anything else is an
313 * error.
314 */
315 if (octet != 3) {
316 return 0;
317 }
318 tmp[3] = num;
319
320 memcpy(dst, &tmp, sizeof(tmp));
321 return 1;
322}
323
324
325# ifdef HAVE_STRUCT_SOCKADDR_IN6
326/** Convert presentation level address to network order binary form
327 *
328 * @note Does not touch dst unless it's returning 1.
329 * @note :: in a full address is silently ignored.
330 * @note Inspired by Mark Andrews.
331 * @author Paul Vixie, 1996.
332 *
333 * @param src presentation level address.
334 * @param dst where to write output address.
335 * @return
336 * - 1 if `src' is a valid [RFC1884 2.2] address.
337 * - 0 if `src' in not a valid [RFC1884 2.2] address.
338 */
339static int inet_pton6(char const *src, unsigned char *dst)
340{
341 static char const xdigits_l[] = "0123456789abcdef",
342 xdigits_u[] = "0123456789ABCDEF";
343 uint8_t tmp[IN6ADDRSZ], *tp, *endp, *colonp;
344 char const *xdigits, *curtok;
345 int ch, saw_xdigit;
346 u_int val;
347
348 memset((tp = tmp), 0, IN6ADDRSZ);
349 endp = tp + IN6ADDRSZ;
350 colonp = NULL;
351 /* Leading :: requires some special handling. */
352 if (*src == ':')
353 if (*++src != ':')
354 return (0);
355 curtok = src;
356 saw_xdigit = 0;
357 val = 0;
358 while ((ch = *src++) != '\0') {
359 char const *pch;
360
361 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
362 pch = strchr((xdigits = xdigits_u), ch);
363 if (pch != NULL) {
364 val <<= 4;
365 val |= (pch - xdigits);
366 if (val > 0xffff)
367 return (0);
368 saw_xdigit = 1;
369 continue;
370 }
371 if (ch == ':') {
372 curtok = src;
373 if (!saw_xdigit) {
374 if (colonp)
375 return (0);
376 colonp = tp;
377 continue;
378 }
379 if (tp + INT16SZ > endp)
380 return (0);
381 *tp++ = (uint8_t) (val >> 8) & 0xff;
382 *tp++ = (uint8_t) val & 0xff;
383 saw_xdigit = 0;
384 val = 0;
385 continue;
386 }
387 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
388 inet_pton4(curtok, (struct in_addr *) tp) > 0) {
389 tp += INADDRSZ;
390 saw_xdigit = 0;
391 break; /* '\0' was seen by inet_pton4(). */
392 }
393 return (0);
394 }
395 if (saw_xdigit) {
396 if (tp + INT16SZ > endp)
397 return (0);
398 *tp++ = (uint8_t) (val >> 8) & 0xff;
399 *tp++ = (uint8_t) val & 0xff;
400 }
401 if (colonp != NULL) {
402 /*
403 * Since some memmove()'s erroneously fail to handle
404 * overlapping regions, we'll do the shift by hand.
405 */
406 int const n = tp - colonp;
407 int i;
408
409 for (i = 1; i <= n; i++) {
410 endp[- i] = colonp[n - i];
411 colonp[n - i] = 0;
412 }
413 tp = endp;
414 }
415 if (tp != endp)
416 return (0);
417 /* bcopy(tmp, dst, IN6ADDRSZ); */
418 memcpy(dst, tmp, IN6ADDRSZ);
419 return (1);
420}
421# endif
422
423/*
424 * Utility function, so that the rest of the server doesn't
425 * have ifdef's around IPv6 support
426 */
427int inet_pton(int af, char const *src, void *dst)
428{
429 if (af == AF_INET) return inet_pton4(src, dst);
430
431# ifdef HAVE_STRUCT_SOCKADDR_IN6
432 if (af == AF_INET6) return inet_pton6(src, dst);
433# endif
434 return -1;
435}
436#endif /* HAVE_INET_PTON */
437
438#ifndef HAVE_INET_NTOP
439/*
440 * Utility function, so that the rest of the server doesn't
441 * have ifdef's around IPv6 support
442 */
443char const *inet_ntop(int af, void const *src, char *dst, size_t cnt)
444{
445 if (af == AF_INET) {
446 uint8_t const *ipaddr = src;
447
448 if (cnt <= INET_ADDRSTRLEN) return NULL;
449
450 snprintf(dst, cnt, "%d.%d.%d.%d",
451 ipaddr[0], ipaddr[1],
452 ipaddr[2], ipaddr[3]);
453 return dst;
454 }
455
456 /*
457 * If the system doesn't define this, we define it
458 * in missing.h
459 */
460 if (af == AF_INET6) {
461 struct in6_addr const *ipaddr = src;
462
463 if (cnt <= INET6_ADDRSTRLEN) return NULL;
464
465 snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
466 fr_nbo_to_uint16(ipaddr->a6_addr),
467 fr_nbo_to_uint16(ipaddr->a6_addr + 2),
468 fr_nbo_to_uint16(ipaddr->a6_addr + 4),
469 fr_nbo_to_uint16(ipaddr->a6_addr + 6),
470 fr_nbo_to_uint16(ipaddr->a6_addr + 8),
471 fr_nbo_to_uint16(ipaddr->a6_addr + 10),
472 fr_nbo_to_uint16(ipaddr->a6_addr + 12),
473 fr_nbo_to_uint16(ipaddr->a6_addr + 14));
474 return dst;
475 }
476
477 return NULL; /* don't support IPv6 */
478}
479#endif
480
481#ifndef HAVE_SENDMMSG
482/** Emulates the real sendmmsg in userland
483 *
484 * The idea behind the proper sendmmsg in FreeBSD and Linux is that multiple
485 * datagram messages can be sent using a single system call.
486 *
487 * This function doesn't achieve that, but it does reduce ifdefs elsewhere
488 * and means we can batch encoding/sending operations.
489 *
490 * @param[in] sockfd to write packets to.
491 * @param[in] msgvec a pointer to an array of mmsghdr structures.
492 * The size of this array is specified in vlen.
493 * @param[in] vlen Length of msgvec.
494 * @param[in] flags same as for sendmsg(2).
495 * @return
496 * - >= 0 The number of messages sent. Check against vlen to determine
497 * if overall operation was successful.
498 * - < 0 on error. Only returned if first operation errors.
499 */
500int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags)
501{
502 unsigned int i;
503
504 for (i = 0; i < vlen; i++) {
505 ssize_t slen;
506
507 slen = sendmsg(sockfd, &msgvec[i].msg_hdr, flags);
508 if (slen < 0) {
509 msgvec[i].msg_len = 0;
510
511 /*
512 * man sendmmsg - Errors are as for sendmsg(2).
513 * An error is returned only if no datagrams could
514 * be sent. See also BUGS.
515 */
516 if (i == 0) return -1;
517 return i;
518 }
519 msgvec[i].msg_len = (unsigned int)slen; /* Number of bytes sent */
520 }
521
522 return i;
523}
524#endif
525
526/*
527 * So we don't have ifdef's in the rest of the code
528 */
529#ifndef HAVE_CLOSEFROM
530 #include <stdlib.h>
531#ifdef HAVE_DIRENT_H
532# include <dirent.h>
533/*
534 * Some versions of Linux don't have closefrom(), but they will
535 * have /proc.
536 *
537 * BSD systems will generally have closefrom(), but not proc.
538 *
539 * OSX doesn't have closefrom() or /proc/self/fd, but it does
540 * have /dev/fd
541 */
542# ifdef __linux__
543# define CLOSEFROM_DIR "/proc/self/fd"
544# elif defined(__APPLE__)
545# define CLOSEFROM_DIR "/dev/fd"
546# else
547# undef HAVE_DIRENT_H
548# endif
549#endif
550
551void closefrom(int fd)
552{
553 int i;
554 int maxfd = 256;
555# ifdef HAVE_DIRENT_H
556 DIR *dir;
557# endif
558
559#ifdef F_CLOSEM
560 if (fcntl(fd, F_CLOSEM) == 0) return;
561# endif
562
563# ifdef F_MAXFD
564 maxfd = fcntl(fd, F_F_MAXFD);
565 if (maxfd >= 0) goto do_close;
566# endif
567
568# ifdef _SC_OPEN_MAX
569 maxfd = sysconf(_SC_OPEN_MAX);
570 if (maxfd < 0) {
571 maxfd = 256;
572 }
573# endif
574
575# ifdef HAVE_DIRENT_H
576 /*
577 * Use /proc/self/fd directory if it exists.
578 */
579 dir = opendir(CLOSEFROM_DIR);
580 if (dir != NULL) {
581 long my_fd;
582 char *endp;
583 struct dirent *dp;
584
585 while ((dp = readdir(dir)) != NULL) {
586 my_fd = strtol(dp->d_name, &endp, 10);
587 if (my_fd <= 0) continue;
588
589 if (*endp) continue;
590
591 if (my_fd == dirfd(dir)) continue;
592
593 if ((my_fd >= fd) && (my_fd <= maxfd)) {
594 (void) close((int) my_fd);
595 }
596 }
597 (void) closedir(dir);
598 return;
599 }
600# endif
601
602# ifdef F_MAXFD
603do_close:
604# endif
605
606 if (fd > maxfd) return;
607
608 /*
609 * FIXME: return EINTR?
610 */
611 for (i = fd; i < maxfd; i++) {
612 close(i);
613 }
614
615 return;
616}
617#endif
618
619#ifndef HAVE_MEMSET_EXPLICIT
620void *memset_explicit(void *ptr,
621#ifdef HAVE_EXPLICIT_BZERO
622 UNUSED
623#endif
624 int ch,
625 size_t len)
626{
627 if (!len) return ptr;
628
629#ifdef HAVE_EXPLICIT_BZERO
630 explicit_bzero(ptr, len);
631#else
632 {
633 volatile unsigned char *volatile p = (volatile unsigned char *volatile) ptr;
634 size_t i = len;
635
636 while (i--) {
637 *(p++) = ch;
638 }
639 }
640#endif
641
642 return ptr;
643}
644#endif
int n
Definition acutest.h:577
strcpy(log_entry->msg, buffer)
va_list args
Definition acutest.h:770
#define RCSID(id)
Definition build.h:483
#define UNUSED
Definition build.h:315
static int sockfd
Definition dhcpclient.c:56
long int ssize_t
unsigned char uint8_t
void * memset_explicit(void *ptr, int ch, size_t len)
Definition missing.c:620
int inet_pton(int af, char const *src, void *dst)
Definition missing.c:427
void closefrom(int fd)
Definition missing.c:551
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
Definition missing.c:443
int strncasecmp(char *s1, char *s2, int n)
Definition missing.c:36
int vdprintf(int fd, char const *format, va_list args)
Definition missing.c:210
void * memrchr(void const *s, int c, size_t n)
GNU libc extension on some platforms.
Definition missing.c:83
char * strsep(char **stringp, char const *delim)
Definition missing.c:123
int strcasecmp(char *s1, char *s2)
Definition missing.c:66
struct tm * gmtime_r(time_t const *l_clock, struct tm *result)
Definition missing.c:201
struct tm * localtime_r(time_t const *l_clock, struct tm *result)
Definition missing.c:163
int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags)
Emulates the real sendmmsg in userland.
Definition missing.c:500
int inet_aton(char const *cp, struct in_addr *inp)
Definition missing.c:97
char * ctime_r(time_t const *l_clock, char *l_buf)
Definition missing.c:182
static int inet_pton4(char const *src, struct in_addr *dst)
Definition missing.c:276
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
Definition nbo.h:146
static const uchar sc[16]
Definition smbdes.c:115
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
close(uq->fd)
int format(printf, 5, 0))