Line data Source code
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 :
13 : #ifdef ANDROID
14 : #include <sys/capability.h>
15 : #include <linux/prctl.h>
16 : #include <private/android_filesystem_config.h>
17 : #endif /* ANDROID */
18 :
19 : #include "os.h"
20 : #include "common.h"
21 :
22 : #ifdef WPA_TRACE
23 :
24 : #include "wpa_debug.h"
25 : #include "trace.h"
26 : #include "list.h"
27 :
28 : static struct dl_list alloc_list;
29 :
30 : #define ALLOC_MAGIC 0xa84ef1b2
31 : #define FREED_MAGIC 0x67fd487a
32 :
33 : struct os_alloc_trace {
34 : unsigned int magic;
35 : struct dl_list list;
36 : size_t len;
37 : WPA_TRACE_INFO
38 : };
39 :
40 : #endif /* WPA_TRACE */
41 :
42 :
43 334 : void os_sleep(os_time_t sec, os_time_t usec)
44 : {
45 334 : if (sec)
46 0 : sleep(sec);
47 334 : if (usec)
48 334 : usleep(usec);
49 334 : }
50 :
51 :
52 1692967 : int os_get_time(struct os_time *t)
53 : {
54 : int res;
55 : struct timeval tv;
56 1692967 : res = gettimeofday(&tv, NULL);
57 1692967 : t->sec = tv.tv_sec;
58 1692967 : t->usec = tv.tv_usec;
59 1692967 : return res;
60 : }
61 :
62 :
63 457907 : int os_get_reltime(struct os_reltime *t)
64 : {
65 : #if defined(CLOCK_BOOTTIME)
66 : static clockid_t clock_id = CLOCK_BOOTTIME;
67 : #elif defined(CLOCK_MONOTONIC)
68 : static clockid_t clock_id = CLOCK_MONOTONIC;
69 : #else
70 : static clockid_t clock_id = CLOCK_REALTIME;
71 : #endif
72 : struct timespec ts;
73 : int res;
74 :
75 : while (1) {
76 457907 : res = clock_gettime(clock_id, &ts);
77 457907 : if (res == 0) {
78 457907 : t->sec = ts.tv_sec;
79 457907 : t->usec = ts.tv_nsec / 1000;
80 457907 : return 0;
81 : }
82 0 : switch (clock_id) {
83 : #ifdef CLOCK_BOOTTIME
84 : case CLOCK_BOOTTIME:
85 0 : clock_id = CLOCK_MONOTONIC;
86 0 : break;
87 : #endif
88 : #ifdef CLOCK_MONOTONIC
89 : case CLOCK_MONOTONIC:
90 0 : clock_id = CLOCK_REALTIME;
91 0 : break;
92 : #endif
93 : case CLOCK_REALTIME:
94 0 : return -1;
95 : }
96 0 : }
97 : }
98 :
99 :
100 0 : int os_mktime(int year, int month, int day, int hour, int min, int sec,
101 : os_time_t *t)
102 : {
103 : struct tm tm, *tm1;
104 : time_t t_local, t1, t2;
105 : os_time_t tz_offset;
106 :
107 0 : if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
108 0 : hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
109 : sec > 60)
110 0 : return -1;
111 :
112 0 : memset(&tm, 0, sizeof(tm));
113 0 : tm.tm_year = year - 1900;
114 0 : tm.tm_mon = month - 1;
115 0 : tm.tm_mday = day;
116 0 : tm.tm_hour = hour;
117 0 : tm.tm_min = min;
118 0 : tm.tm_sec = sec;
119 :
120 0 : t_local = mktime(&tm);
121 :
122 : /* figure out offset to UTC */
123 0 : tm1 = localtime(&t_local);
124 0 : if (tm1) {
125 0 : t1 = mktime(tm1);
126 0 : tm1 = gmtime(&t_local);
127 0 : if (tm1) {
128 0 : t2 = mktime(tm1);
129 0 : tz_offset = t2 - t1;
130 : } else
131 0 : tz_offset = 0;
132 : } else
133 0 : tz_offset = 0;
134 :
135 0 : *t = (os_time_t) t_local - tz_offset;
136 0 : return 0;
137 : }
138 :
139 :
140 6 : int os_gmtime(os_time_t t, struct os_tm *tm)
141 : {
142 : struct tm *tm2;
143 6 : time_t t2 = t;
144 :
145 6 : tm2 = gmtime(&t2);
146 6 : if (tm2 == NULL)
147 0 : return -1;
148 6 : tm->sec = tm2->tm_sec;
149 6 : tm->min = tm2->tm_min;
150 6 : tm->hour = tm2->tm_hour;
151 6 : tm->day = tm2->tm_mday;
152 6 : tm->month = tm2->tm_mon + 1;
153 6 : tm->year = tm2->tm_year + 1900;
154 6 : return 0;
155 : }
156 :
157 :
158 : #ifdef __APPLE__
159 : #include <fcntl.h>
160 : static int os_daemon(int nochdir, int noclose)
161 : {
162 : int devnull;
163 :
164 : if (chdir("/") < 0)
165 : return -1;
166 :
167 : devnull = open("/dev/null", O_RDWR);
168 : if (devnull < 0)
169 : return -1;
170 :
171 : if (dup2(devnull, STDIN_FILENO) < 0) {
172 : close(devnull);
173 : return -1;
174 : }
175 :
176 : if (dup2(devnull, STDOUT_FILENO) < 0) {
177 : close(devnull);
178 : return -1;
179 : }
180 :
181 : if (dup2(devnull, STDERR_FILENO) < 0) {
182 : close(devnull);
183 : return -1;
184 : }
185 :
186 : return 0;
187 : }
188 : #else /* __APPLE__ */
189 : #define os_daemon daemon
190 : #endif /* __APPLE__ */
191 :
192 :
193 0 : int os_daemonize(const char *pid_file)
194 : {
195 : #if defined(__uClinux__) || defined(__sun__)
196 : return -1;
197 : #else /* defined(__uClinux__) || defined(__sun__) */
198 0 : if (os_daemon(0, 0)) {
199 0 : perror("daemon");
200 0 : return -1;
201 : }
202 :
203 0 : if (pid_file) {
204 0 : FILE *f = fopen(pid_file, "w");
205 0 : if (f) {
206 0 : fprintf(f, "%u\n", getpid());
207 0 : fclose(f);
208 : }
209 : }
210 :
211 0 : return -0;
212 : #endif /* defined(__uClinux__) || defined(__sun__) */
213 : }
214 :
215 :
216 2 : void os_daemonize_terminate(const char *pid_file)
217 : {
218 2 : if (pid_file)
219 0 : unlink(pid_file);
220 2 : }
221 :
222 :
223 8380 : int os_get_random(unsigned char *buf, size_t len)
224 : {
225 : FILE *f;
226 : size_t rc;
227 :
228 8380 : f = fopen("/dev/urandom", "rb");
229 8380 : if (f == NULL) {
230 0 : printf("Could not open /dev/urandom.\n");
231 0 : return -1;
232 : }
233 :
234 8380 : rc = fread(buf, 1, len, f);
235 8380 : fclose(f);
236 :
237 8380 : return rc != len ? -1 : 0;
238 : }
239 :
240 :
241 1984 : unsigned long os_random(void)
242 : {
243 1984 : return random();
244 : }
245 :
246 :
247 22 : char * os_rel2abs_path(const char *rel_path)
248 : {
249 22 : char *buf = NULL, *cwd, *ret;
250 22 : size_t len = 128, cwd_len, rel_len, ret_len;
251 : int last_errno;
252 :
253 22 : if (!rel_path)
254 10 : return NULL;
255 :
256 12 : if (rel_path[0] == '/')
257 6 : return os_strdup(rel_path);
258 :
259 : for (;;) {
260 6 : buf = os_malloc(len);
261 6 : if (buf == NULL)
262 0 : return NULL;
263 6 : cwd = getcwd(buf, len);
264 6 : if (cwd == NULL) {
265 0 : last_errno = errno;
266 0 : os_free(buf);
267 0 : if (last_errno != ERANGE)
268 0 : return NULL;
269 0 : len *= 2;
270 0 : if (len > 2000)
271 0 : return NULL;
272 : } else {
273 6 : buf[len - 1] = '\0';
274 6 : break;
275 : }
276 0 : }
277 :
278 6 : cwd_len = os_strlen(cwd);
279 6 : rel_len = os_strlen(rel_path);
280 6 : ret_len = cwd_len + 1 + rel_len + 1;
281 6 : ret = os_malloc(ret_len);
282 6 : if (ret) {
283 6 : os_memcpy(ret, cwd, cwd_len);
284 6 : ret[cwd_len] = '/';
285 6 : os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
286 6 : ret[ret_len - 1] = '\0';
287 : }
288 6 : os_free(buf);
289 6 : return ret;
290 : }
291 :
292 :
293 7 : int os_program_init(void)
294 : {
295 : #ifdef ANDROID
296 : /*
297 : * We ignore errors here since errors are normal if we
298 : * are already running as non-root.
299 : */
300 : #ifdef ANDROID_SETGROUPS_OVERRIDE
301 : gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
302 : #else /* ANDROID_SETGROUPS_OVERRIDE */
303 : gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
304 : #endif /* ANDROID_SETGROUPS_OVERRIDE */
305 : struct __user_cap_header_struct header;
306 : struct __user_cap_data_struct cap;
307 :
308 : setgroups(ARRAY_SIZE(groups), groups);
309 :
310 : prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
311 :
312 : setgid(AID_WIFI);
313 : setuid(AID_WIFI);
314 :
315 : header.version = _LINUX_CAPABILITY_VERSION;
316 : header.pid = 0;
317 : cap.effective = cap.permitted =
318 : (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
319 : cap.inheritable = 0;
320 : capset(&header, &cap);
321 : #endif /* ANDROID */
322 :
323 : #ifdef WPA_TRACE
324 7 : dl_list_init(&alloc_list);
325 : #endif /* WPA_TRACE */
326 7 : return 0;
327 : }
328 :
329 :
330 6 : void os_program_deinit(void)
331 : {
332 : #ifdef WPA_TRACE
333 : struct os_alloc_trace *a;
334 6 : unsigned long total = 0;
335 6 : dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
336 0 : total += a->len;
337 0 : if (a->magic != ALLOC_MAGIC) {
338 0 : wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
339 : "len %lu",
340 : a, a->magic, (unsigned long) a->len);
341 0 : continue;
342 : }
343 0 : wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
344 : a, (unsigned long) a->len);
345 0 : wpa_trace_dump("memleak", a);
346 : }
347 6 : if (total)
348 0 : wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
349 : (unsigned long) total);
350 : #endif /* WPA_TRACE */
351 6 : }
352 :
353 :
354 0 : int os_setenv(const char *name, const char *value, int overwrite)
355 : {
356 0 : return setenv(name, value, overwrite);
357 : }
358 :
359 :
360 0 : int os_unsetenv(const char *name)
361 : {
362 : #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
363 : defined(__OpenBSD__)
364 : unsetenv(name);
365 : return 0;
366 : #else
367 0 : return unsetenv(name);
368 : #endif
369 : }
370 :
371 :
372 13 : char * os_readfile(const char *name, size_t *len)
373 : {
374 : FILE *f;
375 : char *buf;
376 : long pos;
377 :
378 13 : f = fopen(name, "rb");
379 13 : if (f == NULL)
380 2 : return NULL;
381 :
382 11 : if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
383 0 : fclose(f);
384 0 : return NULL;
385 : }
386 11 : *len = pos;
387 11 : if (fseek(f, 0, SEEK_SET) < 0) {
388 0 : fclose(f);
389 0 : return NULL;
390 : }
391 :
392 11 : buf = os_malloc(*len);
393 11 : if (buf == NULL) {
394 0 : fclose(f);
395 0 : return NULL;
396 : }
397 :
398 11 : if (fread(buf, 1, *len, f) != *len) {
399 0 : fclose(f);
400 0 : os_free(buf);
401 0 : return NULL;
402 : }
403 :
404 11 : fclose(f);
405 :
406 11 : return buf;
407 : }
408 :
409 :
410 0 : int os_file_exists(const char *fname)
411 : {
412 0 : FILE *f = fopen(fname, "rb");
413 0 : if (f == NULL)
414 0 : return 0;
415 0 : fclose(f);
416 0 : return 1;
417 : }
418 :
419 :
420 : #ifndef WPA_TRACE
421 : void * os_zalloc(size_t size)
422 : {
423 : return calloc(1, size);
424 : }
425 : #endif /* WPA_TRACE */
426 :
427 :
428 45175 : size_t os_strlcpy(char *dest, const char *src, size_t siz)
429 : {
430 45175 : const char *s = src;
431 45175 : size_t left = siz;
432 :
433 45175 : if (left) {
434 : /* Copy string up to the maximum size of the dest buffer */
435 312470 : while (--left != 0) {
436 267119 : if ((*dest++ = *s++) == '\0')
437 44999 : break;
438 : }
439 : }
440 :
441 45175 : if (left == 0) {
442 : /* Not enough room for the string; force NUL-termination */
443 176 : if (siz != 0)
444 176 : *dest = '\0';
445 176 : while (*s++)
446 : ; /* determine total src string length */
447 : }
448 :
449 45175 : return s - src - 1;
450 : }
451 :
452 :
453 : #ifdef WPA_TRACE
454 :
455 876682 : void * os_malloc(size_t size)
456 : {
457 : struct os_alloc_trace *a;
458 876682 : a = malloc(sizeof(*a) + size);
459 876682 : if (a == NULL)
460 0 : return NULL;
461 876682 : a->magic = ALLOC_MAGIC;
462 876682 : dl_list_add(&alloc_list, &a->list);
463 876682 : a->len = size;
464 876682 : wpa_trace_record(a);
465 876682 : return a + 1;
466 : }
467 :
468 :
469 175060 : void * os_realloc(void *ptr, size_t size)
470 : {
471 : struct os_alloc_trace *a;
472 : size_t copy_len;
473 : void *n;
474 :
475 175060 : if (ptr == NULL)
476 17478 : return os_malloc(size);
477 :
478 157582 : a = (struct os_alloc_trace *) ptr - 1;
479 157582 : if (a->magic != ALLOC_MAGIC) {
480 0 : wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
481 : a, a->magic,
482 0 : a->magic == FREED_MAGIC ? " (already freed)" : "");
483 0 : wpa_trace_show("Invalid os_realloc() call");
484 0 : abort();
485 : }
486 157582 : n = os_malloc(size);
487 157582 : if (n == NULL)
488 0 : return NULL;
489 157582 : copy_len = a->len;
490 157582 : if (copy_len > size)
491 917 : copy_len = size;
492 157582 : os_memcpy(n, a + 1, copy_len);
493 157582 : os_free(ptr);
494 157582 : return n;
495 : }
496 :
497 :
498 1113459 : void os_free(void *ptr)
499 : {
500 : struct os_alloc_trace *a;
501 :
502 1113459 : if (ptr == NULL)
503 1350236 : return;
504 876682 : a = (struct os_alloc_trace *) ptr - 1;
505 876682 : if (a->magic != ALLOC_MAGIC) {
506 0 : wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
507 : a, a->magic,
508 0 : a->magic == FREED_MAGIC ? " (already freed)" : "");
509 0 : wpa_trace_show("Invalid os_free() call");
510 0 : abort();
511 : }
512 876682 : dl_list_del(&a->list);
513 876682 : a->magic = FREED_MAGIC;
514 :
515 876682 : wpa_trace_check_ref(ptr);
516 876682 : free(a);
517 : }
518 :
519 :
520 217844 : void * os_zalloc(size_t size)
521 : {
522 217844 : void *ptr = os_malloc(size);
523 217844 : if (ptr)
524 217844 : os_memset(ptr, 0, size);
525 217844 : return ptr;
526 : }
527 :
528 :
529 12026 : char * os_strdup(const char *s)
530 : {
531 : size_t len;
532 : char *d;
533 12026 : len = os_strlen(s);
534 12026 : d = os_malloc(len + 1);
535 12026 : if (d == NULL)
536 0 : return NULL;
537 12026 : os_memcpy(d, s, len);
538 12026 : d[len] = '\0';
539 12026 : return d;
540 : }
541 :
542 : #endif /* WPA_TRACE */
|