Show contents of the CP payload in message_t stringification
[strongswan.git] / src / scepclient / loglite.c
1 /* error logging functions
2 * Copyright (C) 1997 Angelos D. Keromytis.
3 * Copyright (C) 1998-2001 D. Hugh Redelmeier.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <ctype.h>
19 #include <stdarg.h>
20 #include <syslog.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <signal.h> /* used only if MSG_NOSIGNAL not defined */
25 #include <libgen.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28
29 #include <freeswan.h>
30 #include <debug.h>
31
32 #include <constants.h>
33 #include <defs.h>
34 #include <log.h>
35 #include <whack.h>
36
37 bool
38 log_to_stderr = FALSE, /* should log go to stderr? */
39 log_to_syslog = TRUE; /* should log go to syslog? */
40
41 /**
42 * @brief scepclient dbg function
43 */
44 static void scepclient_dbg(debug_t group, level_t level, char *fmt, ...)
45 {
46 int priority = LOG_INFO;
47 int debug_level;
48 char buffer[8192];
49 char *current = buffer, *next;
50 va_list args;
51
52 if (cur_debugging & DBG_PRIVATE)
53 {
54 debug_level = 4;
55 }
56 else if (cur_debugging & DBG_RAW)
57 {
58 debug_level = 3;
59 }
60 else if (cur_debugging & DBG_PARSING)
61 {
62 debug_level = 2;
63 }
64 else
65 {
66 debug_level = 1;
67 }
68
69 if (level <= debug_level)
70 {
71 if (log_to_stderr)
72 {
73 if (level > 1)
74 {
75 fprintf(stderr, "| ");
76 }
77 va_start(args, fmt);
78 vfprintf(stderr, fmt, args);
79 va_end(args);
80 fprintf(stderr, "\n");
81 }
82 if (log_to_syslog)
83 {
84 /* write in memory buffer first */
85 va_start(args, fmt);
86 vsnprintf(buffer, sizeof(buffer), fmt, args);
87 va_end(args);
88
89 /* do a syslog with every line */
90 while (current)
91 {
92 next = strchr(current, '\n');
93 if (next)
94 {
95 *(next++) = '\0';
96 }
97 syslog(priority, "%s%s\n", (level > 1)? "| ":"", current);
98 current = next;
99 }
100 }
101 }
102 }
103
104 void init_log(const char *program)
105 {
106 /* enable scepclient bugging hook */
107 dbg = scepclient_dbg;
108
109 if (log_to_stderr)
110 {
111 setbuf(stderr, NULL);
112 }
113 if (log_to_syslog)
114 {
115 openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
116 }
117 }
118
119 void close_log(void)
120 {
121 if (log_to_syslog)
122 closelog();
123 }
124
125 void plog(const char *message, ...)
126 {
127 va_list args;
128 char m[LOG_WIDTH]; /* longer messages will be truncated */
129
130 va_start(args, message);
131 vsnprintf(m, sizeof(m), message, args);
132 va_end(args);
133
134 if (log_to_stderr)
135 fprintf(stderr, "%s\n", m);
136 if (log_to_syslog)
137 syslog(LOG_WARNING, "%s", m);
138 }
139
140 void loglog(int mess_no, const char *message, ...)
141 {
142 va_list args;
143 char m[LOG_WIDTH]; /* longer messages will be truncated */
144
145 va_start(args, message);
146 vsnprintf(m, sizeof(m), message, args);
147 va_end(args);
148
149 if (log_to_stderr)
150 fprintf(stderr, "%s\n", m);
151 if (log_to_syslog)
152 syslog(LOG_WARNING, "%s", m);
153 }
154
155 void log_errno_routine(int e, const char *message, ...)
156 {
157 va_list args;
158 char m[LOG_WIDTH]; /* longer messages will be truncated */
159
160 va_start(args, message);
161 vsnprintf(m, sizeof(m), message, args);
162 va_end(args);
163
164 if (log_to_stderr)
165 fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
166 if (log_to_syslog)
167 syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e));
168 }
169
170 void exit_log(const char *message, ...)
171 {
172 va_list args;
173 char m[LOG_WIDTH]; /* longer messages will be truncated */
174
175 va_start(args, message);
176 vsnprintf(m, sizeof(m), message, args);
177 va_end(args);
178
179 if (log_to_stderr)
180 fprintf(stderr, "FATAL ERROR: %s\n", m);
181 if (log_to_syslog)
182 syslog(LOG_ERR, "FATAL ERROR: %s", m);
183 exit(1);
184 }
185
186 void exit_log_errno_routine(int e, const char *message, ...)
187 {
188 va_list args;
189 char m[LOG_WIDTH]; /* longer messages will be truncated */
190
191 va_start(args, message);
192 vsnprintf(m, sizeof(m), message, args);
193 va_end(args);
194
195 if (log_to_stderr)
196 fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
197 if (log_to_syslog)
198 syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
199 exit(1);
200 }
201
202 void whack_log(int mess_no, const char *message, ...)
203 {
204 va_list args;
205 char m[LOG_WIDTH]; /* longer messages will be truncated */
206
207 va_start(args, message);
208 vsnprintf(m, sizeof(m), message, args);
209 va_end(args);
210
211 fprintf(stderr, "%s\n", m);
212 }
213
214 /* Build up a diagnostic in a static buffer.
215 * Although this would be a generally useful function, it is very
216 * hard to come up with a discipline that prevents different uses
217 * from interfering. It is intended that by limiting it to building
218 * diagnostics, we will avoid this problem.
219 * Juggling is performed to allow an argument to be a previous
220 * result: the new string may safely depend on the old one. This
221 * restriction is not checked in any way: violators will produce
222 * confusing results (without crashing!).
223 */
224 char diag_space[sizeof(diag_space)];
225
226 err_t builddiag(const char *fmt, ...)
227 {
228 static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */
229 char t[sizeof(diag_space)]; /* build result here first */
230 va_list args;
231
232 va_start(args, fmt);
233 t[0] = '\0'; /* in case nothing terminates string */
234 vsnprintf(t, sizeof(t), fmt, args);
235 va_end(args);
236 strcpy(diag_space, t);
237 return diag_space;
238 }
239
240 /* Debugging message support */
241
242 #ifdef DEBUG
243
244 void switch_fail(int n, const char *file_str, unsigned long line_no)
245 {
246 char buf[30];
247
248 snprintf(buf, sizeof(buf), "case %d unexpected", n);
249 passert_fail(buf, file_str, line_no);
250 }
251
252 void passert_fail(const char *pred_str, const char *file_str, unsigned long line_no)
253 {
254 /* we will get a possibly unplanned prefix. Hope it works */
255 loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
256 abort(); /* exiting correctly doesn't always work */
257 }
258
259 lset_t
260 base_debugging = DBG_NONE, /* default to reporting nothing */
261 cur_debugging = DBG_NONE;
262
263 void pexpect_log(const char *pred_str, const char *file_str, unsigned long line_no)
264 {
265 /* we will get a possibly unplanned prefix. Hope it works */
266 loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
267 }
268
269 /* log a debugging message (prefixed by "| ") */
270
271 void DBG_log(const char *message, ...)
272 {
273 va_list args;
274 char m[LOG_WIDTH]; /* longer messages will be truncated */
275
276 va_start(args, message);
277 vsnprintf(m, sizeof(m), message, args);
278 va_end(args);
279
280 if (log_to_stderr)
281 fprintf(stderr, "| %s\n", m);
282 if (log_to_syslog)
283 syslog(LOG_DEBUG, "| %s", m);
284 }
285
286 /* dump raw bytes in hex to stderr (for lack of any better destination) */
287
288 void DBG_dump(const char *label, const void *p, size_t len)
289 {
290 # define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */
291 # define DUMP_WIDTH (4 * (1 + 4 * 3) + 1)
292 char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH];
293 char *bp;
294 const unsigned char *cp = p;
295
296 bp = buf;
297
298 if (label != NULL && label[0] != '\0')
299 {
300 /* Handle the label. Care must be taken to avoid buffer overrun. */
301 size_t llen = strlen(label);
302
303 if (llen + 1 > sizeof(buf))
304 {
305 DBG_log("%s", label);
306 }
307 else
308 {
309 strcpy(buf, label);
310 if (buf[llen-1] == '\n')
311 {
312 buf[llen-1] = '\0'; /* get rid of newline */
313 DBG_log("%s", buf);
314 }
315 else if (llen < DUMP_LABEL_WIDTH)
316 {
317 bp = buf + llen;
318 }
319 else
320 {
321 DBG_log("%s", buf);
322 }
323 }
324 }
325
326 do {
327 int i, j;
328
329 for (i = 0; len!=0 && i!=4; i++)
330 {
331 *bp++ = ' ';
332 for (j = 0; len!=0 && j!=4; len--, j++)
333 {
334 static const char hexdig[] = "0123456789abcdef";
335
336 *bp++ = ' ';
337 *bp++ = hexdig[(*cp >> 4) & 0xF];
338 *bp++ = hexdig[*cp & 0xF];
339 cp++;
340 }
341 }
342 *bp = '\0';
343 DBG_log("%s", buf);
344 bp = buf;
345 } while (len != 0);
346 # undef DUMP_LABEL_WIDTH
347 # undef DUMP_WIDTH
348 }
349
350 #endif /* DEBUG */