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

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

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