1 /*
2 * wpa_supplicant/hostapd / common helper functions, etc.
3 * Copyright (c) 2002-2007, 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 "utils/includes.h"
10
11 #include "utils/common.h"
12 #include <time.h>
13
14 extern time_t mktime(struct tm*);
15
16 /**
17 * inc_byte_array - Increment arbitrary length byte array by one
18 * @counter: Pointer to byte array
19 * @len: Length of the counter in bytes
20 *
21 * This function increments the last byte of the counter by one and continues
22 * rolling over to more significant bytes if the byte was incremented from
23 * 0xff to 0x00.
24 */
inc_byte_array(u8 * counter,size_t len)25 void inc_byte_array(u8 *counter, size_t len)
26 {
27 int pos = len - 1;
28 while (pos >= 0) {
29 counter[pos]++;
30 if (counter[pos] != 0)
31 break;
32 pos--;
33 }
34 }
35
hex2num(char c)36 static int hex2num(char c)
37 {
38 if (c >= '0' && c <= '9')
39 return c - '0';
40 if (c >= 'a' && c <= 'f')
41 return c - 'a' + 10;
42 if (c >= 'A' && c <= 'F')
43 return c - 'A' + 10;
44 return -1;
45 }
46
47
hex2byte(const char * hex)48 int hex2byte(const char *hex)
49 {
50 int a, b;
51 a = hex2num(*hex++);
52 if (a < 0)
53 return -1;
54 b = hex2num(*hex++);
55 if (b < 0)
56 return -1;
57 return (a << 4) | b;
58 }
59
60
61 /**
62 * hexstr2bin - Convert ASCII hex string into binary data
63 * @hex: ASCII hex string (e.g., "01ab")
64 * @buf: Buffer for the binary data
65 * @len: Length of the text to convert in bytes (of buf); hex will be double
66 * this size
67 * Returns: 0 on success, -1 on failure (invalid hex string)
68 */
hexstr2bin(const char * hex,u8 * buf,size_t len)69 int hexstr2bin(const char *hex, u8 *buf, size_t len)
70 {
71 size_t i;
72 int a;
73 const char *ipos = hex;
74 u8 *opos = buf;
75
76 for (i = 0; i < len; i++) {
77 a = hex2byte(ipos);
78 if (a < 0)
79 return -1;
80 *opos++ = a;
81 ipos += 2;
82 }
83 return 0;
84 }
85
wpa_get_ntp_timestamp(u8 * buf)86 void wpa_get_ntp_timestamp(u8 *buf)
87 {
88 struct os_time now;
89 u32 sec, usec;
90 be32 tmp;
91
92 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
93 os_get_time(&now);
94 sec = now.sec + 2208988800U; /* Epoch to 1900 */
95 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
96 usec = now.usec;
97 usec = 4295 * usec - (usec >> 5) - (usec >> 9);
98 tmp = host_to_be32(sec);
99 os_memcpy(buf, (u8 *) &tmp, 4);
100 tmp = host_to_be32(usec);
101 os_memcpy(buf + 4, (u8 *) &tmp, 4);
102 }
printf_encode(char * txt,size_t maxlen,const u8 * data,size_t len)103 void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
104 {
105 char *end = txt + maxlen;
106 size_t i;
107
108 for (i = 0; i < len; i++) {
109 if (txt + 4 >= end)
110 break;
111
112 switch (data[i]) {
113 case '\"':
114 *txt++ = '\\';
115 *txt++ = '\"';
116 break;
117 case '\\':
118 *txt++ = '\\';
119 *txt++ = '\\';
120 break;
121 case '\033':
122 *txt++ = '\\';
123 *txt++ = 'e';
124 break;
125 case '\n':
126 *txt++ = '\\';
127 *txt++ = 'n';
128 break;
129 case '\r':
130 *txt++ = '\\';
131 *txt++ = 'r';
132 break;
133 case '\t':
134 *txt++ = '\\';
135 *txt++ = 't';
136 break;
137 default:
138 if (data[i] >= 32 && data[i] <= 127) {
139 *txt++ = data[i];
140 } else {
141 txt += os_snprintf(txt, end - txt, "\\x%02x",
142 data[i]);
143 }
144 break;
145 }
146 }
147
148 *txt = '\0';
149 }
150
151
printf_decode(u8 * buf,size_t maxlen,const char * str)152 size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
153 {
154 const char *pos = str;
155 size_t len = 0;
156 int val;
157
158 while (*pos) {
159 if (len + 1 >= maxlen)
160 break;
161 switch (*pos) {
162 case '\\':
163 pos++;
164 switch (*pos) {
165 case '\\':
166 buf[len++] = '\\';
167 pos++;
168 break;
169 case '"':
170 buf[len++] = '"';
171 pos++;
172 break;
173 case 'n':
174 buf[len++] = '\n';
175 pos++;
176 break;
177 case 'r':
178 buf[len++] = '\r';
179 pos++;
180 break;
181 case 't':
182 buf[len++] = '\t';
183 pos++;
184 break;
185 case 'e':
186 buf[len++] = '\033';
187 pos++;
188 break;
189 case 'x':
190 pos++;
191 val = hex2byte(pos);
192 if (val < 0) {
193 val = hex2num(*pos);
194 if (val < 0)
195 break;
196 buf[len++] = val;
197 pos++;
198 } else {
199 buf[len++] = val;
200 pos += 2;
201 }
202 break;
203 case '0':
204 case '1':
205 case '2':
206 case '3':
207 case '4':
208 case '5':
209 case '6':
210 case '7':
211 val = *pos++ - '0';
212 if (*pos >= '0' && *pos <= '7')
213 val = val * 8 + (*pos++ - '0');
214 if (*pos >= '0' && *pos <= '7')
215 val = val * 8 + (*pos++ - '0');
216 buf[len++] = val;
217 break;
218 default:
219 break;
220 }
221 break;
222 default:
223 buf[len++] = *pos++;
224 break;
225 }
226 }
227 if (maxlen > len)
228 buf[len] = '\0';
229
230 return len;
231 }
232
233
234
wpa_config_parse_string(const char * value,size_t * len)235 char * wpa_config_parse_string(const char *value, size_t *len)
236 {
237 if (*value == '"') {
238 const char *pos;
239 char *str;
240 value++;
241 pos = os_strrchr(value, '"');
242 if (pos == NULL || pos[1] != '\0')
243 return NULL;
244 *len = pos - value;
245 str = dup_binstr(value, *len);
246 if (str == NULL)
247 return NULL;
248 return str;
249 } else if (*value == 'P' && value[1] == '"') {
250 const char *pos;
251 char *tstr, *str;
252 size_t tlen;
253 value += 2;
254 pos = os_strrchr(value, '"');
255 if (pos == NULL || pos[1] != '\0')
256 return NULL;
257 tlen = pos - value;
258 tstr = dup_binstr(value, tlen);
259 if (tstr == NULL)
260 return NULL;
261
262 str = os_malloc(tlen + 1);
263 if (str == NULL) {
264 os_free(tstr);
265 return NULL;
266 }
267
268 *len = printf_decode((u8 *) str, tlen + 1, tstr);
269 os_free(tstr);
270
271 return str;
272 } else {
273 u8 *str;
274 size_t tlen, hlen = os_strlen(value);
275 #ifndef ESP_SUPPLICANT
276 if (hlen & 1)
277 return NULL;
278 #else
279 if (hlen == 5 || hlen == 13) {
280 *len = hlen;
281 str = (u8 *)os_malloc(*len + 1);
282 if (str == NULL) {
283 return NULL;
284 }
285 memcpy(str, value, *len);
286 str[*len] = '\0';
287 return (char *) str;
288 }
289 #endif
290 tlen = hlen / 2;
291 str = os_malloc(tlen + 1);
292 if (str == NULL)
293 return NULL;
294 if (hexstr2bin(value, str, tlen)) {
295 os_free(str);
296 return NULL;
297 }
298 str[tlen] = '\0';
299 *len = tlen;
300 return (char *) str;
301 }
302 }
303
304
wpa_is_hex(const u8 * data,size_t len)305 int wpa_is_hex(const u8 *data, size_t len)
306 {
307 size_t i;
308
309 for (i = 0; i < len; i++) {
310 if (data[i] < 32 || data[i] >= 127)
311 return 1;
312 }
313 return 0;
314 }
315
316
wpa_merge_byte_arrays(u8 * res,size_t res_len,const u8 * src1,size_t src1_len,const u8 * src2,size_t src2_len)317 size_t wpa_merge_byte_arrays(u8 *res, size_t res_len,
318 const u8 *src1, size_t src1_len,
319 const u8 *src2, size_t src2_len)
320 {
321 size_t len = 0;
322
323 os_memset(res, 0, res_len);
324
325 if (src1) {
326 if (src1_len >= res_len) {
327 os_memcpy(res, src1, res_len);
328 return res_len;
329 }
330
331 os_memcpy(res, src1, src1_len);
332 len += src1_len;
333 }
334
335 if (src2) {
336 if (len + src2_len >= res_len) {
337 os_memcpy(res + len, src2, res_len - len);
338 return res_len;
339 }
340
341 os_memcpy(res + len, src2, src2_len);
342 len += src2_len;
343 }
344
345 return len;
346 }
347
348
dup_binstr(const void * src,size_t len)349 char * dup_binstr(const void *src, size_t len)
350 {
351 char *res;
352
353 if (src == NULL)
354 return NULL;
355 res = os_malloc(len + 1);
356 if (res == NULL)
357 return NULL;
358 os_memcpy(res, src, len);
359 res[len] = '\0';
360
361 return res;
362 }
wpa_bin_clear_free(void * bin,size_t len)363 void wpa_bin_clear_free(void *bin, size_t len)
364 {
365 if (bin) {
366 os_memset(bin, 0, len);
367 os_free(bin);
368 }
369 }
370
int_array_len(const int * a)371 int int_array_len(const int *a)
372 {
373 int i;
374 for (i = 0; a && a[i]; i++)
375 ;
376 return i;
377 }
378
bin_clear_free(void * bin,size_t len)379 void bin_clear_free(void *bin, size_t len)
380 {
381 if (bin) {
382 os_memset(bin, 0, len);
383 os_free(bin);
384 }
385 }
386
str_clear_free(char * str)387 void str_clear_free(char *str)
388 {
389 if (str) {
390 size_t len = os_strlen(str);
391 os_memset(str, 0, len);
392 os_free(str);
393 }
394 }
395
os_gmtime(os_time_t t,struct os_tm * tm)396 int os_gmtime(os_time_t t, struct os_tm *tm)
397 {
398 struct tm *tm2;
399 time_t t2 = t;
400
401 tm2 = gmtime(&t2);
402 if (tm2 == NULL)
403 return -1;
404 tm->sec = tm2->tm_sec;
405 tm->min = tm2->tm_min;
406 tm->hour = tm2->tm_hour;
407 tm->day = tm2->tm_mday;
408 tm->month = tm2->tm_mon + 1;
409 tm->year = tm2->tm_year + 1900;
410 return 0;
411 }
412
os_mktime(int year,int month,int day,int hour,int min,int sec,os_time_t * t)413 int os_mktime(int year, int month, int day, int hour, int min, int sec,
414 os_time_t *t)
415 {
416 struct tm tm;
417
418 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
419 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
420 sec > 60)
421 return -1;
422
423 os_memset(&tm, 0, sizeof(tm));
424 tm.tm_year = year - 1900;
425 tm.tm_mon = month - 1;
426 tm.tm_mday = day;
427 tm.tm_hour = hour;
428 tm.tm_min = min;
429 tm.tm_sec = sec;
430
431 *t = (os_time_t) mktime(&tm);
432 return 0;
433 }
434
get_param(const char * cmd,const char * param)435 char * get_param(const char *cmd, const char *param)
436 {
437 const char *pos, *end;
438 char *val;
439 size_t len;
440
441 pos = os_strstr(cmd, param);
442 if (!pos)
443 return NULL;
444
445 pos += os_strlen(param);
446 end = os_strchr(pos, ' ');
447 if (end)
448 len = end - pos;
449 else
450 len = os_strlen(pos);
451 val = os_malloc(len + 1);
452 if (!val)
453 return NULL;
454 os_memcpy(val, pos, len);
455 val[len] = '\0';
456 return val;
457 }
458
os_memdup(const void * src,size_t len)459 void * os_memdup(const void *src, size_t len)
460 {
461 void *r = os_malloc(len);
462
463 if (r && src)
464 os_memcpy(r, src, len);
465 return r;
466 }
467
468 /**
469 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
470 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
471 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
472 * Returns: Characters used (> 0) on success, -1 on failure
473 */
hwaddr_aton2(const char * txt,u8 * addr)474 int hwaddr_aton2(const char *txt, u8 *addr)
475 {
476 int i;
477 const char *pos = txt;
478
479 for (i = 0; i < 6; i++) {
480 int a, b;
481
482 while (*pos == ':' || *pos == '.' || *pos == '-')
483 pos++;
484
485 a = hex2num(*pos++);
486 if (a < 0)
487 return -1;
488 b = hex2num(*pos++);
489 if (b < 0)
490 return -1;
491 *addr++ = (a << 4) | b;
492 }
493
494 return pos - txt;
495 }
496
os_reltime_expired(struct os_time * now,struct os_time * ts,os_time_t timeout_secs)497 static inline int os_reltime_expired(struct os_time *now,
498 struct os_time *ts,
499 os_time_t timeout_secs)
500 {
501 struct os_time age;
502
503 os_time_sub(now, ts, &age);
504 return (age.sec > timeout_secs) ||
505 (age.sec == timeout_secs && age.usec > 0);
506 }
507
os_time_expired(struct os_time * now,struct os_time * ts,os_time_t timeout_secs)508 int os_time_expired(struct os_time *now,
509 struct os_time *ts,
510 os_time_t timeout_secs)
511 {
512 return os_reltime_expired(now, ts, timeout_secs);
513 }
514
rssi_to_rcpi(int rssi)515 u8 rssi_to_rcpi(int rssi)
516 {
517 if (!rssi)
518 return 255; /* not available */
519 if (rssi < -110)
520 return 0;
521 if (rssi > 0)
522 return 220;
523 return (rssi + 110) * 2;
524 }
525
526 /**
527 * wpa_ssid_txt - Convert SSID to a printable string
528 * @ssid: SSID (32-octet string)
529 * @ssid_len: Length of ssid in octets
530 * Returns: Pointer to a printable string
531 *
532 * This function can be used to convert SSIDs into printable form. In most
533 * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
534 * does not limit the used character set, so anything could be used in an SSID.
535 *
536 * This function uses a static buffer, so only one call can be used at the
537 * time, i.e., this is not re-entrant and the returned buffer must be used
538 * before calling this again.
539 */
wpa_ssid_txt(const u8 * ssid,size_t ssid_len)540 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
541 {
542 static char ssid_txt[SSID_MAX_LEN * 4 + 1];
543
544 if (ssid == NULL) {
545 ssid_txt[0] = '\0';
546 return ssid_txt;
547 }
548
549 printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
550 return ssid_txt;
551 }
552
__hide_aliasing_typecast(void * foo)553 void * __hide_aliasing_typecast(void *foo)
554 {
555 return foo;
556 }
557