Merge branch 'vendor/DIFFUTILS'
[dragonfly.git] / contrib / hostapd / src / utils / wpa_debug.c
1 /*
2  * wpa_supplicant/hostapd / Debug prints
3  * Copyright (c) 2002-2007, 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
20 #ifdef CONFIG_DEBUG_FILE
21 static FILE *out_file = NULL;
22 #endif /* CONFIG_DEBUG_FILE */
23 int wpa_debug_level = MSG_INFO;
24 int wpa_debug_show_keys = 0;
25 int wpa_debug_timestamp = 0;
26
27
28 #ifndef CONFIG_NO_STDOUT_DEBUG
29
30 void wpa_debug_print_timestamp(void)
31 {
32         struct os_time tv;
33
34         if (!wpa_debug_timestamp)
35                 return;
36
37         os_get_time(&tv);
38 #ifdef CONFIG_DEBUG_FILE
39         if (out_file) {
40                 fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
41                         (unsigned int) tv.usec);
42         } else
43 #endif /* CONFIG_DEBUG_FILE */
44         printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
45 }
46
47
48 /**
49  * wpa_printf - conditional printf
50  * @level: priority level (MSG_*) of the message
51  * @fmt: printf format string, followed by optional arguments
52  *
53  * This function is used to print conditional debugging and error messages. The
54  * output may be directed to stdout, stderr, and/or syslog based on
55  * configuration.
56  *
57  * Note: New line '\n' is added to the end of the text when printing to stdout.
58  */
59 void wpa_printf(int level, const char *fmt, ...)
60 {
61         va_list ap;
62
63         va_start(ap, fmt);
64         if (level >= wpa_debug_level) {
65                 wpa_debug_print_timestamp();
66 #ifdef CONFIG_DEBUG_FILE
67                 if (out_file) {
68                         vfprintf(out_file, fmt, ap);
69                         fprintf(out_file, "\n");
70                 } else {
71 #endif /* CONFIG_DEBUG_FILE */
72                 vprintf(fmt, ap);
73                 printf("\n");
74 #ifdef CONFIG_DEBUG_FILE
75                 }
76 #endif /* CONFIG_DEBUG_FILE */
77         }
78         va_end(ap);
79 }
80
81
82 static void _wpa_hexdump(int level, const char *title, const u8 *buf,
83                          size_t len, int show)
84 {
85         size_t i;
86         if (level < wpa_debug_level)
87                 return;
88         wpa_debug_print_timestamp();
89 #ifdef CONFIG_DEBUG_FILE
90         if (out_file) {
91                 fprintf(out_file, "%s - hexdump(len=%lu):",
92                         title, (unsigned long) len);
93                 if (buf == NULL) {
94                         fprintf(out_file, " [NULL]");
95                 } else if (show) {
96                         for (i = 0; i < len; i++)
97                                 fprintf(out_file, " %02x", buf[i]);
98                 } else {
99                         fprintf(out_file, " [REMOVED]");
100                 }
101                 fprintf(out_file, "\n");
102         } else {
103 #endif /* CONFIG_DEBUG_FILE */
104         printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
105         if (buf == NULL) {
106                 printf(" [NULL]");
107         } else if (show) {
108                 for (i = 0; i < len; i++)
109                         printf(" %02x", buf[i]);
110         } else {
111                 printf(" [REMOVED]");
112         }
113         printf("\n");
114 #ifdef CONFIG_DEBUG_FILE
115         }
116 #endif /* CONFIG_DEBUG_FILE */
117 }
118
119 void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
120 {
121         _wpa_hexdump(level, title, buf, len, 1);
122 }
123
124
125 void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
126 {
127         _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
128 }
129
130
131 static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
132                                size_t len, int show)
133 {
134         size_t i, llen;
135         const u8 *pos = buf;
136         const size_t line_len = 16;
137
138         if (level < wpa_debug_level)
139                 return;
140         wpa_debug_print_timestamp();
141 #ifdef CONFIG_DEBUG_FILE
142         if (out_file) {
143                 if (!show) {
144                         fprintf(out_file,
145                                 "%s - hexdump_ascii(len=%lu): [REMOVED]\n",
146                                 title, (unsigned long) len);
147                         return;
148                 }
149                 if (buf == NULL) {
150                         fprintf(out_file,
151                                 "%s - hexdump_ascii(len=%lu): [NULL]\n",
152                                 title, (unsigned long) len);
153                         return;
154                 }
155                 fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
156                         title, (unsigned long) len);
157                 while (len) {
158                         llen = len > line_len ? line_len : len;
159                         fprintf(out_file, "    ");
160                         for (i = 0; i < llen; i++)
161                                 fprintf(out_file, " %02x", pos[i]);
162                         for (i = llen; i < line_len; i++)
163                                 fprintf(out_file, "   ");
164                         fprintf(out_file, "   ");
165                         for (i = 0; i < llen; i++) {
166                                 if (isprint(pos[i]))
167                                         fprintf(out_file, "%c", pos[i]);
168                                 else
169                                         fprintf(out_file, "_");
170                         }
171                         for (i = llen; i < line_len; i++)
172                                 fprintf(out_file, " ");
173                         fprintf(out_file, "\n");
174                         pos += llen;
175                         len -= llen;
176                 }
177         } else {
178 #endif /* CONFIG_DEBUG_FILE */
179         if (!show) {
180                 printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
181                        title, (unsigned long) len);
182                 return;
183         }
184         if (buf == NULL) {
185                 printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
186                        title, (unsigned long) len);
187                 return;
188         }
189         printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
190         while (len) {
191                 llen = len > line_len ? line_len : len;
192                 printf("    ");
193                 for (i = 0; i < llen; i++)
194                         printf(" %02x", pos[i]);
195                 for (i = llen; i < line_len; i++)
196                         printf("   ");
197                 printf("   ");
198                 for (i = 0; i < llen; i++) {
199                         if (isprint(pos[i]))
200                                 printf("%c", pos[i]);
201                         else
202                                 printf("_");
203                 }
204                 for (i = llen; i < line_len; i++)
205                         printf(" ");
206                 printf("\n");
207                 pos += llen;
208                 len -= llen;
209         }
210 #ifdef CONFIG_DEBUG_FILE
211         }
212 #endif /* CONFIG_DEBUG_FILE */
213 }
214
215
216 void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
217 {
218         _wpa_hexdump_ascii(level, title, buf, len, 1);
219 }
220
221
222 void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
223                            size_t len)
224 {
225         _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
226 }
227
228
229 int wpa_debug_open_file(const char *path)
230 {
231 #ifdef CONFIG_DEBUG_FILE
232         if (!path)
233                 return 0;
234         out_file = fopen(path, "a");
235         if (out_file == NULL) {
236                 wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
237                            "output file, using standard output");
238                 return -1;
239         }
240 #ifndef _WIN32
241         setvbuf(out_file, NULL, _IOLBF, 0);
242 #endif /* _WIN32 */
243 #endif /* CONFIG_DEBUG_FILE */
244         return 0;
245 }
246
247
248 void wpa_debug_close_file(void)
249 {
250 #ifdef CONFIG_DEBUG_FILE
251         if (!out_file)
252                 return;
253         fclose(out_file);
254         out_file = NULL;
255 #endif /* CONFIG_DEBUG_FILE */
256 }
257
258 #endif /* CONFIG_NO_STDOUT_DEBUG */
259
260
261 #ifndef CONFIG_NO_WPA_MSG
262 static wpa_msg_cb_func wpa_msg_cb = NULL;
263
264 void wpa_msg_register_cb(wpa_msg_cb_func func)
265 {
266         wpa_msg_cb = func;
267 }
268
269
270 void wpa_msg(void *ctx, int level, const char *fmt, ...)
271 {
272         va_list ap;
273         char *buf;
274         const int buflen = 2048;
275         int len;
276
277         buf = os_malloc(buflen);
278         if (buf == NULL) {
279                 wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
280                            "buffer");
281                 return;
282         }
283         va_start(ap, fmt);
284         len = vsnprintf(buf, buflen, fmt, ap);
285         va_end(ap);
286         wpa_printf(level, "%s", buf);
287         if (wpa_msg_cb)
288                 wpa_msg_cb(ctx, level, buf, len);
289         os_free(buf);
290 }
291
292
293 void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
294 {
295         va_list ap;
296         char *buf;
297         const int buflen = 2048;
298         int len;
299
300         if (!wpa_msg_cb)
301                 return;
302
303         buf = os_malloc(buflen);
304         if (buf == NULL) {
305                 wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate "
306                            "message buffer");
307                 return;
308         }
309         va_start(ap, fmt);
310         len = vsnprintf(buf, buflen, fmt, ap);
311         va_end(ap);
312         wpa_msg_cb(ctx, level, buf, len);
313         os_free(buf);
314 }
315 #endif /* CONFIG_NO_WPA_MSG */
316
317
318 #ifndef CONFIG_NO_HOSTAPD_LOGGER
319 static hostapd_logger_cb_func hostapd_logger_cb = NULL;
320
321 void hostapd_logger_register_cb(hostapd_logger_cb_func func)
322 {
323         hostapd_logger_cb = func;
324 }
325
326
327 void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
328                     const char *fmt, ...)
329 {
330         va_list ap;
331         char *buf;
332         const int buflen = 2048;
333         int len;
334
335         buf = os_malloc(buflen);
336         if (buf == NULL) {
337                 wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate "
338                            "message buffer");
339                 return;
340         }
341         va_start(ap, fmt);
342         len = vsnprintf(buf, buflen, fmt, ap);
343         va_end(ap);
344         if (hostapd_logger_cb)
345                 hostapd_logger_cb(ctx, addr, module, level, buf, len);
346         else
347                 wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf);
348         os_free(buf);
349 }
350 #endif /* CONFIG_NO_HOSTAPD_LOGGER */