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