log.c 22 KB

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