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