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