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