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 #ifdef CONFIG_DEBUG_FILE
21 static FILE *out_file = NULL;
22 #endif /* CONFIG_DEBUG_FILE */
23 int wpa_debug_use_file = 0;
24 int wpa_debug_level = MSG_INFO;
25 int wpa_debug_show_keys = 0;
26 int wpa_debug_timestamp = 0;
29 static int hex2num(char c)
31 if (c >= '0' && c <= '9')
33 if (c >= 'a' && c <= 'f')
35 if (c >= 'A' && c <= 'F')
41 static int hex2byte(const char *hex)
55 * hwaddr_aton - Convert ASCII string to MAC address
56 * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
57 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
58 * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
60 int hwaddr_aton(const char *txt, u8 *addr)
64 for (i = 0; i < 6; i++) {
73 *addr++ = (a << 4) | b;
74 if (i < 5 && *txt++ != ':')
83 * hexstr2bin - Convert ASCII hex string into binary data
84 * @hex: ASCII hex string (e.g., "01ab")
85 * @buf: Buffer for the binary data
86 * @len: Length of the text to convert in bytes (of buf); hex will be double
88 * Returns: 0 on success, -1 on failure (invalid hex string)
90 int hexstr2bin(const char *hex, u8 *buf, size_t len)
94 const char *ipos = hex;
97 for (i = 0; i < len; i++) {
109 * inc_byte_array - Increment arbitrary length byte array by one
110 * @counter: Pointer to byte array
111 * @len: Length of the counter in bytes
113 * This function increments the last byte of the counter by one and continues
114 * rolling over to more significant bytes if the byte was incremented from
117 void inc_byte_array(u8 *counter, size_t len)
122 if (counter[pos] != 0)
129 void wpa_get_ntp_timestamp(u8 *buf)
134 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
136 sec = host_to_be32(now.sec + 2208988800U); /* Epoch to 1900 */
137 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
139 usec = host_to_be32(4295 * usec - (usec >> 5) - (usec >> 9));
140 os_memcpy(buf, (u8 *) &sec, 4);
141 os_memcpy(buf + 4, (u8 *) &usec, 4);
146 #ifndef CONFIG_NO_STDOUT_DEBUG
148 void wpa_debug_print_timestamp(void)
152 if (!wpa_debug_timestamp)
156 #ifdef CONFIG_DEBUG_FILE
158 fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
159 (unsigned int) tv.usec);
161 #endif /* CONFIG_DEBUG_FILE */
162 printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
167 * wpa_printf - conditional printf
168 * @level: priority level (MSG_*) of the message
169 * @fmt: printf format string, followed by optional arguments
171 * This function is used to print conditional debugging and error messages. The
172 * output may be directed to stdout, stderr, and/or syslog based on
175 * Note: New line '\n' is added to the end of the text when printing to stdout.
177 void wpa_printf(int level, char *fmt, ...)
182 if (level >= wpa_debug_level) {
183 wpa_debug_print_timestamp();
184 #ifdef CONFIG_DEBUG_FILE
186 vfprintf(out_file, fmt, ap);
187 fprintf(out_file, "\n");
189 #endif /* CONFIG_DEBUG_FILE */
192 #ifdef CONFIG_DEBUG_FILE
194 #endif /* CONFIG_DEBUG_FILE */
200 static void _wpa_hexdump(int level, const char *title, const u8 *buf,
201 size_t len, int show)
204 if (level < wpa_debug_level)
206 wpa_debug_print_timestamp();
207 #ifdef CONFIG_DEBUG_FILE
209 fprintf(out_file, "%s - hexdump(len=%lu):",
210 title, (unsigned long) len);
212 fprintf(out_file, " [NULL]");
214 for (i = 0; i < len; i++)
215 fprintf(out_file, " %02x", buf[i]);
217 fprintf(out_file, " [REMOVED]");
219 fprintf(out_file, "\n");
221 #endif /* CONFIG_DEBUG_FILE */
222 printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
226 for (i = 0; i < len; i++)
227 printf(" %02x", buf[i]);
229 printf(" [REMOVED]");
232 #ifdef CONFIG_DEBUG_FILE
234 #endif /* CONFIG_DEBUG_FILE */
237 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
239 _wpa_hexdump(level, title, buf, len, 1);
243 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
245 _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
249 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
250 size_t len, int show)
254 const size_t line_len = 16;
256 if (level < wpa_debug_level)
258 wpa_debug_print_timestamp();
259 #ifdef CONFIG_DEBUG_FILE
263 "%s - hexdump_ascii(len=%lu): [REMOVED]\n",
264 title, (unsigned long) len);
269 "%s - hexdump_ascii(len=%lu): [NULL]\n",
270 title, (unsigned long) len);
273 fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
274 title, (unsigned long) len);
276 llen = len > line_len ? line_len : len;
277 fprintf(out_file, " ");
278 for (i = 0; i < llen; i++)
279 fprintf(out_file, " %02x", pos[i]);
280 for (i = llen; i < line_len; i++)
281 fprintf(out_file, " ");
282 fprintf(out_file, " ");
283 for (i = 0; i < llen; i++) {
285 fprintf(out_file, "%c", pos[i]);
287 fprintf(out_file, "_");
289 for (i = llen; i < line_len; i++)
290 fprintf(out_file, " ");
291 fprintf(out_file, "\n");
296 #endif /* CONFIG_DEBUG_FILE */
298 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
299 title, (unsigned long) len);
303 printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
304 title, (unsigned long) len);
307 printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
309 llen = len > line_len ? line_len : len;
311 for (i = 0; i < llen; i++)
312 printf(" %02x", pos[i]);
313 for (i = llen; i < line_len; i++)
316 for (i = 0; i < llen; i++) {
318 printf("%c", pos[i]);
322 for (i = llen; i < line_len; i++)
328 #ifdef CONFIG_DEBUG_FILE
330 #endif /* CONFIG_DEBUG_FILE */
334 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
336 _wpa_hexdump_ascii(level, title, buf, len, 1);
340 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
343 _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
347 int wpa_debug_open_file(void)
349 #ifdef CONFIG_DEBUG_FILE
350 static int count = 0;
352 if (!wpa_debug_use_file)
355 os_snprintf(fname, sizeof(fname), "\\Temp\\wpa_supplicant-log-%d.txt",
358 os_snprintf(fname, sizeof(fname), "/tmp/wpa_supplicant-log-%d.txt",
361 out_file = fopen(fname, "w");
362 return out_file == NULL ? -1 : 0;
363 #else /* CONFIG_DEBUG_FILE */
365 #endif /* CONFIG_DEBUG_FILE */
369 void wpa_debug_close_file(void)
371 #ifdef CONFIG_DEBUG_FILE
372 if (!wpa_debug_use_file)
376 #endif /* CONFIG_DEBUG_FILE */
379 #endif /* CONFIG_NO_STDOUT_DEBUG */
382 #ifndef CONFIG_NO_WPA_MSG
383 static wpa_msg_cb_func wpa_msg_cb = NULL;
385 void wpa_msg_register_cb(wpa_msg_cb_func func)
391 void wpa_msg(void *ctx, int level, char *fmt, ...)
395 const int buflen = 2048;
398 buf = os_malloc(buflen);
400 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
405 len = vsnprintf(buf, buflen, fmt, ap);
407 wpa_printf(level, "%s", buf);
409 wpa_msg_cb(ctx, level, buf, len);
412 #endif /* CONFIG_NO_WPA_MSG */
415 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
416 size_t len, int uppercase)
419 char *pos = buf, *end = buf + buf_size;
423 for (i = 0; i < len; i++) {
424 ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
426 if (ret < 0 || ret >= end - pos) {
437 * wpa_snprintf_hex - Print data as a hex string into a buffer
438 * @buf: Memory area to use as the output buffer
439 * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
440 * @data: Data to be printed
441 * @len: Length of data in bytes
442 * Returns: Number of bytes written
444 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
446 return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
451 * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf
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_uppercase(char *buf, size_t buf_size, const u8 *data,
461 return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
465 #ifdef CONFIG_ANSI_C_EXTRA
468 void perror(const char *s)
470 wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
471 s, (int) GetLastError());
473 #endif /* _WIN32_WCE */
480 int getopt(int argc, char *const argv[], const char *optstring)
482 static int optchr = 1;
486 if (optind >= argc) {
487 /* all arguments processed */
491 if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
492 /* no option characters */
497 if (os_strcmp(argv[optind], "--") == 0) {
498 /* no more options */
503 optopt = argv[optind][optchr];
504 cp = os_strchr(optstring, optopt);
505 if (cp == NULL || optopt == ':') {
506 if (argv[optind][++optchr] == '\0') {
514 /* Argument required */
516 if (argv[optind][optchr + 1]) {
517 /* No space between option and argument */
518 optarg = &argv[optind++][optchr + 1];
519 } else if (++optind >= argc) {
520 /* option requires an argument */
523 /* Argument in the next argv */
524 optarg = argv[optind++];
528 if (argv[optind][++optchr] == '\0') {
536 #endif /* CONFIG_ANSI_C_EXTRA */
539 #ifdef CONFIG_NATIVE_WINDOWS
541 * wpa_unicode2ascii_inplace - Convert unicode string into ASCII
542 * @str: Pointer to string to convert
544 * This function converts a unicode string to ASCII using the same
545 * buffer for output. If UNICODE is not set, the buffer is not
548 void wpa_unicode2ascii_inplace(TCHAR *str)
551 char *dst = (char *) str;
553 *dst++ = (char) *str++;
559 TCHAR * wpa_strdup_tchar(const char *str)
563 buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
566 wsprintf(buf, L"%S", str);
569 return os_strdup(str);
572 #endif /* CONFIG_NATIVE_WINDOWS */
576 * wpa_ssid_txt - Convert SSID to a printable string
577 * @ssid: SSID (32-octet string)
578 * @ssid_len: Length of ssid in octets
579 * Returns: Pointer to a printable string
581 * This function can be used to convert SSIDs into printable form. In most
582 * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
583 * does not limit the used character set, so anything could be used in an SSID.
585 * This function uses a static buffer, so only one call can be used at the
586 * time, i.e., this is not re-entrant and the returned buffer must be used
587 * before calling this again.
589 const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len)
591 static char ssid_txt[33];
596 os_memcpy(ssid_txt, ssid, ssid_len);
597 ssid_txt[ssid_len] = '\0';
598 for (pos = ssid_txt; *pos != '\0'; pos++) {
599 if ((u8) *pos < 32 || (u8) *pos >= 127)