1/* 2 * wpa_supplicant/hostapd / OS specific functions for UNIX/POSIX systems 3 * Copyright (c) 2005-2006, 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 "os.h" 18 19#ifdef ANDROID 20#include <linux/capability.h> 21#include <linux/prctl.h> 22#include <private/android_filesystem_config.h> 23#endif 24 25void os_sleep(os_time_t sec, os_time_t usec) 26{ 27 if (sec) 28 sleep(sec); 29 if (usec) 30 usleep(usec); 31} 32 33 34int os_get_time(struct os_time *t) 35{ 36 int res; 37 struct timeval tv; 38 res = gettimeofday(&tv, NULL); 39 t->sec = tv.tv_sec; 40 t->usec = tv.tv_usec; 41 return res; 42} 43 44 45int os_mktime(int year, int month, int day, int hour, int min, int sec, 46 os_time_t *t) 47{ 48 struct tm tm, *tm1; 49 time_t t_local, t1, t2; 50 os_time_t tz_offset; 51 52 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || 53 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || 54 sec > 60) 55 return -1; 56 57 memset(&tm, 0, sizeof(tm)); 58 tm.tm_year = year - 1900; 59 tm.tm_mon = month - 1; 60 tm.tm_mday = day; 61 tm.tm_hour = hour; 62 tm.tm_min = min; 63 tm.tm_sec = sec; 64 65 t_local = mktime(&tm); 66 67 /* figure out offset to UTC */ 68 tm1 = localtime(&t_local); 69 if (tm1) { 70 t1 = mktime(tm1); 71 tm1 = gmtime(&t_local); 72 if (tm1) { 73 t2 = mktime(tm1); 74 tz_offset = t2 - t1; 75 } else 76 tz_offset = 0; 77 } else 78 tz_offset = 0; 79 80 *t = (os_time_t) t_local - tz_offset; 81 return 0; 82} 83 84 85#ifdef __APPLE__ 86#include <fcntl.h> 87static int os_daemon(int nochdir, int noclose) 88{ 89 int devnull; 90 91 if (chdir("/") < 0) 92 return -1; 93 94 devnull = open("/dev/null", O_RDWR); 95 if (devnull < 0) 96 return -1; 97 98 if (dup2(devnull, STDIN_FILENO) < 0) { 99 close(devnull); 100 return -1; 101 } 102 103 if (dup2(devnull, STDOUT_FILENO) < 0) { 104 close(devnull); 105 return -1; 106 } 107 108 if (dup2(devnull, STDERR_FILENO) < 0) { 109 close(devnull); 110 return -1; 111 } 112 113 return 0; 114} 115#else /* __APPLE__ */ 116#define os_daemon daemon 117#endif /* __APPLE__ */ 118 119 120int os_daemonize(const char *pid_file) 121{ 122#ifdef __uClinux__ 123 return -1; 124#else /* __uClinux__ */ 125 if (os_daemon(0, 0)) { 126 perror("daemon"); 127 return -1; 128 } 129 130 if (pid_file) { 131 FILE *f = fopen(pid_file, "w"); 132 if (f) { 133 fprintf(f, "%u\n", getpid()); 134 fclose(f); 135 } 136 } 137 138 return -0; 139#endif /* __uClinux__ */ 140} 141 142 143void os_daemonize_terminate(const char *pid_file) 144{ 145 if (pid_file) 146 unlink(pid_file); 147} 148 149 150int os_get_random(unsigned char *buf, size_t len) 151{ 152 FILE *f; 153 size_t rc; 154 155 f = fopen("/dev/urandom", "rb"); 156 if (f == NULL) { 157 printf("Could not open /dev/urandom.\n"); 158 return -1; 159 } 160 161 rc = fread(buf, 1, len, f); 162 fclose(f); 163 164 return rc != len ? -1 : 0; 165} 166 167 168unsigned long os_random(void) 169{ 170 return random(); 171} 172 173 174char * os_rel2abs_path(const char *rel_path) 175{ 176 char *buf = NULL, *cwd, *ret; 177 size_t len = 128, cwd_len, rel_len, ret_len; 178 int last_errno; 179 180 if (rel_path[0] == '/') 181 return strdup(rel_path); 182 183 for (;;) { 184 buf = malloc(len); 185 if (buf == NULL) 186 return NULL; 187 cwd = getcwd(buf, len); 188 if (cwd == NULL) { 189 last_errno = errno; 190 free(buf); 191 if (last_errno != ERANGE) 192 return NULL; 193 len *= 2; 194 if (len > 2000) 195 return NULL; 196 } else { 197 buf[len - 1] = '\0'; 198 break; 199 } 200 } 201 202 cwd_len = strlen(cwd); 203 rel_len = strlen(rel_path); 204 ret_len = cwd_len + 1 + rel_len + 1; 205 ret = malloc(ret_len); 206 if (ret) { 207 memcpy(ret, cwd, cwd_len); 208 ret[cwd_len] = '/'; 209 memcpy(ret + cwd_len + 1, rel_path, rel_len); 210 ret[ret_len - 1] = '\0'; 211 } 212 free(buf); 213 return ret; 214} 215 216 217int os_program_init(void) 218{ 219#ifdef ANDROID 220 /* We ignore errors here since errors are normal if we 221 * are already running as non-root. 222 */ 223 gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE }; 224 setgroups(sizeof(groups)/sizeof(groups[0]), groups); 225 226 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 227 228 setgid(AID_WIFI); 229 setuid(AID_WIFI); 230 231 struct __user_cap_header_struct header; 232 struct __user_cap_data_struct cap; 233 header.version = _LINUX_CAPABILITY_VERSION; 234 header.pid = 0; 235 cap.effective = cap.permitted = 236 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW); 237 cap.inheritable = 0; 238 capset(&header, &cap); 239#endif 240 241 return 0; 242} 243 244 245void os_program_deinit(void) 246{ 247} 248 249 250int os_setenv(const char *name, const char *value, int overwrite) 251{ 252 return setenv(name, value, overwrite); 253} 254 255 256int os_unsetenv(const char *name) 257{ 258#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \ 259 defined(__OpenBSD__) 260 unsetenv(name); 261 return 0; 262#else 263 return unsetenv(name); 264#endif 265} 266 267 268char * os_readfile(const char *name, size_t *len) 269{ 270 FILE *f; 271 char *buf; 272 273 f = fopen(name, "rb"); 274 if (f == NULL) 275 return NULL; 276 277 fseek(f, 0, SEEK_END); 278 *len = ftell(f); 279 fseek(f, 0, SEEK_SET); 280 281 buf = malloc(*len); 282 if (buf == NULL) { 283 fclose(f); 284 return NULL; 285 } 286 287 if (fread(buf, 1, *len, f) != *len) { 288 fclose(f); 289 free(buf); 290 return NULL; 291 } 292 293 fclose(f); 294 295 return buf; 296} 297 298 299void * os_zalloc(size_t size) 300{ 301 return calloc(1, size); 302} 303 304 305size_t os_strlcpy(char *dest, const char *src, size_t siz) 306{ 307 const char *s = src; 308 size_t left = siz; 309 310 if (left) { 311 /* Copy string up to the maximum size of the dest buffer */ 312 while (--left != 0) { 313 if ((*dest++ = *s++) == '\0') 314 break; 315 } 316 } 317 318 if (left == 0) { 319 /* Not enough room for the string; force NUL-termination */ 320 if (siz != 0) 321 *dest = '\0'; 322 while (*s++) 323 ; /* determine total src string length */ 324 } 325 326 return s - src - 1; 327} 328