]>
Commit | Line | Data |
---|---|---|
6fc6879b JM |
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, 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, 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 | #endif /* CONFIG_NO_WPA_MSG */ | |
292 | ||
293 | ||
294 | #ifndef CONFIG_NO_HOSTAPD_LOGGER | |
295 | static hostapd_logger_cb_func hostapd_logger_cb = NULL; | |
296 | ||
297 | void hostapd_logger_register_cb(hostapd_logger_cb_func func) | |
298 | { | |
299 | hostapd_logger_cb = func; | |
300 | } | |
301 | ||
302 | ||
303 | void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, | |
304 | const char *fmt, ...) | |
305 | { | |
306 | va_list ap; | |
307 | char *buf; | |
308 | const int buflen = 2048; | |
309 | int len; | |
310 | ||
311 | buf = os_malloc(buflen); | |
312 | if (buf == NULL) { | |
313 | wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " | |
314 | "message buffer"); | |
315 | return; | |
316 | } | |
317 | va_start(ap, fmt); | |
318 | len = vsnprintf(buf, buflen, fmt, ap); | |
319 | va_end(ap); | |
320 | if (hostapd_logger_cb) | |
321 | hostapd_logger_cb(ctx, addr, module, level, buf, len); | |
322 | else | |
323 | wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); | |
324 | os_free(buf); | |
325 | } | |
326 | #endif /* CONFIG_NO_HOSTAPD_LOGGER */ |