Annotation of embedaddon/quagga/lib/log.c, revision 1.1.1.2

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
                    446:   if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
                    447:       ((size_t)size > sizeof(array)/sizeof(array[0])))
                    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: 
                    529:   if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
                    530:       ((size_t)size > sizeof(array)/sizeof(array[0])))
                    531:     {
                    532:       zlog_err("Cannot get backtrace, returned invalid # of frames %d "
                    533:               "(valid range is between 1 and %lu)",
                    534:               size, (unsigned long)(sizeof(array)/sizeof(array[0])));
                    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. */
                    639:   for (i = 0; i < sizeof(zl->maxlvl)/sizeof(zl->maxlvl[0]); i++)
                    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: 
                    858:   if (zroute >= sizeof(route_types)/sizeof(route_types[0]))
                    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];
                    865:   for (i = 0; i < sizeof(route_types)/sizeof(route_types[0]); i++)
                    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: {
                    893:   if (command >= sizeof(command_types)/sizeof(command_types[0]))
                    894:     {
                    895:       zlog_err ("unknown zserv command type: %u", command);
                    896:       return unknown.string;
                    897:     }
                    898:   return command_types[command].string;
                    899: }
                    900: 
                    901: #define RTSIZE (sizeof(route_types)/sizeof(route_types[0]))
                    902: 
                    903: int
                    904: proto_name2num(const char *s)
                    905: {
                    906:    unsigned i;
                    907: 
                    908:    for (i=0; i<RTSIZE; ++i)
                    909:      if (strcasecmp(s, route_types[i].string) == 0)
                    910:        return route_types[i].type;
                    911:    return -1;
                    912: }
1.1.1.2 ! misho     913: 
1.1       misho     914: #undef RTSIZE
1.1.1.2 ! misho     915: 
        !           916: int
        !           917: proto_redistnum(int afi, const char *s)
        !           918: {
        !           919:   if (! s)
        !           920:     return -1;
        !           921: 
        !           922:   if (afi == AFI_IP)
        !           923:     {
        !           924:       if (strncmp (s, "k", 1) == 0)
        !           925:        return ZEBRA_ROUTE_KERNEL;
        !           926:       else if (strncmp (s, "c", 1) == 0)
        !           927:        return ZEBRA_ROUTE_CONNECT;
        !           928:       else if (strncmp (s, "s", 1) == 0)
        !           929:        return ZEBRA_ROUTE_STATIC;
        !           930:       else if (strncmp (s, "r", 1) == 0)
        !           931:        return ZEBRA_ROUTE_RIP;
        !           932:       else if (strncmp (s, "o", 1) == 0)
        !           933:        return ZEBRA_ROUTE_OSPF;
        !           934:       else if (strncmp (s, "i", 1) == 0)
        !           935:        return ZEBRA_ROUTE_ISIS;
        !           936:       else if (strncmp (s, "bg", 2) == 0)
        !           937:        return ZEBRA_ROUTE_BGP;
        !           938:       else if (strncmp (s, "ba", 2) == 0)
        !           939:        return ZEBRA_ROUTE_BABEL;
        !           940:     }
        !           941:   if (afi == AFI_IP6)
        !           942:     {
        !           943:       if (strncmp (s, "k", 1) == 0)
        !           944:        return ZEBRA_ROUTE_KERNEL;
        !           945:       else if (strncmp (s, "c", 1) == 0)
        !           946:        return ZEBRA_ROUTE_CONNECT;
        !           947:       else if (strncmp (s, "s", 1) == 0)
        !           948:        return ZEBRA_ROUTE_STATIC;
        !           949:       else if (strncmp (s, "r", 1) == 0)
        !           950:        return ZEBRA_ROUTE_RIPNG;
        !           951:       else if (strncmp (s, "o", 1) == 0)
        !           952:        return ZEBRA_ROUTE_OSPF6;
        !           953:       else if (strncmp (s, "i", 1) == 0)
        !           954:        return ZEBRA_ROUTE_ISIS;
        !           955:       else if (strncmp (s, "bg", 2) == 0)
        !           956:        return ZEBRA_ROUTE_BGP;
        !           957:       else if (strncmp (s, "ba", 2) == 0)
        !           958:        return ZEBRA_ROUTE_BABEL;
        !           959:     }
        !           960:   return -1;
        !           961: }

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