1 /* 2 * wpa_supplicant/hostapd / OS specific functions for UNIX/POSIX systems 3 * Copyright (c) 2005-2006, Jouni Malinen <j (at) 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 25 void 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 34 int 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 45 int 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 int os_daemonize(const char *pid_file) 86 { 87 if (daemon(0, 0)) { 88 perror("daemon"); 89 return -1; 90 } 91 92 if (pid_file) { 93 FILE *f = fopen(pid_file, "w"); 94 if (f) { 95 fprintf(f, "%u\n", getpid()); 96 fclose(f); 97 } 98 } 99 100 return -0; 101 } 102 103 104 void os_daemonize_terminate(const char *pid_file) 105 { 106 if (pid_file) 107 unlink(pid_file); 108 } 109 110 111 int os_get_random(unsigned char *buf, size_t len) 112 { 113 FILE *f; 114 size_t rc; 115 116 f = fopen("/dev/urandom", "rb"); 117 if (f == NULL) { 118 printf("Could not open /dev/urandom.\n"); 119 return -1; 120 } 121 122 rc = fread(buf, 1, len, f); 123 fclose(f); 124 125 return rc != len ? -1 : 0; 126 } 127 128 129 unsigned long os_random(void) 130 { 131 return random(); 132 } 133 134 135 char * os_rel2abs_path(const char *rel_path) 136 { 137 char *buf = NULL, *cwd, *ret; 138 size_t len = 128, cwd_len, rel_len, ret_len; 139 int last_errno; 140 141 if (rel_path[0] == '/') 142 return strdup(rel_path); 143 144 for (;;) { 145 buf = malloc(len); 146 if (buf == NULL) 147 return NULL; 148 cwd = getcwd(buf, len); 149 if (cwd == NULL) { 150 last_errno = errno; 151 free(buf); 152 if (last_errno != ERANGE) 153 return NULL; 154 len *= 2; 155 if (len > 2000) 156 return NULL; 157 } else { 158 buf[len - 1] = '\0'; 159 break; 160 } 161 } 162 163 cwd_len = strlen(cwd); 164 rel_len = strlen(rel_path); 165 ret_len = cwd_len + 1 + rel_len + 1; 166 ret = malloc(ret_len); 167 if (ret) { 168 memcpy(ret, cwd, cwd_len); 169 ret[cwd_len] = '/'; 170 memcpy(ret + cwd_len + 1, rel_path, rel_len); 171 ret[ret_len - 1] = '\0'; 172 } 173 free(buf); 174 return ret; 175 } 176 177 178 int os_program_init(void) 179 { 180 #ifdef ANDROID 181 /* We ignore errors here since errors are normal if we 182 * are already running as non-root. 183 */ 184 gid_t groups[] = { AID_INET, AID_WIFI }; 185 setgroups(sizeof(groups)/sizeof(groups[0]), groups); 186 187 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 188 189 setgid(AID_WIFI); 190 setuid(AID_WIFI); 191 192 struct __user_cap_header_struct header; 193 struct __user_cap_data_struct cap; 194 header.version = _LINUX_CAPABILITY_VERSION; 195 header.pid = 0; 196 cap.effective = cap.permitted = 197 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW); 198 cap.inheritable = 0; 199 capset(&header, &cap); 200 #endif 201 202 return 0; 203 } 204 205 206 void os_program_deinit(void) 207 { 208 } 209 210 211 int os_setenv(const char *name, const char *value, int overwrite) 212 { 213 return setenv(name, value, overwrite); 214 } 215 216 217 int os_unsetenv(const char *name) 218 { 219 #if defined(__FreeBSD__) || defined(__NetBSD__) 220 unsetenv(name); 221 return 0; 222 #else 223 return unsetenv(name); 224 #endif 225 } 226 227 228 char * os_readfile(const char *name, size_t *len) 229 { 230 FILE *f; 231 char *buf; 232 233 f = fopen(name, "rb"); 234 if (f == NULL) 235 return NULL; 236 237 fseek(f, 0, SEEK_END); 238 *len = ftell(f); 239 fseek(f, 0, SEEK_SET); 240 241 buf = malloc(*len); 242 if (buf == NULL) { 243 fclose(f); 244 return NULL; 245 } 246 247 if (fread(buf, 1, *len, f) != *len) { 248 fclose(f); 249 free(buf); 250 return NULL; 251 } 252 253 fclose(f); 254 255 return buf; 256 } 257 258 259 void * os_zalloc(size_t size) 260 { 261 return calloc(1, size); 262 } 263