Updated to hostap_2_6
[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         wpa_trace_deinit();
376 #endif /* WPA_TRACE */
377 }
378
379
380 int os_setenv(const char *name, const char *value, int overwrite)
381 {
382         return setenv(name, value, overwrite);
383 }
384
385
386 int os_unsetenv(const char *name)
387 {
388 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
389     defined(__OpenBSD__)
390         unsetenv(name);
391         return 0;
392 #else
393         return unsetenv(name);
394 #endif
395 }
396
397
398 char * os_readfile(const char *name, size_t *len)
399 {
400         FILE *f;
401         char *buf;
402         long pos;
403
404         f = fopen(name, "rb");
405         if (f == NULL)
406                 return NULL;
407
408         if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
409                 fclose(f);
410                 return NULL;
411         }
412         *len = pos;
413         if (fseek(f, 0, SEEK_SET) < 0) {
414                 fclose(f);
415                 return NULL;
416         }
417
418         buf = os_malloc(*len);
419         if (buf == NULL) {
420                 fclose(f);
421                 return NULL;
422         }
423
424         if (fread(buf, 1, *len, f) != *len) {
425                 fclose(f);
426                 os_free(buf);
427                 return NULL;
428         }
429
430         fclose(f);
431
432         return buf;
433 }
434
435
436 int os_file_exists(const char *fname)
437 {
438         return access(fname, F_OK) == 0;
439 }
440
441
442 int os_fdatasync(FILE *stream)
443 {
444         if (!fflush(stream)) {
445 #ifdef __linux__
446                 return fdatasync(fileno(stream));
447 #else /* !__linux__ */
448 #ifdef F_FULLFSYNC
449                 /* OS X does not implement fdatasync(). */
450                 return fcntl(fileno(stream), F_FULLFSYNC);
451 #else /* F_FULLFSYNC */
452                 return fsync(fileno(stream));
453 #endif /* F_FULLFSYNC */
454 #endif /* __linux__ */
455         }
456
457         return -1;
458 }
459
460
461 #ifndef WPA_TRACE
462 void * os_zalloc(size_t size)
463 {
464         return calloc(1, size);
465 }
466 #endif /* WPA_TRACE */
467
468
469 size_t os_strlcpy(char *dest, const char *src, size_t siz)
470 {
471         const char *s = src;
472         size_t left = siz;
473
474         if (left) {
475                 /* Copy string up to the maximum size of the dest buffer */
476                 while (--left != 0) {
477                         if ((*dest++ = *s++) == '\0')
478                                 break;
479                 }
480         }
481
482         if (left == 0) {
483                 /* Not enough room for the string; force NUL-termination */
484                 if (siz != 0)
485                         *dest = '\0';
486                 while (*s++)
487                         ; /* determine total src string length */
488         }
489
490         return s - src - 1;
491 }
492
493
494 int os_memcmp_const(const void *a, const void *b, size_t len)
495 {
496         const u8 *aa = a;
497         const u8 *bb = b;
498         size_t i;
499         u8 res;
500
501         for (res = 0, i = 0; i < len; i++)
502                 res |= aa[i] ^ bb[i];
503
504         return res;
505 }
506
507
508 #ifdef WPA_TRACE
509
510 #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
511 char wpa_trace_fail_func[256] = { 0 };
512 unsigned int wpa_trace_fail_after;
513
514 static int testing_fail_alloc(void)
515 {
516         const char *func[WPA_TRACE_LEN];
517         size_t i, res, len;
518         char *pos, *next;
519         int match;
520
521         if (!wpa_trace_fail_after)
522                 return 0;
523
524         res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
525         i = 0;
526         if (i < res && os_strcmp(func[i], __func__) == 0)
527                 i++;
528         if (i < res && os_strcmp(func[i], "os_malloc") == 0)
529                 i++;
530         if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
531                 i++;
532         if (i < res && os_strcmp(func[i], "os_calloc") == 0)
533                 i++;
534         if (i < res && os_strcmp(func[i], "os_realloc") == 0)
535                 i++;
536         if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
537                 i++;
538         if (i < res && os_strcmp(func[i], "os_strdup") == 0)
539                 i++;
540
541         pos = wpa_trace_fail_func;
542
543         match = 0;
544         while (i < res) {
545                 int allow_skip = 1;
546                 int maybe = 0;
547
548                 if (*pos == '=') {
549                         allow_skip = 0;
550                         pos++;
551                 } else if (*pos == '?') {
552                         maybe = 1;
553                         pos++;
554                 }
555                 next = os_strchr(pos, ';');
556                 if (next)
557                         len = next - pos;
558                 else
559                         len = os_strlen(pos);
560                 if (os_memcmp(pos, func[i], len) != 0) {
561                         if (maybe && next) {
562                                 pos = next + 1;
563                                 continue;
564                         }
565                         if (allow_skip) {
566                                 i++;
567                                 continue;
568                         }
569                         return 0;
570                 }
571                 if (!next) {
572                         match = 1;
573                         break;
574                 }
575                 pos = next + 1;
576                 i++;
577         }
578         if (!match)
579                 return 0;
580
581         wpa_trace_fail_after--;
582         if (wpa_trace_fail_after == 0) {
583                 wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
584                            wpa_trace_fail_func);
585                 for (i = 0; i < res; i++)
586                         wpa_printf(MSG_INFO, "backtrace[%d] = %s",
587                                    (int) i, func[i]);
588                 return 1;
589         }
590
591         return 0;
592 }
593
594
595 char wpa_trace_test_fail_func[256] = { 0 };
596 unsigned int wpa_trace_test_fail_after;
597
598 int testing_test_fail(void)
599 {
600         const char *func[WPA_TRACE_LEN];
601         size_t i, res, len;
602         char *pos, *next;
603         int match;
604
605         if (!wpa_trace_test_fail_after)
606                 return 0;
607
608         res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
609         i = 0;
610         if (i < res && os_strcmp(func[i], __func__) == 0)
611                 i++;
612
613         pos = wpa_trace_test_fail_func;
614
615         match = 0;
616         while (i < res) {
617                 int allow_skip = 1;
618                 int maybe = 0;
619
620                 if (*pos == '=') {
621                         allow_skip = 0;
622                         pos++;
623                 } else if (*pos == '?') {
624                         maybe = 1;
625                         pos++;
626                 }
627                 next = os_strchr(pos, ';');
628                 if (next)
629                         len = next - pos;
630                 else
631                         len = os_strlen(pos);
632                 if (os_memcmp(pos, func[i], len) != 0) {
633                         if (maybe && next) {
634                                 pos = next + 1;
635                                 continue;
636                         }
637                         if (allow_skip) {
638                                 i++;
639                                 continue;
640                         }
641                         return 0;
642                 }
643                 if (!next) {
644                         match = 1;
645                         break;
646                 }
647                 pos = next + 1;
648                 i++;
649         }
650         if (!match)
651                 return 0;
652
653         wpa_trace_test_fail_after--;
654         if (wpa_trace_test_fail_after == 0) {
655                 wpa_printf(MSG_INFO, "TESTING: fail at %s",
656                            wpa_trace_test_fail_func);
657                 for (i = 0; i < res; i++)
658                         wpa_printf(MSG_INFO, "backtrace[%d] = %s",
659                                    (int) i, func[i]);
660                 return 1;
661         }
662
663         return 0;
664 }
665
666 #else
667
668 static inline int testing_fail_alloc(void)
669 {
670         return 0;
671 }
672 #endif
673
674 void * os_malloc(size_t size)
675 {
676         struct os_alloc_trace *a;
677
678         if (testing_fail_alloc())
679                 return NULL;
680
681         a = malloc(sizeof(*a) + size);
682         if (a == NULL)
683                 return NULL;
684         a->magic = ALLOC_MAGIC;
685         dl_list_add(&alloc_list, &a->list);
686         a->len = size;
687         wpa_trace_record(a);
688         return a + 1;
689 }
690
691
692 void * os_realloc(void *ptr, size_t size)
693 {
694         struct os_alloc_trace *a;
695         size_t copy_len;
696         void *n;
697
698         if (ptr == NULL)
699                 return os_malloc(size);
700
701         a = (struct os_alloc_trace *) ptr - 1;
702         if (a->magic != ALLOC_MAGIC) {
703                 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
704                            a, a->magic,
705                            a->magic == FREED_MAGIC ? " (already freed)" : "");
706                 wpa_trace_show("Invalid os_realloc() call");
707                 abort();
708         }
709         n = os_malloc(size);
710         if (n == NULL)
711                 return NULL;
712         copy_len = a->len;
713         if (copy_len > size)
714                 copy_len = size;
715         os_memcpy(n, a + 1, copy_len);
716         os_free(ptr);
717         return n;
718 }
719
720
721 void os_free(void *ptr)
722 {
723         struct os_alloc_trace *a;
724
725         if (ptr == NULL)
726                 return;
727         a = (struct os_alloc_trace *) ptr - 1;
728         if (a->magic != ALLOC_MAGIC) {
729                 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
730                            a, a->magic,
731                            a->magic == FREED_MAGIC ? " (already freed)" : "");
732                 wpa_trace_show("Invalid os_free() call");
733                 abort();
734         }
735         dl_list_del(&a->list);
736         a->magic = FREED_MAGIC;
737
738         wpa_trace_check_ref(ptr);
739         free(a);
740 }
741
742
743 void * os_zalloc(size_t size)
744 {
745         void *ptr = os_malloc(size);
746         if (ptr)
747                 os_memset(ptr, 0, size);
748         return ptr;
749 }
750
751
752 char * os_strdup(const char *s)
753 {
754         size_t len;
755         char *d;
756         len = os_strlen(s);
757         d = os_malloc(len + 1);
758         if (d == NULL)
759                 return NULL;
760         os_memcpy(d, s, len);
761         d[len] = '\0';
762         return d;
763 }
764
765 #endif /* WPA_TRACE */
766
767
768 int os_exec(const char *program, const char *arg, int wait_completion)
769 {
770         pid_t pid;
771         int pid_status;
772
773         pid = fork();
774         if (pid < 0) {
775                 perror("fork");
776                 return -1;
777         }
778
779         if (pid == 0) {
780                 /* run the external command in the child process */
781                 const int MAX_ARG = 30;
782                 char *_program, *_arg, *pos;
783                 char *argv[MAX_ARG + 1];
784                 int i;
785
786                 _program = os_strdup(program);
787                 _arg = os_strdup(arg);
788
789                 argv[0] = _program;
790
791                 i = 1;
792                 pos = _arg;
793                 while (i < MAX_ARG && pos && *pos) {
794                         while (*pos == ' ')
795                                 pos++;
796                         if (*pos == '\0')
797                                 break;
798                         argv[i++] = pos;
799                         pos = os_strchr(pos, ' ');
800                         if (pos)
801                                 *pos++ = '\0';
802                 }
803                 argv[i] = NULL;
804
805                 execv(program, argv);
806                 perror("execv");
807                 os_free(_program);
808                 os_free(_arg);
809                 exit(0);
810                 return -1;
811         }
812
813         if (wait_completion) {
814                 /* wait for the child process to complete in the parent */
815                 waitpid(pid, &pid_status, 0);
816         }
817
818         return 0;
819 }