blob: 6748dbc0a619873523658df7faa4ba09d97c94e6 [file] [log] [blame]
ajs274a4a42004-12-07 15:39:31 +00001/*
ajsf52d13c2005-10-01 17:38:06 +00002 * $Id: log.c,v 1.26 2005/10/01 17:38:07 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
ajsc4c7d0c2005-02-03 19:22:05 +000034static int logfile_fd = -1; /* Used in signal handler. */
ajs1e221352005-02-03 16:42:40 +000035
paul718e3742002-12-13 20:15:29 +000036struct zlog *zlog_default = NULL;
37
38const char *zlog_proto_names[] =
39{
40 "NONE",
41 "DEFAULT",
42 "ZEBRA",
43 "RIP",
44 "BGP",
45 "OSPF",
46 "RIPNG",
47 "OSPF6",
jardin9e867fe2003-12-23 08:56:18 +000048 "ISIS",
paul718e3742002-12-13 20:15:29 +000049 "MASC",
50 NULL,
51};
52
53const char *zlog_priority[] =
54{
55 "emergencies",
56 "alerts",
57 "critical",
58 "errors",
59 "warnings",
60 "notifications",
61 "informational",
62 "debugging",
63 NULL,
64};
65
66
67
68/* For time string format. */
69#define TIME_BUF 27
70
71/* Utility routine for current time printing. */
72static void
73time_print (FILE *fp)
74{
75 int ret;
76 char buf [TIME_BUF];
77 time_t clock;
78 struct tm *tm;
79
80 time (&clock);
81 tm = localtime (&clock);
82
83 ret = strftime (buf, TIME_BUF, "%Y/%m/%d %H:%M:%S", tm);
84 if (ret == 0) {
85 zlog_warn ("strftime error");
86 }
87
88 fprintf (fp, "%s ", buf);
89}
90
91/* va_list version of zlog. */
ajsd246bd92004-11-23 17:35:08 +000092static void
93vzlog (struct zlog *zl, int priority, const char *format, va_list args)
paul718e3742002-12-13 20:15:29 +000094{
95 /* If zlog is not specified, use default one. */
96 if (zl == NULL)
97 zl = zlog_default;
98
99 /* When zlog_default is also NULL, use stderr for logging. */
100 if (zl == NULL)
101 {
102 time_print (stderr);
103 fprintf (stderr, "%s: ", "unknown");
ajsd246bd92004-11-23 17:35:08 +0000104 vfprintf (stderr, format, args);
paul718e3742002-12-13 20:15:29 +0000105 fprintf (stderr, "\n");
106 fflush (stderr);
107
108 /* In this case we return at here. */
109 return;
110 }
111
paul718e3742002-12-13 20:15:29 +0000112 /* Syslog output */
ajs274a4a42004-12-07 15:39:31 +0000113 if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG])
ajsd246bd92004-11-23 17:35:08 +0000114 {
115 va_list ac;
116 va_copy(ac, args);
117 vsyslog (priority|zlog_default->facility, format, ac);
118 va_end(ac);
119 }
paul718e3742002-12-13 20:15:29 +0000120
121 /* File output. */
ajs274a4a42004-12-07 15:39:31 +0000122 if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp)
paul718e3742002-12-13 20:15:29 +0000123 {
ajsd246bd92004-11-23 17:35:08 +0000124 va_list ac;
paul718e3742002-12-13 20:15:29 +0000125 time_print (zl->fp);
hassob04c6992004-10-04 19:10:31 +0000126 if (zl->record_priority)
127 fprintf (zl->fp, "%s: ", zlog_priority[priority]);
paul718e3742002-12-13 20:15:29 +0000128 fprintf (zl->fp, "%s: ", zlog_proto_names[zl->protocol]);
ajsd246bd92004-11-23 17:35:08 +0000129 va_copy(ac, args);
130 vfprintf (zl->fp, format, ac);
131 va_end(ac);
paul718e3742002-12-13 20:15:29 +0000132 fprintf (zl->fp, "\n");
133 fflush (zl->fp);
134 }
135
136 /* stdout output. */
ajs274a4a42004-12-07 15:39:31 +0000137 if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT])
paul718e3742002-12-13 20:15:29 +0000138 {
ajsd246bd92004-11-23 17:35:08 +0000139 va_list ac;
paul718e3742002-12-13 20:15:29 +0000140 time_print (stdout);
hassob04c6992004-10-04 19:10:31 +0000141 if (zl->record_priority)
142 fprintf (stdout, "%s: ", zlog_priority[priority]);
paul718e3742002-12-13 20:15:29 +0000143 fprintf (stdout, "%s: ", zlog_proto_names[zl->protocol]);
ajsd246bd92004-11-23 17:35:08 +0000144 va_copy(ac, args);
145 vfprintf (stdout, format, ac);
146 va_end(ac);
paul718e3742002-12-13 20:15:29 +0000147 fprintf (stdout, "\n");
148 fflush (stdout);
149 }
150
paul718e3742002-12-13 20:15:29 +0000151 /* Terminal monitor. */
ajs274a4a42004-12-07 15:39:31 +0000152 if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR])
153 vty_log ((zl->record_priority ? zlog_priority[priority] : NULL),
154 zlog_proto_names[zl->protocol], format, args);
paul718e3742002-12-13 20:15:29 +0000155}
156
ajs59a06a92004-11-23 18:19:14 +0000157static char *
158str_append(char *dst, int len, const char *src)
159{
160 while ((len-- > 0) && *src)
161 *dst++ = *src++;
162 return dst;
163}
164
165static char *
166num_append(char *s, int len, u_long x)
167{
168 char buf[30];
ajs7d149b82004-11-28 23:00:01 +0000169 char *t;
ajs59a06a92004-11-23 18:19:14 +0000170
ajs7d149b82004-11-28 23:00:01 +0000171 if (!x)
172 return str_append(s,len,"0");
173 *(t = &buf[sizeof(buf)-1]) = '\0';
ajs59a06a92004-11-23 18:19:14 +0000174 while (x && (t > buf))
175 {
176 *--t = '0'+(x % 10);
177 x /= 10;
178 }
179 return str_append(s,len,t);
180}
181
ajs31364272005-01-18 22:18:59 +0000182#if defined(SA_SIGINFO) || defined(HAVE_GLIBC_BACKTRACE)
ajs7d149b82004-11-28 23:00:01 +0000183static char *
184hex_append(char *s, int len, u_long x)
185{
186 char buf[30];
187 char *t;
188
189 if (!x)
190 return str_append(s,len,"0");
191 *(t = &buf[sizeof(buf)-1]) = '\0';
192 while (x && (t > buf))
193 {
194 u_int cc = (x % 16);
195 *--t = ((cc < 10) ? ('0'+cc) : ('a'+cc-10));
196 x /= 16;
197 }
198 return str_append(s,len,t);
199}
ajs31364272005-01-18 22:18:59 +0000200#endif
ajs7d149b82004-11-28 23:00:01 +0000201
ajs7d149b82004-11-28 23:00:01 +0000202/* Needs to be enhanced to support Solaris. */
203static int
204syslog_connect(void)
205{
206#ifdef SUNOS_5
207 return -1;
208#else
209 int fd;
210 char *s;
211 struct sockaddr_un addr;
212
213 if ((fd = socket(AF_UNIX,SOCK_DGRAM,0)) < 0)
214 return -1;
215 addr.sun_family = AF_UNIX;
216#ifdef _PATH_LOG
217#define SYSLOG_SOCKET_PATH _PATH_LOG
218#else
219#define SYSLOG_SOCKET_PATH "/dev/log"
220#endif
221 s = str_append(addr.sun_path,sizeof(addr.sun_path),SYSLOG_SOCKET_PATH);
222#undef SYSLOG_SOCKET_PATH
223 *s = '\0';
224 if (connect(fd,(struct sockaddr *)&addr,sizeof(addr)) < 0)
225 {
226 close(fd);
227 return -1;
228 }
229 return fd;
230#endif
231}
232
233static void
234syslog_sigsafe(int priority, const char *msg, size_t msglen)
235{
ajs1e221352005-02-03 16:42:40 +0000236 static int syslog_fd = -1;
ajs7d149b82004-11-28 23:00:01 +0000237 char buf[sizeof("<1234567890>ripngd[1234567890]: ")+msglen+50];
238 char *s;
239
240 if ((syslog_fd < 0) && ((syslog_fd = syslog_connect()) < 0))
241 return;
242
243#define LOC s,buf+sizeof(buf)-s
244 s = buf;
245 s = str_append(LOC,"<");
246 s = num_append(LOC,priority);
247 s = str_append(LOC,">");
248 /* forget about the timestamp, too difficult in a signal handler */
249 s = str_append(LOC,zlog_default->ident);
250 if (zlog_default->syslog_options & LOG_PID)
251 {
252 s = str_append(LOC,"[");
253 s = num_append(LOC,getpid());
254 s = str_append(LOC,"]");
255 }
256 s = str_append(LOC,": ");
257 s = str_append(LOC,msg);
258 write(syslog_fd,buf,s-buf);
259#undef LOC
260}
261
ajs1e221352005-02-03 16:42:40 +0000262static int
263open_crashlog(void)
264{
265#define CRASHLOG_PREFIX "/var/tmp/quagga."
266#define CRASHLOG_SUFFIX "crashlog"
267 if (zlog_default && zlog_default->ident)
268 {
269 /* Avoid strlen since it is not async-signal-safe. */
270 const char *p;
271 size_t ilen;
272
273 for (p = zlog_default->ident, ilen = 0; *p; p++)
274 ilen++;
275 {
276 char buf[sizeof(CRASHLOG_PREFIX)+ilen+sizeof(CRASHLOG_SUFFIX)+3];
277 char *s = buf;
278#define LOC s,buf+sizeof(buf)-s
279 s = str_append(LOC, CRASHLOG_PREFIX);
280 s = str_append(LOC, zlog_default->ident);
281 s = str_append(LOC, ".");
282 s = str_append(LOC, CRASHLOG_SUFFIX);
283#undef LOC
284 *s = '\0';
285 return open(buf, O_WRONLY|O_CREAT|O_EXCL, LOGFILE_MASK);
286 }
287 }
288 return open(CRASHLOG_PREFIX CRASHLOG_SUFFIX, O_WRONLY|O_CREAT|O_EXCL,
289 LOGFILE_MASK);
290#undef CRASHLOG_SUFFIX
291#undef CRASHLOG_PREFIX
292}
293
ajs7d149b82004-11-28 23:00:01 +0000294/* Note: the goal here is to use only async-signal-safe functions. */
ajs59a06a92004-11-23 18:19:14 +0000295void
ajs31364272005-01-18 22:18:59 +0000296zlog_signal(int signo, const char *action
297#ifdef SA_SIGINFO
298 , siginfo_t *siginfo, void *program_counter
299#endif
300 )
ajs59a06a92004-11-23 18:19:14 +0000301{
302 time_t now;
ajs40abf232005-01-12 17:27:27 +0000303 char buf[sizeof("DEFAULT: Received signal S at T (si_addr 0xP, PC 0xP); aborting...")+100];
ajs59a06a92004-11-23 18:19:14 +0000304 char *s = buf;
ajs7d149b82004-11-28 23:00:01 +0000305 char *msgstart = buf;
ajs59a06a92004-11-23 18:19:14 +0000306#define LOC s,buf+sizeof(buf)-s
307
308 time(&now);
309 if (zlog_default)
310 {
311 s = str_append(LOC,zlog_proto_names[zlog_default->protocol]);
312 *s++ = ':';
313 *s++ = ' ';
ajs7d149b82004-11-28 23:00:01 +0000314 msgstart = s;
ajs59a06a92004-11-23 18:19:14 +0000315 }
316 s = str_append(LOC,"Received signal ");
317 s = num_append(LOC,signo);
318 s = str_append(LOC," at ");
319 s = num_append(LOC,now);
ajs31364272005-01-18 22:18:59 +0000320#ifdef SA_SIGINFO
ajs40abf232005-01-12 17:27:27 +0000321 s = str_append(LOC," (si_addr 0x");
322 s = hex_append(LOC,(u_long)(siginfo->si_addr));
323 if (program_counter)
324 {
325 s = str_append(LOC,", PC 0x");
326 s = hex_append(LOC,(u_long)program_counter);
327 }
328 s = str_append(LOC,"); ");
ajs31364272005-01-18 22:18:59 +0000329#else /* SA_SIGINFO */
330 s = str_append(LOC,"; ");
331#endif /* SA_SIGINFO */
ajs59a06a92004-11-23 18:19:14 +0000332 s = str_append(LOC,action);
ajs7d149b82004-11-28 23:00:01 +0000333 if (s < buf+sizeof(buf))
334 *s++ = '\n';
ajs59a06a92004-11-23 18:19:14 +0000335
ajs274a4a42004-12-07 15:39:31 +0000336 /* N.B. implicit priority is most severe */
ajs1e221352005-02-03 16:42:40 +0000337#define PRI LOG_CRIT
ajs274a4a42004-12-07 15:39:31 +0000338
ajs1e221352005-02-03 16:42:40 +0000339#define DUMP(FD) write(FD, buf, s-buf);
340 /* If no file logging configured, try to write to fallback log file. */
ajsc4c7d0c2005-02-03 19:22:05 +0000341 if ((logfile_fd >= 0) || ((logfile_fd = open_crashlog()) >= 0))
342 DUMP(logfile_fd)
ajs59a06a92004-11-23 18:19:14 +0000343 if (!zlog_default)
ajsc4c7d0c2005-02-03 19:22:05 +0000344 DUMP(STDERR_FILENO)
ajs59a06a92004-11-23 18:19:14 +0000345 else
346 {
ajs274a4a42004-12-07 15:39:31 +0000347 if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT])
ajsc4c7d0c2005-02-03 19:22:05 +0000348 DUMP(STDOUT_FILENO)
ajs274a4a42004-12-07 15:39:31 +0000349 /* Remove trailing '\n' for monitor and syslog */
350 *--s = '\0';
351 if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
352 vty_log_fixed(buf,s-buf);
353 if (PRI <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
354 syslog_sigsafe(PRI|zlog_default->facility,msgstart,s-msgstart);
ajs59a06a92004-11-23 18:19:14 +0000355 }
356#undef DUMP
357
ajs31364272005-01-18 22:18:59 +0000358 zlog_backtrace_sigsafe(PRI,
359#ifdef SA_SIGINFO
360 program_counter
361#else
362 NULL
363#endif
364 );
ajs274a4a42004-12-07 15:39:31 +0000365#undef PRI
ajs063ee522004-11-26 18:11:14 +0000366#undef LOC
367}
ajs59a06a92004-11-23 18:19:14 +0000368
ajs063ee522004-11-26 18:11:14 +0000369/* Log a backtrace using only async-signal-safe functions.
370 Needs to be enhanced to support syslog logging. */
371void
ajs239c26f2005-01-17 15:22:28 +0000372zlog_backtrace_sigsafe(int priority, void *program_counter)
ajs063ee522004-11-26 18:11:14 +0000373{
374#ifdef HAVE_GLIBC_BACKTRACE
ajs239c26f2005-01-17 15:22:28 +0000375 static const char pclabel[] = "Program counter: ";
ajs063ee522004-11-26 18:11:14 +0000376 void *array[20];
377 int size;
378 char buf[100];
379 char *s;
380#define LOC s,buf+sizeof(buf)-s
381
ajs063ee522004-11-26 18:11:14 +0000382 if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
383 ((size_t)size > sizeof(array)/sizeof(array[0])))
384 return;
385 s = buf;
386 s = str_append(LOC,"Backtrace for ");
387 s = num_append(LOC,size);
388 s = str_append(LOC," stack frames:\n");
ajs59a06a92004-11-23 18:19:14 +0000389
ajs1e221352005-02-03 16:42:40 +0000390#define DUMP(FD) { \
ajs239c26f2005-01-17 15:22:28 +0000391 if (program_counter) \
392 { \
ajs1e221352005-02-03 16:42:40 +0000393 write(FD, pclabel, sizeof(pclabel)-1); \
394 backtrace_symbols_fd(&program_counter, 1, FD); \
ajs239c26f2005-01-17 15:22:28 +0000395 } \
ajs1e221352005-02-03 16:42:40 +0000396 write(FD, buf, s-buf); \
397 backtrace_symbols_fd(array, size, FD); \
ajs59a06a92004-11-23 18:19:14 +0000398}
399
ajsc4c7d0c2005-02-03 19:22:05 +0000400 if ((logfile_fd >= 0) || ((logfile_fd = open_crashlog()) >= 0))
401 DUMP(logfile_fd)
ajs59a06a92004-11-23 18:19:14 +0000402 if (!zlog_default)
ajsc4c7d0c2005-02-03 19:22:05 +0000403 DUMP(STDERR_FILENO)
ajs59a06a92004-11-23 18:19:14 +0000404 else
405 {
ajs274a4a42004-12-07 15:39:31 +0000406 if (priority <= zlog_default->maxlvl[ZLOG_DEST_STDOUT])
ajsc4c7d0c2005-02-03 19:22:05 +0000407 DUMP(STDOUT_FILENO)
ajs274a4a42004-12-07 15:39:31 +0000408 /* Remove trailing '\n' for monitor and syslog */
409 *--s = '\0';
410 if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
411 vty_log_fixed(buf,s-buf);
412 if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
413 syslog_sigsafe(priority|zlog_default->facility,buf,s-buf);
414 {
415 int i;
416 /* Just print the function addresses. */
417 for (i = 0; i < size; i++)
418 {
419 s = buf;
420 s = str_append(LOC,"[bt ");
421 s = num_append(LOC,i);
422 s = str_append(LOC,"] 0x");
423 s = hex_append(LOC,(u_long)(array[i]));
424 *s = '\0';
425 if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
426 vty_log_fixed(buf,s-buf);
427 if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
ajs7d149b82004-11-28 23:00:01 +0000428 syslog_sigsafe(priority|zlog_default->facility,buf,s-buf);
ajs274a4a42004-12-07 15:39:31 +0000429 }
430 }
ajs59a06a92004-11-23 18:19:14 +0000431 }
432#undef DUMP
ajs59a06a92004-11-23 18:19:14 +0000433#undef LOC
ajs063ee522004-11-26 18:11:14 +0000434#endif /* HAVE_GLIBC_BACKTRACE */
435}
436
437void
438zlog_backtrace(int priority)
439{
440#ifndef HAVE_GLIBC_BACKTRACE
441 zlog(NULL, priority, "No backtrace available on this platform.");
442#else
443 void *array[20];
444 int size, i;
445 char **strings;
446
447 if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
448 ((size_t)size > sizeof(array)/sizeof(array[0])))
449 {
450 zlog_err("Cannot get backtrace, returned invalid # of frames %d "
451 "(valid range is between 1 and %u)",
452 size, sizeof(array)/sizeof(array[0]));
453 return;
454 }
455 zlog(NULL, priority, "Backtrace for %d stack frames:", size);
456 if (!(strings = backtrace_symbols(array, size)))
457 {
458 zlog_err("Cannot get backtrace symbols (out of memory?)");
459 for (i = 0; i < size; i++)
460 zlog(NULL, priority, "[bt %d] %p",i,array[i]);
461 }
462 else
463 {
464 for (i = 0; i < size; i++)
465 zlog(NULL, priority, "[bt %d] %s",i,strings[i]);
466 free(strings);
467 }
468#endif /* HAVE_GLIBC_BACKTRACE */
ajs59a06a92004-11-23 18:19:14 +0000469}
470
paul718e3742002-12-13 20:15:29 +0000471void
472zlog (struct zlog *zl, int priority, const char *format, ...)
473{
ajsd246bd92004-11-23 17:35:08 +0000474 va_list args;
paul718e3742002-12-13 20:15:29 +0000475
ajsd246bd92004-11-23 17:35:08 +0000476 va_start(args, format);
paul718e3742002-12-13 20:15:29 +0000477 vzlog (zl, priority, format, args);
ajsd246bd92004-11-23 17:35:08 +0000478 va_end (args);
paul718e3742002-12-13 20:15:29 +0000479}
480
ajsd246bd92004-11-23 17:35:08 +0000481#define ZLOG_FUNC(FUNCNAME,PRIORITY) \
482void \
483FUNCNAME(const char *format, ...) \
484{ \
485 va_list args; \
486 va_start(args, format); \
487 vzlog (NULL, PRIORITY, format, args); \
488 va_end(args); \
paul718e3742002-12-13 20:15:29 +0000489}
490
ajsd246bd92004-11-23 17:35:08 +0000491ZLOG_FUNC(zlog_err, LOG_ERR)
paul718e3742002-12-13 20:15:29 +0000492
ajsd246bd92004-11-23 17:35:08 +0000493ZLOG_FUNC(zlog_warn, LOG_WARNING)
paul718e3742002-12-13 20:15:29 +0000494
ajsd246bd92004-11-23 17:35:08 +0000495ZLOG_FUNC(zlog_info, LOG_INFO)
paul718e3742002-12-13 20:15:29 +0000496
ajsd246bd92004-11-23 17:35:08 +0000497ZLOG_FUNC(zlog_notice, LOG_NOTICE)
498
499ZLOG_FUNC(zlog_debug, LOG_DEBUG)
500
501#undef ZLOG_FUNC
502
503#define PLOG_FUNC(FUNCNAME,PRIORITY) \
504void \
505FUNCNAME(struct zlog *zl, const char *format, ...) \
506{ \
507 va_list args; \
508 va_start(args, format); \
509 vzlog (zl, PRIORITY, format, args); \
510 va_end(args); \
paul718e3742002-12-13 20:15:29 +0000511}
512
ajsd246bd92004-11-23 17:35:08 +0000513PLOG_FUNC(plog_err, LOG_ERR)
paul718e3742002-12-13 20:15:29 +0000514
ajsd246bd92004-11-23 17:35:08 +0000515PLOG_FUNC(plog_warn, LOG_WARNING)
paul718e3742002-12-13 20:15:29 +0000516
ajsd246bd92004-11-23 17:35:08 +0000517PLOG_FUNC(plog_info, LOG_INFO)
paul718e3742002-12-13 20:15:29 +0000518
ajsd246bd92004-11-23 17:35:08 +0000519PLOG_FUNC(plog_notice, LOG_NOTICE)
paul718e3742002-12-13 20:15:29 +0000520
ajsd246bd92004-11-23 17:35:08 +0000521PLOG_FUNC(plog_debug, LOG_DEBUG)
paul718e3742002-12-13 20:15:29 +0000522
ajsd246bd92004-11-23 17:35:08 +0000523#undef PLOG_FUNC
paul718e3742002-12-13 20:15:29 +0000524
ajscee3df12004-11-24 17:14:49 +0000525void
526_zlog_assert_failed (const char *assertion, const char *file,
527 unsigned int line, const char *function)
528{
ajsc4c7d0c2005-02-03 19:22:05 +0000529 /* Force fallback file logging? */
530 if (zlog_default && !zlog_default->fp &&
531 ((logfile_fd = open_crashlog()) >= 0) &&
532 ((zlog_default->fp = fdopen(logfile_fd, "w")) != NULL))
533 zlog_default->maxlvl[ZLOG_DEST_FILE] = LOG_ERR;
ajs1e221352005-02-03 16:42:40 +0000534 zlog(NULL, LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s",
535 assertion,file,line,(function ? function : "?"));
536 zlog_backtrace(LOG_CRIT);
ajscee3df12004-11-24 17:14:49 +0000537 abort();
538}
539
paul718e3742002-12-13 20:15:29 +0000540
541/* Open log stream */
542struct zlog *
ajs274a4a42004-12-07 15:39:31 +0000543openzlog (const char *progname, zlog_proto_t protocol,
paul718e3742002-12-13 20:15:29 +0000544 int syslog_flags, int syslog_facility)
545{
546 struct zlog *zl;
ajs274a4a42004-12-07 15:39:31 +0000547 u_int i;
paul718e3742002-12-13 20:15:29 +0000548
ajs274a4a42004-12-07 15:39:31 +0000549 zl = XCALLOC(MTYPE_ZLOG, sizeof (struct zlog));
paul718e3742002-12-13 20:15:29 +0000550
551 zl->ident = progname;
paul718e3742002-12-13 20:15:29 +0000552 zl->protocol = protocol;
553 zl->facility = syslog_facility;
ajs7d149b82004-11-28 23:00:01 +0000554 zl->syslog_options = syslog_flags;
paul718e3742002-12-13 20:15:29 +0000555
ajs274a4a42004-12-07 15:39:31 +0000556 /* Set default logging levels. */
557 for (i = 0; i < sizeof(zl->maxlvl)/sizeof(zl->maxlvl[0]); i++)
558 zl->maxlvl[i] = ZLOG_DISABLED;
559 zl->maxlvl[ZLOG_DEST_MONITOR] = LOG_DEBUG;
560 zl->default_lvl = LOG_DEBUG;
561
paul718e3742002-12-13 20:15:29 +0000562 openlog (progname, syslog_flags, zl->facility);
563
564 return zl;
565}
566
567void
568closezlog (struct zlog *zl)
569{
570 closelog();
571 fclose (zl->fp);
572
573 XFREE (MTYPE_ZLOG, zl);
574}
575
576/* Called from command.c. */
577void
ajs274a4a42004-12-07 15:39:31 +0000578zlog_set_level (struct zlog *zl, zlog_dest_t dest, int log_level)
paul718e3742002-12-13 20:15:29 +0000579{
580 if (zl == NULL)
581 zl = zlog_default;
582
ajs274a4a42004-12-07 15:39:31 +0000583 zl->maxlvl[dest] = log_level;
paul718e3742002-12-13 20:15:29 +0000584}
585
586int
ajs274a4a42004-12-07 15:39:31 +0000587zlog_set_file (struct zlog *zl, const char *filename, int log_level)
paul718e3742002-12-13 20:15:29 +0000588{
589 FILE *fp;
gdtaa593d52003-12-22 20:15:53 +0000590 mode_t oldumask;
paul718e3742002-12-13 20:15:29 +0000591
592 /* There is opend file. */
593 zlog_reset_file (zl);
594
595 /* Set default zl. */
596 if (zl == NULL)
597 zl = zlog_default;
598
599 /* Open file. */
gdtaa593d52003-12-22 20:15:53 +0000600 oldumask = umask (0777 & ~LOGFILE_MASK);
paul718e3742002-12-13 20:15:29 +0000601 fp = fopen (filename, "a");
gdtaa593d52003-12-22 20:15:53 +0000602 umask(oldumask);
ajs274a4a42004-12-07 15:39:31 +0000603 if (fp == NULL)
604 return 0;
paul718e3742002-12-13 20:15:29 +0000605
606 /* Set flags. */
607 zl->filename = strdup (filename);
ajs274a4a42004-12-07 15:39:31 +0000608 zl->maxlvl[ZLOG_DEST_FILE] = log_level;
paul718e3742002-12-13 20:15:29 +0000609 zl->fp = fp;
ajsc4c7d0c2005-02-03 19:22:05 +0000610 logfile_fd = fileno(fp);
paul718e3742002-12-13 20:15:29 +0000611
612 return 1;
613}
614
615/* Reset opend file. */
616int
617zlog_reset_file (struct zlog *zl)
618{
619 if (zl == NULL)
620 zl = zlog_default;
621
paul718e3742002-12-13 20:15:29 +0000622 if (zl->fp)
623 fclose (zl->fp);
624 zl->fp = NULL;
ajsc4c7d0c2005-02-03 19:22:05 +0000625 logfile_fd = -1;
ajs274a4a42004-12-07 15:39:31 +0000626 zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
paul718e3742002-12-13 20:15:29 +0000627
628 if (zl->filename)
629 free (zl->filename);
630 zl->filename = NULL;
631
632 return 1;
633}
634
635/* Reopen log file. */
636int
637zlog_rotate (struct zlog *zl)
638{
ajs274a4a42004-12-07 15:39:31 +0000639 int level;
paul718e3742002-12-13 20:15:29 +0000640
641 if (zl == NULL)
642 zl = zlog_default;
643
644 if (zl->fp)
645 fclose (zl->fp);
646 zl->fp = NULL;
ajsc4c7d0c2005-02-03 19:22:05 +0000647 logfile_fd = -1;
ajs274a4a42004-12-07 15:39:31 +0000648 level = zl->maxlvl[ZLOG_DEST_FILE];
649 zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
paul718e3742002-12-13 20:15:29 +0000650
651 if (zl->filename)
652 {
gdtaa593d52003-12-22 20:15:53 +0000653 mode_t oldumask;
ajs274a4a42004-12-07 15:39:31 +0000654 int save_errno;
gdtaa593d52003-12-22 20:15:53 +0000655
656 oldumask = umask (0777 & ~LOGFILE_MASK);
ajs274a4a42004-12-07 15:39:31 +0000657 zl->fp = fopen (zl->filename, "a");
658 save_errno = errno;
659 umask(oldumask);
660 if (zl->fp == NULL)
gdtaa593d52003-12-22 20:15:53 +0000661 {
ajs274a4a42004-12-07 15:39:31 +0000662 zlog_err("Log rotate failed: cannot open file %s for append: %s",
663 zl->filename, safe_strerror(save_errno));
gdtaa593d52003-12-22 20:15:53 +0000664 return -1;
665 }
ajsc4c7d0c2005-02-03 19:22:05 +0000666 logfile_fd = fileno(zl->fp);
ajs274a4a42004-12-07 15:39:31 +0000667 zl->maxlvl[ZLOG_DEST_FILE] = level;
paul718e3742002-12-13 20:15:29 +0000668 }
669
670 return 1;
671}
672
paul718e3742002-12-13 20:15:29 +0000673/* Message lookup function. */
hasso8c328f12004-10-05 21:01:23 +0000674const char *
paul718e3742002-12-13 20:15:29 +0000675lookup (struct message *mes, int key)
676{
677 struct message *pnt;
678
679 for (pnt = mes; pnt->key != 0; pnt++)
680 if (pnt->key == key)
681 return pnt->str;
682
683 return "";
684}
685
686/* Very old hacky version of message lookup function. Still partly
hassob04c6992004-10-04 19:10:31 +0000687 used in bgpd and ospfd. FIXME Seems that it's not used any more. */
hasso8c328f12004-10-05 21:01:23 +0000688const char *
paul718e3742002-12-13 20:15:29 +0000689mes_lookup (struct message *meslist, int max, int index)
690{
691 if (index < 0 || index >= max)
692 {
693 zlog_err ("message index out of bound: %d", max);
694 return NULL;
695 }
696 return meslist[index].str;
697}
ajsca359762004-11-19 23:40:16 +0000698
699/* Wrapper around strerror to handle case where it returns NULL. */
700const char *
701safe_strerror(int errnum)
702{
703 const char *s = strerror(errnum);
704 return (s != NULL) ? s : "Unknown error";
705}
ajsf52d13c2005-10-01 17:38:06 +0000706
707/* Note: this table must match the ordering in lib/zebra.h */
708static const struct zebra_route_desc {
709 u_int zroute;
710 const char *string;
711 char chr;
712} route_types[] = {
713 { ZEBRA_ROUTE_SYSTEM, "system", 'X' },
714 { ZEBRA_ROUTE_KERNEL, "kernel", 'K' },
715 { ZEBRA_ROUTE_CONNECT, "connected", 'C' },
716 { ZEBRA_ROUTE_STATIC, "static", 'S' },
717 { ZEBRA_ROUTE_RIP, "rip", 'R' },
718 { ZEBRA_ROUTE_RIPNG, "ripng", 'R' },
719 { ZEBRA_ROUTE_OSPF, "ospf", 'O' },
720 { ZEBRA_ROUTE_OSPF6, "ospf6", 'O' },
721 { ZEBRA_ROUTE_ISIS, "isis", 'I' },
722 { ZEBRA_ROUTE_BGP, "bgp", 'B' },
723 { ZEBRA_ROUTE_HSLS, "hsls", 'H' },
724};
725
726static const struct zebra_route_desc *
727zroute_lookup(u_int zroute)
728{
729 static const struct zebra_route_desc unknown = { 0, "unknown", '?' };
730 u_int i;
731
732 if (zroute >= sizeof(route_types)/sizeof(route_types[0]))
733 {
734 zlog_err("unknown zebra route type: %u", zroute);
735 return &unknown;
736 }
737 if (zroute == route_types[zroute].zroute)
738 return &route_types[zroute];
739 for (i = 0; i < sizeof(route_types)/sizeof(route_types[0]); i++)
740 {
741 if (zroute == route_types[i].zroute)
742 {
743 zlog_warn("internal error: route type table out of order "
744 "while searching for %u, please notify developers", zroute);
745 return &route_types[i];
746 }
747 }
748 zlog_err("internal error: cannot find route type %u in table!", zroute);
749 return &unknown;
750}
751
752const char *
753zebra_route_string(u_int zroute)
754{
755 return zroute_lookup(zroute)->string;
756}
757
758char
759zebra_route_char(u_int zroute)
760{
761 return zroute_lookup(zroute)->chr;
762}