Annotation of embedaddon/quagga/lib/log.c, revision 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>