mapped libstrongswan debug level to pluto debug options
[strongswan.git] / src / pluto / log.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 * RCSID $Id$
16 */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <ctype.h>
21 #include <stdarg.h>
22 #include <syslog.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <signal.h> /* used only if MSG_NOSIGNAL not defined */
27 #include <sys/queue.h>
28 #include <libgen.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31
32 #include <freeswan.h>
33 #include <debug.h>
34
35 #include "constants.h"
36 #include "defs.h"
37 #include "log.h"
38 #include "server.h"
39 #include "state.h"
40 #include "connections.h"
41 #include "kernel.h"
42 #include "whack.h" /* needs connections.h */
43 #include "timer.h"
44
45 /* close one per-peer log */
46 static void perpeer_logclose(struct connection *c); /* forward */
47
48
49 bool
50 log_to_stderr = TRUE, /* should log go to stderr? */
51 log_to_syslog = TRUE, /* should log go to syslog? */
52 log_to_perpeer= FALSE; /* should log go to per-IP file? */
53
54 bool
55 logged_txt_warning = FALSE; /* should we complain about finding KEY? */
56
57 /* should we complain when we find no local id */
58 bool
59 logged_myid_fqdn_txt_warning = FALSE,
60 logged_myid_ip_txt_warning = FALSE,
61 logged_myid_fqdn_key_warning = FALSE,
62 logged_myid_ip_key_warning = FALSE;
63
64 /* may include trailing / */
65 const char *base_perpeer_logdir = PERPEERLOGDIR;
66 static int perpeer_count = 0;
67
68 /* from sys/queue.h */
69 static TAILQ_HEAD(perpeer, connection) perpeer_list;
70
71
72 /* Context for logging.
73 *
74 * Global variables: must be carefully adjusted at transaction boundaries!
75 * If the context provides a whack file descriptor, messages
76 * should be copied to it -- see whack_log()
77 */
78 int whack_log_fd = NULL_FD; /* only set during whack_handle() */
79 struct state *cur_state = NULL; /* current state, for diagnostics */
80 struct connection *cur_connection = NULL; /* current connection, for diagnostics */
81 const ip_address *cur_from = NULL; /* source of current current message */
82 u_int16_t cur_from_port; /* host order */
83
84 /**
85 * pluto dbg function for libstrongswan
86 */
87 static void pluto_dbg(int level, char *fmt, ...)
88 {
89 int priority = LOG_INFO;
90 char buffer[8192];
91 char *current = buffer, *next;
92 va_list args;
93 int debug_level;
94
95 if (cur_debugging & DBG_PRIVATE)
96 {
97 debug_level = 4;
98 }
99 else if (cur_debugging & DBG_RAW)
100 {
101 debug_level = 3;
102 }
103 else if (cur_debugging & DBG_PARSING)
104 {
105 debug_level = 2;
106 }
107 else
108 {
109 debug_level = 1;
110 }
111
112 if (level <= debug_level)
113 {
114 va_start(args, fmt);
115
116 if (log_to_stderr)
117 {
118 vfprintf(stderr, fmt, args);
119 fprintf(stderr, "\n");
120 }
121 if (log_to_syslog)
122 {
123 /* write in memory buffer first */
124 vsnprintf(buffer, sizeof(buffer), fmt, args);
125
126 /* do a syslog with every line */
127 while (current)
128 {
129 next = strchr(current, '\n');
130 if (next)
131 {
132 *(next++) = '\0';
133 }
134 syslog(priority, "|%s\n", current);
135 current = next;
136 }
137 }
138 va_end(args);
139 }
140 }
141
142 void
143 init_log(const char *program)
144 {
145 /* enable pluto debugging hook for libstrongswan */
146 dbg = pluto_dbg;
147
148 if (log_to_stderr)
149 {
150 setbuf(stderr, NULL);
151 }
152 if (log_to_syslog)
153 {
154 openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
155 }
156 TAILQ_INIT(&perpeer_list);
157 }
158
159 void
160 close_peerlog(void)
161 {
162 /* exit if the queue has not been initialized */
163 if (perpeer_list.tqh_first == NULL)
164 return;
165
166 /* end of queue is given by pointer to "HEAD" */
167 while (TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list)
168 perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer));
169 }
170
171 void
172 close_log(void)
173 {
174 if (log_to_syslog)
175 closelog();
176
177 close_peerlog();
178 }
179
180 /* Sanitize character string in situ: turns dangerous characters into \OOO.
181 * With a bit of work, we could use simpler reps for \\, \r, etc.,
182 * but this is only to protect against something that shouldn't be used.
183 * Truncate resulting string to what fits in buffer.
184 */
185 static size_t
186 sanitize(char *buf, size_t size)
187 {
188 # define UGLY_WIDTH 4 /* width for ugly character: \OOO */
189 size_t len;
190 size_t added = 0;
191 char *p;
192
193 passert(size >= UGLY_WIDTH); /* need room to swing cat */
194
195 /* find right side of string to be sanitized and count
196 * number of columns to be added. Stop on end of string
197 * or lack of room for more result.
198 */
199 for (p = buf; *p != '\0' && &p[added] < &buf[size - UGLY_WIDTH]; )
200 {
201 unsigned char c = *p++;
202
203 if (c == '\\' || !isprint(c))
204 added += UGLY_WIDTH - 1;
205 }
206
207 /* at this point, p points after last original character to be
208 * included. added is how many characters are added to sanitize.
209 * so p[added] will point after last sanitized character.
210 */
211
212 p[added] = '\0';
213 len = &p[added] - buf;
214
215 /* scan backwards, copying characters to their new home
216 * and inserting the expansions for ugly characters.
217 * It is finished when no more shifting is required.
218 * This is a predecrement loop.
219 */
220 while (added != 0)
221 {
222 char fmtd[UGLY_WIDTH + 1];
223 unsigned char c;
224
225 while ((c = *--p) != '\\' && isprint(c))
226 p[added] = c;
227 added -= UGLY_WIDTH - 1;
228 snprintf(fmtd, sizeof(fmtd), "\\%03o", c);
229 memcpy(p + added, fmtd, UGLY_WIDTH);
230 }
231 return len;
232 # undef UGLY_WIDTH
233 }
234
235 /* format a string for the log, with suitable prefixes.
236 * A format starting with ~ indicates that this is a reprocessing
237 * of the message, so prefixing and quoting is suppressed.
238 */
239 static void
240 fmt_log(char *buf, size_t buf_len, const char *fmt, va_list ap)
241 {
242 bool reproc = *fmt == '~';
243 size_t ps;
244 struct connection *c = cur_state != NULL ? cur_state->st_connection
245 : cur_connection;
246
247 buf[0] = '\0';
248 if (reproc)
249 fmt++; /* ~ at start of format suppresses this prefix */
250 else if (c != NULL)
251 {
252 /* start with name of connection */
253 char *const be = buf + buf_len;
254 char *bp = buf;
255
256 snprintf(bp, be - bp, "\"%s\"", c->name);
257 bp += strlen(bp);
258
259 /* if it fits, put in any connection instance information */
260 if (be - bp > CONN_INST_BUF)
261 {
262 fmt_conn_instance(c, bp);
263 bp += strlen(bp);
264 }
265
266 if (cur_state != NULL)
267 {
268 /* state number */
269 snprintf(bp, be - bp, " #%lu", cur_state->st_serialno);
270 bp += strlen(bp);
271 }
272 snprintf(bp, be - bp, ": ");
273 }
274 else if (cur_from != NULL)
275 {
276 /* peer's IP address */
277 /* Note: must not use ip_str() because our caller might! */
278 char ab[ADDRTOT_BUF];
279
280 (void) addrtot(cur_from, 0, ab, sizeof(ab));
281 snprintf(buf, buf_len, "packet from %s:%u: "
282 , ab, (unsigned)cur_from_port);
283 }
284
285 ps = strlen(buf);
286 vsnprintf(buf + ps, buf_len - ps, fmt, ap);
287 if (!reproc)
288 (void)sanitize(buf, buf_len);
289 }
290
291 static void
292 perpeer_logclose(struct connection *c)
293 {
294 /* only free/close things if we had used them! */
295 if (c->log_file != NULL)
296 {
297 passert(perpeer_count > 0);
298
299 TAILQ_REMOVE(&perpeer_list, c, log_link);
300 perpeer_count--;
301 fclose(c->log_file);
302 c->log_file=NULL;
303 }
304 }
305
306 void
307 perpeer_logfree(struct connection *c)
308 {
309 perpeer_logclose(c);
310 if (c->log_file_name != NULL)
311 {
312 free(c->log_file_name);
313 c->log_file_name = NULL;
314 c->log_file_err = FALSE;
315 }
316 }
317
318 /* open the per-peer log */
319 static void
320 open_peerlog(struct connection *c)
321 {
322 syslog(LOG_INFO, "opening log file for conn %s", c->name);
323
324 if (c->log_file_name == NULL)
325 {
326 char peername[ADDRTOT_BUF], dname[ADDRTOT_BUF];
327 int peernamelen, lf_len;
328
329 addrtot(&c->spd.that.host_addr, 'Q', peername, sizeof(peername));
330 peernamelen = strlen(peername);
331
332 /* copy IP address, turning : and . into / */
333 {
334 char c, *p, *q;
335
336 p = peername;
337 q = dname;
338 do {
339 c = *p++;
340 if (c == '.' || c == ':')
341 c = '/';
342 *q++ = c;
343 } while (c != '\0');
344 }
345
346 lf_len = peernamelen * 2
347 + strlen(base_perpeer_logdir)
348 + sizeof("//.log")
349 + 1;
350 c->log_file_name = malloc(lf_len);
351
352 fprintf(stderr, "base dir |%s| dname |%s| peername |%s|"
353 , base_perpeer_logdir, dname, peername);
354 snprintf(c->log_file_name, lf_len, "%s/%s/%s.log"
355 , base_perpeer_logdir, dname, peername);
356
357 syslog(LOG_DEBUG, "conn %s logfile is %s", c->name, c->log_file_name);
358 }
359
360 /* now open the file, creating directories if necessary */
361
362 { /* create the directory */
363 char *dname;
364 int bpl_len = strlen(base_perpeer_logdir);
365 char *slashloc;
366
367 dname = clone_str(c->log_file_name);
368 dname = dirname(dname);
369
370 if (access(dname, W_OK) != 0)
371 {
372 if (errno != ENOENT)
373 {
374 if (c->log_file_err)
375 {
376 syslog(LOG_CRIT, "can not write to %s: %s"
377 , dname, strerror(errno));
378 c->log_file_err = TRUE;
379 free(dname);
380 return;
381 }
382 }
383
384 /* directory does not exist, walk path creating dirs */
385 /* start at base_perpeer_logdir */
386 slashloc = dname + bpl_len;
387 slashloc++; /* since, by construction there is a slash
388 right there */
389
390 while (*slashloc != '\0')
391 {
392 char saveslash;
393
394 /* look for next slash */
395 while (*slashloc != '\0' && *slashloc != '/') slashloc++;
396
397 saveslash = *slashloc;
398
399 *slashloc = '\0';
400
401 if (mkdir(dname, 0750) != 0 && errno != EEXIST)
402 {
403 syslog(LOG_CRIT, "can not create dir %s: %s"
404 , dname, strerror(errno));
405 c->log_file_err = TRUE;
406 free(dname);
407 return;
408 }
409 syslog(LOG_DEBUG, "created new directory %s", dname);
410 *slashloc = saveslash;
411 slashloc++;
412 }
413 }
414 free(dname);
415 }
416
417 c->log_file = fopen(c->log_file_name, "a");
418 if (c->log_file == NULL)
419 {
420 if (c->log_file_err)
421 {
422 syslog(LOG_CRIT, "logging system can not open %s: %s"
423 , c->log_file_name, strerror(errno));
424 c->log_file_err = TRUE;
425 }
426 return;
427 }
428
429 /* look for a connection to close! */
430 while (perpeer_count >= MAX_PEERLOG_COUNT)
431 {
432 /* can not be NULL because perpeer_count > 0 */
433 passert(TAILQ_LAST(&perpeer_list, perpeer) != (void *)&perpeer_list);
434
435 perpeer_logclose(TAILQ_LAST(&perpeer_list, perpeer));
436 }
437
438 /* insert this into the list */
439 TAILQ_INSERT_HEAD(&perpeer_list, c, log_link);
440 passert(c->log_file != NULL);
441 perpeer_count++;
442 }
443
444 /* log a line to cur_connection's log */
445 static void
446 peerlog(const char *prefix, const char *m)
447 {
448 if (cur_connection == NULL)
449 {
450 /* we can not log it in this case. Oh well. */
451 return;
452 }
453
454 if (cur_connection->log_file == NULL)
455 {
456 open_peerlog(cur_connection);
457 }
458
459 /* despite our attempts above, we may not be able to open the file. */
460 if (cur_connection->log_file != NULL)
461 {
462 char datebuf[32];
463 time_t n;
464 struct tm *t;
465
466 time(&n);
467 t = localtime(&n);
468
469 strftime(datebuf, sizeof(datebuf), "%Y-%m-%d %T", t);
470 fprintf(cur_connection->log_file, "%s %s%s\n", datebuf, prefix, m);
471
472 /* now move it to the front of the list */
473 TAILQ_REMOVE(&perpeer_list, cur_connection, log_link);
474 TAILQ_INSERT_HEAD(&perpeer_list, cur_connection, log_link);
475 }
476 }
477
478 void
479 plog(const char *message, ...)
480 {
481 va_list args;
482 char m[LOG_WIDTH]; /* longer messages will be truncated */
483
484 va_start(args, message);
485 fmt_log(m, sizeof(m), message, args);
486 va_end(args);
487
488 if (log_to_stderr)
489 fprintf(stderr, "%s\n", m);
490 if (log_to_syslog)
491 syslog(LOG_WARNING, "%s", m);
492 if (log_to_perpeer)
493 peerlog("", m);
494
495 whack_log(RC_LOG, "~%s", m);
496 }
497
498 void
499 loglog(int mess_no, const char *message, ...)
500 {
501 va_list args;
502 char m[LOG_WIDTH]; /* longer messages will be truncated */
503
504 va_start(args, message);
505 fmt_log(m, sizeof(m), message, args);
506 va_end(args);
507
508 if (log_to_stderr)
509 fprintf(stderr, "%s\n", m);
510 if (log_to_syslog)
511 syslog(LOG_WARNING, "%s", m);
512 if (log_to_perpeer)
513 peerlog("", m);
514
515 whack_log(mess_no, "~%s", m);
516 }
517
518 void
519 log_errno_routine(int e, const char *message, ...)
520 {
521 va_list args;
522 char m[LOG_WIDTH]; /* longer messages will be truncated */
523
524 va_start(args, message);
525 fmt_log(m, sizeof(m), message, args);
526 va_end(args);
527
528 if (log_to_stderr)
529 fprintf(stderr, "ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
530 if (log_to_syslog)
531 syslog(LOG_ERR, "ERROR: %s. Errno %d: %s", m, e, strerror(e));
532 if (log_to_perpeer)
533 {
534 peerlog(strerror(e), m);
535 }
536
537 whack_log(RC_LOG_SERIOUS
538 , "~ERROR: %s. Errno %d: %s", m, e, strerror(e));
539 }
540
541 void
542 exit_log(const char *message, ...)
543 {
544 va_list args;
545 char m[LOG_WIDTH]; /* longer messages will be truncated */
546
547 va_start(args, message);
548 fmt_log(m, sizeof(m), message, args);
549 va_end(args);
550
551 if (log_to_stderr)
552 fprintf(stderr, "FATAL ERROR: %s\n", m);
553 if (log_to_syslog)
554 syslog(LOG_ERR, "FATAL ERROR: %s", m);
555 if (log_to_perpeer)
556 peerlog("FATAL ERROR: ", m);
557
558 whack_log(RC_LOG_SERIOUS, "~FATAL ERROR: %s", m);
559
560 exit_pluto(1);
561 }
562
563 void
564 exit_log_errno_routine(int e, const char *message, ...)
565 {
566 va_list args;
567 char m[LOG_WIDTH]; /* longer messages will be truncated */
568
569 va_start(args, message);
570 fmt_log(m, sizeof(m), message, args);
571 va_end(args);
572
573 if (log_to_stderr)
574 fprintf(stderr, "FATAL ERROR: %s. Errno %d: %s\n", m, e, strerror(e));
575 if (log_to_syslog)
576 syslog(LOG_ERR, "FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
577 if (log_to_perpeer)
578 peerlog(strerror(e), m);
579
580 whack_log(RC_LOG_SERIOUS
581 , "~FATAL ERROR: %s. Errno %d: %s", m, e, strerror(e));
582
583 exit_pluto(1);
584 }
585
586 /* emit message to whack.
587 * form is "ddd statename text" where
588 * - ddd is a decimal status code (RC_*) as described in whack.h
589 * - text is a human-readable annotation
590 */
591 #ifdef DEBUG
592 static volatile sig_atomic_t dying_breath = FALSE;
593 #endif
594
595 void
596 whack_log(int mess_no, const char *message, ...)
597 {
598 int wfd = whack_log_fd != NULL_FD ? whack_log_fd
599 : cur_state != NULL ? cur_state->st_whack_sock
600 : NULL_FD;
601
602 if (wfd != NULL_FD
603 #ifdef DEBUG
604 || dying_breath
605 #endif
606 )
607 {
608 va_list args;
609 char m[LOG_WIDTH]; /* longer messages will be truncated */
610 int prelen = snprintf(m, sizeof(m), "%03d ", mess_no);
611
612 passert(prelen >= 0);
613
614 va_start(args, message);
615 fmt_log(m+prelen, sizeof(m)-prelen, message, args);
616 va_end(args);
617
618 #if DEBUG
619 if (dying_breath)
620 {
621 /* status output copied to log */
622 if (log_to_stderr)
623 fprintf(stderr, "%s\n", m + prelen);
624 if (log_to_syslog)
625 syslog(LOG_WARNING, "%s", m + prelen);
626 if (log_to_perpeer)
627 peerlog("", m);
628 }
629 #endif
630
631 if (wfd != NULL_FD)
632 {
633 /* write to whack socket, but suppress possible SIGPIPE */
634 size_t len = strlen(m);
635 #ifdef MSG_NOSIGNAL /* depends on version of glibc??? */
636 m[len] = '\n'; /* don't need NUL, do need NL */
637 (void) send(wfd, m, len + 1, MSG_NOSIGNAL);
638 #else /* !MSG_NOSIGNAL */
639 int r;
640 struct sigaction act
641 , oldact;
642
643 m[len] = '\n'; /* don't need NUL, do need NL */
644 act.sa_handler = SIG_IGN;
645 sigemptyset(&act.sa_mask);
646 act.sa_flags = 0; /* no nothing */
647 r = sigaction(SIGPIPE, &act, &oldact);
648 passert(r == 0);
649
650 (void) write(wfd, m, len + 1);
651
652 r = sigaction(SIGPIPE, &oldact, NULL);
653 passert(r == 0);
654 #endif /* !MSG_NOSIGNAL */
655 }
656 }
657 }
658
659 /* Build up a diagnostic in a static buffer.
660 * Although this would be a generally useful function, it is very
661 * hard to come up with a discipline that prevents different uses
662 * from interfering. It is intended that by limiting it to building
663 * diagnostics, we will avoid this problem.
664 * Juggling is performed to allow an argument to be a previous
665 * result: the new string may safely depend on the old one. This
666 * restriction is not checked in any way: violators will produce
667 * confusing results (without crashing!).
668 */
669 char diag_space[sizeof(diag_space)];
670
671 err_t
672 builddiag(const char *fmt, ...)
673 {
674 static char diag_space[LOG_WIDTH]; /* longer messages will be truncated */
675 char t[sizeof(diag_space)]; /* build result here first */
676 va_list args;
677
678 va_start(args, fmt);
679 t[0] = '\0'; /* in case nothing terminates string */
680 vsnprintf(t, sizeof(t), fmt, args);
681 va_end(args);
682 strcpy(diag_space, t);
683 return diag_space;
684 }
685
686 /* Debugging message support */
687
688 #ifdef DEBUG
689
690 void
691 switch_fail(int n, const char *file_str, unsigned long line_no)
692 {
693 char buf[30];
694
695 snprintf(buf, sizeof(buf), "case %d unexpected", n);
696 passert_fail(buf, file_str, line_no);
697 }
698
699 void
700 passert_fail(const char *pred_str, const char *file_str, unsigned long line_no)
701 {
702 /* we will get a possibly unplanned prefix. Hope it works */
703 loglog(RC_LOG_SERIOUS, "ASSERTION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
704 if (!dying_breath)
705 {
706 dying_breath = TRUE;
707 show_status(TRUE, NULL);
708 }
709 abort(); /* exiting correctly doesn't always work */
710 }
711
712 void
713 pexpect_log(const char *pred_str, const char *file_str, unsigned long line_no)
714 {
715 /* we will get a possibly unplanned prefix. Hope it works */
716 loglog(RC_LOG_SERIOUS, "EXPECTATION FAILED at %s:%lu: %s", file_str, line_no, pred_str);
717 }
718
719 lset_t
720 base_debugging = DBG_NONE, /* default to reporting nothing */
721 cur_debugging = DBG_NONE;
722
723 void
724 extra_debugging(const struct connection *c)
725 {
726 if(c == NULL)
727 {
728 reset_debugging();
729 return;
730 }
731
732 if (c!= NULL && c->extra_debugging != 0)
733 {
734 plog("enabling for connection: %s"
735 , bitnamesof(debug_bit_names, c->extra_debugging & ~cur_debugging));
736 cur_debugging |= c->extra_debugging;
737 }
738 }
739
740 /* log a debugging message (prefixed by "| ") */
741
742 void
743 DBG_log(const char *message, ...)
744 {
745 va_list args;
746 char m[LOG_WIDTH]; /* longer messages will be truncated */
747
748 va_start(args, message);
749 vsnprintf(m, sizeof(m), message, args);
750 va_end(args);
751
752 (void)sanitize(m, sizeof(m));
753
754 if (log_to_stderr)
755 fprintf(stderr, "| %s\n", m);
756 if (log_to_syslog)
757 syslog(LOG_DEBUG, "| %s", m);
758 if (log_to_perpeer)
759 peerlog("| ", m);
760 }
761
762 /* dump raw bytes in hex to stderr (for lack of any better destination) */
763
764 void
765 DBG_dump(const char *label, const void *p, size_t len)
766 {
767 # define DUMP_LABEL_WIDTH 20 /* arbitrary modest boundary */
768 # define DUMP_WIDTH (4 * (1 + 4 * 3) + 1)
769 char buf[DUMP_LABEL_WIDTH + DUMP_WIDTH];
770 char *bp;
771 const unsigned char *cp = p;
772
773 bp = buf;
774
775 if (label != NULL && label[0] != '\0')
776 {
777 /* Handle the label. Care must be taken to avoid buffer overrun. */
778 size_t llen = strlen(label);
779
780 if (llen + 1 > sizeof(buf))
781 {
782 DBG_log("%s", label);
783 }
784 else
785 {
786 strcpy(buf, label);
787 if (buf[llen-1] == '\n')
788 {
789 buf[llen-1] = '\0'; /* get rid of newline */
790 DBG_log("%s", buf);
791 }
792 else if (llen < DUMP_LABEL_WIDTH)
793 {
794 bp = buf + llen;
795 }
796 else
797 {
798 DBG_log("%s", buf);
799 }
800 }
801 }
802
803 do {
804 int i, j;
805
806 for (i = 0; len!=0 && i!=4; i++)
807 {
808 *bp++ = ' ';
809 for (j = 0; len!=0 && j!=4; len--, j++)
810 {
811 static const char hexdig[] = "0123456789abcdef";
812
813 *bp++ = ' ';
814 *bp++ = hexdig[(*cp >> 4) & 0xF];
815 *bp++ = hexdig[*cp & 0xF];
816 cp++;
817 }
818 }
819 *bp = '\0';
820 DBG_log("%s", buf);
821 bp = buf;
822 } while (len != 0);
823 # undef DUMP_LABEL_WIDTH
824 # undef DUMP_WIDTH
825 }
826
827 #endif /* DEBUG */
828
829 void
830 show_status(bool all, const char *name)
831 {
832 if (all)
833 {
834 show_ifaces_status();
835 show_myid_status();
836 show_debug_status();
837 whack_log(RC_COMMENT, BLANK_FORMAT); /* spacer */
838 }
839 show_connections_status(all, name);
840 show_states_status(all, name);
841 #ifdef KLIPS
842 show_shunt_status();
843 #endif
844 }
845
846 /* ip_str: a simple to use variant of addrtot.
847 * It stores its result in a static buffer.
848 * This means that newer calls overwrite the storage of older calls.
849 * Note: this is not used in any of the logging functions, so their
850 * callers may use it.
851 */
852 const char *
853 ip_str(const ip_address *src)
854 {
855 static char buf[ADDRTOT_BUF];
856
857 addrtot(src, 0, buf, sizeof(buf));
858 return buf;
859 }
860
861 /*
862 * a routine that attempts to schedule itself daily.
863 *
864 */
865
866 void
867 daily_log_reset(void)
868 {
869 /* now perform actions */
870 logged_txt_warning = FALSE;
871
872 logged_myid_fqdn_txt_warning = FALSE;
873 logged_myid_ip_txt_warning = FALSE;
874 logged_myid_fqdn_key_warning = FALSE;
875 logged_myid_ip_key_warning = FALSE;
876 }
877
878 void
879 daily_log_event(void)
880 {
881 struct tm *ltime;
882 time_t n, interval;
883
884 /* attempt to schedule oneself to midnight, local time
885 * do this by getting seconds in the day, and delaying
886 * by 86400 - hour*3600+minutes*60+seconds.
887 */
888 time(&n);
889 ltime = localtime(&n);
890 interval = (24 * 60 * 60)
891 - (ltime->tm_sec
892 + ltime->tm_min * 60
893 + ltime->tm_hour * 3600);
894
895 event_schedule(EVENT_LOG_DAILY, interval, NULL);
896
897 daily_log_reset();
898 }
899
900 /*
901 * Local Variables:
902 * c-basic-offset:4
903 * c-style: pluto
904 * End:
905 */