File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / lib / log.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:11 2016 UTC (8 years ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>