[bgpd] struct peer must have bgp field valid (redistribute crash)
[jleu-quagga.git] / lib / log.c
blob3eb0bd523dbe363644f4bc08ca70e10ffc3acb03
1 /*
2 * $Id$
4 * Logging of zebra
5 * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro
7 * This file is part of GNU Zebra.
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.
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.
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.
25 #include <zebra.h>
27 #include "log.h"
28 #include "memory.h"
29 #include "command.h"
30 #ifndef SUNOS_5
31 #include <sys/un.h>
32 #endif
34 static int logfile_fd = -1; /* Used in signal handler. */
36 struct zlog *zlog_default = NULL;
38 const char *zlog_proto_names[] =
40 "NONE",
41 "DEFAULT",
42 "ZEBRA",
43 "RIP",
44 "BGP",
45 "OSPF",
46 "RIPNG",
47 "OSPF6",
48 "ISIS",
49 "MASC",
50 NULL,
53 const char *zlog_priority[] =
55 "emergencies",
56 "alerts",
57 "critical",
58 "errors",
59 "warnings",
60 "notifications",
61 "informational",
62 "debugging",
63 NULL,
68 /* For time string format. */
69 #define TIME_BUF 27
71 /* Utility routine for current time printing. */
72 static void
73 time_print (FILE *fp)
75 int ret;
76 char buf [TIME_BUF];
77 time_t clock;
78 struct tm *tm;
80 time (&clock);
81 tm = localtime (&clock);
83 ret = strftime (buf, TIME_BUF, "%Y/%m/%d %H:%M:%S", tm);
84 if (ret == 0) {
85 zlog_warn ("strftime error");
88 fprintf (fp, "%s ", buf);
91 /* va_list version of zlog. */
92 static void
93 vzlog (struct zlog *zl, int priority, const char *format, va_list args)
95 /* If zlog is not specified, use default one. */
96 if (zl == NULL)
97 zl = zlog_default;
99 /* When zlog_default is also NULL, use stderr for logging. */
100 if (zl == NULL)
102 time_print (stderr);
103 fprintf (stderr, "%s: ", "unknown");
104 vfprintf (stderr, format, args);
105 fprintf (stderr, "\n");
106 fflush (stderr);
108 /* In this case we return at here. */
109 return;
112 /* Syslog output */
113 if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG])
115 va_list ac;
116 va_copy(ac, args);
117 vsyslog (priority|zlog_default->facility, format, ac);
118 va_end(ac);
121 /* File output. */
122 if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp)
124 va_list ac;
125 time_print (zl->fp);
126 if (zl->record_priority)
127 fprintf (zl->fp, "%s: ", zlog_priority[priority]);
128 fprintf (zl->fp, "%s: ", zlog_proto_names[zl->protocol]);
129 va_copy(ac, args);
130 vfprintf (zl->fp, format, ac);
131 va_end(ac);
132 fprintf (zl->fp, "\n");
133 fflush (zl->fp);
136 /* stdout output. */
137 if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT])
139 va_list ac;
140 time_print (stdout);
141 if (zl->record_priority)
142 fprintf (stdout, "%s: ", zlog_priority[priority]);
143 fprintf (stdout, "%s: ", zlog_proto_names[zl->protocol]);
144 va_copy(ac, args);
145 vfprintf (stdout, format, ac);
146 va_end(ac);
147 fprintf (stdout, "\n");
148 fflush (stdout);
151 /* Terminal monitor. */
152 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);
157 static char *
158 str_append(char *dst, int len, const char *src)
160 while ((len-- > 0) && *src)
161 *dst++ = *src++;
162 return dst;
165 static char *
166 num_append(char *s, int len, u_long x)
168 char buf[30];
169 char *t;
171 if (!x)
172 return str_append(s,len,"0");
173 *(t = &buf[sizeof(buf)-1]) = '\0';
174 while (x && (t > buf))
176 *--t = '0'+(x % 10);
177 x /= 10;
179 return str_append(s,len,t);
182 #if defined(SA_SIGINFO) || defined(HAVE_STACK_TRACE)
183 static char *
184 hex_append(char *s, int len, u_long x)
186 char buf[30];
187 char *t;
189 if (!x)
190 return str_append(s,len,"0");
191 *(t = &buf[sizeof(buf)-1]) = '\0';
192 while (x && (t > buf))
194 u_int cc = (x % 16);
195 *--t = ((cc < 10) ? ('0'+cc) : ('a'+cc-10));
196 x /= 16;
198 return str_append(s,len,t);
200 #endif
202 /* Needs to be enhanced to support Solaris. */
203 static int
204 syslog_connect(void)
206 #ifdef SUNOS_5
207 return -1;
208 #else
209 int fd;
210 char *s;
211 struct sockaddr_un addr;
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)
226 close(fd);
227 return -1;
229 return fd;
230 #endif
233 static void
234 syslog_sigsafe(int priority, const char *msg, size_t msglen)
236 static int syslog_fd = -1;
237 char buf[sizeof("<1234567890>ripngd[1234567890]: ")+msglen+50];
238 char *s;
240 if ((syslog_fd < 0) && ((syslog_fd = syslog_connect()) < 0))
241 return;
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)
252 s = str_append(LOC,"[");
253 s = num_append(LOC,getpid());
254 s = str_append(LOC,"]");
256 s = str_append(LOC,": ");
257 s = str_append(LOC,msg);
258 write(syslog_fd,buf,s-buf);
259 #undef LOC
262 static int
263 open_crashlog(void)
265 #define CRASHLOG_PREFIX "/var/tmp/quagga."
266 #define CRASHLOG_SUFFIX "crashlog"
267 if (zlog_default && zlog_default->ident)
269 /* Avoid strlen since it is not async-signal-safe. */
270 const char *p;
271 size_t ilen;
273 for (p = zlog_default->ident, ilen = 0; *p; p++)
274 ilen++;
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);
288 return open(CRASHLOG_PREFIX CRASHLOG_SUFFIX, O_WRONLY|O_CREAT|O_EXCL,
289 LOGFILE_MASK);
290 #undef CRASHLOG_SUFFIX
291 #undef CRASHLOG_PREFIX
294 /* Note: the goal here is to use only async-signal-safe functions. */
295 void
296 zlog_signal(int signo, const char *action
297 #ifdef SA_SIGINFO
298 , siginfo_t *siginfo, void *program_counter
299 #endif
302 time_t now;
303 char buf[sizeof("DEFAULT: Received signal S at T (si_addr 0xP, PC 0xP); aborting...")+100];
304 char *s = buf;
305 char *msgstart = buf;
306 #define LOC s,buf+sizeof(buf)-s
308 time(&now);
309 if (zlog_default)
311 s = str_append(LOC,zlog_proto_names[zlog_default->protocol]);
312 *s++ = ':';
313 *s++ = ' ';
314 msgstart = s;
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);
320 #ifdef SA_SIGINFO
321 s = str_append(LOC," (si_addr 0x");
322 s = hex_append(LOC,(u_long)(siginfo->si_addr));
323 if (program_counter)
325 s = str_append(LOC,", PC 0x");
326 s = hex_append(LOC,(u_long)program_counter);
328 s = str_append(LOC,"); ");
329 #else /* SA_SIGINFO */
330 s = str_append(LOC,"; ");
331 #endif /* SA_SIGINFO */
332 s = str_append(LOC,action);
333 if (s < buf+sizeof(buf))
334 *s++ = '\n';
336 /* N.B. implicit priority is most severe */
337 #define PRI LOG_CRIT
339 #define DUMP(FD) write(FD, buf, s-buf);
340 /* If no file logging configured, try to write to fallback log file. */
341 if ((logfile_fd >= 0) || ((logfile_fd = open_crashlog()) >= 0))
342 DUMP(logfile_fd)
343 if (!zlog_default)
344 DUMP(STDERR_FILENO)
345 else
347 if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT])
348 DUMP(STDOUT_FILENO)
349 /* 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);
356 #undef DUMP
358 zlog_backtrace_sigsafe(PRI,
359 #ifdef SA_SIGINFO
360 program_counter
361 #else
362 NULL
363 #endif
365 #undef PRI
366 #undef LOC
369 /* Log a backtrace using only async-signal-safe functions.
370 Needs to be enhanced to support syslog logging. */
371 void
372 zlog_backtrace_sigsafe(int priority, void *program_counter)
374 #ifdef HAVE_STACK_TRACE
375 static const char pclabel[] = "Program counter: ";
376 void *array[20];
377 int size;
378 char buf[100];
379 char *s;
380 #define LOC s,buf+sizeof(buf)-s
382 #ifdef HAVE_GLIBC_BACKTRACE
383 if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
384 ((size_t)size > sizeof(array)/sizeof(array[0])))
385 return;
387 #define DUMP(FD) { \
388 if (program_counter) \
390 write(FD, pclabel, sizeof(pclabel)-1); \
391 backtrace_symbols_fd(&program_counter, 1, FD); \
393 write(FD, buf, s-buf); \
394 backtrace_symbols_fd(array, size, FD); \
396 #elif defined(HAVE_PRINTSTACK)
397 #define DUMP(FD) { \
398 if (program_counter) \
399 write((FD), pclabel, sizeof(pclabel)-1); \
400 write((FD), buf, s-buf); \
401 printstack((FD)); \
403 #endif /* HAVE_GLIBC_BACKTRACE, HAVE_PRINTSTACK */
405 s = buf;
406 s = str_append(LOC,"Backtrace for ");
407 s = num_append(LOC,size);
408 s = str_append(LOC," stack frames:\n");
410 if ((logfile_fd >= 0) || ((logfile_fd = open_crashlog()) >= 0))
411 DUMP(logfile_fd)
412 if (!zlog_default)
413 DUMP(STDERR_FILENO)
414 else
416 if (priority <= zlog_default->maxlvl[ZLOG_DEST_STDOUT])
417 DUMP(STDOUT_FILENO)
418 /* Remove trailing '\n' for monitor and syslog */
419 *--s = '\0';
420 if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
421 vty_log_fixed(buf,s-buf);
422 if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
423 syslog_sigsafe(priority|zlog_default->facility,buf,s-buf);
425 int i;
426 /* Just print the function addresses. */
427 for (i = 0; i < size; i++)
429 s = buf;
430 s = str_append(LOC,"[bt ");
431 s = num_append(LOC,i);
432 s = str_append(LOC,"] 0x");
433 s = hex_append(LOC,(u_long)(array[i]));
434 *s = '\0';
435 if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR])
436 vty_log_fixed(buf,s-buf);
437 if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG])
438 syslog_sigsafe(priority|zlog_default->facility,buf,s-buf);
442 #undef DUMP
443 #undef LOC
444 #endif /* HAVE_STRACK_TRACE */
447 void
448 zlog_backtrace(int priority)
450 #ifndef HAVE_GLIBC_BACKTRACE
451 zlog(NULL, priority, "No backtrace available on this platform.");
452 #else
453 void *array[20];
454 int size, i;
455 char **strings;
457 if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
458 ((size_t)size > sizeof(array)/sizeof(array[0])))
460 zlog_err("Cannot get backtrace, returned invalid # of frames %d "
461 "(valid range is between 1 and %u)",
462 size, sizeof(array)/sizeof(array[0]));
463 return;
465 zlog(NULL, priority, "Backtrace for %d stack frames:", size);
466 if (!(strings = backtrace_symbols(array, size)))
468 zlog_err("Cannot get backtrace symbols (out of memory?)");
469 for (i = 0; i < size; i++)
470 zlog(NULL, priority, "[bt %d] %p",i,array[i]);
472 else
474 for (i = 0; i < size; i++)
475 zlog(NULL, priority, "[bt %d] %s",i,strings[i]);
476 free(strings);
478 #endif /* HAVE_GLIBC_BACKTRACE */
481 void
482 zlog (struct zlog *zl, int priority, const char *format, ...)
484 va_list args;
486 va_start(args, format);
487 vzlog (zl, priority, format, args);
488 va_end (args);
491 #define ZLOG_FUNC(FUNCNAME,PRIORITY) \
492 void \
493 FUNCNAME(const char *format, ...) \
495 va_list args; \
496 va_start(args, format); \
497 vzlog (NULL, PRIORITY, format, args); \
498 va_end(args); \
501 ZLOG_FUNC(zlog_err, LOG_ERR)
503 ZLOG_FUNC(zlog_warn, LOG_WARNING)
505 ZLOG_FUNC(zlog_info, LOG_INFO)
507 ZLOG_FUNC(zlog_notice, LOG_NOTICE)
509 ZLOG_FUNC(zlog_debug, LOG_DEBUG)
511 #undef ZLOG_FUNC
513 #define PLOG_FUNC(FUNCNAME,PRIORITY) \
514 void \
515 FUNCNAME(struct zlog *zl, const char *format, ...) \
517 va_list args; \
518 va_start(args, format); \
519 vzlog (zl, PRIORITY, format, args); \
520 va_end(args); \
523 PLOG_FUNC(plog_err, LOG_ERR)
525 PLOG_FUNC(plog_warn, LOG_WARNING)
527 PLOG_FUNC(plog_info, LOG_INFO)
529 PLOG_FUNC(plog_notice, LOG_NOTICE)
531 PLOG_FUNC(plog_debug, LOG_DEBUG)
533 #undef PLOG_FUNC
535 void
536 _zlog_assert_failed (const char *assertion, const char *file,
537 unsigned int line, const char *function)
539 /* Force fallback file logging? */
540 if (zlog_default && !zlog_default->fp &&
541 ((logfile_fd = open_crashlog()) >= 0) &&
542 ((zlog_default->fp = fdopen(logfile_fd, "w")) != NULL))
543 zlog_default->maxlvl[ZLOG_DEST_FILE] = LOG_ERR;
544 zlog(NULL, LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s",
545 assertion,file,line,(function ? function : "?"));
546 zlog_backtrace(LOG_CRIT);
547 abort();
551 /* Open log stream */
552 struct zlog *
553 openzlog (const char *progname, zlog_proto_t protocol,
554 int syslog_flags, int syslog_facility)
556 struct zlog *zl;
557 u_int i;
559 zl = XCALLOC(MTYPE_ZLOG, sizeof (struct zlog));
561 zl->ident = progname;
562 zl->protocol = protocol;
563 zl->facility = syslog_facility;
564 zl->syslog_options = syslog_flags;
566 /* Set default logging levels. */
567 for (i = 0; i < sizeof(zl->maxlvl)/sizeof(zl->maxlvl[0]); i++)
568 zl->maxlvl[i] = ZLOG_DISABLED;
569 zl->maxlvl[ZLOG_DEST_MONITOR] = LOG_DEBUG;
570 zl->default_lvl = LOG_DEBUG;
572 openlog (progname, syslog_flags, zl->facility);
574 return zl;
577 void
578 closezlog (struct zlog *zl)
580 closelog();
581 fclose (zl->fp);
583 XFREE (MTYPE_ZLOG, zl);
586 /* Called from command.c. */
587 void
588 zlog_set_level (struct zlog *zl, zlog_dest_t dest, int log_level)
590 if (zl == NULL)
591 zl = zlog_default;
593 zl->maxlvl[dest] = log_level;
597 zlog_set_file (struct zlog *zl, const char *filename, int log_level)
599 FILE *fp;
600 mode_t oldumask;
602 /* There is opend file. */
603 zlog_reset_file (zl);
605 /* Set default zl. */
606 if (zl == NULL)
607 zl = zlog_default;
609 /* Open file. */
610 oldumask = umask (0777 & ~LOGFILE_MASK);
611 fp = fopen (filename, "a");
612 umask(oldumask);
613 if (fp == NULL)
614 return 0;
616 /* Set flags. */
617 zl->filename = strdup (filename);
618 zl->maxlvl[ZLOG_DEST_FILE] = log_level;
619 zl->fp = fp;
620 logfile_fd = fileno(fp);
622 return 1;
625 /* Reset opend file. */
627 zlog_reset_file (struct zlog *zl)
629 if (zl == NULL)
630 zl = zlog_default;
632 if (zl->fp)
633 fclose (zl->fp);
634 zl->fp = NULL;
635 logfile_fd = -1;
636 zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
638 if (zl->filename)
639 free (zl->filename);
640 zl->filename = NULL;
642 return 1;
645 /* Reopen log file. */
647 zlog_rotate (struct zlog *zl)
649 int level;
651 if (zl == NULL)
652 zl = zlog_default;
654 if (zl->fp)
655 fclose (zl->fp);
656 zl->fp = NULL;
657 logfile_fd = -1;
658 level = zl->maxlvl[ZLOG_DEST_FILE];
659 zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
661 if (zl->filename)
663 mode_t oldumask;
664 int save_errno;
666 oldumask = umask (0777 & ~LOGFILE_MASK);
667 zl->fp = fopen (zl->filename, "a");
668 save_errno = errno;
669 umask(oldumask);
670 if (zl->fp == NULL)
672 zlog_err("Log rotate failed: cannot open file %s for append: %s",
673 zl->filename, safe_strerror(save_errno));
674 return -1;
676 logfile_fd = fileno(zl->fp);
677 zl->maxlvl[ZLOG_DEST_FILE] = level;
680 return 1;
683 /* Message lookup function. */
684 const char *
685 lookup (struct message *mes, int key)
687 struct message *pnt;
689 for (pnt = mes; pnt->key != 0; pnt++)
690 if (pnt->key == key)
691 return pnt->str;
693 return "";
696 /* Very old hacky version of message lookup function. Still partly
697 used in bgpd and ospfd. FIXME Seems that it's not used any more. */
698 const char *
699 mes_lookup (struct message *meslist, int max, int index)
701 if (index < 0 || index >= max)
703 zlog_err ("message index out of bound: %d", max);
704 return NULL;
706 return meslist[index].str;
709 /* Wrapper around strerror to handle case where it returns NULL. */
710 const char *
711 safe_strerror(int errnum)
713 const char *s = strerror(errnum);
714 return (s != NULL) ? s : "Unknown error";
717 struct zebra_desc_table
719 unsigned int type;
720 const char *string;
721 char chr;
724 #define DESC_ENTRY(T,S,C) [(T)] = { (T), (S), (C) }
725 static const struct zebra_desc_table route_types[] = {
726 DESC_ENTRY (ZEBRA_ROUTE_SYSTEM, "system", 'X' ),
727 DESC_ENTRY (ZEBRA_ROUTE_KERNEL, "kernel", 'K' ),
728 DESC_ENTRY (ZEBRA_ROUTE_CONNECT, "connected", 'C' ),
729 DESC_ENTRY (ZEBRA_ROUTE_STATIC, "static", 'S' ),
730 DESC_ENTRY (ZEBRA_ROUTE_RIP, "rip", 'R' ),
731 DESC_ENTRY (ZEBRA_ROUTE_RIPNG, "ripng", 'R' ),
732 DESC_ENTRY (ZEBRA_ROUTE_OSPF, "ospf", 'O' ),
733 DESC_ENTRY (ZEBRA_ROUTE_OSPF6, "ospf6", 'O' ),
734 DESC_ENTRY (ZEBRA_ROUTE_ISIS, "isis", 'I' ),
735 DESC_ENTRY (ZEBRA_ROUTE_BGP, "bgp", 'B' ),
736 DESC_ENTRY (ZEBRA_ROUTE_HSLS, "hsls", 'H' ),
738 #undef DESC_ENTRY
740 #define DESC_ENTRY(T) [(T)] = { (T), (#T), '\0' }
741 static const struct zebra_desc_table command_types[] = {
742 DESC_ENTRY (ZEBRA_INTERFACE_ADD),
743 DESC_ENTRY (ZEBRA_INTERFACE_DELETE),
744 DESC_ENTRY (ZEBRA_INTERFACE_ADDRESS_ADD),
745 DESC_ENTRY (ZEBRA_INTERFACE_ADDRESS_DELETE),
746 DESC_ENTRY (ZEBRA_INTERFACE_UP),
747 DESC_ENTRY (ZEBRA_INTERFACE_DOWN),
748 DESC_ENTRY (ZEBRA_IPV4_ROUTE_ADD),
749 DESC_ENTRY (ZEBRA_IPV4_ROUTE_DELETE),
750 DESC_ENTRY (ZEBRA_IPV6_ROUTE_ADD),
751 DESC_ENTRY (ZEBRA_IPV6_ROUTE_DELETE),
752 DESC_ENTRY (ZEBRA_REDISTRIBUTE_ADD),
753 DESC_ENTRY (ZEBRA_REDISTRIBUTE_DELETE),
754 DESC_ENTRY (ZEBRA_REDISTRIBUTE_DEFAULT_ADD),
755 DESC_ENTRY (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE),
756 DESC_ENTRY (ZEBRA_IPV4_NEXTHOP_LOOKUP),
757 DESC_ENTRY (ZEBRA_IPV6_NEXTHOP_LOOKUP),
758 DESC_ENTRY (ZEBRA_IPV4_IMPORT_LOOKUP),
759 DESC_ENTRY (ZEBRA_IPV6_IMPORT_LOOKUP),
760 DESC_ENTRY (ZEBRA_INTERFACE_RENAME),
761 DESC_ENTRY (ZEBRA_ROUTER_ID_ADD),
762 DESC_ENTRY (ZEBRA_ROUTER_ID_DELETE),
763 DESC_ENTRY (ZEBRA_ROUTER_ID_UPDATE),
765 #undef DESC_ENTRY
767 static const struct zebra_desc_table unknown = { 0, "unknown", '?' };
769 static const struct zebra_desc_table *
770 zroute_lookup(u_int zroute)
772 u_int i;
774 if (zroute >= sizeof(route_types)/sizeof(route_types[0]))
776 zlog_err("unknown zebra route type: %u", zroute);
777 return &unknown;
779 if (zroute == route_types[zroute].type)
780 return &route_types[zroute];
781 for (i = 0; i < sizeof(route_types)/sizeof(route_types[0]); i++)
783 if (zroute == route_types[i].type)
785 zlog_warn("internal error: route type table out of order "
786 "while searching for %u, please notify developers", zroute);
787 return &route_types[i];
790 zlog_err("internal error: cannot find route type %u in table!", zroute);
791 return &unknown;
794 const char *
795 zebra_route_string(u_int zroute)
797 return zroute_lookup(zroute)->string;
800 char
801 zebra_route_char(u_int zroute)
803 return zroute_lookup(zroute)->chr;
806 const char *
807 zserv_command_string (unsigned int command)
809 if (command >= sizeof(command_types)/sizeof(command_types[0]))
811 zlog_err ("unknown zserv command type: %u", command);
812 return unknown.string;
814 return command_types[command].string;