1 /*
2 * wpa_supplicant/hostapd / Internal implementation of OS specific functions
3 * Copyright (c) 2005-2006, 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 * This file is an example of operating system specific wrapper functions.
9 * This version implements many of the functions internally, so it can be used
10 * to fill in missing functions from the target system C libraries.
11 *
12 * Some of the functions are using standard C library calls in order to keep
13 * this file in working condition to allow the functions to be tested on a
14 * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for
15 * this file to work correctly. Note that these implementations are only
16 * examples and are not optimized for speed.
17 */
18
19 #include "includes.h"
20 #include <time.h>
21 #include <sys/wait.h>
22
23 #undef OS_REJECT_C_LIB_FUNCTIONS
24 #include "common.h"
25
os_sleep(os_time_t sec,os_time_t usec)26 void os_sleep(os_time_t sec, os_time_t usec)
27 {
28 #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
29 const struct timespec req = { sec, usec * 1000 };
30
31 nanosleep(&req, NULL);
32 #else
33 if (sec)
34 sleep(sec);
35 if (usec)
36 usleep(usec);
37 #endif
38 }
39
40
os_get_time(struct os_time * t)41 int os_get_time(struct os_time *t)
42 {
43 int res;
44 struct timeval tv;
45 res = gettimeofday(&tv, NULL);
46 t->sec = tv.tv_sec;
47 t->usec = tv.tv_usec;
48 return res;
49 }
50
51
os_get_reltime(struct os_reltime * t)52 int os_get_reltime(struct os_reltime *t)
53 {
54 int res;
55 struct timeval tv;
56 res = gettimeofday(&tv, NULL);
57 t->sec = tv.tv_sec;
58 t->usec = tv.tv_usec;
59 return res;
60 }
61
62
os_mktime(int year,int month,int day,int hour,int min,int sec,os_time_t * t)63 int os_mktime(int year, int month, int day, int hour, int min, int sec,
64 os_time_t *t)
65 {
66 struct tm tm;
67
68 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
69 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
70 sec > 60)
71 return -1;
72
73 os_memset(&tm, 0, sizeof(tm));
74 tm.tm_year = year - 1900;
75 tm.tm_mon = month - 1;
76 tm.tm_mday = day;
77 tm.tm_hour = hour;
78 tm.tm_min = min;
79 tm.tm_sec = sec;
80
81 *t = (os_time_t) mktime(&tm);
82 return 0;
83 }
84
85
os_gmtime(os_time_t t,struct os_tm * tm)86 int os_gmtime(os_time_t t, struct os_tm *tm)
87 {
88 struct tm *tm2;
89 time_t t2 = t;
90
91 tm2 = gmtime(&t2);
92 if (tm2 == NULL)
93 return -1;
94 tm->sec = tm2->tm_sec;
95 tm->min = tm2->tm_min;
96 tm->hour = tm2->tm_hour;
97 tm->day = tm2->tm_mday;
98 tm->month = tm2->tm_mon + 1;
99 tm->year = tm2->tm_year + 1900;
100 return 0;
101 }
102
103
os_daemonize(const char * pid_file)104 int os_daemonize(const char *pid_file)
105 {
106 if (daemon(0, 0)) {
107 wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno));
108 return -1;
109 }
110
111 if (pid_file) {
112 FILE *f = fopen(pid_file, "w");
113 if (f) {
114 fprintf(f, "%u\n", getpid());
115 fclose(f);
116 }
117 }
118
119 return -0;
120 }
121
122
os_daemonize_terminate(const char * pid_file)123 void os_daemonize_terminate(const char *pid_file)
124 {
125 if (pid_file)
126 unlink(pid_file);
127 }
128
129
os_get_random(unsigned char * buf,size_t len)130 int os_get_random(unsigned char *buf, size_t len)
131 {
132 FILE *f;
133 size_t rc;
134
135 f = fopen("/dev/urandom", "rb");
136 if (f == NULL) {
137 printf("Could not open /dev/urandom.\n");
138 return -1;
139 }
140
141 rc = fread(buf, 1, len, f);
142 fclose(f);
143
144 return rc != len ? -1 : 0;
145 }
146
147
os_random(void)148 unsigned long os_random(void)
149 {
150 return random();
151 }
152
153
os_rel2abs_path(const char * rel_path)154 char * os_rel2abs_path(const char *rel_path)
155 {
156 char *buf = NULL, *cwd, *ret;
157 size_t len = 128, cwd_len, rel_len, ret_len;
158
159 if (rel_path[0] == '/')
160 return os_strdup(rel_path);
161
162 for (;;) {
163 buf = os_malloc(len);
164 if (buf == NULL)
165 return NULL;
166 cwd = getcwd(buf, len);
167 if (cwd == NULL) {
168 os_free(buf);
169 if (errno != ERANGE) {
170 return NULL;
171 }
172 len *= 2;
173 } else {
174 break;
175 }
176 }
177
178 cwd_len = os_strlen(cwd);
179 rel_len = os_strlen(rel_path);
180 ret_len = cwd_len + 1 + rel_len + 1;
181 ret = os_malloc(ret_len);
182 if (ret) {
183 os_memcpy(ret, cwd, cwd_len);
184 ret[cwd_len] = '/';
185 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
186 ret[ret_len - 1] = '\0';
187 }
188 os_free(buf);
189 return ret;
190 }
191
192
os_program_init(void)193 int os_program_init(void)
194 {
195 return 0;
196 }
197
198
os_program_deinit(void)199 void os_program_deinit(void)
200 {
201 }
202
203
os_setenv(const char * name,const char * value,int overwrite)204 int os_setenv(const char *name, const char *value, int overwrite)
205 {
206 return setenv(name, value, overwrite);
207 }
208
209
os_unsetenv(const char * name)210 int os_unsetenv(const char *name)
211 {
212 #if defined(__FreeBSD__) || defined(__NetBSD__)
213 unsetenv(name);
214 return 0;
215 #else
216 return unsetenv(name);
217 #endif
218 }
219
220
os_readfile(const char * name,size_t * len)221 char * os_readfile(const char *name, size_t *len)
222 {
223 FILE *f;
224 char *buf;
225
226 f = fopen(name, "rb");
227 if (f == NULL)
228 return NULL;
229
230 fseek(f, 0, SEEK_END);
231 *len = ftell(f);
232 fseek(f, 0, SEEK_SET);
233
234 buf = os_malloc(*len);
235 if (buf == NULL) {
236 fclose(f);
237 return NULL;
238 }
239
240 if (fread(buf, 1, *len, f) != *len) {
241 fclose(f);
242 os_free(buf);
243 return NULL;
244 }
245
246 fclose(f);
247
248 return buf;
249 }
250
251
os_fdatasync(FILE * stream)252 int os_fdatasync(FILE *stream)
253 {
254 return 0;
255 }
256
257
os_zalloc(size_t size)258 void * os_zalloc(size_t size)
259 {
260 void *n = os_malloc(size);
261 if (n)
262 os_memset(n, 0, size);
263 return n;
264 }
265
266
os_malloc(size_t size)267 void * os_malloc(size_t size)
268 {
269 return malloc(size);
270 }
271
272
os_realloc(void * ptr,size_t size)273 void * os_realloc(void *ptr, size_t size)
274 {
275 return realloc(ptr, size);
276 }
277
278
os_free(void * ptr)279 void os_free(void *ptr)
280 {
281 free(ptr);
282 }
283
284
os_memcpy(void * dest,const void * src,size_t n)285 void * os_memcpy(void *dest, const void *src, size_t n)
286 {
287 char *d = dest;
288 const char *s = src;
289 while (n--)
290 *d++ = *s++;
291 return dest;
292 }
293
294
os_memmove(void * dest,const void * src,size_t n)295 void * os_memmove(void *dest, const void *src, size_t n)
296 {
297 if (dest < src)
298 os_memcpy(dest, src, n);
299 else {
300 /* overlapping areas */
301 char *d = (char *) dest + n;
302 const char *s = (const char *) src + n;
303 while (n--)
304 *--d = *--s;
305 }
306 return dest;
307 }
308
309
os_memset(void * s,int c,size_t n)310 void * os_memset(void *s, int c, size_t n)
311 {
312 char *p = s;
313 while (n--)
314 *p++ = c;
315 return s;
316 }
317
318
os_memcmp(const void * s1,const void * s2,size_t n)319 int os_memcmp(const void *s1, const void *s2, size_t n)
320 {
321 const unsigned char *p1 = s1, *p2 = s2;
322
323 if (n == 0)
324 return 0;
325
326 while (*p1 == *p2) {
327 p1++;
328 p2++;
329 n--;
330 if (n == 0)
331 return 0;
332 }
333
334 return *p1 - *p2;
335 }
336
337
os_strdup(const char * s)338 char * os_strdup(const char *s)
339 {
340 char *res;
341 size_t len;
342 if (s == NULL)
343 return NULL;
344 len = os_strlen(s);
345 res = os_malloc(len + 1);
346 if (res)
347 os_memcpy(res, s, len + 1);
348 return res;
349 }
350
351
os_strlen(const char * s)352 size_t os_strlen(const char *s)
353 {
354 const char *p = s;
355 while (*p)
356 p++;
357 return p - s;
358 }
359
360
os_strcasecmp(const char * s1,const char * s2)361 int os_strcasecmp(const char *s1, const char *s2)
362 {
363 /*
364 * Ignoring case is not required for main functionality, so just use
365 * the case sensitive version of the function.
366 */
367 return os_strcmp(s1, s2);
368 }
369
370
os_strncasecmp(const char * s1,const char * s2,size_t n)371 int os_strncasecmp(const char *s1, const char *s2, size_t n)
372 {
373 /*
374 * Ignoring case is not required for main functionality, so just use
375 * the case sensitive version of the function.
376 */
377 return os_strncmp(s1, s2, n);
378 }
379
380
os_strchr(const char * s,int c)381 char * os_strchr(const char *s, int c)
382 {
383 while (*s) {
384 if (*s == c)
385 return (char *) s;
386 s++;
387 }
388 return NULL;
389 }
390
391
os_strrchr(const char * s,int c)392 char * os_strrchr(const char *s, int c)
393 {
394 const char *p = s;
395 while (*p)
396 p++;
397 p--;
398 while (p >= s) {
399 if (*p == c)
400 return (char *) p;
401 p--;
402 }
403 return NULL;
404 }
405
406
os_strcmp(const char * s1,const char * s2)407 int os_strcmp(const char *s1, const char *s2)
408 {
409 while (*s1 == *s2) {
410 if (*s1 == '\0')
411 break;
412 s1++;
413 s2++;
414 }
415
416 return *s1 - *s2;
417 }
418
419
os_strncmp(const char * s1,const char * s2,size_t n)420 int os_strncmp(const char *s1, const char *s2, size_t n)
421 {
422 if (n == 0)
423 return 0;
424
425 while (*s1 == *s2) {
426 if (*s1 == '\0')
427 break;
428 s1++;
429 s2++;
430 n--;
431 if (n == 0)
432 return 0;
433 }
434
435 return *s1 - *s2;
436 }
437
438
os_strlcpy(char * dest,const char * src,size_t siz)439 size_t os_strlcpy(char *dest, const char *src, size_t siz)
440 {
441 const char *s = src;
442 size_t left = siz;
443
444 if (left) {
445 /* Copy string up to the maximum size of the dest buffer */
446 while (--left != 0) {
447 if ((*dest++ = *s++) == '\0')
448 break;
449 }
450 }
451
452 if (left == 0) {
453 /* Not enough room for the string; force NUL-termination */
454 if (siz != 0)
455 *dest = '\0';
456 while (*s++)
457 ; /* determine total src string length */
458 }
459
460 return s - src - 1;
461 }
462
463
os_memcmp_const(const void * a,const void * b,size_t len)464 int os_memcmp_const(const void *a, const void *b, size_t len)
465 {
466 const u8 *aa = a;
467 const u8 *bb = b;
468 size_t i;
469 u8 res;
470
471 for (res = 0, i = 0; i < len; i++)
472 res |= aa[i] ^ bb[i];
473
474 return res;
475 }
476
477
os_strstr(const char * haystack,const char * needle)478 char * os_strstr(const char *haystack, const char *needle)
479 {
480 size_t len = os_strlen(needle);
481 while (*haystack) {
482 if (os_strncmp(haystack, needle, len) == 0)
483 return (char *) haystack;
484 haystack++;
485 }
486
487 return NULL;
488 }
489
490
os_snprintf(char * str,size_t size,const char * format,...)491 int os_snprintf(char *str, size_t size, const char *format, ...)
492 {
493 va_list ap;
494 int ret;
495
496 /* See http://www.ijs.si/software/snprintf/ for portable
497 * implementation of snprintf.
498 */
499
500 va_start(ap, format);
501 ret = vsnprintf(str, size, format, ap);
502 va_end(ap);
503 if (size > 0)
504 str[size - 1] = '\0';
505 return ret;
506 }
507
508
os_exec(const char * program,const char * arg,int wait_completion)509 int os_exec(const char *program, const char *arg, int wait_completion)
510 {
511 pid_t pid;
512 int pid_status;
513
514 pid = fork();
515 if (pid < 0) {
516 wpa_printf(MSG_ERROR, "fork: %s", strerror(errno));
517 return -1;
518 }
519
520 if (pid == 0) {
521 /* run the external command in the child process */
522 const int MAX_ARG = 30;
523 char *_program, *_arg, *pos;
524 char *argv[MAX_ARG + 1];
525 int i;
526
527 _program = os_strdup(program);
528 _arg = os_strdup(arg);
529
530 argv[0] = _program;
531
532 i = 1;
533 pos = _arg;
534 while (i < MAX_ARG && pos && *pos) {
535 while (*pos == ' ')
536 pos++;
537 if (*pos == '\0')
538 break;
539 argv[i++] = pos;
540 pos = os_strchr(pos, ' ');
541 if (pos)
542 *pos++ = '\0';
543 }
544 argv[i] = NULL;
545
546 execv(program, argv);
547 wpa_printf(MSG_ERROR, "execv: %s", strerror(errno));
548 os_free(_program);
549 os_free(_arg);
550 exit(0);
551 return -1;
552 }
553
554 if (wait_completion) {
555 /* wait for the child process to complete in the parent */
556 waitpid(pid, &pid_status, 0);
557 }
558
559 return 0;
560 }
561