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)