blob: dbd378fd7ee226a927deb7df97796bce2a709fec [file] [log] [blame]
ajs274a4a42004-12-07 15:39:31 +00001/*
ajs1e221352005-02-03 16:42:40 +00002 * $Id: log.c,v 1.24 2005/02/03 16:42:40 ajs Exp $
ajs274a4a42004-12-07 15:39:31 +00003 *
4 * Logging of zebra
paul718e3742002-12-13 20:15:29 +00005 * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro
6 *
7 * This file is part of GNU Zebra.
8 *
9 * GNU Zebra is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
12 * later version.
13 *
14 * GNU Zebra is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with GNU Zebra; see the file COPYING. If not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 * 02111-1307, USA.
23 */
24
25#include <zebra.h>
26
27#include "log.h"
28#include "memory.h"
29#include "command.h"
ajs7d149b82004-11-28 23:00:01 +000030#ifndef SUNOS_5
31#include <sys/un.h>
32#endif
paul718e3742002-12-13 20:15:29 +000033
ajs1e221352005-02-03 16:42:40 +000034static int crashlog_fd = -1; /* Used for last-resort crash logfile when a
35 signal is caught. */
36
paul718e3742002-12-13 20:15:29 +000037struct zlog *zlog_default = NULL;
38
39const char *zlog_proto_names[] =
40{
41 "NONE",
42 "DEFAULT",
43 "ZEBRA",
44 "RIP",
45 "BGP",
46 "OSPF",
47 "RIPNG",
48 "OSPF6",
jardin9e867fe2003-12-23 08:56:18 +000049 "ISIS",
paul718e3742002-12-13 20:15:29 +000050 "MASC",
51 NULL,
52};
53
54const char *zlog_priority[] =
55{
56 "emergencies",
57 "alerts",
58 "critical",
59 "errors",
60 "warnings",
61 "notifications",
62 "informational",
63 "debugging",
64 NULL,
65};
66
67
68
69/* For time string format. */
70#define TIME_BUF 27
71
72/* Utility routine for current time printing. */
73static void
74time_print (FILE *fp)
75{
76 int ret;
77 char buf [TIME_BUF];
78 time_t clock;
79 struct tm *tm;
80
81 time (&clock);
82 tm = localtime (&clock);
83
84 ret = strftime (buf, TIME_BUF, "%Y/%m/%d %H:%M:%S", tm);
85 if (ret == 0) {
86 zlog_warn ("strftime error");
87 }
88
89 fprintf (fp, "%s ", buf);
90}
91
92/* va_list version of zlog. */
ajsd246bd92004-11-23 17:35:08 +000093static void
94vzlog (struct zlog *zl, int priority, const char *format, va_list args)
paul718e3742002-12-13 20:15:29 +000095{
96 /* If zlog is not specified, use default one. */
97 if (zl == NULL)
98 zl = zlog_default;
99
100 /* When zlog_default is also NULL, use stderr for logging. */
101 if (zl == NULL)
102 {
103 time_print (stderr);
104 fprintf (stderr, "%s: ", "unknown");
ajsd246bd92004-11-23 17:35:08 +0000105 vfprintf (stderr, format, args);
paul718e3742002-12-13 20:15:29 +0000106 fprintf (stderr, "\n");
107 fflush (stderr);
108
109 /* In this case we return at here. */
110 return;
111 }
112
paul718e3742002-12-13 20:15:29 +0000113 /* Syslog output */
ajs274a4a42004-12-07 15:39:31 +0000114 if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG])
ajsd246bd92004-11-23 17:35:08 +0000115 {
116 va_list ac;
117 va_copy(ac, args);
118 vsyslog (priority|zlog_default->facility, format, ac);
119 va_end(ac);
120 }
paul718e3742002-12-13 20:15:29 +0000121
122 /* File output. */
ajs274a4a42004-12-07 15:39:31 +0000123 if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp)
paul718e3742002-12-13 20:15:29 +0000124 {
ajsd246bd92004-11-23 17:35:08 +0000125 va_list ac;
paul718e3742002-12-13 20:15:29 +0000126 time_print (zl->fp);
hassob04c6992004-10-04 19:10:31 +0000127 if (zl->record_priority)
128 fprintf (zl->fp, "%s: ", zlog_priority[priority]);
paul718e3742002-12-13 20:15:29 +0000129 fprintf (zl->fp, "%s: ", zlog_proto_names[zl->protocol]);
ajsd246bd92004-11-23 17:35:08 +0000130 va_copy(ac, args);
131 vfprintf (zl->fp, format, ac);
132 va_end(ac);
paul718e3742002-12-13 20:15:29 +0000133 fprintf (zl->fp, "\n");
134 fflush (zl->fp);
135 }
136
137 /* stdout output. */
ajs274a4a42004-12-07 15:39:31 +0000138 if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT])
paul718e3742002-12-13 20:15:29 +0000139 {
ajsd246bd92004-11-23 17:35:08 +0000140 va_list ac;
paul718e3742002-12-13 20:15:29 +0000141 time_print (stdout);
hassob04c6992004-10-04 19:10:31 +0000142 if (zl->record_priority)
143 fprintf (stdout, "%s: ", zlog_priority[priority]);
paul718e3742002-12-13 20:15:29 +0000144 fprintf (stdout, "%s: ", zlog_proto_names[zl->protocol]);
ajsd246bd92004-11-23 17:35:08 +0000145 va_copy(ac, args);
146 vfprintf (stdout, format, ac);
147 va_end(ac);
paul718e3742002-12-13 20:15:29 +0000148 fprintf (stdout, "\n");
149 fflush (stdout);
150 }
151
paul718e3742002-12-13 20:15:29 +0000152 /* Terminal monitor. */
ajs274a4a42004-12-07 15:39:31 +0000153 if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR])
154 vty_log ((zl->record_priority ? zlog_priority[priority] : NULL),
155 zlog_proto_names[zl->protocol], format, args);
paul718e3742002-12-13 20:15:29 +0000156}
157
ajs59a06a92004-11-23 18:19:14 +0000158static char *
159str_append(char *dst, int len, const char *src)
160{
161 while ((len-- > 0) && *src)
162 *dst++ = *src++;
163 return dst;
164}
165
166static char *
167num_append(char *s, int len, u_long x)
168{
169 char buf[30];
ajs7d149b82004-11-28 23:00:01 +0000170 char *t;
ajs59a06a92004-11-23 18:19:14 +0000171
ajs7d149b82004-11-28 23:00:01 +0000172 if (!x)
173 return str_append(s,len,"0");
174 *(t = &buf[sizeof(buf)-1]) = '\0';
ajs59a06a92004-11-23 18:19:14 +0000175 while (x && (t > buf))
176 {
177 *--t = '0'+(x % 10);
178 x /= 10;
179 }
180 return str_append(s,len,t);
181}
182
ajs31364272005-01-18 22:18:59 +0000183#if defined(SA_SIGINFO) || defined(HAVE_GLIBC_BACKTRACE)
ajs7d149b82004-11-28 23:00:01 +0000184static char *
185hex_append(char *s, int len, u_long x)
186{
187 char buf[30];
188 char *t;
189
190 if (!x)
191 return str_append(s,len,"0");
192 *(t = &buf[sizeof(buf)-1]) = '\0';
193 while (x && (t > buf))
194 {
195 u_int cc = (x % 16);
196 *--t = ((cc < 10) ? ('0'+cc) : ('a'+cc-10));
197 x /= 16;
198 }
199 return str_append(s,len,t);
200}
ajs31364272005-01-18 22:18:59 +0000201#endif
ajs7d149b82004-11-28 23:00:01 +0000202
ajs7d149b82004-11-28 23:00:01 +0000203/* Needs to be enhanced to support Solaris. */
204static int
205syslog_connect(void)
206{
207#ifdef SUNOS_5
208 return -1;
209#else
210 int fd;
211 char *s;
212 struct sockaddr_un addr;
213
214 if ((fd = socket(AF_UNIX,SOCK_DGRAM,0)) < 0)
215 return -1;
216 addr.sun_family = AF_UNIX;
217#ifdef _PATH_LOG
218#define SYSLOG_SOCKET_PATH _PATH_LOG
219#else
220#define SYSLOG_SOCKET_PATH "/dev/log"
221#endif
222 s = str_append(addr.sun_path,sizeof(addr.sun_path),SYSLOG_SOCKET_PATH);
223#undef SYSLOG_SOCKET_PATH
224 *s = '\0';
225 if (connect(fd,(struct sockaddr *)&addr,sizeof(addr)) < 0)
226 {
227 close(fd);
228 return -1;
229 }
230 return fd;
231#endif
232}
233
234static void
235syslog_sigsafe(int priority, const char *msg, size_t msglen)
236{
ajs1e221352005-02-03 16:42:40 +0000237 static int syslog_fd = -1;
ajs7d149b82004-11-28 23:00:01 +0000238 char buf[sizeof("<1234567890>ripngd[1234567890]: ")+msglen+50];
239 char *s;
240
241 if ((syslog_fd < 0) && ((syslog_fd = syslog_connect()) < 0))
242 return;
243
244#define LOC s,buf+sizeof(buf)-s
245 s = buf;
246 s = str_append(LOC,"<");
247 s = num_append(LOC,priority);
248 s = str_append(LOC,">");
249 /* forget about the timestamp, too difficult in a signal handler */
250 s = str_append(LOC,zlog_default->ident);
251 if (zlog_default->syslog_options & LOG_PID)
252 {
253 s = str_append(LOC,"[");
254 s = num_append(LOC,getpid());
255 s = str_append(LOC,"]");
256 }
257 s = str_append(LOC,": ");
258 s = str_append(LOC,msg);
259 write(syslog_fd,buf,s-buf);
260#undef LOC
261}
262
ajs1e221352005-02-03 16:42:40 +0000263static int
264open_crashlog(void)
265{
266#define CRASHLOG_PREFIX "/var/tmp/quagga."
267#define CRASHLOG_SUFFIX "crashlog"
268 if (zlog_default && zlog_default->ident)
269 {
270 /* Avoid strlen since it is not async-signal-safe. */
271 const char *p;
272 size_t ilen;
273
274 for (p = zlog_default->ident, ilen = 0; *p; p++)
275 ilen++;
276 {
277 char buf[sizeof(CRASHLOG_PREFIX)+ilen+sizeof(CRASHLOG_SUFFIX)+3];
278 char *s = buf;
279#define LOC s,buf+sizeof(buf)-s
280 s = str_append(LOC, CRASHLOG_PREFIX);
281 s = str_append(LOC, zlog_default->ident);
282 s = str_append(LOC, ".");
283 s = str_append(LOC, CRASHLOG_SUFFIX);
284#undef LOC
285 *s = '\0';
286 return open(buf, O_WRONLY|O_CREAT|O_EXCL, LOGFILE_MASK);
287 }
288 }
289 return open(CRASHLOG_PREFIX CRASHLOG_SUFFIX, O_WRONLY|O_CREAT|O_EXCL,
290 LOGFILE_MASK);
291#undef CRASHLOG_SUFFIX
292#undef CRASHLOG_PREFIX
293}
294
ajs7d149b82004-11-28 23:00:01 +0000295/* Note: the goal here is to use only async-signal-safe functions. */
ajs59a06a92004-11-23 18:19:14 +0000296void
ajs31364272005-01-18 22:18:59 +0000297zlog_signal(int signo, const char *action
298#ifdef SA_SIGINFO
299 , siginfo_t *siginfo, void *program_counter
300#endif
301 )
ajs59a06a92004-11-23 18:19:14 +0000302{
303 time_t now;
ajs40abf232005-01-12 17:27:27 +0000304 char buf[sizeof("DEFAULT: Received signal S at T (si_addr 0xP, PC 0xP); aborting...")+100];
ajs59a06a92004-11-23 18:19:14 +0000305 char *s = buf;
ajs7d149b82004-11-28 23:00:01 +0000306 char *msgstart = buf;
ajs59a06a92004-11-23 18:19:14 +0000307#define LOC s,buf+sizeof(buf)-s
308
309 time(&now);
310 if (zlog_default)
311 {
312 s = str_append(LOC,zlog_proto_names[zlog_default->protocol]);
313 *s++ = ':';
314 *s++ = ' ';
ajs7d149b82004-11-28 23:00:01 +0000315 msgstart = s;
ajs59a06a92004-11-23 18:19:14 +0000316 }
317 s = str_append(LOC,"Received signal ");
318 s = num_append(LOC,signo);
319 s = str_append(LOC," at ");
320 s = num_append(LOC,now);
ajs31364272005-01-18 22:18:59 +0000321#ifdef SA_SIGINFO
ajs40abf232005-01-12 17:27:27 +0000322 s = str_append(LOC," (si_addr 0x");
323 s = hex_append(LOC,(u_long)(siginfo->si_addr));
324 if (program_counter)
325 {
326 s = str_append(LOC,", PC 0x");
327 s = hex_append(LOC,(u_long)program_counter);
328 }
329 s = str_append(LOC,"); ");
ajs31364272005-01-18 22:18:59 +0000330#else /* SA_SIGINFO */
331 s = str_append(LOC,"; ");
332#endif /* SA_SIGINFO */
ajs59a06a92004-11-23 18:19:14 +0000333 s = str_append(LOC,action);
ajs7d149b82004-11-28 23:00:01 +0000334 if (s < buf+sizeof(buf))
335 *s++ = '\n';
ajs59a06a92004-11-23 18:19:14 +0000336
ajs274a4a42004-12-07 15:39:31 +0000337 /* N.B. implicit priority is most severe */
ajs1e221352005-02-03 16:42:40 +0000338#define PRI LOG_CRIT
ajs274a4a42004-12-07 15:39:31 +0000339
ajs1e221352005-02-03 16:42:40 +0000340#define DUMP(FD) write(FD, buf, s-buf);
341 /* If no file logging configured, try to write to fallback log file. */
342 if ((!zlog_default || !zlog_default->fp) &&
343 ((crashlog_fd = open_crashlog()) >= 0))
344 DUMP(crashlog_fd)
ajs59a06a92004-11-23 18:19:14 +0000345 if (!zlog_default)
ajs1e221352005-02-03 16:42:40 +0000346 DUMP(fileno(stderr))
ajs59a06a92004-11-23 18:19:14 +0000347 else
348 {
ajs274a4a42004-12-07 15:39:31 +0000349 if ((PRI <= zlog_default->maxlvl[ZLOG_DEST_FILE]) && zlog_default->fp)
ajs1e221352005-02-03 16:42:40 +0000350 DUMP(fileno(zlog_default->fp))
ajs274a4a42004-12-07 15:39:31 +0000351 if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT])
ajs1e221352005-02-03 16:42:40 +0000352 DUMP(fileno(stdout))
ajs274a4a42004-12-07 15:39:31 +0000353 /* Remove trailing '\n' for monitor and syslog */
354 *--s = '\0';
355 if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
356 vty_log_fixed(buf,s-buf);
357 if (PRI <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
358 syslog_sigsafe(PRI|zlog_default->facility,msgstart,s-msgstart);
ajs59a06a92004-11-23 18:19:14 +0000359 }
360#undef DUMP
361
ajs31364272005-01-18 22:18:59 +0000362 zlog_backtrace_sigsafe(PRI,
363#ifdef SA_SIGINFO
364 program_counter
365#else
366 NULL
367#endif
368 );
ajs274a4a42004-12-07 15:39:31 +0000369#undef PRI
ajs063ee522004-11-26 18:11:14 +0000370#undef LOC
371}
ajs59a06a92004-11-23 18:19:14 +0000372
ajs063ee522004-11-26 18:11:14 +0000373/* Log a backtrace using only async-signal-safe functions.
374 Needs to be enhanced to support syslog logging. */
375void
ajs239c26f2005-01-17 15:22:28 +0000376zlog_backtrace_sigsafe(int priority, void *program_counter)
ajs063ee522004-11-26 18:11:14 +0000377{
378#ifdef HAVE_GLIBC_BACKTRACE
ajs239c26f2005-01-17 15:22:28 +0000379 static const char pclabel[] = "Program counter: ";
ajs063ee522004-11-26 18:11:14 +0000380 void *array[20];
381 int size;
382 char buf[100];
383 char *s;
384#define LOC s,buf+sizeof(buf)-s
385
ajs063ee522004-11-26 18:11:14 +0000386 if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
387 ((size_t)size > sizeof(array)/sizeof(array[0])))
388 return;
389 s = buf;
390 s = str_append(LOC,"Backtrace for ");
391 s = num_append(LOC,size);
392 s = str_append(LOC," stack frames:\n");
ajs59a06a92004-11-23 18:19:14 +0000393
ajs1e221352005-02-03 16:42:40 +0000394#define DUMP(FD) { \
ajs239c26f2005-01-17 15:22:28 +0000395 if (program_counter) \
396 { \
ajs1e221352005-02-03 16:42:40 +0000397 write(FD, pclabel, sizeof(pclabel)-1); \
398 backtrace_symbols_fd(&program_counter, 1, FD); \
ajs239c26f2005-01-17 15:22:28 +0000399 } \
ajs1e221352005-02-03 16:42:40 +0000400 write(FD, buf, s-buf); \
401 backtrace_symbols_fd(array, size, FD); \
ajs59a06a92004-11-23 18:19:14 +0000402}
403
ajs1e221352005-02-03 16:42:40 +0000404 if (crashlog_fd >= 0)
405 DUMP(crashlog_fd)
ajs59a06a92004-11-23 18:19:14 +0000406 if (!zlog_default)
ajs1e221352005-02-03 16:42:40 +0000407 DUMP(fileno(stderr))
ajs59a06a92004-11-23 18:19:14 +0000408 else
409 {
ajs274a4a42004-12-07 15:39:31 +0000410 if ((priority <= zlog_default->maxlvl[ZLOG_DEST_FILE]) &&
411 zlog_default->fp)
ajs1e221352005-02-03 16:42:40 +0000412 DUMP(fileno(zlog_default->fp))
ajs274a4a42004-12-07 15:39:31 +0000413 if (priority <= zlog_default->maxlvl[ZLOG_DEST_STDOUT])
ajs1e221352005-02-03 16:42:40 +0000414 DUMP(fileno(stdout))
ajs274a4a42004-12-07 15:39:31 +0000415 /* Remove trailing '\n' for monitor and syslog */
416 *--s = '\0';
417 if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
418 vty_log_fixed(buf,s-buf);
419 if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
420 syslog_sigsafe(priority|zlog_default->facility,buf,s-buf);
421 {
422 int i;
423 /* Just print the function addresses. */
424 for (i = 0; i < size; i++)
425 {
426 s = buf;
427 s = str_append(LOC,"[bt ");
428 s = num_append(LOC,i);
429 s = str_append(LOC,"] 0x");
430 s = hex_append(LOC,(u_long)(array[i]));
431 *s = '\0';
432 if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
433 vty_log_fixed(buf,s-buf);
434 if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
ajs7d149b82004-11-28 23:00:01 +0000435 syslog_sigsafe(priority|zlog_default->facility,buf,s-buf);
ajs274a4a42004-12-07 15:39:31 +0000436 }
437 }
ajs59a06a92004-11-23 18:19:14 +0000438 }
439#undef DUMP
ajs59a06a92004-11-23 18:19:14 +0000440#undef LOC
ajs063ee522004-11-26 18:11:14 +0000441#endif /* HAVE_GLIBC_BACKTRACE */
442}
443
444void
445zlog_backtrace(int priority)
446{
447#ifndef HAVE_GLIBC_BACKTRACE
448 zlog(NULL, priority, "No backtrace available on this platform.");
449#else
450 void *array[20];
451 int size, i;
452 char **strings;
453
454 if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
455 ((size_t)size > sizeof(array)/sizeof(array[0])))
456 {
457 zlog_err("Cannot get backtrace, returned invalid # of frames %d "
458 "(valid range is between 1 and %u)",
459 size, sizeof(array)/sizeof(array[0]));
460 return;
461 }
462 zlog(NULL, priority, "Backtrace for %d stack frames:", size);
463 if (!(strings = backtrace_symbols(array, size)))
464 {
465 zlog_err("Cannot get backtrace symbols (out of memory?)");
466 for (i = 0; i < size; i++)
467 zlog(NULL, priority, "[bt %d] %p",i,array[i]);
468 }
469 else
470 {
471 for (i = 0; i < size; i++)
472 zlog(NULL, priority, "[bt %d] %s",i,strings[i]);
473 free(strings);
474 }
475#endif /* HAVE_GLIBC_BACKTRACE */
ajs59a06a92004-11-23 18:19:14 +0000476}
477
paul718e3742002-12-13 20:15:29 +0000478void
479zlog (struct zlog *zl, int priority, const char *format, ...)
480{
ajsd246bd92004-11-23 17:35:08 +0000481 va_list args;
paul718e3742002-12-13 20:15:29 +0000482
ajsd246bd92004-11-23 17:35:08 +0000483 va_start(args, format);
paul718e3742002-12-13 20:15:29 +0000484 vzlog (zl, priority, format, args);
ajsd246bd92004-11-23 17:35:08 +0000485 va_end (args);
paul718e3742002-12-13 20:15:29 +0000486}
487
ajsd246bd92004-11-23 17:35:08 +0000488#define ZLOG_FUNC(FUNCNAME,PRIORITY) \
489void \
490FUNCNAME(const char *format, ...) \
491{ \
492 va_list args; \
493 va_start(args, format); \
494 vzlog (NULL, PRIORITY, format, args); \
495 va_end(args); \
paul718e3742002-12-13 20:15:29 +0000496}
497
ajsd246bd92004-11-23 17:35:08 +0000498ZLOG_FUNC(zlog_err, LOG_ERR)
paul718e3742002-12-13 20:15:29 +0000499
ajsd246bd92004-11-23 17:35:08 +0000500ZLOG_FUNC(zlog_warn, LOG_WARNING)
paul718e3742002-12-13 20:15:29 +0000501
ajsd246bd92004-11-23 17:35:08 +0000502ZLOG_FUNC(zlog_info, LOG_INFO)
paul718e3742002-12-13 20:15:29 +0000503
ajsd246bd92004-11-23 17:35:08 +0000504ZLOG_FUNC(zlog_notice, LOG_NOTICE)
505
506ZLOG_FUNC(zlog_debug, LOG_DEBUG)
507
508#undef ZLOG_FUNC
509
510#define PLOG_FUNC(FUNCNAME,PRIORITY) \
511void \
512FUNCNAME(struct zlog *zl, const char *format, ...) \
513{ \
514 va_list args; \
515 va_start(args, format); \
516 vzlog (zl, PRIORITY, format, args); \
517 va_end(args); \
paul718e3742002-12-13 20:15:29 +0000518}
519
ajsd246bd92004-11-23 17:35:08 +0000520PLOG_FUNC(plog_err, LOG_ERR)
paul718e3742002-12-13 20:15:29 +0000521
ajsd246bd92004-11-23 17:35:08 +0000522PLOG_FUNC(plog_warn, LOG_WARNING)
paul718e3742002-12-13 20:15:29 +0000523
ajsd246bd92004-11-23 17:35:08 +0000524PLOG_FUNC(plog_info, LOG_INFO)
paul718e3742002-12-13 20:15:29 +0000525
ajsd246bd92004-11-23 17:35:08 +0000526PLOG_FUNC(plog_notice, LOG_NOTICE)
paul718e3742002-12-13 20:15:29 +0000527
ajsd246bd92004-11-23 17:35:08 +0000528PLOG_FUNC(plog_debug, LOG_DEBUG)
paul718e3742002-12-13 20:15:29 +0000529
ajsd246bd92004-11-23 17:35:08 +0000530#undef PLOG_FUNC
paul718e3742002-12-13 20:15:29 +0000531
ajscee3df12004-11-24 17:14:49 +0000532void
533_zlog_assert_failed (const char *assertion, const char *file,
534 unsigned int line, const char *function)
535{
ajs1e221352005-02-03 16:42:40 +0000536 if (zlog_default && !zlog_default->fp)
537 {
538 /* Force fallback file logging. */
539 int fd;
540 FILE *fp;
541
542 if (((fd = open_crashlog()) >= 0) && ((fp = fdopen(fd, "w")) != NULL))
543 {
544 zlog_default->fp = fp;
545 zlog_default->maxlvl[ZLOG_DEST_FILE] = LOG_ERR;
546 }
547 }
548 zlog(NULL, LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s",
549 assertion,file,line,(function ? function : "?"));
550 zlog_backtrace(LOG_CRIT);
ajscee3df12004-11-24 17:14:49 +0000551 abort();
552}
553
paul718e3742002-12-13 20:15:29 +0000554
555/* Open log stream */
556struct zlog *
ajs274a4a42004-12-07 15:39:31 +0000557openzlog (const char *progname, zlog_proto_t protocol,
paul718e3742002-12-13 20:15:29 +0000558 int syslog_flags, int syslog_facility)
559{
560 struct zlog *zl;
ajs274a4a42004-12-07 15:39:31 +0000561 u_int i;
paul718e3742002-12-13 20:15:29 +0000562
ajs274a4a42004-12-07 15:39:31 +0000563 zl = XCALLOC(MTYPE_ZLOG, sizeof (struct zlog));
paul718e3742002-12-13 20:15:29 +0000564
565 zl->ident = progname;
paul718e3742002-12-13 20:15:29 +0000566 zl->protocol = protocol;
567 zl->facility = syslog_facility;
ajs7d149b82004-11-28 23:00:01 +0000568 zl->syslog_options = syslog_flags;
paul718e3742002-12-13 20:15:29 +0000569
ajs274a4a42004-12-07 15:39:31 +0000570 /* Set default logging levels. */
571 for (i = 0; i < sizeof(zl->maxlvl)/sizeof(zl->maxlvl[0]); i++)
572 zl->maxlvl[i] = ZLOG_DISABLED;
573 zl->maxlvl[ZLOG_DEST_MONITOR] = LOG_DEBUG;
574 zl->default_lvl = LOG_DEBUG;
575
paul718e3742002-12-13 20:15:29 +0000576 openlog (progname, syslog_flags, zl->facility);
577
578 return zl;
579}
580
581void
582closezlog (struct zlog *zl)
583{
584 closelog();
585 fclose (zl->fp);
586
587 XFREE (MTYPE_ZLOG, zl);
588}
589
590/* Called from command.c. */
591void
ajs274a4a42004-12-07 15:39:31 +0000592zlog_set_level (struct zlog *zl, zlog_dest_t dest, int log_level)
paul718e3742002-12-13 20:15:29 +0000593{
594 if (zl == NULL)
595 zl = zlog_default;
596
ajs274a4a42004-12-07 15:39:31 +0000597 zl->maxlvl[dest] = log_level;
paul718e3742002-12-13 20:15:29 +0000598}
599
600int
ajs274a4a42004-12-07 15:39:31 +0000601zlog_set_file (struct zlog *zl, const char *filename, int log_level)
paul718e3742002-12-13 20:15:29 +0000602{
603 FILE *fp;
gdtaa593d52003-12-22 20:15:53 +0000604 mode_t oldumask;
paul718e3742002-12-13 20:15:29 +0000605
606 /* There is opend file. */
607 zlog_reset_file (zl);
608
609 /* Set default zl. */
610 if (zl == NULL)
611 zl = zlog_default;
612
613 /* Open file. */
gdtaa593d52003-12-22 20:15:53 +0000614 oldumask = umask (0777 & ~LOGFILE_MASK);
paul718e3742002-12-13 20:15:29 +0000615 fp = fopen (filename, "a");
gdtaa593d52003-12-22 20:15:53 +0000616 umask(oldumask);
ajs274a4a42004-12-07 15:39:31 +0000617 if (fp == NULL)
618 return 0;
paul718e3742002-12-13 20:15:29 +0000619
620 /* Set flags. */
621 zl->filename = strdup (filename);
ajs274a4a42004-12-07 15:39:31 +0000622 zl->maxlvl[ZLOG_DEST_FILE] = log_level;
paul718e3742002-12-13 20:15:29 +0000623 zl->fp = fp;
624
625 return 1;
626}
627
628/* Reset opend file. */
629int
630zlog_reset_file (struct zlog *zl)
631{
632 if (zl == NULL)
633 zl = zlog_default;
634
paul718e3742002-12-13 20:15:29 +0000635 if (zl->fp)
636 fclose (zl->fp);
637 zl->fp = NULL;
ajs274a4a42004-12-07 15:39:31 +0000638 zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
paul718e3742002-12-13 20:15:29 +0000639
640 if (zl->filename)
641 free (zl->filename);
642 zl->filename = NULL;
643
644 return 1;
645}
646
647/* Reopen log file. */
648int
649zlog_rotate (struct zlog *zl)
650{
ajs274a4a42004-12-07 15:39:31 +0000651 int level;
paul718e3742002-12-13 20:15:29 +0000652
653 if (zl == NULL)
654 zl = zlog_default;
655
656 if (zl->fp)
657 fclose (zl->fp);
658 zl->fp = NULL;
ajs274a4a42004-12-07 15:39:31 +0000659 level = zl->maxlvl[ZLOG_DEST_FILE];
660 zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
paul718e3742002-12-13 20:15:29 +0000661
662 if (zl->filename)
663 {
gdtaa593d52003-12-22 20:15:53 +0000664 mode_t oldumask;
ajs274a4a42004-12-07 15:39:31 +0000665 int save_errno;
gdtaa593d52003-12-22 20:15:53 +0000666
667 oldumask = umask (0777 & ~LOGFILE_MASK);
ajs274a4a42004-12-07 15:39:31 +0000668 zl->fp = fopen (zl->filename, "a");
669 save_errno = errno;
670 umask(oldumask);
671 if (zl->fp == NULL)
gdtaa593d52003-12-22 20:15:53 +0000672 {
ajs274a4a42004-12-07 15:39:31 +0000673 zlog_err("Log rotate failed: cannot open file %s for append: %s",
674 zl->filename, safe_strerror(save_errno));
gdtaa593d52003-12-22 20:15:53 +0000675 return -1;
676 }
ajs274a4a42004-12-07 15:39:31 +0000677 zl->maxlvl[ZLOG_DEST_FILE] = level;
paul718e3742002-12-13 20:15:29 +0000678 }
679
680 return 1;
681}
682
paul718e3742002-12-13 20:15:29 +0000683/* Message lookup function. */
hasso8c328f12004-10-05 21:01:23 +0000684const char *
paul718e3742002-12-13 20:15:29 +0000685lookup (struct message *mes, int key)
686{
687 struct message *pnt;
688
689 for (pnt = mes; pnt->key != 0; pnt++)
690 if (pnt->key == key)
691 return pnt->str;
692
693 return "";
694}
695
696/* Very old hacky version of message lookup function. Still partly
hassob04c6992004-10-04 19:10:31 +0000697 used in bgpd and ospfd. FIXME Seems that it's not used any more. */
hasso8c328f12004-10-05 21:01:23 +0000698const char *
paul718e3742002-12-13 20:15:29 +0000699mes_lookup (struct message *meslist, int max, int index)
700{
701 if (index < 0 || index >= max)
702 {
703 zlog_err ("message index out of bound: %d", max);
704 return NULL;
705 }
706 return meslist[index].str;
707}
ajsca359762004-11-19 23:40:16 +0000708
709/* Wrapper around strerror to handle case where it returns NULL. */
710const char *
711safe_strerror(int errnum)
712{
713 const char *s = strerror(errnum);
714 return (s != NULL) ? s : "Unknown error";
715}