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

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

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