Merge from vendor branch AWK:
[dragonfly.git] / contrib / hostapd-0.4.9 / common.c
1 /*
2  * wpa_supplicant/hostapd / common helper functions, etc.
3  * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.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 <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <errno.h>
20 #include <stdarg.h>
21 #include <ctype.h>
22 #include <time.h>
23 #include <sys/time.h>
24 #ifdef CONFIG_NATIVE_WINDOWS
25 #include <winsock2.h>
26 #include <wincrypt.h>
27 #endif /* CONFIG_NATIVE_WINDOWS */
28
29 #include "common.h"
30
31
32 int wpa_debug_level = MSG_INFO;
33 int wpa_debug_show_keys = 0;
34 int wpa_debug_timestamp = 0;
35
36
37 int hostapd_get_rand(u8 *buf, size_t len)
38 {
39 #ifdef CONFIG_NATIVE_WINDOWS
40         HCRYPTPROV prov;
41         BOOL ret;
42
43         if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL,
44                                  CRYPT_VERIFYCONTEXT))
45                 return -1;
46
47         ret = CryptGenRandom(prov, len, buf);
48         CryptReleaseContext(prov, 0);
49
50         return ret ? 0 : -1;
51 #else /* CONFIG_NATIVE_WINDOWS */
52         FILE *f;
53         size_t rc;
54
55         f = fopen("/dev/urandom", "r");
56         if (f == NULL) {
57                 printf("Could not open /dev/urandom.\n");
58                 return -1;
59         }
60
61         rc = fread(buf, 1, len, f);
62         fclose(f);
63
64         return rc != len ? -1 : 0;
65 #endif /* CONFIG_NATIVE_WINDOWS */
66 }
67
68
69 void hostapd_hexdump(const char *title, const u8 *buf, size_t len)
70 {
71         size_t i;
72         printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
73         for (i = 0; i < len; i++)
74                 printf(" %02x", buf[i]);
75         printf("\n");
76 }
77
78
79 static int hex2num(char c)
80 {
81         if (c >= '0' && c <= '9')
82                 return c - '0';
83         if (c >= 'a' && c <= 'f')
84                 return c - 'a' + 10;
85         if (c >= 'A' && c <= 'F')
86                 return c - 'A' + 10;
87         return -1;
88 }
89
90
91 static int hex2byte(const char *hex)
92 {
93         int a, b;
94         a = hex2num(*hex++);
95         if (a < 0)
96                 return -1;
97         b = hex2num(*hex++);
98         if (b < 0)
99                 return -1;
100         return (a << 4) | b;
101 }
102
103
104 /**
105  * hwaddr_aton - Convert ASCII string to MAC address
106  * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
107  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
108  * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
109  */
110 int hwaddr_aton(const char *txt, u8 *addr)
111 {
112         int i;
113
114         for (i = 0; i < 6; i++) {
115                 int a, b;
116
117                 a = hex2num(*txt++);
118                 if (a < 0)
119                         return -1;
120                 b = hex2num(*txt++);
121                 if (b < 0)
122                         return -1;
123                 *addr++ = (a << 4) | b;
124                 if (i < 5 && *txt++ != ':')
125                         return -1;
126         }
127
128         return 0;
129 }
130
131
132 /**
133  * hexstr2bin - Convert ASCII hex string into binary data
134  * @hex: ASCII hex string (e.g., "01ab")
135  * @buf: Buffer for the binary data
136  * @len: Length of the text to convert in bytes (of buf); hex will be double
137  * this size
138  * Returns: 0 on success, -1 on failure (invalid hex string)
139  */
140 int hexstr2bin(const char *hex, u8 *buf, size_t len)
141 {
142         int i, a;
143         const char *ipos = hex;
144         u8 *opos = buf;
145
146         for (i = 0; i < len; i++) {
147                 a = hex2byte(ipos);
148                 if (a < 0)
149                         return -1;
150                 *opos++ = a;
151                 ipos += 2;
152         }
153         return 0;
154 }
155
156
157 char * rel2abs_path(const char *rel_path)
158 {
159         char *buf = NULL, *cwd, *ret;
160         size_t len = 128, cwd_len, rel_len, ret_len;
161
162         if (rel_path[0] == '/')
163                 return strdup(rel_path);
164
165         for (;;) {
166                 buf = malloc(len);
167                 if (buf == NULL)
168                         return NULL;
169                 cwd = getcwd(buf, len);
170                 if (cwd == NULL) {
171                         free(buf);
172                         if (errno != ERANGE) {
173                                 return NULL;
174                         }
175                         len *= 2;
176                 } else {
177                         break;
178                 }
179         }
180
181         cwd_len = strlen(cwd);
182         rel_len = strlen(rel_path);
183         ret_len = cwd_len + 1 + rel_len + 1;
184         ret = malloc(ret_len);
185         if (ret) {
186                 memcpy(ret, cwd, cwd_len);
187                 ret[cwd_len] = '/';
188                 memcpy(ret + cwd_len + 1, rel_path, rel_len);
189                 ret[ret_len - 1] = '\0';
190         }
191         free(buf);
192         return ret;
193 }
194
195
196 /**
197  * inc_byte_array - Increment arbitrary length byte array by one
198  * @counter: Pointer to byte array
199  * @len: Length of the counter in bytes
200  *
201  * This function increments the last byte of the counter by one and continues
202  * rolling over to more significant bytes if the byte was incremented from
203  * 0xff to 0x00.
204  */
205 void inc_byte_array(u8 *counter, size_t len)
206 {
207         int pos = len - 1;
208         while (pos >= 0) {
209                 counter[pos]++;
210                 if (counter[pos] != 0)
211                         break;
212                 pos--;
213         }
214 }
215
216
217 void print_char(char c)
218 {
219         if (c >= 32 && c < 127)
220                 printf("%c", c);
221         else
222                 printf("<%02x>", c);
223 }
224
225
226 void fprint_char(FILE *f, char c)
227 {
228         if (c >= 32 && c < 127)
229                 fprintf(f, "%c", c);
230         else
231                 fprintf(f, "<%02x>", c);
232 }
233
234
235 #ifndef CONFIG_NO_STDOUT_DEBUG
236
237 void wpa_debug_print_timestamp(void)
238 {
239         struct timeval tv;
240         char buf[16];
241
242         if (!wpa_debug_timestamp)
243                 return;
244
245         gettimeofday(&tv, NULL);
246         if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S",
247                      localtime((const time_t *) &tv.tv_sec)) <= 0) {
248                 snprintf(buf, sizeof(buf), "%u", (int) tv.tv_sec);
249         }
250         printf("%s.%06u: ", buf, (unsigned int) tv.tv_usec);
251 }
252
253
254 /**
255  * wpa_printf - conditional printf
256  * @level: priority level (MSG_*) of the message
257  * @fmt: printf format string, followed by optional arguments
258  *
259  * This function is used to print conditional debugging and error messages. The
260  * output may be directed to stdout, stderr, and/or syslog based on
261  * configuration.
262  *
263  * Note: New line '\n' is added to the end of the text when printing to stdout.
264  */
265 void wpa_printf(int level, char *fmt, ...)
266 {
267         va_list ap;
268
269         va_start(ap, fmt);
270         if (level >= wpa_debug_level) {
271                 wpa_debug_print_timestamp();
272                 vprintf(fmt, ap);
273                 printf("\n");
274         }
275         va_end(ap);
276 }
277
278
279 static void _wpa_hexdump(int level, const char *title, const u8 *buf,
280                          size_t len, int show)
281 {
282         size_t i;
283         if (level < wpa_debug_level)
284                 return;
285         wpa_debug_print_timestamp();
286         printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
287         if (buf == NULL) {
288                 printf(" [NULL]");
289         } else if (show) {
290                 for (i = 0; i < len; i++)
291                         printf(" %02x", buf[i]);
292         } else {
293                 printf(" [REMOVED]");
294         }
295         printf("\n");
296 }
297
298 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
299 {
300         _wpa_hexdump(level, title, buf, len, 1);
301 }
302
303
304 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
305 {
306         _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
307 }
308
309
310 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
311                                size_t len, int show)
312 {
313         int i, llen;
314         const u8 *pos = buf;
315         const int line_len = 16;
316
317         if (level < wpa_debug_level)
318                 return;
319         wpa_debug_print_timestamp();
320         if (!show) {
321                 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
322                        title, (unsigned long) len);
323                 return;
324         }
325         if (buf == NULL) {
326                 printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
327                        title, (unsigned long) len);
328                 return;
329         }
330         printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
331         while (len) {
332                 llen = len > line_len ? line_len : len;
333                 printf("    ");
334                 for (i = 0; i < llen; i++)
335                         printf(" %02x", pos[i]);
336                 for (i = llen; i < line_len; i++)
337                         printf("   ");
338                 printf("   ");
339                 for (i = 0; i < llen; i++) {
340                         if (isprint(pos[i]))
341                                 printf("%c", pos[i]);
342                         else
343                                 printf("_");
344                 }
345                 for (i = llen; i < line_len; i++)
346                         printf(" ");
347                 printf("\n");
348                 pos += llen;
349                 len -= llen;
350         }
351 }
352
353
354 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
355 {
356         _wpa_hexdump_ascii(level, title, buf, len, 1);
357 }
358
359
360 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
361                            size_t len)
362 {
363         _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
364 }
365
366 #endif /* CONFIG_NO_STDOUT_DEBUG */
367
368
369 #ifdef CONFIG_NATIVE_WINDOWS
370
371 #define EPOCHFILETIME (116444736000000000ULL)
372
373 int gettimeofday(struct timeval *tv, struct timezone *tz)
374 {
375         FILETIME ft;
376         LARGE_INTEGER li;
377         ULONGLONG t;
378
379         GetSystemTimeAsFileTime(&ft);
380         li.LowPart = ft.dwLowDateTime;
381         li.HighPart = ft.dwHighDateTime;
382         t = (li.QuadPart - EPOCHFILETIME) / 10;
383         tv->tv_sec = (long) (t / 1000000);
384         tv->tv_usec = (long) (t % 1000000);
385
386         return 0;
387 }
388 #endif /* CONFIG_NATIVE_WINDOWS */