log.c 25 KB

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