• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * wpa_supplicant/hostapd / common helper functions, etc.
3  * Copyright (c) 2002-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 "common.h"
18 
19 
20 #ifdef CONFIG_DEBUG_FILE
21 static FILE *out_file = NULL;
22 #endif /* CONFIG_DEBUG_FILE */
23 int wpa_debug_level = MSG_INFO;
24 int wpa_debug_show_keys = 0;
25 int wpa_debug_timestamp = 0;
26 
27 
hex2num(char c)28 static int hex2num(char c)
29 {
30 	if (c >= '0' && c <= '9')
31 		return c - '0';
32 	if (c >= 'a' && c <= 'f')
33 		return c - 'a' + 10;
34 	if (c >= 'A' && c <= 'F')
35 		return c - 'A' + 10;
36 	return -1;
37 }
38 
39 
hex2byte(const char * hex)40 static int hex2byte(const char *hex)
41 {
42 	int a, b;
43 	a = hex2num(*hex++);
44 	if (a < 0)
45 		return -1;
46 	b = hex2num(*hex++);
47 	if (b < 0)
48 		return -1;
49 	return (a << 4) | b;
50 }
51 
52 
53 /**
54  * hwaddr_aton - Convert ASCII string to MAC address
55  * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
56  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
57  * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
58  */
hwaddr_aton(const char * txt,u8 * addr)59 int hwaddr_aton(const char *txt, u8 *addr)
60 {
61 	int i;
62 
63 	for (i = 0; i < 6; i++) {
64 		int a, b;
65 
66 		a = hex2num(*txt++);
67 		if (a < 0)
68 			return -1;
69 		b = hex2num(*txt++);
70 		if (b < 0)
71 			return -1;
72 		*addr++ = (a << 4) | b;
73 		if (i < 5 && *txt++ != ':')
74 			return -1;
75 	}
76 
77 	return 0;
78 }
79 
80 
81 /**
82  * hexstr2bin - Convert ASCII hex string into binary data
83  * @hex: ASCII hex string (e.g., "01ab")
84  * @buf: Buffer for the binary data
85  * @len: Length of the text to convert in bytes (of buf); hex will be double
86  * this size
87  * Returns: 0 on success, -1 on failure (invalid hex string)
88  */
hexstr2bin(const char * hex,u8 * buf,size_t len)89 int hexstr2bin(const char *hex, u8 *buf, size_t len)
90 {
91 	size_t i;
92 	int a;
93 	const char *ipos = hex;
94 	u8 *opos = buf;
95 
96 	for (i = 0; i < len; i++) {
97 		a = hex2byte(ipos);
98 		if (a < 0)
99 			return -1;
100 		*opos++ = a;
101 		ipos += 2;
102 	}
103 	return 0;
104 }
105 
106 
107 /**
108  * inc_byte_array - Increment arbitrary length byte array by one
109  * @counter: Pointer to byte array
110  * @len: Length of the counter in bytes
111  *
112  * This function increments the last byte of the counter by one and continues
113  * rolling over to more significant bytes if the byte was incremented from
114  * 0xff to 0x00.
115  */
inc_byte_array(u8 * counter,size_t len)116 void inc_byte_array(u8 *counter, size_t len)
117 {
118 	int pos = len - 1;
119 	while (pos >= 0) {
120 		counter[pos]++;
121 		if (counter[pos] != 0)
122 			break;
123 		pos--;
124 	}
125 }
126 
127 
wpa_get_ntp_timestamp(u8 * buf)128 void wpa_get_ntp_timestamp(u8 *buf)
129 {
130 	struct os_time now;
131 	u32 sec, usec;
132 
133 	/* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
134 	os_get_time(&now);
135 	sec = host_to_be32(now.sec + 2208988800U); /* Epoch to 1900 */
136 	/* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
137 	usec = now.usec;
138 	usec = host_to_be32(4295 * usec - (usec >> 5) - (usec >> 9));
139 	os_memcpy(buf, (u8 *) &sec, 4);
140 	os_memcpy(buf + 4, (u8 *) &usec, 4);
141 }
142 
143 #ifdef ANDROID
144 
145 #include <android/log.h>
146 
android_printf(int level,char * format,...)147 void android_printf(int level, char *format, ...)
148 {
149 	if (level >= wpa_debug_level) {
150 		va_list ap;
151 		if (level == MSG_ERROR) {
152 			level = ANDROID_LOG_ERROR;
153 		} else if (level == MSG_WARNING) {
154 			level = ANDROID_LOG_WARN;
155 		} else if (level == MSG_INFO) {
156 			level = ANDROID_LOG_INFO;
157 		} else {
158 			level = ANDROID_LOG_DEBUG;
159 		}
160 		va_start(ap, format);
161 		__android_log_vprint(level, "wpa_supplicant", format, ap);
162 		va_end(ap);
163 	}
164 }
165 
166 #else /* ANDROID */
167 
168 #ifndef CONFIG_NO_STDOUT_DEBUG
169 
wpa_debug_print_timestamp(void)170 void wpa_debug_print_timestamp(void)
171 {
172 	struct os_time tv;
173 
174 	if (!wpa_debug_timestamp)
175 		return;
176 
177 	os_get_time(&tv);
178 #ifdef CONFIG_DEBUG_FILE
179 	if (out_file) {
180 		fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
181 			(unsigned int) tv.usec);
182 	} else
183 #endif /* CONFIG_DEBUG_FILE */
184 	printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
185 }
186 
187 
188 /**
189  * wpa_printf - conditional printf
190  * @level: priority level (MSG_*) of the message
191  * @fmt: printf format string, followed by optional arguments
192  *
193  * This function is used to print conditional debugging and error messages. The
194  * output may be directed to stdout, stderr, and/or syslog based on
195  * configuration.
196  *
197  * Note: New line '\n' is added to the end of the text when printing to stdout.
198  */
wpa_printf(int level,char * fmt,...)199 void wpa_printf(int level, char *fmt, ...)
200 {
201 	va_list ap;
202 
203 	va_start(ap, fmt);
204 	if (level >= wpa_debug_level) {
205 		wpa_debug_print_timestamp();
206 #ifdef CONFIG_DEBUG_FILE
207 		if (out_file) {
208 			vfprintf(out_file, fmt, ap);
209 			fprintf(out_file, "\n");
210 		} else {
211 #endif /* CONFIG_DEBUG_FILE */
212 		vprintf(fmt, ap);
213 		printf("\n");
214 #ifdef CONFIG_DEBUG_FILE
215 		}
216 #endif /* CONFIG_DEBUG_FILE */
217 	}
218 	va_end(ap);
219 }
220 
221 
_wpa_hexdump(int level,const char * title,const u8 * buf,size_t len,int show)222 static void _wpa_hexdump(int level, const char *title, const u8 *buf,
223 			 size_t len, int show)
224 {
225 	size_t i;
226 	if (level < wpa_debug_level)
227 		return;
228 	wpa_debug_print_timestamp();
229 #ifdef CONFIG_DEBUG_FILE
230 	if (out_file) {
231 		fprintf(out_file, "%s - hexdump(len=%lu):",
232 			title, (unsigned long) len);
233 		if (buf == NULL) {
234 			fprintf(out_file, " [NULL]");
235 		} else if (show) {
236 			for (i = 0; i < len; i++)
237 				fprintf(out_file, " %02x", buf[i]);
238 		} else {
239 			fprintf(out_file, " [REMOVED]");
240 		}
241 		fprintf(out_file, "\n");
242 	} else {
243 #endif /* CONFIG_DEBUG_FILE */
244 	printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
245 	if (buf == NULL) {
246 		printf(" [NULL]");
247 	} else if (show) {
248 		for (i = 0; i < len; i++)
249 			printf(" %02x", buf[i]);
250 	} else {
251 		printf(" [REMOVED]");
252 	}
253 	printf("\n");
254 #ifdef CONFIG_DEBUG_FILE
255 	}
256 #endif /* CONFIG_DEBUG_FILE */
257 }
258 
wpa_hexdump(int level,const char * title,const u8 * buf,size_t len)259 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
260 {
261 	_wpa_hexdump(level, title, buf, len, 1);
262 }
263 
264 
wpa_hexdump_key(int level,const char * title,const u8 * buf,size_t len)265 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
266 {
267 	_wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
268 }
269 
270 
_wpa_hexdump_ascii(int level,const char * title,const u8 * buf,size_t len,int show)271 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
272 			       size_t len, int show)
273 {
274 	size_t i, llen;
275 	const u8 *pos = buf;
276 	const size_t line_len = 16;
277 
278 	if (level < wpa_debug_level)
279 		return;
280 	wpa_debug_print_timestamp();
281 #ifdef CONFIG_DEBUG_FILE
282 	if (out_file) {
283 		if (!show) {
284 			fprintf(out_file,
285 				"%s - hexdump_ascii(len=%lu): [REMOVED]\n",
286 				title, (unsigned long) len);
287 			return;
288 		}
289 		if (buf == NULL) {
290 			fprintf(out_file,
291 				"%s - hexdump_ascii(len=%lu): [NULL]\n",
292 				title, (unsigned long) len);
293 			return;
294 		}
295 		fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
296 			title, (unsigned long) len);
297 		while (len) {
298 			llen = len > line_len ? line_len : len;
299 			fprintf(out_file, "    ");
300 			for (i = 0; i < llen; i++)
301 				fprintf(out_file, " %02x", pos[i]);
302 			for (i = llen; i < line_len; i++)
303 				fprintf(out_file, "   ");
304 			fprintf(out_file, "   ");
305 			for (i = 0; i < llen; i++) {
306 				if (isprint(pos[i]))
307 					fprintf(out_file, "%c", pos[i]);
308 				else
309 					fprintf(out_file, "_");
310 			}
311 			for (i = llen; i < line_len; i++)
312 				fprintf(out_file, " ");
313 			fprintf(out_file, "\n");
314 			pos += llen;
315 			len -= llen;
316 		}
317 	} else {
318 #endif /* CONFIG_DEBUG_FILE */
319 	if (!show) {
320 		printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
321 		       title, (unsigned long) len);
322 		return;
323 	}
324 	if (buf == NULL) {
325 		printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
326 		       title, (unsigned long) len);
327 		return;
328 	}
329 	printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
330 	while (len) {
331 		llen = len > line_len ? line_len : len;
332 		printf("    ");
333 		for (i = 0; i < llen; i++)
334 			printf(" %02x", pos[i]);
335 		for (i = llen; i < line_len; i++)
336 			printf("   ");
337 		printf("   ");
338 		for (i = 0; i < llen; i++) {
339 			if (isprint(pos[i]))
340 				printf("%c", pos[i]);
341 			else
342 				printf("_");
343 		}
344 		for (i = llen; i < line_len; i++)
345 			printf(" ");
346 		printf("\n");
347 		pos += llen;
348 		len -= llen;
349 	}
350 #ifdef CONFIG_DEBUG_FILE
351 	}
352 #endif /* CONFIG_DEBUG_FILE */
353 }
354 
355 
wpa_hexdump_ascii(int level,const char * title,const u8 * buf,size_t len)356 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
357 {
358 	_wpa_hexdump_ascii(level, title, buf, len, 1);
359 }
360 
361 
wpa_hexdump_ascii_key(int level,const char * title,const u8 * buf,size_t len)362 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
363 			   size_t len)
364 {
365 	_wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
366 }
367 
368 
wpa_debug_open_file(const char * path)369 int wpa_debug_open_file(const char *path)
370 {
371 #ifdef CONFIG_DEBUG_FILE
372 	if (!path)
373 		return 0;
374 	out_file = fopen(path, "a");
375 	if (out_file == NULL) {
376 		wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
377 			   "output file, using standard output");
378 		return -1;
379 	}
380 #ifndef _WIN32
381 	setvbuf(out_file, NULL, _IOLBF, 0);
382 #endif /* _WIN32 */
383 #endif /* CONFIG_DEBUG_FILE */
384 	return 0;
385 }
386 
387 
wpa_debug_close_file(void)388 void wpa_debug_close_file(void)
389 {
390 #ifdef CONFIG_DEBUG_FILE
391 	if (!out_file)
392 		return;
393 	fclose(out_file);
394 	out_file = NULL;
395 #endif /* CONFIG_DEBUG_FILE */
396 }
397 
398 #endif /* CONFIG_NO_STDOUT_DEBUG */
399 
400 #endif /* ANDROID */
401 
402 #ifndef CONFIG_NO_WPA_MSG
403 static wpa_msg_cb_func wpa_msg_cb = NULL;
404 
wpa_msg_register_cb(wpa_msg_cb_func func)405 void wpa_msg_register_cb(wpa_msg_cb_func func)
406 {
407 	wpa_msg_cb = func;
408 }
409 
410 
wpa_msg(void * ctx,int level,char * fmt,...)411 void wpa_msg(void *ctx, int level, char *fmt, ...)
412 {
413 	va_list ap;
414 	char *buf;
415 	const int buflen = 2048;
416 	int len;
417 
418 	buf = os_malloc(buflen);
419 	if (buf == NULL) {
420 		wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
421 			   "buffer");
422 		return;
423 	}
424 	va_start(ap, fmt);
425 	len = vsnprintf(buf, buflen, fmt, ap);
426 	va_end(ap);
427 	wpa_printf(level, "%s", buf);
428 	if (wpa_msg_cb)
429 		wpa_msg_cb(ctx, level, buf, len);
430 	os_free(buf);
431 }
432 #endif /* CONFIG_NO_WPA_MSG */
433 
434 
_wpa_snprintf_hex(char * buf,size_t buf_size,const u8 * data,size_t len,int uppercase)435 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
436 				    size_t len, int uppercase)
437 {
438 	size_t i;
439 	char *pos = buf, *end = buf + buf_size;
440 	int ret;
441 	if (buf_size == 0)
442 		return 0;
443 	for (i = 0; i < len; i++) {
444 		ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
445 				  data[i]);
446 		if (ret < 0 || ret >= end - pos) {
447 			end[-1] = '\0';
448 			return pos - buf;
449 		}
450 		pos += ret;
451 	}
452 	end[-1] = '\0';
453 	return pos - buf;
454 }
455 
456 /**
457  * wpa_snprintf_hex - Print data as a hex string into a buffer
458  * @buf: Memory area to use as the output buffer
459  * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
460  * @data: Data to be printed
461  * @len: Length of data in bytes
462  * Returns: Number of bytes written
463  */
wpa_snprintf_hex(char * buf,size_t buf_size,const u8 * data,size_t len)464 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
465 {
466 	return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
467 }
468 
469 
470 /**
471  * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf
472  * @buf: Memory area to use as the output buffer
473  * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
474  * @data: Data to be printed
475  * @len: Length of data in bytes
476  * Returns: Number of bytes written
477  */
wpa_snprintf_hex_uppercase(char * buf,size_t buf_size,const u8 * data,size_t len)478 int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
479 			       size_t len)
480 {
481 	return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
482 }
483 
484 
485 #ifdef CONFIG_ANSI_C_EXTRA
486 
487 #ifdef _WIN32_WCE
perror(const char * s)488 void perror(const char *s)
489 {
490 	wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
491 		   s, (int) GetLastError());
492 }
493 #endif /* _WIN32_WCE */
494 
495 
496 int optind = 1;
497 int optopt;
498 char *optarg;
499 
getopt(int argc,char * const argv[],const char * optstring)500 int getopt(int argc, char *const argv[], const char *optstring)
501 {
502 	static int optchr = 1;
503 	char *cp;
504 
505 	if (optchr == 1) {
506 		if (optind >= argc) {
507 			/* all arguments processed */
508 			return EOF;
509 		}
510 
511 		if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
512 			/* no option characters */
513 			return EOF;
514 		}
515 	}
516 
517 	if (os_strcmp(argv[optind], "--") == 0) {
518 		/* no more options */
519 		optind++;
520 		return EOF;
521 	}
522 
523 	optopt = argv[optind][optchr];
524 	cp = os_strchr(optstring, optopt);
525 	if (cp == NULL || optopt == ':') {
526 		if (argv[optind][++optchr] == '\0') {
527 			optchr = 1;
528 			optind++;
529 		}
530 		return '?';
531 	}
532 
533 	if (cp[1] == ':') {
534 		/* Argument required */
535 		optchr = 1;
536 		if (argv[optind][optchr + 1]) {
537 			/* No space between option and argument */
538 			optarg = &argv[optind++][optchr + 1];
539 		} else if (++optind >= argc) {
540 			/* option requires an argument */
541 			return '?';
542 		} else {
543 			/* Argument in the next argv */
544 			optarg = argv[optind++];
545 		}
546 	} else {
547 		/* No argument */
548 		if (argv[optind][++optchr] == '\0') {
549 			optchr = 1;
550 			optind++;
551 		}
552 		optarg = NULL;
553 	}
554 	return *cp;
555 }
556 #endif /* CONFIG_ANSI_C_EXTRA */
557 
558 
559 #ifdef CONFIG_NATIVE_WINDOWS
560 /**
561  * wpa_unicode2ascii_inplace - Convert unicode string into ASCII
562  * @str: Pointer to string to convert
563  *
564  * This function converts a unicode string to ASCII using the same
565  * buffer for output. If UNICODE is not set, the buffer is not
566  * modified.
567  */
wpa_unicode2ascii_inplace(TCHAR * str)568 void wpa_unicode2ascii_inplace(TCHAR *str)
569 {
570 #ifdef UNICODE
571 	char *dst = (char *) str;
572 	while (*str)
573 		*dst++ = (char) *str++;
574 	*dst = '\0';
575 #endif /* UNICODE */
576 }
577 
578 
wpa_strdup_tchar(const char * str)579 TCHAR * wpa_strdup_tchar(const char *str)
580 {
581 #ifdef UNICODE
582 	TCHAR *buf;
583 	buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
584 	if (buf == NULL)
585 		return NULL;
586 	wsprintf(buf, L"%S", str);
587 	return buf;
588 #else /* UNICODE */
589 	return os_strdup(str);
590 #endif /* UNICODE */
591 }
592 #endif /* CONFIG_NATIVE_WINDOWS */
593 
594 
595 /**
596  * wpa_ssid_txt - Convert SSID to a printable string
597  * @ssid: SSID (32-octet string)
598  * @ssid_len: Length of ssid in octets
599  * Returns: Pointer to a printable string
600  *
601  * This function can be used to convert SSIDs into printable form. In most
602  * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
603  * does not limit the used character set, so anything could be used in an SSID.
604  *
605  * This function uses a static buffer, so only one call can be used at the
606  * time, i.e., this is not re-entrant and the returned buffer must be used
607  * before calling this again.
608  */
wpa_ssid_txt(u8 * ssid,size_t ssid_len)609 const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len)
610 {
611 	static char ssid_txt[33];
612 	char *pos;
613 
614 	if (ssid_len > 32)
615 		ssid_len = 32;
616 	os_memcpy(ssid_txt, ssid, ssid_len);
617 	ssid_txt[ssid_len] = '\0';
618 	for (pos = ssid_txt; *pos != '\0'; pos++) {
619 		if ((u8) *pos < 32 || (u8) *pos >= 127)
620 			*pos = '_';
621 	}
622 	return ssid_txt;
623 }
624