source: rtems-libbsd/freebsd/contrib/wpa/src/utils/os_unix.c @ 83afe13

5
Last change on this file since 83afe13 was 2b2563d, checked in by Sebastian Huber <sebastian.huber@…>, on 12/20/18 at 10:12:40

Update to FreeBSD head 2018-12-20

Git mirror commit 19a6ceb89dbacf74697d493e48c388767126d418.

It includes an update of wpa_supplicant to version 2.7.

It includes an update of the OpenSSL baseline to version 1.1.1a.

Update #3472.

  • Property mode set to 100644
File size: 15.1 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * OS specific functions for UNIX/POSIX systems
5 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
6 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11#include "includes.h"
12
13#include <time.h>
14#include <sys/wait.h>
15
16#ifdef ANDROID
17#include <sys/capability.h>
18#include <sys/prctl.h>
19#include <private/android_filesystem_config.h>
20#endif /* ANDROID */
21
22#ifdef __MACH__
23#include <CoreServices/CoreServices.h>
24#include <mach/mach.h>
25#include <mach/mach_time.h>
26#endif /* __MACH__ */
27
28#ifdef __rtems__
29#include <stdlib.h>
30#endif /* __rtems__ */
31
32
33#include "os.h"
34#include "common.h"
35
36#ifdef WPA_TRACE
37
38#include "wpa_debug.h"
39#include "trace.h"
40#include "list.h"
41
42static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list);
43
44#define ALLOC_MAGIC 0xa84ef1b2
45#define FREED_MAGIC 0x67fd487a
46
47struct os_alloc_trace {
48        unsigned int magic;
49        struct dl_list list;
50        size_t len;
51        WPA_TRACE_INFO
52} __attribute__((aligned(16)));
53
54#endif /* WPA_TRACE */
55
56
57void os_sleep(os_time_t sec, os_time_t usec)
58{
59        if (sec)
60                sleep(sec);
61        if (usec)
62                usleep(usec);
63}
64
65
66int os_get_time(struct os_time *t)
67{
68        int res;
69        struct timeval tv;
70        res = gettimeofday(&tv, NULL);
71        t->sec = tv.tv_sec;
72        t->usec = tv.tv_usec;
73        return res;
74}
75
76
77int os_get_reltime(struct os_reltime *t)
78{
79#ifndef __MACH__
80#if defined(CLOCK_BOOTTIME)
81        static clockid_t clock_id = CLOCK_BOOTTIME;
82#elif defined(CLOCK_MONOTONIC)
83        static clockid_t clock_id = CLOCK_MONOTONIC;
84#else
85        static clockid_t clock_id = CLOCK_REALTIME;
86#endif
87        struct timespec ts;
88        int res;
89
90        if (TEST_FAIL())
91                return -1;
92
93        while (1) {
94                res = clock_gettime(clock_id, &ts);
95                if (res == 0) {
96                        t->sec = ts.tv_sec;
97                        t->usec = ts.tv_nsec / 1000;
98                        return 0;
99                }
100                switch (clock_id) {
101#ifdef CLOCK_BOOTTIME
102                case CLOCK_BOOTTIME:
103                        clock_id = CLOCK_MONOTONIC;
104                        break;
105#endif
106#ifdef CLOCK_MONOTONIC
107                case CLOCK_MONOTONIC:
108                        clock_id = CLOCK_REALTIME;
109                        break;
110#endif
111                case CLOCK_REALTIME:
112                        return -1;
113                }
114        }
115#else /* __MACH__ */
116        uint64_t abstime, nano;
117        static mach_timebase_info_data_t info = { 0, 0 };
118
119        if (!info.denom) {
120                if (mach_timebase_info(&info) != KERN_SUCCESS)
121                        return -1;
122        }
123
124        abstime = mach_absolute_time();
125        nano = (abstime * info.numer) / info.denom;
126
127        t->sec = nano / NSEC_PER_SEC;
128        t->usec = (nano - (((uint64_t) t->sec) * NSEC_PER_SEC)) / NSEC_PER_USEC;
129
130        return 0;
131#endif /* __MACH__ */
132}
133
134
135int os_mktime(int year, int month, int day, int hour, int min, int sec,
136              os_time_t *t)
137{
138        struct tm tm, *tm1;
139        time_t t_local, t1, t2;
140        os_time_t tz_offset;
141
142        if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
143            hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
144            sec > 60)
145                return -1;
146
147        memset(&tm, 0, sizeof(tm));
148        tm.tm_year = year - 1900;
149        tm.tm_mon = month - 1;
150        tm.tm_mday = day;
151        tm.tm_hour = hour;
152        tm.tm_min = min;
153        tm.tm_sec = sec;
154
155        t_local = mktime(&tm);
156
157        /* figure out offset to UTC */
158        tm1 = localtime(&t_local);
159        if (tm1) {
160                t1 = mktime(tm1);
161                tm1 = gmtime(&t_local);
162                if (tm1) {
163                        t2 = mktime(tm1);
164                        tz_offset = t2 - t1;
165                } else
166                        tz_offset = 0;
167        } else
168                tz_offset = 0;
169
170        *t = (os_time_t) t_local - tz_offset;
171        return 0;
172}
173
174
175int os_gmtime(os_time_t t, struct os_tm *tm)
176{
177        struct tm *tm2;
178        time_t t2 = t;
179
180        tm2 = gmtime(&t2);
181        if (tm2 == NULL)
182                return -1;
183        tm->sec = tm2->tm_sec;
184        tm->min = tm2->tm_min;
185        tm->hour = tm2->tm_hour;
186        tm->day = tm2->tm_mday;
187        tm->month = tm2->tm_mon + 1;
188        tm->year = tm2->tm_year + 1900;
189        return 0;
190}
191
192
193#ifdef __APPLE__
194#include <fcntl.h>
195static int os_daemon(int nochdir, int noclose)
196{
197        int devnull;
198
199        if (chdir("/") < 0)
200                return -1;
201
202        devnull = open("/dev/null", O_RDWR);
203        if (devnull < 0)
204                return -1;
205
206        if (dup2(devnull, STDIN_FILENO) < 0) {
207                close(devnull);
208                return -1;
209        }
210
211        if (dup2(devnull, STDOUT_FILENO) < 0) {
212                close(devnull);
213                return -1;
214        }
215
216        if (dup2(devnull, STDERR_FILENO) < 0) {
217                close(devnull);
218                return -1;
219        }
220
221        return 0;
222}
223#else /* __APPLE__ */
224#define os_daemon daemon
225#endif /* __APPLE__ */
226
227
228#ifdef __FreeBSD__
229#include <err.h>
230#include <libutil.h>
231#include <stdint.h>
232#endif /* __FreeBSD__ */
233
234int os_daemonize(const char *pid_file)
235{
236#if defined(__uClinux__) || defined(__sun__) || defined(__rtems__)
237        return -1;
238#else /* defined(__uClinux__) || defined(__sun__) */
239#ifdef __FreeBSD__
240        pid_t otherpid;
241        struct pidfh *pfh;
242
243        pfh = pidfile_open(pid_file, 0600, &otherpid);
244        if (pfh == NULL) {
245                if (errno == EEXIST) {
246                        errx(1, "Daemon already running, pid: %jd.",
247                            (intmax_t)otherpid);
248                }
249                warn("Cannot open or create pidfile.");
250        }
251#endif /* __FreeBSD__ */
252
253        if (os_daemon(0, 0)) {
254                perror("daemon");
255#ifdef __FreeBSD__
256                pidfile_remove(pfh);
257#endif /* __FreeBSD__ */
258                return -1;
259        }
260
261#ifndef __FreeBSD__
262        if (pid_file) {
263                FILE *f = fopen(pid_file, "w");
264                if (f) {
265                        fprintf(f, "%u\n", getpid());
266                        fclose(f);
267                }
268        }
269#else /* __FreeBSD__ */
270        pidfile_write(pfh);
271#endif /* __FreeBSD__ */
272
273        return -0;
274#endif /* defined(__uClinux__) || defined(__sun__) */
275}
276
277
278void os_daemonize_terminate(const char *pid_file)
279{
280        if (pid_file)
281                unlink(pid_file);
282}
283
284
285int os_get_random(unsigned char *buf, size_t len)
286{
287        FILE *f;
288        size_t rc;
289
290        if (TEST_FAIL())
291                return -1;
292
293#ifdef __rtems__
294        arc4random_buf(buf, len);
295        return 0;
296#else /* __rtems__ */
297        f = fopen("/dev/urandom", "rb");
298        if (f == NULL) {
299                printf("Could not open /dev/urandom.\n");
300                return -1;
301        }
302
303        rc = fread(buf, 1, len, f);
304        fclose(f);
305
306        return rc != len ? -1 : 0;
307#endif /* __rtems__ */
308}
309
310
311unsigned long os_random(void)
312{
313        return random();
314}
315
316
317char * os_rel2abs_path(const char *rel_path)
318{
319        char *buf = NULL, *cwd, *ret;
320        size_t len = 128, cwd_len, rel_len, ret_len;
321        int last_errno;
322
323        if (!rel_path)
324                return NULL;
325
326        if (rel_path[0] == '/')
327                return os_strdup(rel_path);
328
329        for (;;) {
330                buf = os_malloc(len);
331                if (buf == NULL)
332                        return NULL;
333                cwd = getcwd(buf, len);
334                if (cwd == NULL) {
335                        last_errno = errno;
336                        os_free(buf);
337                        if (last_errno != ERANGE)
338                                return NULL;
339                        len *= 2;
340                        if (len > 2000)
341                                return NULL;
342                } else {
343                        buf[len - 1] = '\0';
344                        break;
345                }
346        }
347
348        cwd_len = os_strlen(cwd);
349        rel_len = os_strlen(rel_path);
350        ret_len = cwd_len + 1 + rel_len + 1;
351        ret = os_malloc(ret_len);
352        if (ret) {
353                os_memcpy(ret, cwd, cwd_len);
354                ret[cwd_len] = '/';
355                os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
356                ret[ret_len - 1] = '\0';
357        }
358        os_free(buf);
359        return ret;
360}
361
362
363int os_program_init(void)
364{
365#ifdef ANDROID
366        /*
367         * We ignore errors here since errors are normal if we
368         * are already running as non-root.
369         */
370#ifdef ANDROID_SETGROUPS_OVERRIDE
371        gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
372#else /* ANDROID_SETGROUPS_OVERRIDE */
373        gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
374#endif /* ANDROID_SETGROUPS_OVERRIDE */
375        struct __user_cap_header_struct header;
376        struct __user_cap_data_struct cap;
377
378        setgroups(ARRAY_SIZE(groups), groups);
379
380        prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
381
382        setgid(AID_WIFI);
383        setuid(AID_WIFI);
384
385        header.version = _LINUX_CAPABILITY_VERSION;
386        header.pid = 0;
387        cap.effective = cap.permitted =
388                (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
389        cap.inheritable = 0;
390        capset(&header, &cap);
391#endif /* ANDROID */
392
393        return 0;
394}
395
396
397void os_program_deinit(void)
398{
399#ifdef WPA_TRACE
400        struct os_alloc_trace *a;
401        unsigned long total = 0;
402        dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
403                total += a->len;
404                if (a->magic != ALLOC_MAGIC) {
405                        wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
406                                   "len %lu",
407                                   a, a->magic, (unsigned long) a->len);
408                        continue;
409                }
410                wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
411                           a, (unsigned long) a->len);
412                wpa_trace_dump("memleak", a);
413        }
414        if (total)
415                wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
416                           (unsigned long) total);
417        wpa_trace_deinit();
418#endif /* WPA_TRACE */
419}
420
421
422int os_setenv(const char *name, const char *value, int overwrite)
423{
424        return setenv(name, value, overwrite);
425}
426
427
428int os_unsetenv(const char *name)
429{
430#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
431    defined(__OpenBSD__)
432        unsetenv(name);
433        return 0;
434#else
435        return unsetenv(name);
436#endif
437}
438
439
440char * os_readfile(const char *name, size_t *len)
441{
442        FILE *f;
443        char *buf;
444        long pos;
445
446        f = fopen(name, "rb");
447        if (f == NULL)
448                return NULL;
449
450        if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
451                fclose(f);
452                return NULL;
453        }
454        *len = pos;
455        if (fseek(f, 0, SEEK_SET) < 0) {
456                fclose(f);
457                return NULL;
458        }
459
460        buf = os_malloc(*len);
461        if (buf == NULL) {
462                fclose(f);
463                return NULL;
464        }
465
466        if (fread(buf, 1, *len, f) != *len) {
467                fclose(f);
468                os_free(buf);
469                return NULL;
470        }
471
472        fclose(f);
473
474        return buf;
475}
476
477
478int os_file_exists(const char *fname)
479{
480        return access(fname, F_OK) == 0;
481}
482
483
484int os_fdatasync(FILE *stream)
485{
486        if (!fflush(stream)) {
487#ifdef __linux__
488                return fdatasync(fileno(stream));
489#else /* !__linux__ */
490#ifdef F_FULLFSYNC
491                /* OS X does not implement fdatasync(). */
492                return fcntl(fileno(stream), F_FULLFSYNC);
493#else /* F_FULLFSYNC */
494                return fsync(fileno(stream));
495#endif /* F_FULLFSYNC */
496#endif /* __linux__ */
497        }
498
499        return -1;
500}
501
502
503#ifndef WPA_TRACE
504void * os_zalloc(size_t size)
505{
506        return calloc(1, size);
507}
508#endif /* WPA_TRACE */
509
510
511size_t os_strlcpy(char *dest, const char *src, size_t siz)
512{
513        const char *s = src;
514        size_t left = siz;
515
516        if (left) {
517                /* Copy string up to the maximum size of the dest buffer */
518                while (--left != 0) {
519                        if ((*dest++ = *s++) == '\0')
520                                break;
521                }
522        }
523
524        if (left == 0) {
525                /* Not enough room for the string; force NUL-termination */
526                if (siz != 0)
527                        *dest = '\0';
528                while (*s++)
529                        ; /* determine total src string length */
530        }
531
532        return s - src - 1;
533}
534
535
536int os_memcmp_const(const void *a, const void *b, size_t len)
537{
538        const u8 *aa = a;
539        const u8 *bb = b;
540        size_t i;
541        u8 res;
542
543        for (res = 0, i = 0; i < len; i++)
544                res |= aa[i] ^ bb[i];
545
546        return res;
547}
548
549
550void * os_memdup(const void *src, size_t len)
551{
552        void *r = os_malloc(len);
553
554        if (r)
555                os_memcpy(r, src, len);
556        return r;
557}
558
559
560#ifdef WPA_TRACE
561
562#if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
563char wpa_trace_fail_func[256] = { 0 };
564unsigned int wpa_trace_fail_after;
565
566static int testing_fail_alloc(void)
567{
568        const char *func[WPA_TRACE_LEN];
569        size_t i, res, len;
570        char *pos, *next;
571        int match;
572
573        if (!wpa_trace_fail_after)
574                return 0;
575
576        res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
577        i = 0;
578        if (i < res && os_strcmp(func[i], __func__) == 0)
579                i++;
580        if (i < res && os_strcmp(func[i], "os_malloc") == 0)
581                i++;
582        if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
583                i++;
584        if (i < res && os_strcmp(func[i], "os_calloc") == 0)
585                i++;
586        if (i < res && os_strcmp(func[i], "os_realloc") == 0)
587                i++;
588        if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
589                i++;
590        if (i < res && os_strcmp(func[i], "os_strdup") == 0)
591                i++;
592        if (i < res && os_strcmp(func[i], "os_memdup") == 0)
593                i++;
594
595        pos = wpa_trace_fail_func;
596
597        match = 0;
598        while (i < res) {
599                int allow_skip = 1;
600                int maybe = 0;
601
602                if (*pos == '=') {
603                        allow_skip = 0;
604                        pos++;
605                } else if (*pos == '?') {
606                        maybe = 1;
607                        pos++;
608                }
609                next = os_strchr(pos, ';');
610                if (next)
611                        len = next - pos;
612                else
613                        len = os_strlen(pos);
614                if (os_memcmp(pos, func[i], len) != 0) {
615                        if (maybe && next) {
616                                pos = next + 1;
617                                continue;
618                        }
619                        if (allow_skip) {
620                                i++;
621                                continue;
622                        }
623                        return 0;
624                }
625                if (!next) {
626                        match = 1;
627                        break;
628                }
629                pos = next + 1;
630                i++;
631        }
632        if (!match)
633                return 0;
634
635        wpa_trace_fail_after--;
636        if (wpa_trace_fail_after == 0) {
637                wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
638                           wpa_trace_fail_func);
639                for (i = 0; i < res; i++)
640                        wpa_printf(MSG_INFO, "backtrace[%d] = %s",
641                                   (int) i, func[i]);
642                return 1;
643        }
644
645        return 0;
646}
647
648
649char wpa_trace_test_fail_func[256] = { 0 };
650unsigned int wpa_trace_test_fail_after;
651
652int testing_test_fail(void)
653{
654        const char *func[WPA_TRACE_LEN];
655        size_t i, res, len;
656        char *pos, *next;
657        int match;
658
659        if (!wpa_trace_test_fail_after)
660                return 0;
661
662        res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
663        i = 0;
664        if (i < res && os_strcmp(func[i], __func__) == 0)
665                i++;
666
667        pos = wpa_trace_test_fail_func;
668
669        match = 0;
670        while (i < res) {
671                int allow_skip = 1;
672                int maybe = 0;
673
674                if (*pos == '=') {
675                        allow_skip = 0;
676                        pos++;
677                } else if (*pos == '?') {
678                        maybe = 1;
679                        pos++;
680                }
681                next = os_strchr(pos, ';');
682                if (next)
683                        len = next - pos;
684                else
685                        len = os_strlen(pos);
686                if (os_memcmp(pos, func[i], len) != 0) {
687                        if (maybe && next) {
688                                pos = next + 1;
689                                continue;
690                        }
691                        if (allow_skip) {
692                                i++;
693                                continue;
694                        }
695                        return 0;
696                }
697                if (!next) {
698                        match = 1;
699                        break;
700                }
701                pos = next + 1;
702                i++;
703        }
704        if (!match)
705                return 0;
706
707        wpa_trace_test_fail_after--;
708        if (wpa_trace_test_fail_after == 0) {
709                wpa_printf(MSG_INFO, "TESTING: fail at %s",
710                           wpa_trace_test_fail_func);
711                for (i = 0; i < res; i++)
712                        wpa_printf(MSG_INFO, "backtrace[%d] = %s",
713                                   (int) i, func[i]);
714                return 1;
715        }
716
717        return 0;
718}
719
720#else
721
722static inline int testing_fail_alloc(void)
723{
724        return 0;
725}
726#endif
727
728void * os_malloc(size_t size)
729{
730        struct os_alloc_trace *a;
731
732        if (testing_fail_alloc())
733                return NULL;
734
735        a = malloc(sizeof(*a) + size);
736        if (a == NULL)
737                return NULL;
738        a->magic = ALLOC_MAGIC;
739        dl_list_add(&alloc_list, &a->list);
740        a->len = size;
741        wpa_trace_record(a);
742        return a + 1;
743}
744
745
746void * os_realloc(void *ptr, size_t size)
747{
748        struct os_alloc_trace *a;
749        size_t copy_len;
750        void *n;
751
752        if (ptr == NULL)
753                return os_malloc(size);
754
755        a = (struct os_alloc_trace *) ptr - 1;
756        if (a->magic != ALLOC_MAGIC) {
757                wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
758                           a, a->magic,
759                           a->magic == FREED_MAGIC ? " (already freed)" : "");
760                wpa_trace_show("Invalid os_realloc() call");
761                abort();
762        }
763        n = os_malloc(size);
764        if (n == NULL)
765                return NULL;
766        copy_len = a->len;
767        if (copy_len > size)
768                copy_len = size;
769        os_memcpy(n, a + 1, copy_len);
770        os_free(ptr);
771        return n;
772}
773
774
775void os_free(void *ptr)
776{
777        struct os_alloc_trace *a;
778
779        if (ptr == NULL)
780                return;
781        a = (struct os_alloc_trace *) ptr - 1;
782        if (a->magic != ALLOC_MAGIC) {
783                wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
784                           a, a->magic,
785                           a->magic == FREED_MAGIC ? " (already freed)" : "");
786                wpa_trace_show("Invalid os_free() call");
787                abort();
788        }
789        dl_list_del(&a->list);
790        a->magic = FREED_MAGIC;
791
792        wpa_trace_check_ref(ptr);
793        free(a);
794}
795
796
797void * os_zalloc(size_t size)
798{
799        void *ptr = os_malloc(size);
800        if (ptr)
801                os_memset(ptr, 0, size);
802        return ptr;
803}
804
805
806char * os_strdup(const char *s)
807{
808        size_t len;
809        char *d;
810        len = os_strlen(s);
811        d = os_malloc(len + 1);
812        if (d == NULL)
813                return NULL;
814        os_memcpy(d, s, len);
815        d[len] = '\0';
816        return d;
817}
818
819#endif /* WPA_TRACE */
820
821
822int os_exec(const char *program, const char *arg, int wait_completion)
823{
824        pid_t pid;
825        int pid_status;
826
827        pid = fork();
828        if (pid < 0) {
829                perror("fork");
830                return -1;
831        }
832
833        if (pid == 0) {
834                /* run the external command in the child process */
835                const int MAX_ARG = 30;
836                char *_program, *_arg, *pos;
837                char *argv[MAX_ARG + 1];
838                int i;
839
840                _program = os_strdup(program);
841                _arg = os_strdup(arg);
842
843                argv[0] = _program;
844
845                i = 1;
846                pos = _arg;
847                while (i < MAX_ARG && pos && *pos) {
848                        while (*pos == ' ')
849                                pos++;
850                        if (*pos == '\0')
851                                break;
852                        argv[i++] = pos;
853                        pos = os_strchr(pos, ' ');
854                        if (pos)
855                                *pos++ = '\0';
856                }
857                argv[i] = NULL;
858
859                execv(program, argv);
860                perror("execv");
861                os_free(_program);
862                os_free(_arg);
863                exit(0);
864                return -1;
865        }
866
867        if (wait_completion) {
868                /* wait for the child process to complete in the parent */
869                waitpid(pid, &pid_status, 0);
870        }
871
872        return 0;
873}
Note: See TracBrowser for help on using the repository browser.