2 * wpa_supplicant/hostapd / common helper functions, etc.
3 * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
20 #include <cutils/log.h>
24 #ifdef CONFIG_DEBUG_FILE
25 static FILE *out_file = NULL;
26 #endif /* CONFIG_DEBUG_FILE */
27 int wpa_debug_level = MSG_INFO;
28 int wpa_debug_show_keys = 0;
29 int wpa_debug_timestamp = 0;
32 static int hex2num(char c)
34 if (c >= '0' && c <= '9')
36 if (c >= 'a' && c <= 'f')
38 if (c >= 'A' && c <= 'F')
44 static int hex2byte(const char *hex)
58 * hwaddr_aton - Convert ASCII string to MAC address
59 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
60 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
61 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
63 int hwaddr_aton(const char *txt, u8 *addr)
67 for (i = 0; i < 6; i++) {
76 *addr++ = (a << 4) | b;
77 if (i < 5 && *txt++ != ':')
86 * hexstr2bin - Convert ASCII hex string into binary data
87 * @hex: ASCII hex string (e.g., "01ab")
88 * @buf: Buffer for the binary data
89 * @len: Length of the text to convert in bytes (of buf); hex will be double
91 * Returns: 0 on success, -1 on failure (invalid hex string)
93 int hexstr2bin(const char *hex, u8 *buf, size_t len)
97 const char *ipos = hex;
100 for (i = 0; i < len; i++) {
112 * inc_byte_array - Increment arbitrary length byte array by one
113 * @counter: Pointer to byte array
114 * @len: Length of the counter in bytes
116 * This function increments the last byte of the counter by one and continues
117 * rolling over to more significant bytes if the byte was incremented from
120 void inc_byte_array(u8 *counter, size_t len)
125 if (counter[pos] != 0)
132 void wpa_get_ntp_timestamp(u8 *buf)
137 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
139 sec = host_to_be32(now.sec + 2208988800U); /* Epoch to 1900 */
140 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
142 usec = host_to_be32(4295 * usec - (usec >> 5) - (usec >> 9));
143 os_memcpy(buf, (u8 *) &sec, 4);
144 os_memcpy(buf + 4, (u8 *) &usec, 4);
149 #ifndef CONFIG_NO_STDOUT_DEBUG
151 void wpa_debug_print_timestamp(void)
155 if (!wpa_debug_timestamp)
159 #ifdef CONFIG_DEBUG_FILE
161 fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
162 (unsigned int) tv.usec);
164 #endif /* CONFIG_DEBUG_FILE */
165 printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
170 * wpa_printf - conditional printf
171 * @level: priority level (MSG_*) of the message
172 * @fmt: printf format string, followed by optional arguments
174 * This function is used to print conditional debugging and error messages. The
175 * output may be directed to stdout, stderr, and/or syslog based on
178 * Note: New line '\n' is added to the end of the text when printing to stdout.
180 void wpa_printf(int level, char *fmt, ...)
185 if (level >= wpa_debug_level) {
186 wpa_debug_print_timestamp();
187 #ifdef CONFIG_DEBUG_FILE
189 vfprintf(out_file, fmt, ap);
190 fprintf(out_file, "\n");
192 #endif /* CONFIG_DEBUG_FILE */
195 #ifdef CONFIG_DEBUG_FILE
197 #endif /* CONFIG_DEBUG_FILE */
199 if (level == MSG_DEBUG)
200 level = ANDROID_LOG_DEBUG;
201 else if (level == MSG_INFO)
202 level = ANDROID_LOG_INFO;
203 else if (level == MSG_WARNING)
204 level = ANDROID_LOG_WARN;
205 else if (level == MSG_ERROR)
206 level = ANDROID_LOG_ERROR;
208 level = ANDROID_LOG_DEBUG;
210 LOG_PRI_VA(level, "wpa_supplicant", fmt, ap);
217 static void _wpa_hexdump(int level, const char *title, const u8 *buf,
218 size_t len, int show)
221 if (level < wpa_debug_level)
223 wpa_debug_print_timestamp();
224 #ifdef CONFIG_DEBUG_FILE
226 fprintf(out_file, "%s - hexdump(len=%lu):",
227 title, (unsigned long) len);
229 fprintf(out_file, " [NULL]");
231 for (i = 0; i < len; i++)
232 fprintf(out_file, " %02x", buf[i]);
234 fprintf(out_file, " [REMOVED]");
236 fprintf(out_file, "\n");
238 #endif /* CONFIG_DEBUG_FILE */
239 printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
243 for (i = 0; i < len; i++)
244 printf(" %02x", buf[i]);
246 printf(" [REMOVED]");
249 #ifdef CONFIG_DEBUG_FILE
251 #endif /* CONFIG_DEBUG_FILE */
254 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
256 _wpa_hexdump(level, title, buf, len, 1);
260 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
262 _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
266 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
267 size_t len, int show)
271 const size_t line_len = 16;
273 if (level < wpa_debug_level)
275 wpa_debug_print_timestamp();
276 #ifdef CONFIG_DEBUG_FILE
280 "%s - hexdump_ascii(len=%lu): [REMOVED]\n",
281 title, (unsigned long) len);
286 "%s - hexdump_ascii(len=%lu): [NULL]\n",
287 title, (unsigned long) len);
290 fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
291 title, (unsigned long) len);
293 llen = len > line_len ? line_len : len;
294 fprintf(out_file, " ");
295 for (i = 0; i < llen; i++)
296 fprintf(out_file, " %02x", pos[i]);
297 for (i = llen; i < line_len; i++)
298 fprintf(out_file, " ");
299 fprintf(out_file, " ");
300 for (i = 0; i < llen; i++) {
302 fprintf(out_file, "%c", pos[i]);
304 fprintf(out_file, "_");
306 for (i = llen; i < line_len; i++)
307 fprintf(out_file, " ");
308 fprintf(out_file, "\n");
313 #endif /* CONFIG_DEBUG_FILE */
315 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
316 title, (unsigned long) len);
320 printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
321 title, (unsigned long) len);
324 printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
326 llen = len > line_len ? line_len : len;
328 for (i = 0; i < llen; i++)
329 printf(" %02x", pos[i]);
330 for (i = llen; i < line_len; i++)
333 for (i = 0; i < llen; i++) {
335 printf("%c", pos[i]);
339 for (i = llen; i < line_len; i++)
345 #ifdef CONFIG_DEBUG_FILE
347 #endif /* CONFIG_DEBUG_FILE */
351 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
353 _wpa_hexdump_ascii(level, title, buf, len, 1);
357 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
360 _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
364 int wpa_debug_open_file(const char *path)
366 #ifdef CONFIG_DEBUG_FILE
369 out_file = fopen(path, "a");
370 if (out_file == NULL) {
371 wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
372 "output file, using standard output");
376 setvbuf(out_file, NULL, _IOLBF, 0);
378 #endif /* CONFIG_DEBUG_FILE */
383 void wpa_debug_close_file(void)
385 #ifdef CONFIG_DEBUG_FILE
390 #endif /* CONFIG_DEBUG_FILE */
393 #endif /* CONFIG_NO_STDOUT_DEBUG */
396 #ifndef CONFIG_NO_WPA_MSG
397 static wpa_msg_cb_func wpa_msg_cb = NULL;
399 void wpa_msg_register_cb(wpa_msg_cb_func func)
405 void wpa_msg(void *ctx, int level, char *fmt, ...)
409 const int buflen = 2048;
412 buf = os_malloc(buflen);
414 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
419 len = vsnprintf(buf, buflen, fmt, ap);
421 wpa_printf(level, "%s", buf);
423 wpa_msg_cb(ctx, level, buf, len);
426 #endif /* CONFIG_NO_WPA_MSG */
429 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
430 size_t len, int uppercase)
433 char *pos = buf, *end = buf + buf_size;
437 for (i = 0; i < len; i++) {
438 ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
440 if (ret < 0 || ret >= end - pos) {
451 * wpa_snprintf_hex - Print data as a hex string into a buffer
452 * @buf: Memory area to use as the output buffer
453 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
454 * @data: Data to be printed
455 * @len: Length of data in bytes
456 * Returns: Number of bytes written
458 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
460 return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
465 * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf
466 * @buf: Memory area to use as the output buffer
467 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
468 * @data: Data to be printed
469 * @len: Length of data in bytes
470 * Returns: Number of bytes written
472 int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
475 return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
479 #ifdef CONFIG_ANSI_C_EXTRA
482 void perror(const char *s)
484 wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
485 s, (int) GetLastError());
487 #endif /* _WIN32_WCE */
494 int getopt(int argc, char *const argv[], const char *optstring)
496 static int optchr = 1;
500 if (optind >= argc) {
501 /* all arguments processed */
505 if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
506 /* no option characters */
511 if (os_strcmp(argv[optind], "--") == 0) {
512 /* no more options */
517 optopt = argv[optind][optchr];
518 cp = os_strchr(optstring, optopt);
519 if (cp == NULL || optopt == ':') {
520 if (argv[optind][++optchr] == '\0') {
528 /* Argument required */
530 if (argv[optind][optchr + 1]) {
531 /* No space between option and argument */
532 optarg = &argv[optind++][optchr + 1];
533 } else if (++optind >= argc) {
534 /* option requires an argument */
537 /* Argument in the next argv */
538 optarg = argv[optind++];
542 if (argv[optind][++optchr] == '\0') {
550 #endif /* CONFIG_ANSI_C_EXTRA */
553 #ifdef CONFIG_NATIVE_WINDOWS
555 * wpa_unicode2ascii_inplace - Convert unicode string into ASCII
556 * @str: Pointer to string to convert
558 * This function converts a unicode string to ASCII using the same
559 * buffer for output. If UNICODE is not set, the buffer is not
562 void wpa_unicode2ascii_inplace(TCHAR *str)
565 char *dst = (char *) str;
567 *dst++ = (char) *str++;
573 TCHAR * wpa_strdup_tchar(const char *str)
577 buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
580 wsprintf(buf, L"%S", str);
583 return os_strdup(str);
586 #endif /* CONFIG_NATIVE_WINDOWS */
590 * wpa_ssid_txt - Convert SSID to a printable string
591 * @ssid: SSID (32-octet string)
592 * @ssid_len: Length of ssid in octets
593 * Returns: Pointer to a printable string
595 * This function can be used to convert SSIDs into printable form. In most
596 * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
597 * does not limit the used character set, so anything could be used in an SSID.
599 * This function uses a static buffer, so only one call can be used at the
600 * time, i.e., this is not re-entrant and the returned buffer must be used
601 * before calling this again.
603 const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len)
605 static char ssid_txt[33];
610 os_memcpy(ssid_txt, ssid, ssid_len);
611 ssid_txt[ssid_len] = '\0';
612 for (pos = ssid_txt; *pos != '\0'; pos++) {
613 if ((u8) *pos < 32 || (u8) *pos >= 127)