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