bgp_dump.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. /* BGP-4 dump routine
  2. Copyright (C) 1999 Kunihiro Ishiguro
  3. This file is part of GNU Zebra.
  4. GNU Zebra is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by the
  6. Free Software Foundation; either version 2, or (at your option) any
  7. later version.
  8. GNU Zebra is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Zebra; see the file COPYING. If not, write to the Free
  14. Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  15. 02111-1307, USA. */
  16. #include <zebra.h>
  17. #include "log.h"
  18. #include "stream.h"
  19. #include "sockunion.h"
  20. #include "command.h"
  21. #include "prefix.h"
  22. #include "thread.h"
  23. #include "linklist.h"
  24. #include "bgpd/bgp_table.h"
  25. #include "bgpd/bgpd.h"
  26. #include "bgpd/bgp_route.h"
  27. #include "bgpd/bgp_attr.h"
  28. #include "bgpd/bgp_dump.h"
  29. enum bgp_dump_type
  30. {
  31. BGP_DUMP_ALL,
  32. BGP_DUMP_UPDATES,
  33. BGP_DUMP_ROUTES
  34. };
  35. enum MRT_MSG_TYPES {
  36. MSG_NULL,
  37. MSG_START, /* sender is starting up */
  38. MSG_DIE, /* receiver should shut down */
  39. MSG_I_AM_DEAD, /* sender is shutting down */
  40. MSG_PEER_DOWN, /* sender's peer is down */
  41. MSG_PROTOCOL_BGP, /* msg is a BGP packet */
  42. MSG_PROTOCOL_RIP, /* msg is a RIP packet */
  43. MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */
  44. MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */
  45. MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */
  46. MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */
  47. MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */
  48. MSG_TABLE_DUMP, /* routing table dump */
  49. MSG_TABLE_DUMP_V2 /* routing table dump, version 2 */
  50. };
  51. static int bgp_dump_interval_func (struct thread *);
  52. struct bgp_dump
  53. {
  54. enum bgp_dump_type type;
  55. char *filename;
  56. FILE *fp;
  57. unsigned int interval;
  58. char *interval_str;
  59. struct thread *t_interval;
  60. };
  61. /* BGP packet dump output buffer. */
  62. struct stream *bgp_dump_obuf;
  63. /* BGP dump strucuture for 'dump bgp all' */
  64. struct bgp_dump bgp_dump_all;
  65. /* BGP dump structure for 'dump bgp updates' */
  66. struct bgp_dump bgp_dump_updates;
  67. /* BGP dump structure for 'dump bgp routes' */
  68. struct bgp_dump bgp_dump_routes;
  69. /* Dump whole BGP table is very heavy process. */
  70. struct thread *t_bgp_dump_routes;
  71. /* Some define for BGP packet dump. */
  72. static FILE *
  73. bgp_dump_open_file (struct bgp_dump *bgp_dump)
  74. {
  75. int ret;
  76. time_t clock;
  77. struct tm *tm;
  78. char fullpath[MAXPATHLEN];
  79. char realpath[MAXPATHLEN];
  80. mode_t oldumask;
  81. time (&clock);
  82. tm = localtime (&clock);
  83. if (bgp_dump->filename[0] != DIRECTORY_SEP)
  84. {
  85. sprintf (fullpath, "%s/%s", vty_get_cwd (), bgp_dump->filename);
  86. ret = strftime (realpath, MAXPATHLEN, fullpath, tm);
  87. }
  88. else
  89. ret = strftime (realpath, MAXPATHLEN, bgp_dump->filename, tm);
  90. if (ret == 0)
  91. {
  92. zlog_warn ("bgp_dump_open_file: strftime error");
  93. return NULL;
  94. }
  95. if (bgp_dump->fp)
  96. fclose (bgp_dump->fp);
  97. oldumask = umask(0777 & ~LOGFILE_MASK);
  98. bgp_dump->fp = fopen (realpath, "w");
  99. if (bgp_dump->fp == NULL)
  100. {
  101. zlog_warn ("bgp_dump_open_file: %s: %s", realpath, strerror (errno));
  102. umask(oldumask);
  103. return NULL;
  104. }
  105. umask(oldumask);
  106. return bgp_dump->fp;
  107. }
  108. static int
  109. bgp_dump_interval_add (struct bgp_dump *bgp_dump, int interval)
  110. {
  111. int secs_into_day;
  112. time_t t;
  113. struct tm *tm;
  114. if (interval > 0)
  115. {
  116. /* Periodic dump every interval seconds */
  117. if ((interval < 86400) && ((86400 % interval) == 0))
  118. {
  119. /* Dump at predictable times: if a day has a whole number of
  120. * intervals, dump every interval seconds starting from midnight
  121. */
  122. (void) time(&t);
  123. tm = localtime(&t);
  124. secs_into_day = tm->tm_sec + 60*tm->tm_min + 60*60*tm->tm_hour;
  125. interval = interval - secs_into_day % interval; /* always > 0 */
  126. }
  127. bgp_dump->t_interval = thread_add_timer (master, bgp_dump_interval_func,
  128. bgp_dump, interval);
  129. }
  130. else
  131. {
  132. /* One-off dump: execute immediately, don't affect any scheduled dumps */
  133. bgp_dump->t_interval = thread_add_event (master, bgp_dump_interval_func,
  134. bgp_dump, 0);
  135. }
  136. return 0;
  137. }
  138. /* Dump common header. */
  139. static void
  140. bgp_dump_header (struct stream *obuf, int type, int subtype)
  141. {
  142. time_t now;
  143. /* Set header. */
  144. time (&now);
  145. /* Put dump packet header. */
  146. stream_putl (obuf, now);
  147. stream_putw (obuf, type);
  148. stream_putw (obuf, subtype);
  149. stream_putl (obuf, 0); /* len */
  150. }
  151. static void
  152. bgp_dump_set_size (struct stream *s, int type)
  153. {
  154. stream_putl_at (s, 8, stream_get_endp (s) - BGP_DUMP_HEADER_SIZE);
  155. }
  156. static void
  157. bgp_dump_routes_index_table(struct bgp *bgp)
  158. {
  159. struct peer *peer;
  160. struct listnode *node;
  161. uint16_t peerno = 0;
  162. struct stream *obuf;
  163. obuf = bgp_dump_obuf;
  164. stream_reset (obuf);
  165. /* MRT header */
  166. bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE);
  167. /* Collector BGP ID */
  168. stream_put_in_addr (obuf, &bgp->router_id);
  169. /* View name */
  170. if(bgp->name)
  171. {
  172. stream_putw (obuf, strlen(bgp->name));
  173. stream_put(obuf, bgp->name, strlen(bgp->name));
  174. }
  175. else
  176. {
  177. stream_putw(obuf, 0);
  178. }
  179. /* Peer count */
  180. stream_putw (obuf, listcount(bgp->peer));
  181. /* Walk down all peers */
  182. for(ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
  183. {
  184. /* Peer's type */
  185. if (sockunion_family(&peer->su) == AF_INET)
  186. {
  187. stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP);
  188. }
  189. #ifdef HAVE_IPV6
  190. else if (sockunion_family(&peer->su) == AF_INET6)
  191. {
  192. stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6);
  193. }
  194. #endif /* HAVE_IPV6 */
  195. /* Peer's BGP ID */
  196. stream_put_in_addr (obuf, &peer->remote_id);
  197. /* Peer's IP address */
  198. if (sockunion_family(&peer->su) == AF_INET)
  199. {
  200. stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
  201. }
  202. #ifdef HAVE_IPV6
  203. else if (sockunion_family(&peer->su) == AF_INET6)
  204. {
  205. stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
  206. IPV6_MAX_BYTELEN);
  207. }
  208. #endif /* HAVE_IPV6 */
  209. /* Peer's AS number. */
  210. /* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */
  211. stream_putl (obuf, peer->as);
  212. /* Store the peer number for this peer */
  213. peer->table_dump_index = peerno;
  214. peerno++;
  215. }
  216. bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
  217. fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
  218. fflush (bgp_dump_routes.fp);
  219. }
  220. /* Runs under child process. */
  221. static unsigned int
  222. bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
  223. {
  224. struct stream *obuf;
  225. struct bgp_info *info;
  226. struct bgp_node *rn;
  227. struct bgp *bgp;
  228. struct bgp_table *table;
  229. bgp = bgp_get_default ();
  230. if (!bgp)
  231. return seq;
  232. if (bgp_dump_routes.fp == NULL)
  233. return seq;
  234. /* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers,
  235. so this should only be done on the first call to bgp_dump_routes_func.
  236. ( this function will be called once for ipv4 and once for ipv6 ) */
  237. if(first_run)
  238. bgp_dump_routes_index_table(bgp);
  239. obuf = bgp_dump_obuf;
  240. stream_reset(obuf);
  241. /* Walk down each BGP route. */
  242. table = bgp->rib[afi][SAFI_UNICAST];
  243. for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
  244. {
  245. if(!rn->info)
  246. continue;
  247. stream_reset(obuf);
  248. /* MRT header */
  249. if (afi == AFI_IP)
  250. {
  251. bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST);
  252. }
  253. #ifdef HAVE_IPV6
  254. else if (afi == AFI_IP6)
  255. {
  256. bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST);
  257. }
  258. #endif /* HAVE_IPV6 */
  259. /* Sequence number */
  260. stream_putl(obuf, seq);
  261. /* Prefix length */
  262. stream_putc (obuf, rn->p.prefixlen);
  263. /* Prefix */
  264. if (afi == AFI_IP)
  265. {
  266. /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
  267. stream_write(obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8);
  268. }
  269. #ifdef HAVE_IPV6
  270. else if (afi == AFI_IP6)
  271. {
  272. /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
  273. stream_write (obuf, (u_char *)&rn->p.u.prefix6, (rn->p.prefixlen+7)/8);
  274. }
  275. #endif /* HAVE_IPV6 */
  276. /* Save where we are now, so we can overwride the entry count later */
  277. int sizep = stream_get_endp(obuf);
  278. /* Entry count */
  279. uint16_t entry_count = 0;
  280. /* Entry count, note that this is overwritten later */
  281. stream_putw(obuf, 0);
  282. for (info = rn->info; info; info = info->next)
  283. {
  284. entry_count++;
  285. /* Peer index */
  286. stream_putw(obuf, info->peer->table_dump_index);
  287. /* Originated */
  288. #ifdef HAVE_CLOCK_MONOTONIC
  289. stream_putl (obuf, time(NULL) - (bgp_clock() - info->uptime));
  290. #else
  291. stream_putl (obuf, info->uptime);
  292. #endif /* HAVE_CLOCK_MONOTONIC */
  293. /* Dump attribute. */
  294. /* Skip prefix & AFI/SAFI for MP_NLRI */
  295. bgp_dump_routes_attr (obuf, info->attr, &rn->p);
  296. }
  297. /* Overwrite the entry count, now that we know the right number */
  298. stream_putw_at (obuf, sizep, entry_count);
  299. seq++;
  300. bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
  301. fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
  302. }
  303. fflush (bgp_dump_routes.fp);
  304. return seq;
  305. }
  306. static int
  307. bgp_dump_interval_func (struct thread *t)
  308. {
  309. struct bgp_dump *bgp_dump;
  310. bgp_dump = THREAD_ARG (t);
  311. bgp_dump->t_interval = NULL;
  312. /* Reschedule dump even if file couldn't be opened this time... */
  313. if (bgp_dump_open_file (bgp_dump) != NULL)
  314. {
  315. /* In case of bgp_dump_routes, we need special route dump function. */
  316. if (bgp_dump->type == BGP_DUMP_ROUTES)
  317. {
  318. unsigned int seq = bgp_dump_routes_func (AFI_IP, 1, 0);
  319. #ifdef HAVE_IPV6
  320. bgp_dump_routes_func (AFI_IP6, 0, seq);
  321. #endif /* HAVE_IPV6 */
  322. /* Close the file now. For a RIB dump there's no point in leaving
  323. * it open until the next scheduled dump starts. */
  324. fclose(bgp_dump->fp); bgp_dump->fp = NULL;
  325. }
  326. }
  327. /* if interval is set reschedule */
  328. if (bgp_dump->interval > 0)
  329. bgp_dump_interval_add (bgp_dump, bgp_dump->interval);
  330. return 0;
  331. }
  332. /* Dump common information. */
  333. static void
  334. bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4)
  335. {
  336. char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  337. /* Source AS number and Destination AS number. */
  338. if (forceas4 || CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
  339. {
  340. stream_putl (obuf, peer->as);
  341. stream_putl (obuf, peer->local_as);
  342. }
  343. else
  344. {
  345. stream_putw (obuf, peer->as);
  346. stream_putw (obuf, peer->local_as);
  347. }
  348. if (peer->su.sa.sa_family == AF_INET)
  349. {
  350. stream_putw (obuf, peer->ifindex);
  351. stream_putw (obuf, AFI_IP);
  352. stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN);
  353. if (peer->su_local)
  354. stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN);
  355. else
  356. stream_put (obuf, empty, IPV4_MAX_BYTELEN);
  357. }
  358. #ifdef HAVE_IPV6
  359. else if (peer->su.sa.sa_family == AF_INET6)
  360. {
  361. /* Interface Index and Address family. */
  362. stream_putw (obuf, peer->ifindex);
  363. stream_putw (obuf, AFI_IP6);
  364. /* Source IP Address and Destination IP Address. */
  365. stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN);
  366. if (peer->su_local)
  367. stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN);
  368. else
  369. stream_put (obuf, empty, IPV6_MAX_BYTELEN);
  370. }
  371. #endif /* HAVE_IPV6 */
  372. }
  373. /* Dump BGP status change. */
  374. void
  375. bgp_dump_state (struct peer *peer, int status_old, int status_new)
  376. {
  377. struct stream *obuf;
  378. /* If dump file pointer is disabled return immediately. */
  379. if (bgp_dump_all.fp == NULL)
  380. return;
  381. /* Make dump stream. */
  382. obuf = bgp_dump_obuf;
  383. stream_reset (obuf);
  384. bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4);
  385. bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/
  386. stream_putw (obuf, status_old);
  387. stream_putw (obuf, status_new);
  388. /* Set length. */
  389. bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
  390. /* Write to the stream. */
  391. fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_all.fp);
  392. fflush (bgp_dump_all.fp);
  393. }
  394. static void
  395. bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
  396. struct stream *packet)
  397. {
  398. struct stream *obuf;
  399. /* If dump file pointer is disabled return immediately. */
  400. if (bgp_dump->fp == NULL)
  401. return;
  402. /* Make dump stream. */
  403. obuf = bgp_dump_obuf;
  404. stream_reset (obuf);
  405. /* Dump header and common part. */
  406. if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
  407. {
  408. bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4);
  409. }
  410. else
  411. {
  412. bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE);
  413. }
  414. bgp_dump_common (obuf, peer, 0);
  415. /* Packet contents. */
  416. stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet));
  417. /* Set length. */
  418. bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
  419. /* Write to the stream. */
  420. fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump->fp);
  421. fflush (bgp_dump->fp);
  422. }
  423. /* Called from bgp_packet.c when BGP packet is received. */
  424. void
  425. bgp_dump_packet (struct peer *peer, int type, struct stream *packet)
  426. {
  427. /* bgp_dump_all. */
  428. bgp_dump_packet_func (&bgp_dump_all, peer, packet);
  429. /* bgp_dump_updates. */
  430. if (type == BGP_MSG_UPDATE)
  431. bgp_dump_packet_func (&bgp_dump_updates, peer, packet);
  432. }
  433. static unsigned int
  434. bgp_dump_parse_time (const char *str)
  435. {
  436. int i;
  437. int len;
  438. int seen_h;
  439. int seen_m;
  440. int time;
  441. unsigned int total;
  442. time = 0;
  443. total = 0;
  444. seen_h = 0;
  445. seen_m = 0;
  446. len = strlen (str);
  447. for (i = 0; i < len; i++)
  448. {
  449. if (isdigit ((int) str[i]))
  450. {
  451. time *= 10;
  452. time += str[i] - '0';
  453. }
  454. else if (str[i] == 'H' || str[i] == 'h')
  455. {
  456. if (seen_h)
  457. return 0;
  458. if (seen_m)
  459. return 0;
  460. total += time * 60 *60;
  461. time = 0;
  462. seen_h = 1;
  463. }
  464. else if (str[i] == 'M' || str[i] == 'm')
  465. {
  466. if (seen_m)
  467. return 0;
  468. total += time * 60;
  469. time = 0;
  470. seen_h = 1;
  471. }
  472. else
  473. return 0;
  474. }
  475. return total + time;
  476. }
  477. static int
  478. bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump,
  479. enum bgp_dump_type type, const char *path,
  480. const char *interval_str)
  481. {
  482. unsigned int interval;
  483. if (interval_str)
  484. {
  485. /* Check interval string. */
  486. interval = bgp_dump_parse_time (interval_str);
  487. if (interval == 0)
  488. {
  489. vty_out (vty, "Malformed interval string%s", VTY_NEWLINE);
  490. return CMD_WARNING;
  491. }
  492. /* Don't schedule duplicate dumps if the dump command is given twice */
  493. if (interval == bgp_dump->interval &&
  494. type == bgp_dump->type &&
  495. path && bgp_dump->filename && !strcmp (path, bgp_dump->filename))
  496. {
  497. return CMD_SUCCESS;
  498. }
  499. /* Set interval. */
  500. bgp_dump->interval = interval;
  501. if (bgp_dump->interval_str)
  502. free (bgp_dump->interval_str);
  503. bgp_dump->interval_str = strdup (interval_str);
  504. }
  505. else
  506. {
  507. interval = 0;
  508. }
  509. /* Create interval thread. */
  510. bgp_dump_interval_add (bgp_dump, interval);
  511. /* Set type. */
  512. bgp_dump->type = type;
  513. /* Set file name. */
  514. if (bgp_dump->filename)
  515. free (bgp_dump->filename);
  516. bgp_dump->filename = strdup (path);
  517. /* This should be called when interval is expired. */
  518. bgp_dump_open_file (bgp_dump);
  519. return CMD_SUCCESS;
  520. }
  521. static int
  522. bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump)
  523. {
  524. /* Set file name. */
  525. if (bgp_dump->filename)
  526. {
  527. free (bgp_dump->filename);
  528. bgp_dump->filename = NULL;
  529. }
  530. /* This should be called when interval is expired. */
  531. if (bgp_dump->fp)
  532. {
  533. fclose (bgp_dump->fp);
  534. bgp_dump->fp = NULL;
  535. }
  536. /* Create interval thread. */
  537. if (bgp_dump->t_interval)
  538. {
  539. thread_cancel (bgp_dump->t_interval);
  540. bgp_dump->t_interval = NULL;
  541. }
  542. bgp_dump->interval = 0;
  543. if (bgp_dump->interval_str)
  544. {
  545. free (bgp_dump->interval_str);
  546. bgp_dump->interval_str = NULL;
  547. }
  548. return CMD_SUCCESS;
  549. }
  550. DEFUN (dump_bgp_all,
  551. dump_bgp_all_cmd,
  552. "dump bgp all PATH",
  553. "Dump packet\n"
  554. "BGP packet dump\n"
  555. "Dump all BGP packets\n"
  556. "Output filename\n")
  557. {
  558. return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], NULL);
  559. }
  560. DEFUN (dump_bgp_all_interval,
  561. dump_bgp_all_interval_cmd,
  562. "dump bgp all PATH INTERVAL",
  563. "Dump packet\n"
  564. "BGP packet dump\n"
  565. "Dump all BGP packets\n"
  566. "Output filename\n"
  567. "Interval of output\n")
  568. {
  569. return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], argv[1]);
  570. }
  571. DEFUN (no_dump_bgp_all,
  572. no_dump_bgp_all_cmd,
  573. "no dump bgp all [PATH] [INTERVAL]",
  574. NO_STR
  575. "Dump packet\n"
  576. "BGP packet dump\n"
  577. "Dump all BGP packets\n")
  578. {
  579. return bgp_dump_unset (vty, &bgp_dump_all);
  580. }
  581. DEFUN (dump_bgp_updates,
  582. dump_bgp_updates_cmd,
  583. "dump bgp updates PATH",
  584. "Dump packet\n"
  585. "BGP packet dump\n"
  586. "Dump BGP updates only\n"
  587. "Output filename\n")
  588. {
  589. return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], NULL);
  590. }
  591. DEFUN (dump_bgp_updates_interval,
  592. dump_bgp_updates_interval_cmd,
  593. "dump bgp updates PATH INTERVAL",
  594. "Dump packet\n"
  595. "BGP packet dump\n"
  596. "Dump BGP updates only\n"
  597. "Output filename\n"
  598. "Interval of output\n")
  599. {
  600. return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], argv[1]);
  601. }
  602. DEFUN (no_dump_bgp_updates,
  603. no_dump_bgp_updates_cmd,
  604. "no dump bgp updates [PATH] [INTERVAL]",
  605. NO_STR
  606. "Dump packet\n"
  607. "BGP packet dump\n"
  608. "Dump BGP updates only\n")
  609. {
  610. return bgp_dump_unset (vty, &bgp_dump_updates);
  611. }
  612. DEFUN (dump_bgp_routes,
  613. dump_bgp_routes_cmd,
  614. "dump bgp routes-mrt PATH",
  615. "Dump packet\n"
  616. "BGP packet dump\n"
  617. "Dump whole BGP routing table\n"
  618. "Output filename\n")
  619. {
  620. return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], NULL);
  621. }
  622. DEFUN (dump_bgp_routes_interval,
  623. dump_bgp_routes_interval_cmd,
  624. "dump bgp routes-mrt PATH INTERVAL",
  625. "Dump packet\n"
  626. "BGP packet dump\n"
  627. "Dump whole BGP routing table\n"
  628. "Output filename\n"
  629. "Interval of output\n")
  630. {
  631. return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], argv[1]);
  632. }
  633. DEFUN (no_dump_bgp_routes,
  634. no_dump_bgp_routes_cmd,
  635. "no dump bgp routes-mrt [PATH] [INTERVAL]",
  636. NO_STR
  637. "Dump packet\n"
  638. "BGP packet dump\n"
  639. "Dump whole BGP routing table\n")
  640. {
  641. return bgp_dump_unset (vty, &bgp_dump_routes);
  642. }
  643. /* BGP node structure. */
  644. static struct cmd_node bgp_dump_node =
  645. {
  646. DUMP_NODE,
  647. "",
  648. 1
  649. };
  650. #if 0
  651. char *
  652. config_time2str (unsigned int interval)
  653. {
  654. static char buf[BUFSIZ];
  655. buf[0] = '\0';
  656. if (interval / 3600)
  657. {
  658. sprintf (buf, "%dh", interval / 3600);
  659. interval %= 3600;
  660. }
  661. if (interval / 60)
  662. {
  663. sprintf (buf + strlen (buf), "%dm", interval /60);
  664. interval %= 60;
  665. }
  666. if (interval)
  667. {
  668. sprintf (buf + strlen (buf), "%d", interval);
  669. }
  670. return buf;
  671. }
  672. #endif
  673. static int
  674. config_write_bgp_dump (struct vty *vty)
  675. {
  676. if (bgp_dump_all.filename)
  677. {
  678. if (bgp_dump_all.interval_str)
  679. vty_out (vty, "dump bgp all %s %s%s",
  680. bgp_dump_all.filename, bgp_dump_all.interval_str,
  681. VTY_NEWLINE);
  682. else
  683. vty_out (vty, "dump bgp all %s%s",
  684. bgp_dump_all.filename, VTY_NEWLINE);
  685. }
  686. if (bgp_dump_updates.filename)
  687. {
  688. if (bgp_dump_updates.interval_str)
  689. vty_out (vty, "dump bgp updates %s %s%s",
  690. bgp_dump_updates.filename, bgp_dump_updates.interval_str,
  691. VTY_NEWLINE);
  692. else
  693. vty_out (vty, "dump bgp updates %s%s",
  694. bgp_dump_updates.filename, VTY_NEWLINE);
  695. }
  696. if (bgp_dump_routes.filename)
  697. {
  698. if (bgp_dump_routes.interval_str)
  699. vty_out (vty, "dump bgp routes-mrt %s %s%s",
  700. bgp_dump_routes.filename, bgp_dump_routes.interval_str,
  701. VTY_NEWLINE);
  702. else
  703. vty_out (vty, "dump bgp routes-mrt %s%s",
  704. bgp_dump_routes.filename, VTY_NEWLINE);
  705. }
  706. return 0;
  707. }
  708. /* Initialize BGP packet dump functionality. */
  709. void
  710. bgp_dump_init (void)
  711. {
  712. memset (&bgp_dump_all, 0, sizeof (struct bgp_dump));
  713. memset (&bgp_dump_updates, 0, sizeof (struct bgp_dump));
  714. memset (&bgp_dump_routes, 0, sizeof (struct bgp_dump));
  715. bgp_dump_obuf = stream_new (BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
  716. + BGP_DUMP_HEADER_SIZE);
  717. install_node (&bgp_dump_node, config_write_bgp_dump);
  718. install_element (CONFIG_NODE, &dump_bgp_all_cmd);
  719. install_element (CONFIG_NODE, &dump_bgp_all_interval_cmd);
  720. install_element (CONFIG_NODE, &no_dump_bgp_all_cmd);
  721. install_element (CONFIG_NODE, &dump_bgp_updates_cmd);
  722. install_element (CONFIG_NODE, &dump_bgp_updates_interval_cmd);
  723. install_element (CONFIG_NODE, &no_dump_bgp_updates_cmd);
  724. install_element (CONFIG_NODE, &dump_bgp_routes_cmd);
  725. install_element (CONFIG_NODE, &dump_bgp_routes_interval_cmd);
  726. install_element (CONFIG_NODE, &no_dump_bgp_routes_cmd);
  727. }
  728. void
  729. bgp_dump_finish (void)
  730. {
  731. stream_free (bgp_dump_obuf);
  732. bgp_dump_obuf = NULL;
  733. }