OSDN Git Service

Merge korg/donut into korg/master
[android-x86/external-wpa_supplicant.git] / common.c
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 #ifdef ANDROID
20 #include <cutils/log.h>
21 #endif
22
23
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;
30
31
32 static int hex2num(char c)
33 {
34         if (c >= '0' && c <= '9')
35                 return c - '0';
36         if (c >= 'a' && c <= 'f')
37                 return c - 'a' + 10;
38         if (c >= 'A' && c <= 'F')
39                 return c - 'A' + 10;
40         return -1;
41 }
42
43
44 static int hex2byte(const char *hex)
45 {
46         int a, b;
47         a = hex2num(*hex++);
48         if (a < 0)
49                 return -1;
50         b = hex2num(*hex++);
51         if (b < 0)
52                 return -1;
53         return (a << 4) | b;
54 }
55
56
57 /**
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)
62  */
63 int hwaddr_aton(const char *txt, u8 *addr)
64 {
65         int i;
66
67         for (i = 0; i < 6; i++) {
68                 int a, b;
69
70                 a = hex2num(*txt++);
71                 if (a < 0)
72                         return -1;
73                 b = hex2num(*txt++);
74                 if (b < 0)
75                         return -1;
76                 *addr++ = (a << 4) | b;
77                 if (i < 5 && *txt++ != ':')
78                         return -1;
79         }
80
81         return 0;
82 }
83
84
85 /**
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
90  * this size
91  * Returns: 0 on success, -1 on failure (invalid hex string)
92  */
93 int hexstr2bin(const char *hex, u8 *buf, size_t len)
94 {
95         size_t i;
96         int a;
97         const char *ipos = hex;
98         u8 *opos = buf;
99
100         for (i = 0; i < len; i++) {
101                 a = hex2byte(ipos);
102                 if (a < 0)
103                         return -1;
104                 *opos++ = a;
105                 ipos += 2;
106         }
107         return 0;
108 }
109
110
111 /**
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
115  *
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
118  * 0xff to 0x00.
119  */
120 void inc_byte_array(u8 *counter, size_t len)
121 {
122         int pos = len - 1;
123         while (pos >= 0) {
124                 counter[pos]++;
125                 if (counter[pos] != 0)
126                         break;
127                 pos--;
128         }
129 }
130
131
132 void wpa_get_ntp_timestamp(u8 *buf)
133 {
134         struct os_time now;
135         u32 sec, usec;
136
137         /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
138         os_get_time(&now);
139         sec = host_to_be32(now.sec + 2208988800U); /* Epoch to 1900 */
140         /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
141         usec = now.usec;
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);
145 }
146
147
148
149 #ifndef CONFIG_NO_STDOUT_DEBUG
150
151 void wpa_debug_print_timestamp(void)
152 {
153         struct os_time tv;
154
155         if (!wpa_debug_timestamp)
156                 return;
157
158         os_get_time(&tv);
159 #ifdef CONFIG_DEBUG_FILE
160         if (out_file) {
161                 fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
162                         (unsigned int) tv.usec);
163         } else
164 #endif /* CONFIG_DEBUG_FILE */
165         printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
166 }
167
168
169 /**
170  * wpa_printf - conditional printf
171  * @level: priority level (MSG_*) of the message
172  * @fmt: printf format string, followed by optional arguments
173  *
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
176  * configuration.
177  *
178  * Note: New line '\n' is added to the end of the text when printing to stdout.
179  */
180 void wpa_printf(int level, char *fmt, ...)
181 {
182         va_list ap;
183
184         va_start(ap, fmt);
185         if (level >= wpa_debug_level) {
186                 wpa_debug_print_timestamp();
187 #ifdef CONFIG_DEBUG_FILE
188                 if (out_file) {
189                         vfprintf(out_file, fmt, ap);
190                         fprintf(out_file, "\n");
191                 } else {
192 #endif /* CONFIG_DEBUG_FILE */
193                 vprintf(fmt, ap);
194                 printf("\n");
195 #ifdef CONFIG_DEBUG_FILE
196                 }
197 #endif /* CONFIG_DEBUG_FILE */
198 #ifdef ANDROID
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;
207         else
208             level = ANDROID_LOG_DEBUG;
209
210         LOG_PRI_VA(level, "wpa_supplicant", fmt, ap);
211 #endif
212         }
213         va_end(ap);
214 }
215
216
217 static void _wpa_hexdump(int level, const char *title, const u8 *buf,
218                          size_t len, int show)
219 {
220         size_t i;
221         if (level < wpa_debug_level)
222                 return;
223         wpa_debug_print_timestamp();
224 #ifdef CONFIG_DEBUG_FILE
225         if (out_file) {
226                 fprintf(out_file, "%s - hexdump(len=%lu):",
227                         title, (unsigned long) len);
228                 if (buf == NULL) {
229                         fprintf(out_file, " [NULL]");
230                 } else if (show) {
231                         for (i = 0; i < len; i++)
232                                 fprintf(out_file, " %02x", buf[i]);
233                 } else {
234                         fprintf(out_file, " [REMOVED]");
235                 }
236                 fprintf(out_file, "\n");
237         } else {
238 #endif /* CONFIG_DEBUG_FILE */
239         printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
240         if (buf == NULL) {
241                 printf(" [NULL]");
242         } else if (show) {
243                 for (i = 0; i < len; i++)
244                         printf(" %02x", buf[i]);
245         } else {
246                 printf(" [REMOVED]");
247         }
248         printf("\n");
249 #ifdef CONFIG_DEBUG_FILE
250         }
251 #endif /* CONFIG_DEBUG_FILE */
252 }
253
254 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
255 {
256         _wpa_hexdump(level, title, buf, len, 1);
257 }
258
259
260 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
261 {
262         _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
263 }
264
265
266 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
267                                size_t len, int show)
268 {
269         size_t i, llen;
270         const u8 *pos = buf;
271         const size_t line_len = 16;
272
273         if (level < wpa_debug_level)
274                 return;
275         wpa_debug_print_timestamp();
276 #ifdef CONFIG_DEBUG_FILE
277         if (out_file) {
278                 if (!show) {
279                         fprintf(out_file,
280                                 "%s - hexdump_ascii(len=%lu): [REMOVED]\n",
281                                 title, (unsigned long) len);
282                         return;
283                 }
284                 if (buf == NULL) {
285                         fprintf(out_file,
286                                 "%s - hexdump_ascii(len=%lu): [NULL]\n",
287                                 title, (unsigned long) len);
288                         return;
289                 }
290                 fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
291                         title, (unsigned long) len);
292                 while (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++) {
301                                 if (isprint(pos[i]))
302                                         fprintf(out_file, "%c", pos[i]);
303                                 else
304                                         fprintf(out_file, "_");
305                         }
306                         for (i = llen; i < line_len; i++)
307                                 fprintf(out_file, " ");
308                         fprintf(out_file, "\n");
309                         pos += llen;
310                         len -= llen;
311                 }
312         } else {
313 #endif /* CONFIG_DEBUG_FILE */
314         if (!show) {
315                 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
316                        title, (unsigned long) len);
317                 return;
318         }
319         if (buf == NULL) {
320                 printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
321                        title, (unsigned long) len);
322                 return;
323         }
324         printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
325         while (len) {
326                 llen = len > line_len ? line_len : len;
327                 printf("    ");
328                 for (i = 0; i < llen; i++)
329                         printf(" %02x", pos[i]);
330                 for (i = llen; i < line_len; i++)
331                         printf("   ");
332                 printf("   ");
333                 for (i = 0; i < llen; i++) {
334                         if (isprint(pos[i]))
335                                 printf("%c", pos[i]);
336                         else
337                                 printf("_");
338                 }
339                 for (i = llen; i < line_len; i++)
340                         printf(" ");
341                 printf("\n");
342                 pos += llen;
343                 len -= llen;
344         }
345 #ifdef CONFIG_DEBUG_FILE
346         }
347 #endif /* CONFIG_DEBUG_FILE */
348 }
349
350
351 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
352 {
353         _wpa_hexdump_ascii(level, title, buf, len, 1);
354 }
355
356
357 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
358                            size_t len)
359 {
360         _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
361 }
362
363
364 int wpa_debug_open_file(const char *path)
365 {
366 #ifdef CONFIG_DEBUG_FILE
367         if (!path)
368                 return 0;
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");
373                 return -1;
374         }
375 #ifndef _WIN32
376         setvbuf(out_file, NULL, _IOLBF, 0);
377 #endif /* _WIN32 */
378 #endif /* CONFIG_DEBUG_FILE */
379         return 0;
380 }
381
382
383 void wpa_debug_close_file(void)
384 {
385 #ifdef CONFIG_DEBUG_FILE
386         if (!out_file)
387                 return;
388         fclose(out_file);
389         out_file = NULL;
390 #endif /* CONFIG_DEBUG_FILE */
391 }
392
393 #endif /* CONFIG_NO_STDOUT_DEBUG */
394
395
396 #ifndef CONFIG_NO_WPA_MSG
397 static wpa_msg_cb_func wpa_msg_cb = NULL;
398
399 void wpa_msg_register_cb(wpa_msg_cb_func func)
400 {
401         wpa_msg_cb = func;
402 }
403
404
405 void wpa_msg(void *ctx, int level, char *fmt, ...)
406 {
407         va_list ap;
408         char *buf;
409         const int buflen = 2048;
410         int len;
411
412         buf = os_malloc(buflen);
413         if (buf == NULL) {
414                 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
415                            "buffer");
416                 return;
417         }
418         va_start(ap, fmt);
419         len = vsnprintf(buf, buflen, fmt, ap);
420         va_end(ap);
421         wpa_printf(level, "%s", buf);
422         if (wpa_msg_cb)
423                 wpa_msg_cb(ctx, level, buf, len);
424         os_free(buf);
425 }
426 #endif /* CONFIG_NO_WPA_MSG */
427
428
429 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
430                                     size_t len, int uppercase)
431 {
432         size_t i;
433         char *pos = buf, *end = buf + buf_size;
434         int ret;
435         if (buf_size == 0)
436                 return 0;
437         for (i = 0; i < len; i++) {
438                 ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
439                                   data[i]);
440                 if (ret < 0 || ret >= end - pos) {
441                         end[-1] = '\0';
442                         return pos - buf;
443                 }
444                 pos += ret;
445         }
446         end[-1] = '\0';
447         return pos - buf;
448 }
449
450 /**
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
457  */
458 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
459 {
460         return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
461 }
462
463
464 /**
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
471  */
472 int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
473                                size_t len)
474 {
475         return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
476 }
477
478
479 #ifdef CONFIG_ANSI_C_EXTRA
480
481 #ifdef _WIN32_WCE
482 void perror(const char *s)
483 {
484         wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
485                    s, (int) GetLastError());
486 }
487 #endif /* _WIN32_WCE */
488
489
490 int optind = 1;
491 int optopt;
492 char *optarg;
493
494 int getopt(int argc, char *const argv[], const char *optstring)
495 {
496         static int optchr = 1;
497         char *cp;
498
499         if (optchr == 1) {
500                 if (optind >= argc) {
501                         /* all arguments processed */
502                         return EOF;
503                 }
504
505                 if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
506                         /* no option characters */
507                         return EOF;
508                 }
509         }
510
511         if (os_strcmp(argv[optind], "--") == 0) {
512                 /* no more options */
513                 optind++;
514                 return EOF;
515         }
516
517         optopt = argv[optind][optchr];
518         cp = os_strchr(optstring, optopt);
519         if (cp == NULL || optopt == ':') {
520                 if (argv[optind][++optchr] == '\0') {
521                         optchr = 1;
522                         optind++;
523                 }
524                 return '?';
525         }
526
527         if (cp[1] == ':') {
528                 /* Argument required */
529                 optchr = 1;
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 */
535                         return '?';
536                 } else {
537                         /* Argument in the next argv */
538                         optarg = argv[optind++];
539                 }
540         } else {
541                 /* No argument */
542                 if (argv[optind][++optchr] == '\0') {
543                         optchr = 1;
544                         optind++;
545                 }
546                 optarg = NULL;
547         }
548         return *cp;
549 }
550 #endif /* CONFIG_ANSI_C_EXTRA */
551
552
553 #ifdef CONFIG_NATIVE_WINDOWS
554 /**
555  * wpa_unicode2ascii_inplace - Convert unicode string into ASCII
556  * @str: Pointer to string to convert
557  *
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
560  * modified.
561  */
562 void wpa_unicode2ascii_inplace(TCHAR *str)
563 {
564 #ifdef UNICODE
565         char *dst = (char *) str;
566         while (*str)
567                 *dst++ = (char) *str++;
568         *dst = '\0';
569 #endif /* UNICODE */
570 }
571
572
573 TCHAR * wpa_strdup_tchar(const char *str)
574 {
575 #ifdef UNICODE
576         TCHAR *buf;
577         buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
578         if (buf == NULL)
579                 return NULL;
580         wsprintf(buf, L"%S", str);
581         return buf;
582 #else /* UNICODE */
583         return os_strdup(str);
584 #endif /* UNICODE */
585 }
586 #endif /* CONFIG_NATIVE_WINDOWS */
587
588
589 /**
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
594  *
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.
598  *
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.
602  */
603 const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len)
604 {
605         static char ssid_txt[33];
606         char *pos;
607
608         if (ssid_len > 32)
609                 ssid_len = 32;
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)
614                         *pos = '_';
615         }
616         return ssid_txt;
617 }