Sync mly(4) with FreeBSD.
[dragonfly.git] / contrib / hostapd-0.5.8 / common.c
blobc8d6f130a960a9b33d32374ffc3eea8112537104
1 /*
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
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #include "common.h"
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')
32 return c - '0';
33 if (c >= 'a' && c <= 'f')
34 return c - 'a' + 10;
35 if (c >= 'A' && c <= 'F')
36 return c - 'A' + 10;
37 return -1;
41 static int hex2byte(const char *hex)
43 int a, b;
44 a = hex2num(*hex++);
45 if (a < 0)
46 return -1;
47 b = hex2num(*hex++);
48 if (b < 0)
49 return -1;
50 return (a << 4) | b;
54 /**
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)
62 int i;
64 for (i = 0; i < 6; i++) {
65 int a, b;
67 a = hex2num(*txt++);
68 if (a < 0)
69 return -1;
70 b = hex2num(*txt++);
71 if (b < 0)
72 return -1;
73 *addr++ = (a << 4) | b;
74 if (i < 5 && *txt++ != ':')
75 return -1;
78 return 0;
82 /**
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
87 * this size
88 * Returns: 0 on success, -1 on failure (invalid hex string)
90 int hexstr2bin(const char *hex, u8 *buf, size_t len)
92 size_t i;
93 int a;
94 const char *ipos = hex;
95 u8 *opos = buf;
97 for (i = 0; i < len; i++) {
98 a = hex2byte(ipos);
99 if (a < 0)
100 return -1;
101 *opos++ = a;
102 ipos += 2;
104 return 0;
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
115 * 0xff to 0x00.
117 void inc_byte_array(u8 *counter, size_t len)
119 int pos = len - 1;
120 while (pos >= 0) {
121 counter[pos]++;
122 if (counter[pos] != 0)
123 break;
124 pos--;
129 void wpa_get_ntp_timestamp(u8 *buf)
131 struct os_time now;
132 u32 sec, usec;
134 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
135 os_get_time(&now);
136 sec = host_to_be32(now.sec + 2208988800U); /* Epoch to 1900 */
137 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
138 usec = now.usec;
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)
150 struct os_time tv;
152 if (!wpa_debug_timestamp)
153 return;
155 os_get_time(&tv);
156 #ifdef CONFIG_DEBUG_FILE
157 if (out_file) {
158 fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
159 (unsigned int) tv.usec);
160 } else
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
173 * configuration.
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, ...)
179 va_list ap;
181 va_start(ap, fmt);
182 if (level >= wpa_debug_level) {
183 wpa_debug_print_timestamp();
184 #ifdef CONFIG_DEBUG_FILE
185 if (out_file) {
186 vfprintf(out_file, fmt, ap);
187 fprintf(out_file, "\n");
188 } else {
189 #endif /* CONFIG_DEBUG_FILE */
190 vprintf(fmt, ap);
191 printf("\n");
192 #ifdef CONFIG_DEBUG_FILE
194 #endif /* CONFIG_DEBUG_FILE */
196 va_end(ap);
200 static void _wpa_hexdump(int level, const char *title, const u8 *buf,
201 size_t len, int show)
203 size_t i;
204 if (level < wpa_debug_level)
205 return;
206 wpa_debug_print_timestamp();
207 #ifdef CONFIG_DEBUG_FILE
208 if (out_file) {
209 fprintf(out_file, "%s - hexdump(len=%lu):",
210 title, (unsigned long) len);
211 if (buf == NULL) {
212 fprintf(out_file, " [NULL]");
213 } else if (show) {
214 for (i = 0; i < len; i++)
215 fprintf(out_file, " %02x", buf[i]);
216 } else {
217 fprintf(out_file, " [REMOVED]");
219 fprintf(out_file, "\n");
220 } else {
221 #endif /* CONFIG_DEBUG_FILE */
222 printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
223 if (buf == NULL) {
224 printf(" [NULL]");
225 } else if (show) {
226 for (i = 0; i < len; i++)
227 printf(" %02x", buf[i]);
228 } else {
229 printf(" [REMOVED]");
231 printf("\n");
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)
252 size_t i, llen;
253 const u8 *pos = buf;
254 const size_t line_len = 16;
256 if (level < wpa_debug_level)
257 return;
258 wpa_debug_print_timestamp();
259 #ifdef CONFIG_DEBUG_FILE
260 if (out_file) {
261 if (!show) {
262 fprintf(out_file,
263 "%s - hexdump_ascii(len=%lu): [REMOVED]\n",
264 title, (unsigned long) len);
265 return;
267 if (buf == NULL) {
268 fprintf(out_file,
269 "%s - hexdump_ascii(len=%lu): [NULL]\n",
270 title, (unsigned long) len);
271 return;
273 fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
274 title, (unsigned long) len);
275 while (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++) {
284 if (isprint(pos[i]))
285 fprintf(out_file, "%c", pos[i]);
286 else
287 fprintf(out_file, "_");
289 for (i = llen; i < line_len; i++)
290 fprintf(out_file, " ");
291 fprintf(out_file, "\n");
292 pos += llen;
293 len -= llen;
295 } else {
296 #endif /* CONFIG_DEBUG_FILE */
297 if (!show) {
298 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
299 title, (unsigned long) len);
300 return;
302 if (buf == NULL) {
303 printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
304 title, (unsigned long) len);
305 return;
307 printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
308 while (len) {
309 llen = len > line_len ? line_len : len;
310 printf(" ");
311 for (i = 0; i < llen; i++)
312 printf(" %02x", pos[i]);
313 for (i = llen; i < line_len; i++)
314 printf(" ");
315 printf(" ");
316 for (i = 0; i < llen; i++) {
317 if (isprint(pos[i]))
318 printf("%c", pos[i]);
319 else
320 printf("_");
322 for (i = llen; i < line_len; i++)
323 printf(" ");
324 printf("\n");
325 pos += llen;
326 len -= llen;
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,
341 size_t len)
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;
351 char fname[64];
352 if (!wpa_debug_use_file)
353 return 0;
354 #ifdef _WIN32
355 os_snprintf(fname, sizeof(fname), "\\Temp\\wpa_supplicant-log-%d.txt",
356 count++);
357 #else /* _WIN32 */
358 os_snprintf(fname, sizeof(fname), "/tmp/wpa_supplicant-log-%d.txt",
359 count++);
360 #endif /* _WIN32 */
361 out_file = fopen(fname, "w");
362 return out_file == NULL ? -1 : 0;
363 #else /* CONFIG_DEBUG_FILE */
364 return 0;
365 #endif /* CONFIG_DEBUG_FILE */
369 void wpa_debug_close_file(void)
371 #ifdef CONFIG_DEBUG_FILE
372 if (!wpa_debug_use_file)
373 return;
374 fclose(out_file);
375 out_file = NULL;
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)
387 wpa_msg_cb = func;
391 void wpa_msg(void *ctx, int level, char *fmt, ...)
393 va_list ap;
394 char *buf;
395 const int buflen = 2048;
396 int len;
398 buf = os_malloc(buflen);
399 if (buf == NULL) {
400 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
401 "buffer");
402 return;
404 va_start(ap, fmt);
405 len = vsnprintf(buf, buflen, fmt, ap);
406 va_end(ap);
407 wpa_printf(level, "%s", buf);
408 if (wpa_msg_cb)
409 wpa_msg_cb(ctx, level, buf, len);
410 os_free(buf);
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)
418 size_t i;
419 char *pos = buf, *end = buf + buf_size;
420 int ret;
421 if (buf_size == 0)
422 return 0;
423 for (i = 0; i < len; i++) {
424 ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
425 data[i]);
426 if (ret < 0 || ret >= end - pos) {
427 end[-1] = '\0';
428 return pos - buf;
430 pos += ret;
432 end[-1] = '\0';
433 return pos - buf;
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,
459 size_t len)
461 return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
465 #ifdef CONFIG_ANSI_C_EXTRA
467 #ifdef _WIN32_WCE
468 void perror(const char *s)
470 wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
471 s, (int) GetLastError());
473 #endif /* _WIN32_WCE */
476 int optind = 1;
477 int optopt;
478 char *optarg;
480 int getopt(int argc, char *const argv[], const char *optstring)
482 static int optchr = 1;
483 char *cp;
485 if (optchr == 1) {
486 if (optind >= argc) {
487 /* all arguments processed */
488 return EOF;
491 if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
492 /* no option characters */
493 return EOF;
497 if (os_strcmp(argv[optind], "--") == 0) {
498 /* no more options */
499 optind++;
500 return EOF;
503 optopt = argv[optind][optchr];
504 cp = os_strchr(optstring, optopt);
505 if (cp == NULL || optopt == ':') {
506 if (argv[optind][++optchr] == '\0') {
507 optchr = 1;
508 optind++;
510 return '?';
513 if (cp[1] == ':') {
514 /* Argument required */
515 optchr = 1;
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 */
521 return '?';
522 } else {
523 /* Argument in the next argv */
524 optarg = argv[optind++];
526 } else {
527 /* No argument */
528 if (argv[optind][++optchr] == '\0') {
529 optchr = 1;
530 optind++;
532 optarg = NULL;
534 return *cp;
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
546 * modified.
548 void wpa_unicode2ascii_inplace(TCHAR *str)
550 #ifdef UNICODE
551 char *dst = (char *) str;
552 while (*str)
553 *dst++ = (char) *str++;
554 *dst = '\0';
555 #endif /* UNICODE */
559 TCHAR * wpa_strdup_tchar(const char *str)
561 #ifdef UNICODE
562 TCHAR *buf;
563 buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
564 if (buf == NULL)
565 return NULL;
566 wsprintf(buf, L"%S", str);
567 return buf;
568 #else /* UNICODE */
569 return os_strdup(str);
570 #endif /* UNICODE */
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];
592 char *pos;
594 if (ssid_len > 32)
595 ssid_len = 32;
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)
600 *pos = '_';
602 return ssid_txt;