Annotation of embedaddon/quagga/lib/log.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Logging of zebra
3: * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro
4: *
5: * This file is part of GNU Zebra.
6: *
7: * GNU Zebra is free software; you can redistribute it and/or modify it
8: * under the terms of the GNU General Public License as published by the
9: * Free Software Foundation; either version 2, or (at your option) any
10: * later version.
11: *
12: * GNU Zebra is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License
18: * along with GNU Zebra; see the file COPYING. If not, write to the Free
19: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20: * 02111-1307, USA.
21: */
22:
23: #include <zebra.h>
24:
25: #include "log.h"
26: #include "memory.h"
27: #include "command.h"
28: #ifndef SUNOS_5
29: #include <sys/un.h>
30: #endif
31: /* for printstack on solaris */
32: #ifdef HAVE_UCONTEXT_H
33: #include <ucontext.h>
34: #endif
35:
36: static int logfile_fd = -1; /* Used in signal handler. */
37:
38: struct zlog *zlog_default = NULL;
39:
40: const char *zlog_proto_names[] =
41: {
42: "NONE",
43: "DEFAULT",
44: "ZEBRA",
45: "RIP",
46: "BGP",
47: "OSPF",
48: "RIPNG",
49: "OSPF6",
50: "ISIS",
51: "MASC",
52: NULL,
53: };
54:
55: const char *zlog_priority[] =
56: {
57: "emergencies",
58: "alerts",
59: "critical",
60: "errors",
61: "warnings",
62: "notifications",
63: "informational",
64: "debugging",
65: NULL,
66: };
67:
68:
69:
70: /* For time string format. */
71:
72: size_t
73: quagga_timestamp(int timestamp_precision, char *buf, size_t buflen)
74: {
75: static struct {
76: time_t last;
77: size_t len;
78: char buf[28];
79: } cache;
80: struct timeval clock;
81:
82: /* would it be sufficient to use global 'recent_time' here? I fear not... */
83: gettimeofday(&clock, NULL);
84:
85: /* first, we update the cache if the time has changed */
86: if (cache.last != clock.tv_sec)
87: {
88: struct tm *tm;
89: cache.last = clock.tv_sec;
90: tm = localtime(&cache.last);
91: cache.len = strftime(cache.buf, sizeof(cache.buf),
92: "%Y/%m/%d %H:%M:%S", tm);
93: }
94: /* note: it's not worth caching the subsecond part, because
95: chances are that back-to-back calls are not sufficiently close together
96: for the clock not to have ticked forward */
97:
98: if (buflen > cache.len)
99: {
100: memcpy(buf, cache.buf, cache.len);
101: if ((timestamp_precision > 0) &&
102: (buflen > cache.len+1+timestamp_precision))
103: {
104: /* should we worry about locale issues? */
105: static const int divisor[] = {0, 100000, 10000, 1000, 100, 10, 1};
106: int prec;
107: char *p = buf+cache.len+1+(prec = timestamp_precision);
108: *p-- = '\0';
109: while (prec > 6)
110: /* this is unlikely to happen, but protect anyway */
111: {
112: *p-- = '0';
113: prec--;
114: }
115: clock.tv_usec /= divisor[prec];
116: do
117: {
118: *p-- = '0'+(clock.tv_usec % 10);
119: clock.tv_usec /= 10;
120: }
121: while (--prec > 0);
122: *p = '.';
123: return cache.len+1+timestamp_precision;
124: }
125: buf[cache.len] = '\0';
126: return cache.len;
127: }
128: if (buflen > 0)
129: buf[0] = '\0';
130: return 0;
131: }
132:
133: /* Utility routine for current time printing. */
134: static void
135: time_print(FILE *fp, struct timestamp_control *ctl)
136: {
137: if (!ctl->already_rendered)
138: {
139: ctl->len = quagga_timestamp(ctl->precision, ctl->buf, sizeof(ctl->buf));
140: ctl->already_rendered = 1;
141: }
142: fprintf(fp, "%s ", ctl->buf);
143: }
144:
145:
146: /* va_list version of zlog. */
147: static void
148: vzlog (struct zlog *zl, int priority, const char *format, va_list args)
149: {
150: struct timestamp_control tsctl;
151: tsctl.already_rendered = 0;
152:
153: /* If zlog is not specified, use default one. */
154: if (zl == NULL)
155: zl = zlog_default;
156:
157: /* When zlog_default is also NULL, use stderr for logging. */
158: if (zl == NULL)
159: {
160: tsctl.precision = 0;
161: time_print(stderr, &tsctl);
162: fprintf (stderr, "%s: ", "unknown");
163: vfprintf (stderr, format, args);
164: fprintf (stderr, "\n");
165: fflush (stderr);
166:
167: /* In this case we return at here. */
168: return;
169: }
170: tsctl.precision = zl->timestamp_precision;
171:
172: /* Syslog output */
173: if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG])
174: {
175: va_list ac;
176: va_copy(ac, args);
177: vsyslog (priority|zlog_default->facility, format, ac);
178: va_end(ac);
179: }
180:
181: /* File output. */
182: if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp)
183: {
184: va_list ac;
185: time_print (zl->fp, &tsctl);
186: if (zl->record_priority)
187: fprintf (zl->fp, "%s: ", zlog_priority[priority]);
188: fprintf (zl->fp, "%s: ", zlog_proto_names[zl->protocol]);
189: va_copy(ac, args);
190: vfprintf (zl->fp, format, ac);
191: va_end(ac);
192: fprintf (zl->fp, "\n");
193: fflush (zl->fp);
194: }
195:
196: /* stdout output. */
197: if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT])
198: {
199: va_list ac;
200: time_print (stdout, &tsctl);
201: if (zl->record_priority)
202: fprintf (stdout, "%s: ", zlog_priority[priority]);
203: fprintf (stdout, "%s: ", zlog_proto_names[zl->protocol]);
204: va_copy(ac, args);
205: vfprintf (stdout, format, ac);
206: va_end(ac);
207: fprintf (stdout, "\n");
208: fflush (stdout);
209: }
210:
211: /* Terminal monitor. */
212: if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR])
213: vty_log ((zl->record_priority ? zlog_priority[priority] : NULL),
214: zlog_proto_names[zl->protocol], format, &tsctl, args);
215: }
216:
217: static char *
218: str_append(char *dst, int len, const char *src)
219: {
220: while ((len-- > 0) && *src)
221: *dst++ = *src++;
222: return dst;
223: }
224:
225: static char *
226: num_append(char *s, int len, u_long x)
227: {
228: char buf[30];
229: char *t;
230:
231: if (!x)
232: return str_append(s,len,"0");
233: *(t = &buf[sizeof(buf)-1]) = '\0';
234: while (x && (t > buf))
235: {
236: *--t = '0'+(x % 10);
237: x /= 10;
238: }
239: return str_append(s,len,t);
240: }
241:
242: #if defined(SA_SIGINFO) || defined(HAVE_STACK_TRACE)
243: static char *
244: hex_append(char *s, int len, u_long x)
245: {
246: char buf[30];
247: char *t;
248:
249: if (!x)
250: return str_append(s,len,"0");
251: *(t = &buf[sizeof(buf)-1]) = '\0';
252: while (x && (t > buf))
253: {
254: u_int cc = (x % 16);
255: *--t = ((cc < 10) ? ('0'+cc) : ('a'+cc-10));
256: x /= 16;
257: }
258: return str_append(s,len,t);
259: }
260: #endif
261:
262: /* Needs to be enhanced to support Solaris. */
263: static int
264: syslog_connect(void)
265: {
266: #ifdef SUNOS_5
267: return -1;
268: #else
269: int fd;
270: char *s;
271: struct sockaddr_un addr;
272:
273: if ((fd = socket(AF_UNIX,SOCK_DGRAM,0)) < 0)
274: return -1;
275: addr.sun_family = AF_UNIX;
276: #ifdef _PATH_LOG
277: #define SYSLOG_SOCKET_PATH _PATH_LOG
278: #else
279: #define SYSLOG_SOCKET_PATH "/dev/log"
280: #endif
281: s = str_append(addr.sun_path,sizeof(addr.sun_path),SYSLOG_SOCKET_PATH);
282: #undef SYSLOG_SOCKET_PATH
283: *s = '\0';
284: if (connect(fd,(struct sockaddr *)&addr,sizeof(addr)) < 0)
285: {
286: close(fd);
287: return -1;
288: }
289: return fd;
290: #endif
291: }
292:
293: static void
294: syslog_sigsafe(int priority, const char *msg, size_t msglen)
295: {
296: static int syslog_fd = -1;
297: char buf[sizeof("<1234567890>ripngd[1234567890]: ")+msglen+50];
298: char *s;
299:
300: if ((syslog_fd < 0) && ((syslog_fd = syslog_connect()) < 0))
301: return;
302:
303: #define LOC s,buf+sizeof(buf)-s
304: s = buf;
305: s = str_append(LOC,"<");
306: s = num_append(LOC,priority);
307: s = str_append(LOC,">");
308: /* forget about the timestamp, too difficult in a signal handler */
309: s = str_append(LOC,zlog_default->ident);
310: if (zlog_default->syslog_options & LOG_PID)
311: {
312: s = str_append(LOC,"[");
313: s = num_append(LOC,getpid());
314: s = str_append(LOC,"]");
315: }
316: s = str_append(LOC,": ");
317: s = str_append(LOC,msg);
318: write(syslog_fd,buf,s-buf);
319: #undef LOC
320: }
321:
322: static int
323: open_crashlog(void)
324: {
325: #define CRASHLOG_PREFIX "/var/tmp/quagga."
326: #define CRASHLOG_SUFFIX "crashlog"
327: if (zlog_default && zlog_default->ident)
328: {
329: /* Avoid strlen since it is not async-signal-safe. */
330: const char *p;
331: size_t ilen;
332:
333: for (p = zlog_default->ident, ilen = 0; *p; p++)
334: ilen++;
335: {
336: char buf[sizeof(CRASHLOG_PREFIX)+ilen+sizeof(CRASHLOG_SUFFIX)+3];
337: char *s = buf;
338: #define LOC s,buf+sizeof(buf)-s
339: s = str_append(LOC, CRASHLOG_PREFIX);
340: s = str_append(LOC, zlog_default->ident);
341: s = str_append(LOC, ".");
342: s = str_append(LOC, CRASHLOG_SUFFIX);
343: #undef LOC
344: *s = '\0';
345: return open(buf, O_WRONLY|O_CREAT|O_EXCL, LOGFILE_MASK);
346: }
347: }
348: return open(CRASHLOG_PREFIX CRASHLOG_SUFFIX, O_WRONLY|O_CREAT|O_EXCL,
349: LOGFILE_MASK);
350: #undef CRASHLOG_SUFFIX
351: #undef CRASHLOG_PREFIX
352: }
353:
354: /* Note: the goal here is to use only async-signal-safe functions. */
355: void
356: zlog_signal(int signo, const char *action
357: #ifdef SA_SIGINFO
358: , siginfo_t *siginfo, void *program_counter
359: #endif
360: )
361: {
362: time_t now;
363: char buf[sizeof("DEFAULT: Received signal S at T (si_addr 0xP, PC 0xP); aborting...")+100];
364: char *s = buf;
365: char *msgstart = buf;
366: #define LOC s,buf+sizeof(buf)-s
367:
368: time(&now);
369: if (zlog_default)
370: {
371: s = str_append(LOC,zlog_proto_names[zlog_default->protocol]);
372: *s++ = ':';
373: *s++ = ' ';
374: msgstart = s;
375: }
376: s = str_append(LOC,"Received signal ");
377: s = num_append(LOC,signo);
378: s = str_append(LOC," at ");
379: s = num_append(LOC,now);
380: #ifdef SA_SIGINFO
381: s = str_append(LOC," (si_addr 0x");
382: s = hex_append(LOC,(u_long)(siginfo->si_addr));
383: if (program_counter)
384: {
385: s = str_append(LOC,", PC 0x");
386: s = hex_append(LOC,(u_long)program_counter);
387: }
388: s = str_append(LOC,"); ");
389: #else /* SA_SIGINFO */
390: s = str_append(LOC,"; ");
391: #endif /* SA_SIGINFO */
392: s = str_append(LOC,action);
393: if (s < buf+sizeof(buf))
394: *s++ = '\n';
395:
396: /* N.B. implicit priority is most severe */
397: #define PRI LOG_CRIT
398:
399: #define DUMP(FD) write(FD, buf, s-buf);
400: /* If no file logging configured, try to write to fallback log file. */
401: if ((logfile_fd >= 0) || ((logfile_fd = open_crashlog()) >= 0))
402: DUMP(logfile_fd)
403: if (!zlog_default)
404: DUMP(STDERR_FILENO)
405: else
406: {
407: if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT])
408: DUMP(STDOUT_FILENO)
409: /* Remove trailing '\n' for monitor and syslog */
410: *--s = '\0';
411: if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
412: vty_log_fixed(buf,s-buf);
413: if (PRI <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
414: syslog_sigsafe(PRI|zlog_default->facility,msgstart,s-msgstart);
415: }
416: #undef DUMP
417:
418: zlog_backtrace_sigsafe(PRI,
419: #ifdef SA_SIGINFO
420: program_counter
421: #else
422: NULL
423: #endif
424: );
425: #undef PRI
426: #undef LOC
427: }
428:
429: /* Log a backtrace using only async-signal-safe functions.
430: Needs to be enhanced to support syslog logging. */
431: void
432: zlog_backtrace_sigsafe(int priority, void *program_counter)
433: {
434: #ifdef HAVE_STACK_TRACE
435: static const char pclabel[] = "Program counter: ";
436: void *array[64];
437: int size;
438: char buf[100];
439: char *s, **bt = NULL;
440: #define LOC s,buf+sizeof(buf)-s
441:
442: #ifdef HAVE_GLIBC_BACKTRACE
443: if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
444: ((size_t)size > sizeof(array)/sizeof(array[0])))
445: return;
446:
447: #define DUMP(FD) { \
448: if (program_counter) \
449: { \
450: write(FD, pclabel, sizeof(pclabel)-1); \
451: backtrace_symbols_fd(&program_counter, 1, FD); \
452: } \
453: write(FD, buf, s-buf); \
454: backtrace_symbols_fd(array, size, FD); \
455: }
456: #elif defined(HAVE_PRINTSTACK)
457: #define DUMP(FD) { \
458: if (program_counter) \
459: write((FD), pclabel, sizeof(pclabel)-1); \
460: write((FD), buf, s-buf); \
461: printstack((FD)); \
462: }
463: #endif /* HAVE_GLIBC_BACKTRACE, HAVE_PRINTSTACK */
464:
465: s = buf;
466: s = str_append(LOC,"Backtrace for ");
467: s = num_append(LOC,size);
468: s = str_append(LOC," stack frames:\n");
469:
470: if ((logfile_fd >= 0) || ((logfile_fd = open_crashlog()) >= 0))
471: DUMP(logfile_fd)
472: if (!zlog_default)
473: DUMP(STDERR_FILENO)
474: else
475: {
476: if (priority <= zlog_default->maxlvl[ZLOG_DEST_STDOUT])
477: DUMP(STDOUT_FILENO)
478: /* Remove trailing '\n' for monitor and syslog */
479: *--s = '\0';
480: if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
481: vty_log_fixed(buf,s-buf);
482: if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
483: syslog_sigsafe(priority|zlog_default->facility,buf,s-buf);
484: {
485: int i;
486: #ifdef HAVE_GLIBC_BACKTRACE
487: bt = backtrace_symbols(array, size);
488: #endif
489: /* Just print the function addresses. */
490: for (i = 0; i < size; i++)
491: {
492: s = buf;
493: if (bt)
494: s = str_append(LOC, bt[i]);
495: else {
496: s = str_append(LOC,"[bt ");
497: s = num_append(LOC,i);
498: s = str_append(LOC,"] 0x");
499: s = hex_append(LOC,(u_long)(array[i]));
500: }
501: *s = '\0';
502: if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
503: vty_log_fixed(buf,s-buf);
504: if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
505: syslog_sigsafe(priority|zlog_default->facility,buf,s-buf);
506: }
507: if (bt)
508: free(bt);
509: }
510: }
511: #undef DUMP
512: #undef LOC
513: #endif /* HAVE_STRACK_TRACE */
514: }
515:
516: void
517: zlog_backtrace(int priority)
518: {
519: #ifndef HAVE_GLIBC_BACKTRACE
520: zlog(NULL, priority, "No backtrace available on this platform.");
521: #else
522: void *array[20];
523: int size, i;
524: char **strings;
525:
526: if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
527: ((size_t)size > sizeof(array)/sizeof(array[0])))
528: {
529: zlog_err("Cannot get backtrace, returned invalid # of frames %d "
530: "(valid range is between 1 and %lu)",
531: size, (unsigned long)(sizeof(array)/sizeof(array[0])));
532: return;
533: }
534: zlog(NULL, priority, "Backtrace for %d stack frames:", size);
535: if (!(strings = backtrace_symbols(array, size)))
536: {
537: zlog_err("Cannot get backtrace symbols (out of memory?)");
538: for (i = 0; i < size; i++)
539: zlog(NULL, priority, "[bt %d] %p",i,array[i]);
540: }
541: else
542: {
543: for (i = 0; i < size; i++)
544: zlog(NULL, priority, "[bt %d] %s",i,strings[i]);
545: free(strings);
546: }
547: #endif /* HAVE_GLIBC_BACKTRACE */
548: }
549:
550: void
551: zlog (struct zlog *zl, int priority, const char *format, ...)
552: {
553: va_list args;
554:
555: va_start(args, format);
556: vzlog (zl, priority, format, args);
557: va_end (args);
558: }
559:
560: #define ZLOG_FUNC(FUNCNAME,PRIORITY) \
561: void \
562: FUNCNAME(const char *format, ...) \
563: { \
564: va_list args; \
565: va_start(args, format); \
566: vzlog (NULL, PRIORITY, format, args); \
567: va_end(args); \
568: }
569:
570: ZLOG_FUNC(zlog_err, LOG_ERR)
571:
572: ZLOG_FUNC(zlog_warn, LOG_WARNING)
573:
574: ZLOG_FUNC(zlog_info, LOG_INFO)
575:
576: ZLOG_FUNC(zlog_notice, LOG_NOTICE)
577:
578: ZLOG_FUNC(zlog_debug, LOG_DEBUG)
579:
580: #undef ZLOG_FUNC
581:
582: #define PLOG_FUNC(FUNCNAME,PRIORITY) \
583: void \
584: FUNCNAME(struct zlog *zl, const char *format, ...) \
585: { \
586: va_list args; \
587: va_start(args, format); \
588: vzlog (zl, PRIORITY, format, args); \
589: va_end(args); \
590: }
591:
592: PLOG_FUNC(plog_err, LOG_ERR)
593:
594: PLOG_FUNC(plog_warn, LOG_WARNING)
595:
596: PLOG_FUNC(plog_info, LOG_INFO)
597:
598: PLOG_FUNC(plog_notice, LOG_NOTICE)
599:
600: PLOG_FUNC(plog_debug, LOG_DEBUG)
601:
602: #undef PLOG_FUNC
603:
604: void
605: _zlog_assert_failed (const char *assertion, const char *file,
606: unsigned int line, const char *function)
607: {
608: /* Force fallback file logging? */
609: if (zlog_default && !zlog_default->fp &&
610: ((logfile_fd = open_crashlog()) >= 0) &&
611: ((zlog_default->fp = fdopen(logfile_fd, "w")) != NULL))
612: zlog_default->maxlvl[ZLOG_DEST_FILE] = LOG_ERR;
613: zlog(NULL, LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s",
614: assertion,file,line,(function ? function : "?"));
615: zlog_backtrace(LOG_CRIT);
616: abort();
617: }
618:
619:
620: /* Open log stream */
621: struct zlog *
622: openzlog (const char *progname, zlog_proto_t protocol,
623: int syslog_flags, int syslog_facility)
624: {
625: struct zlog *zl;
626: u_int i;
627:
628: zl = XCALLOC(MTYPE_ZLOG, sizeof (struct zlog));
629:
630: zl->ident = progname;
631: zl->protocol = protocol;
632: zl->facility = syslog_facility;
633: zl->syslog_options = syslog_flags;
634:
635: /* Set default logging levels. */
636: for (i = 0; i < sizeof(zl->maxlvl)/sizeof(zl->maxlvl[0]); i++)
637: zl->maxlvl[i] = ZLOG_DISABLED;
638: zl->maxlvl[ZLOG_DEST_MONITOR] = LOG_DEBUG;
639: zl->default_lvl = LOG_DEBUG;
640:
641: openlog (progname, syslog_flags, zl->facility);
642:
643: return zl;
644: }
645:
646: void
647: closezlog (struct zlog *zl)
648: {
649: closelog();
650:
651: if (zl->fp != NULL)
652: fclose (zl->fp);
653:
654: if (zl->filename != NULL)
655: free (zl->filename);
656:
657: XFREE (MTYPE_ZLOG, zl);
658: }
659:
660: /* Called from command.c. */
661: void
662: zlog_set_level (struct zlog *zl, zlog_dest_t dest, int log_level)
663: {
664: if (zl == NULL)
665: zl = zlog_default;
666:
667: zl->maxlvl[dest] = log_level;
668: }
669:
670: int
671: zlog_set_file (struct zlog *zl, const char *filename, int log_level)
672: {
673: FILE *fp;
674: mode_t oldumask;
675:
676: /* There is opend file. */
677: zlog_reset_file (zl);
678:
679: /* Set default zl. */
680: if (zl == NULL)
681: zl = zlog_default;
682:
683: /* Open file. */
684: oldumask = umask (0777 & ~LOGFILE_MASK);
685: fp = fopen (filename, "a");
686: umask(oldumask);
687: if (fp == NULL)
688: return 0;
689:
690: /* Set flags. */
691: zl->filename = strdup (filename);
692: zl->maxlvl[ZLOG_DEST_FILE] = log_level;
693: zl->fp = fp;
694: logfile_fd = fileno(fp);
695:
696: return 1;
697: }
698:
699: /* Reset opend file. */
700: int
701: zlog_reset_file (struct zlog *zl)
702: {
703: if (zl == NULL)
704: zl = zlog_default;
705:
706: if (zl->fp)
707: fclose (zl->fp);
708: zl->fp = NULL;
709: logfile_fd = -1;
710: zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
711:
712: if (zl->filename)
713: free (zl->filename);
714: zl->filename = NULL;
715:
716: return 1;
717: }
718:
719: /* Reopen log file. */
720: int
721: zlog_rotate (struct zlog *zl)
722: {
723: int level;
724:
725: if (zl == NULL)
726: zl = zlog_default;
727:
728: if (zl->fp)
729: fclose (zl->fp);
730: zl->fp = NULL;
731: logfile_fd = -1;
732: level = zl->maxlvl[ZLOG_DEST_FILE];
733: zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
734:
735: if (zl->filename)
736: {
737: mode_t oldumask;
738: int save_errno;
739:
740: oldumask = umask (0777 & ~LOGFILE_MASK);
741: zl->fp = fopen (zl->filename, "a");
742: save_errno = errno;
743: umask(oldumask);
744: if (zl->fp == NULL)
745: {
746: zlog_err("Log rotate failed: cannot open file %s for append: %s",
747: zl->filename, safe_strerror(save_errno));
748: return -1;
749: }
750: logfile_fd = fileno(zl->fp);
751: zl->maxlvl[ZLOG_DEST_FILE] = level;
752: }
753:
754: return 1;
755: }
756:
757: /* Message lookup function. */
758: const char *
759: lookup (const struct message *mes, int key)
760: {
761: const struct message *pnt;
762:
763: for (pnt = mes; pnt->key != 0; pnt++)
764: if (pnt->key == key)
765: return pnt->str;
766:
767: return "";
768: }
769:
770: /* Older/faster version of message lookup function, but requires caller to pass
771: * in the array size (instead of relying on a 0 key to terminate the search).
772: *
773: * The return value is the message string if found, or the 'none' pointer
774: * provided otherwise.
775: */
776: const char *
777: mes_lookup (const struct message *meslist, int max, int index,
778: const char *none, const char *mesname)
779: {
780: int pos = index - meslist[0].key;
781:
782: /* first check for best case: index is in range and matches the key
783: * value in that slot.
784: * NB: key numbering might be offset from 0. E.g. protocol constants
785: * often start at 1.
786: */
787: if ((pos >= 0) && (pos < max)
788: && (meslist[pos].key == index))
789: return meslist[pos].str;
790:
791: /* fall back to linear search */
792: {
793: int i;
794:
795: for (i = 0; i < max; i++, meslist++)
796: {
797: if (meslist->key == index)
798: {
799: const char *str = (meslist->str ? meslist->str : none);
800:
801: zlog_debug ("message index %d [%s] found in %s at position %d (max is %d)",
802: index, str, mesname, i, max);
803: return str;
804: }
805: }
806: }
807: zlog_err("message index %d not found in %s (max is %d)", index, mesname, max);
808: assert (none);
809: return none;
810: }
811:
812: /* Wrapper around strerror to handle case where it returns NULL. */
813: const char *
814: safe_strerror(int errnum)
815: {
816: const char *s = strerror(errnum);
817: return (s != NULL) ? s : "Unknown error";
818: }
819:
820: struct zebra_desc_table
821: {
822: unsigned int type;
823: const char *string;
824: char chr;
825: };
826:
827: #define DESC_ENTRY(T,S,C) [(T)] = { (T), (S), (C) }
828: static const struct zebra_desc_table route_types[] = {
829: DESC_ENTRY (ZEBRA_ROUTE_SYSTEM, "system", 'X' ),
830: DESC_ENTRY (ZEBRA_ROUTE_KERNEL, "kernel", 'K' ),
831: DESC_ENTRY (ZEBRA_ROUTE_CONNECT, "connected", 'C' ),
832: DESC_ENTRY (ZEBRA_ROUTE_STATIC, "static", 'S' ),
833: DESC_ENTRY (ZEBRA_ROUTE_RIP, "rip", 'R' ),
834: DESC_ENTRY (ZEBRA_ROUTE_RIPNG, "ripng", 'R' ),
835: DESC_ENTRY (ZEBRA_ROUTE_OSPF, "ospf", 'O' ),
836: DESC_ENTRY (ZEBRA_ROUTE_OSPF6, "ospf6", 'O' ),
837: DESC_ENTRY (ZEBRA_ROUTE_ISIS, "isis", 'I' ),
838: DESC_ENTRY (ZEBRA_ROUTE_BGP, "bgp", 'B' ),
839: DESC_ENTRY (ZEBRA_ROUTE_HSLS, "hsls", 'H' ),
840: };
841: #undef DESC_ENTRY
842:
843: #define DESC_ENTRY(T) [(T)] = { (T), (#T), '\0' }
844: static const struct zebra_desc_table command_types[] = {
845: DESC_ENTRY (ZEBRA_INTERFACE_ADD),
846: DESC_ENTRY (ZEBRA_INTERFACE_DELETE),
847: DESC_ENTRY (ZEBRA_INTERFACE_ADDRESS_ADD),
848: DESC_ENTRY (ZEBRA_INTERFACE_ADDRESS_DELETE),
849: DESC_ENTRY (ZEBRA_INTERFACE_UP),
850: DESC_ENTRY (ZEBRA_INTERFACE_DOWN),
851: DESC_ENTRY (ZEBRA_IPV4_ROUTE_ADD),
852: DESC_ENTRY (ZEBRA_IPV4_ROUTE_DELETE),
853: DESC_ENTRY (ZEBRA_IPV6_ROUTE_ADD),
854: DESC_ENTRY (ZEBRA_IPV6_ROUTE_DELETE),
855: DESC_ENTRY (ZEBRA_REDISTRIBUTE_ADD),
856: DESC_ENTRY (ZEBRA_REDISTRIBUTE_DELETE),
857: DESC_ENTRY (ZEBRA_REDISTRIBUTE_DEFAULT_ADD),
858: DESC_ENTRY (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE),
859: DESC_ENTRY (ZEBRA_IPV4_NEXTHOP_LOOKUP),
860: DESC_ENTRY (ZEBRA_IPV6_NEXTHOP_LOOKUP),
861: DESC_ENTRY (ZEBRA_IPV4_IMPORT_LOOKUP),
862: DESC_ENTRY (ZEBRA_IPV6_IMPORT_LOOKUP),
863: DESC_ENTRY (ZEBRA_INTERFACE_RENAME),
864: DESC_ENTRY (ZEBRA_ROUTER_ID_ADD),
865: DESC_ENTRY (ZEBRA_ROUTER_ID_DELETE),
866: DESC_ENTRY (ZEBRA_ROUTER_ID_UPDATE),
867: };
868: #undef DESC_ENTRY
869:
870: static const struct zebra_desc_table unknown = { 0, "unknown", '?' };
871:
872: static const struct zebra_desc_table *
873: zroute_lookup(u_int zroute)
874: {
875: u_int i;
876:
877: if (zroute >= sizeof(route_types)/sizeof(route_types[0]))
878: {
879: zlog_err("unknown zebra route type: %u", zroute);
880: return &unknown;
881: }
882: if (zroute == route_types[zroute].type)
883: return &route_types[zroute];
884: for (i = 0; i < sizeof(route_types)/sizeof(route_types[0]); i++)
885: {
886: if (zroute == route_types[i].type)
887: {
888: zlog_warn("internal error: route type table out of order "
889: "while searching for %u, please notify developers", zroute);
890: return &route_types[i];
891: }
892: }
893: zlog_err("internal error: cannot find route type %u in table!", zroute);
894: return &unknown;
895: }
896:
897: const char *
898: zebra_route_string(u_int zroute)
899: {
900: return zroute_lookup(zroute)->string;
901: }
902:
903: char
904: zebra_route_char(u_int zroute)
905: {
906: return zroute_lookup(zroute)->chr;
907: }
908:
909: const char *
910: zserv_command_string (unsigned int command)
911: {
912: if (command >= sizeof(command_types)/sizeof(command_types[0]))
913: {
914: zlog_err ("unknown zserv command type: %u", command);
915: return unknown.string;
916: }
917: return command_types[command].string;
918: }
919:
920: #define RTSIZE (sizeof(route_types)/sizeof(route_types[0]))
921:
922: int
923: proto_name2num(const char *s)
924: {
925: unsigned i;
926:
927: for (i=0; i<RTSIZE; ++i)
928: if (strcasecmp(s, route_types[i].string) == 0)
929: return route_types[i].type;
930: return -1;
931: }
932: #undef RTSIZE
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>