bgp_dump.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:17k
源码类别:

网络

开发平台:

Unix_Linux

  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 "bgpd/bgp_table.h"
  24. #include "bgpd/bgpd.h"
  25. #include "bgpd/bgp_route.h"
  26. #include "bgpd/bgp_attr.h"
  27. #include "bgpd/bgp_dump.h"
  28. enum bgp_dump_type
  29. {
  30.   BGP_DUMP_ALL,
  31.   BGP_DUMP_UPDATES,
  32.   BGP_DUMP_ROUTES
  33. };
  34. enum MRT_MSG_TYPES {
  35.    MSG_NULL,
  36.    MSG_START,                   /* sender is starting up */
  37.    MSG_DIE,                     /* receiver should shut down */
  38.    MSG_I_AM_DEAD,               /* sender is shutting down */
  39.    MSG_PEER_DOWN,               /* sender's peer is down */
  40.    MSG_PROTOCOL_BGP,            /* msg is a BGP packet */
  41.    MSG_PROTOCOL_RIP,            /* msg is a RIP packet */
  42.    MSG_PROTOCOL_IDRP,           /* msg is an IDRP packet */
  43.    MSG_PROTOCOL_RIPNG,          /* msg is a RIPNG packet */
  44.    MSG_PROTOCOL_BGP4PLUS,       /* msg is a BGP4+ packet */
  45.    MSG_PROTOCOL_BGP4PLUS_01,    /* msg is a BGP4+ (draft 01) packet */
  46.    MSG_PROTOCOL_OSPF,           /* msg is an OSPF packet */
  47.    MSG_TABLE_DUMP               /* routing table dump */
  48. };
  49. struct bgp_dump
  50. {
  51.   enum bgp_dump_type type;
  52.   char *filename;
  53.   FILE *fp;
  54.   unsigned int interval;
  55.   char *interval_str;
  56.   struct thread *t_interval;
  57. };
  58. /* BGP packet dump output buffer. */
  59. struct stream *bgp_dump_obuf;
  60. /* BGP dump strucuture for 'dump bgp all' */
  61. struct bgp_dump bgp_dump_all;
  62. /* BGP dump structure for 'dump bgp updates' */
  63. struct bgp_dump bgp_dump_updates;
  64. /* BGP dump structure for 'dump bgp routes' */
  65. struct bgp_dump bgp_dump_routes;
  66. /* Dump whole BGP table is very heavy process.  */
  67. struct thread *t_bgp_dump_routes;
  68. /* Some define for BGP packet dump. */
  69. FILE *
  70. bgp_dump_open_file (struct bgp_dump *bgp_dump)
  71. {
  72.   int ret;
  73.   time_t clock;
  74.   struct tm *tm;
  75.   char fullpath[MAXPATHLEN];
  76.   char realpath[MAXPATHLEN];
  77.   time (&clock);
  78.   tm = localtime (&clock);
  79.   if (bgp_dump->filename[0] != DIRECTORY_SEP)
  80.     {
  81.       sprintf (fullpath, "%s/%s", vty_get_cwd (), bgp_dump->filename);
  82.       ret = strftime (realpath, MAXPATHLEN, fullpath, tm);
  83.     }
  84.   else
  85.     ret = strftime (realpath, MAXPATHLEN, bgp_dump->filename, tm);
  86.   if (ret == 0)
  87.     {
  88.       zlog_warn ("bgp_dump_open_file: strftime error");
  89.       return NULL;
  90.     }
  91.   if (bgp_dump->fp)
  92.     fclose (bgp_dump->fp);
  93.   bgp_dump->fp = fopen (realpath, "w");
  94.   if (bgp_dump->fp == NULL)
  95.     return NULL;
  96.   return bgp_dump->fp;
  97. }
  98. int
  99. bgp_dump_interval_add (struct bgp_dump *bgp_dump, int interval)
  100. {
  101.   int bgp_dump_interval_func (struct thread *);
  102.   bgp_dump->t_interval = thread_add_timer (master, bgp_dump_interval_func, 
  103.    bgp_dump, interval);
  104.   return 0;
  105. }
  106. /* Dump common header. */
  107. void
  108. bgp_dump_header (struct stream *obuf, int type, int subtype)
  109. {
  110.   time_t now;
  111.   /* Set header. */
  112.   time (&now);
  113.   /* Put dump packet header. */
  114.   stream_putl (obuf, now);
  115.   stream_putw (obuf, type);
  116.   stream_putw (obuf, subtype);
  117.   stream_putl (obuf, 0); /* len */
  118. }
  119. void
  120. bgp_dump_set_size (struct stream *s, int type)
  121. {
  122.   stream_putl_at (s, 8, stream_get_putp (s) - BGP_DUMP_HEADER_SIZE);
  123. }
  124. void
  125. bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi,
  126.        int type, unsigned int seq)
  127. {
  128.   struct stream *obuf;
  129.   struct attr *attr;
  130.   struct peer *peer;
  131.   int plen;
  132.   int safi = 0;
  133.   /* Make dump stream. */
  134.   obuf = bgp_dump_obuf;
  135.   stream_reset (obuf);
  136.   attr = info->attr;
  137.   peer = info->peer;
  138.   /* We support MRT's old format. */
  139.   if (type == MSG_TABLE_DUMP)
  140.     {
  141.       bgp_dump_header (obuf, MSG_TABLE_DUMP, afi);
  142.       stream_putw (obuf, 0); /* View # */
  143.       stream_putw (obuf, seq); /* Sequence number. */
  144.     }
  145.   else
  146.     {
  147.       bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY);
  148.       
  149.       stream_putl (obuf, info->uptime); /* Time Last Change */
  150.       stream_putw (obuf, afi); /* Address Family */
  151.       stream_putc (obuf, safi); /* SAFI */
  152.     }
  153.   if (afi == AFI_IP)
  154.     {
  155.       if (type == MSG_TABLE_DUMP)
  156. {
  157.   /* Prefix */
  158.   stream_put_in_addr (obuf, &p->u.prefix4);
  159.   stream_putc (obuf, p->prefixlen);
  160.   /* Status */
  161.   stream_putc (obuf, 1);
  162.   /* Originated */
  163.   stream_putl (obuf, info->uptime);
  164.   /* Peer's IP address */
  165.   stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
  166.   /* Peer's AS number. */
  167.   stream_putw (obuf, peer->as);
  168.   /* Dump attribute. */
  169.   bgp_dump_routes_attr (obuf, attr);
  170. }
  171.       else
  172. {
  173.   /* Next-Hop-Len */
  174.   stream_putc (obuf, IPV4_MAX_BYTELEN);
  175.   stream_put_in_addr (obuf, &attr->nexthop);
  176.   stream_putc (obuf, p->prefixlen);
  177.   plen = PSIZE (p->prefixlen);
  178.   stream_put (obuf, &p->u.prefix4, plen);
  179.   bgp_dump_routes_attr (obuf, attr);
  180. }
  181.     }
  182. #ifdef HAVE_IPV6
  183.   else if (afi == AFI_IP6)
  184.     {
  185.       if (type == MSG_TABLE_DUMP)
  186. {
  187.   /* Prefix */
  188.   stream_write (obuf, (u_char *)&p->u.prefix6, IPV6_MAX_BYTELEN);
  189.   stream_putc (obuf, p->prefixlen);
  190.   /* Status */
  191.   stream_putc (obuf, 1);
  192.   /* Originated */
  193.   stream_putl (obuf, info->uptime);
  194.   /* Peer's IP address */
  195.   stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
  196. IPV6_MAX_BYTELEN);
  197.   /* Peer's AS number. */
  198.   stream_putw (obuf, peer->as);
  199.   /* Dump attribute. */
  200.   bgp_dump_routes_attr (obuf, attr);
  201. }
  202.       else
  203. {
  204.   ;
  205. }
  206.     }
  207. #endif /* HAVE_IPV6 */
  208.   /* Set length. */
  209.   bgp_dump_set_size (obuf, type);
  210.   fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump_routes.fp);
  211.   fflush (bgp_dump_routes.fp);
  212. }
  213. /* Runs under child process. */
  214. void
  215. bgp_dump_routes_func (int afi)
  216. {
  217.   struct stream *obuf;
  218.   struct bgp_node *rn;
  219.   struct bgp_info *info;
  220.   struct bgp *bgp;
  221.   struct bgp_table *table;
  222.   unsigned int seq = 0;
  223.   obuf = bgp_dump_obuf;
  224.   bgp = bgp_get_default ();
  225.   if (!bgp)
  226.     return;
  227.   if (bgp_dump_routes.fp == NULL)
  228.     return;
  229.   /* Walk down each BGP route. */
  230.   table = bgp->rib[afi][SAFI_UNICAST];
  231.   for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
  232.     for (info = rn->info; info; info = info->next)
  233.       bgp_dump_routes_entry (&rn->p, info, afi, MSG_TABLE_DUMP, seq++);
  234. }
  235. int
  236. bgp_dump_interval_func (struct thread *t)
  237. {
  238.   struct bgp_dump *bgp_dump;
  239.   bgp_dump = THREAD_ARG (t);
  240.   bgp_dump->t_interval = NULL;
  241.   if (bgp_dump_open_file (bgp_dump) == NULL)
  242.     return 0;
  243.   /* In case of bgp_dump_routes, we need special route dump function. */
  244.   if (bgp_dump->type == BGP_DUMP_ROUTES)
  245.     {
  246.       bgp_dump_routes_func (AFI_IP);
  247.       bgp_dump_routes_func (AFI_IP6);
  248.     }
  249.   bgp_dump_interval_add (bgp_dump, bgp_dump->interval);
  250.   
  251.   return 0;
  252. }
  253. /* Dump common information. */
  254. void
  255. bgp_dump_common (struct stream *obuf, struct peer *peer)
  256. {
  257.   char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  258.   /* Source AS number and Destination AS number. */
  259.   stream_putw (obuf, peer->as);
  260.   stream_putw (obuf, peer->local_as);
  261.   if (peer->afc[AFI_IP][SAFI_UNICAST])
  262.     {
  263.       stream_putw (obuf, peer->ifindex);
  264.       stream_putw (obuf, AFI_IP);
  265.       stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN);
  266.       if (peer->su_local)
  267. stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN);
  268.       else
  269. stream_put (obuf, empty, IPV4_MAX_BYTELEN);
  270.     }
  271. #ifdef HAVE_IPV6
  272.   else if (peer->afc[AFI_IP6][SAFI_UNICAST])
  273.     {
  274.       /* Interface Index and Address family. */
  275.       stream_putw (obuf, peer->ifindex);
  276.       stream_putw (obuf, AFI_IP6);
  277.       /* Source IP Address and Destination IP Address. */
  278.       stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN);
  279.       if (peer->su_local)
  280. stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN);
  281.       else
  282. stream_put (obuf, empty, IPV6_MAX_BYTELEN);
  283.     }
  284. #endif /* HAVE_IPV6 */
  285. }
  286. /* Dump BGP status change. */
  287. void
  288. bgp_dump_state (struct peer *peer, int status_old, int status_new)
  289. {
  290.   struct stream *obuf;
  291.   /* If dump file pointer is disabled return immediately. */
  292.   if (bgp_dump_all.fp == NULL)
  293.     return;
  294.   /* Make dump stream. */
  295.   obuf = bgp_dump_obuf;
  296.   stream_reset (obuf);
  297.   bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE);
  298.   bgp_dump_common (obuf, peer);
  299.   stream_putw (obuf, status_old);
  300.   stream_putw (obuf, status_new);
  301.   /* Set length. */
  302.   bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
  303.   /* Write to the stream. */
  304.   fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump_all.fp);
  305.   fflush (bgp_dump_all.fp);
  306. }
  307. void
  308. bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
  309.       struct stream *packet)
  310. {
  311.   struct stream *obuf;
  312.   /* If dump file pointer is disabled return immediately. */
  313.   if (bgp_dump->fp == NULL)
  314.     return;
  315.   /* Make dump stream. */
  316.   obuf = bgp_dump_obuf;
  317.   stream_reset (obuf);
  318.   /* Dump header and common part. */
  319.   bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE);
  320.   bgp_dump_common (obuf, peer);
  321.   /* Packet contents. */
  322.   stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet));
  323.   
  324.   /* Set length. */
  325.   bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
  326.   /* Write to the stream. */
  327.   fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump->fp);
  328.   fflush (bgp_dump->fp);
  329. }
  330. /* Called from bgp_packet.c when BGP packet is received. */
  331. void
  332. bgp_dump_packet (struct peer *peer, int type, struct stream *packet)
  333. {
  334.   /* bgp_dump_all. */
  335.   bgp_dump_packet_func (&bgp_dump_all, peer, packet);
  336.   /* bgp_dump_updates. */
  337.   if (type == BGP_MSG_UPDATE)
  338.     bgp_dump_packet_func (&bgp_dump_updates, peer, packet);
  339. }
  340. unsigned int
  341. bgp_dump_parse_time (char *str)
  342. {
  343.   int i;
  344.   int len;
  345.   int seen_h;
  346.   int seen_m;
  347.   int time;
  348.   unsigned int total;
  349.   time = 0;
  350.   total = 0;
  351.   seen_h = 0;
  352.   seen_m = 0;
  353.   len = strlen (str);
  354.   for (i = 0; i < len; i++)
  355.     {
  356.       if (isdigit ((int) str[i]))
  357. {
  358.   time *= 10;
  359.   time += str[i] - '0';
  360. }
  361.       else if (str[i] == 'H' || str[i] == 'h')
  362. {
  363.   if (seen_h)
  364.     return 0;
  365.   if (seen_m)
  366.     return 0;
  367.   total += time * 60 *60;
  368.   time = 0;
  369.   seen_h = 1;
  370. }
  371.       else if (str[i] == 'M' || str[i] == 'm')
  372. {
  373.   if (seen_m)
  374.     return 0;
  375.   total += time * 60;
  376.   time = 0;
  377.   seen_h = 1;
  378. }
  379.       else
  380. return 0;
  381.     }
  382.   return total + time;
  383. }
  384. int
  385. bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump, int type,
  386.       char *path, char *interval_str)
  387. {
  388.   if (interval_str)
  389.     {
  390.       unsigned int interval;
  391.       /* Check interval string. */
  392.       interval = bgp_dump_parse_time (interval_str);
  393.       if (interval == 0)
  394. {
  395.   vty_out (vty, "Malformed interval string%s", VTY_NEWLINE);
  396.   return CMD_WARNING;
  397. }
  398.       /* Set interval. */
  399.       bgp_dump->interval = interval;
  400.       if (bgp_dump->interval_str)
  401. free (bgp_dump->interval_str);
  402.       bgp_dump->interval_str = strdup (interval_str);
  403.       /* Create interval thread. */
  404.       bgp_dump_interval_add (bgp_dump, interval);
  405.     }
  406.   /* Set type. */
  407.   bgp_dump->type = type;
  408.   /* Set file name. */
  409.   if (bgp_dump->filename)
  410.     free (bgp_dump->filename);
  411.   bgp_dump->filename = strdup (path);
  412.   /* This should be called when interval is expired. */
  413.   bgp_dump_open_file (bgp_dump);
  414.   return CMD_SUCCESS;
  415. }
  416. int
  417. bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump)
  418. {
  419.   /* Set file name. */
  420.   if (bgp_dump->filename)
  421.     {
  422.       free (bgp_dump->filename);
  423.       bgp_dump->filename = NULL;
  424.     }
  425.   /* This should be called when interval is expired. */
  426.   if (bgp_dump->fp)
  427.     {
  428.       fclose (bgp_dump->fp);
  429.       bgp_dump->fp = NULL;
  430.     }
  431.   /* Create interval thread. */
  432.   if (bgp_dump->t_interval)
  433.     {
  434.       thread_cancel (bgp_dump->t_interval);
  435.       bgp_dump->t_interval = NULL;
  436.     }
  437.   bgp_dump->interval = 0;
  438.   if (bgp_dump->interval_str)
  439.     {
  440.       free (bgp_dump->interval_str);
  441.       bgp_dump->interval_str = NULL;
  442.     }
  443.   
  444.   return CMD_SUCCESS;
  445. }
  446. DEFUN (dump_bgp_all,
  447.        dump_bgp_all_cmd,
  448.        "dump bgp all PATH",
  449.        "Dump packetn"
  450.        "BGP packet dumpn"
  451.        "Dump all BGP packetsn"
  452.        "Output filenamen")
  453. {
  454.   return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], NULL);
  455. }
  456. DEFUN (dump_bgp_all_interval,
  457.        dump_bgp_all_interval_cmd,
  458.        "dump bgp all PATH INTERVAL",
  459.        "Dump packetn"
  460.        "BGP packet dumpn"
  461.        "Dump all BGP packetsn"
  462.        "Output filenamen"
  463.        "Interval of outputn")
  464. {
  465.   return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], argv[1]);
  466. }
  467. DEFUN (no_dump_bgp_all,
  468.        no_dump_bgp_all_cmd,
  469.        "no dump bgp all [PATH] [INTERVAL]",
  470.        NO_STR
  471.        "Dump packetn"
  472.        "BGP packet dumpn"
  473.        "Dump all BGP packetsn")
  474. {
  475.   return bgp_dump_unset (vty, &bgp_dump_all);
  476. }
  477. DEFUN (dump_bgp_updates,
  478.        dump_bgp_updates_cmd,
  479.        "dump bgp updates PATH",
  480.        "Dump packetn"
  481.        "BGP packet dumpn"
  482.        "Dump BGP updates onlyn"
  483.        "Output filenamen")
  484. {
  485.   return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], NULL);
  486. }
  487. DEFUN (dump_bgp_updates_interval,
  488.        dump_bgp_updates_interval_cmd,
  489.        "dump bgp updates PATH INTERVAL",
  490.        "Dump packetn"
  491.        "BGP packet dumpn"
  492.        "Dump BGP updates onlyn"
  493.        "Output filenamen"
  494.        "Interval of outputn")
  495. {
  496.   return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], argv[1]);
  497. }
  498. DEFUN (no_dump_bgp_updates,
  499.        no_dump_bgp_updates_cmd,
  500.        "no dump bgp updates [PATH] [INTERVAL]",
  501.        NO_STR
  502.        "Dump packetn"
  503.        "BGP packet dumpn"
  504.        "Dump BGP updates onlyn")
  505. {
  506.   return bgp_dump_unset (vty, &bgp_dump_updates);
  507. }
  508. DEFUN (dump_bgp_routes,
  509.        dump_bgp_routes_cmd,
  510.        "dump bgp routes-mrt PATH",
  511.        "Dump packetn"
  512.        "BGP packet dumpn"
  513.        "Dump whole BGP routing tablen"
  514.        "Output filenamen")
  515. {
  516.   return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], NULL);
  517. }
  518. DEFUN (dump_bgp_routes_interval,
  519.        dump_bgp_routes_interval_cmd,
  520.        "dump bgp routes-mrt PATH INTERVAL",
  521.        "Dump packetn"
  522.        "BGP packet dumpn"
  523.        "Dump whole BGP routing tablen"
  524.        "Output filenamen"
  525.        "Interval of outputn")
  526. {
  527.   return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], argv[1]);
  528. }
  529. DEFUN (no_dump_bgp_routes,
  530.        no_dump_bgp_routes_cmd,
  531.        "no dump bgp routes-mrt [PATH] [INTERVAL]",
  532.        NO_STR
  533.        "Dump packetn"
  534.        "BGP packet dumpn"
  535.        "Dump whole BGP routing tablen")
  536. {
  537.   return bgp_dump_unset (vty, &bgp_dump_routes);
  538. }
  539. /* BGP node structure. */
  540. struct cmd_node bgp_dump_node =
  541. {
  542.   DUMP_NODE,
  543.   "",
  544. };
  545. #if 0
  546. char *
  547. config_time2str (unsigned int interval)
  548. {
  549.   static char buf[BUFSIZ];
  550.   buf[0] = '';
  551.   if (interval / 3600)
  552.     {
  553.       sprintf (buf, "%dh", interval / 3600);
  554.       interval %= 3600;
  555.     }
  556.   if (interval / 60)
  557.     {
  558.       sprintf (buf + strlen (buf), "%dm", interval /60);
  559.       interval %= 60;
  560.     }
  561.   if (interval)
  562.     {
  563.       sprintf (buf + strlen (buf), "%d", interval);
  564.     }
  565.   return buf;
  566. }
  567. #endif
  568. int
  569. config_write_bgp_dump (struct vty *vty)
  570. {
  571.   if (bgp_dump_all.filename)
  572.     {
  573.       if (bgp_dump_all.interval_str)
  574. vty_out (vty, "dump bgp all %s %s%s", 
  575.  bgp_dump_all.filename, bgp_dump_all.interval_str,
  576.  VTY_NEWLINE);
  577.       else
  578. vty_out (vty, "dump bgp all %s%s", 
  579.  bgp_dump_all.filename, VTY_NEWLINE);
  580.     }
  581.   if (bgp_dump_updates.filename)
  582.     {
  583.       if (bgp_dump_updates.interval_str)
  584. vty_out (vty, "dump bgp updates %s %s%s", 
  585.  bgp_dump_updates.filename, bgp_dump_updates.interval_str,
  586.  VTY_NEWLINE);
  587.       else
  588. vty_out (vty, "dump bgp updates %s%s", 
  589.  bgp_dump_updates.filename, VTY_NEWLINE);
  590.     }
  591.   if (bgp_dump_routes.filename)
  592.     {
  593.       if (bgp_dump_routes.interval_str)
  594. vty_out (vty, "dump bgp routes-mrt %s %s%s", 
  595.  bgp_dump_routes.filename, bgp_dump_routes.interval_str,
  596.  VTY_NEWLINE);
  597.       else
  598. vty_out (vty, "dump bgp routes-mrt %s%s", 
  599.  bgp_dump_routes.filename, VTY_NEWLINE);
  600.     }
  601.   return 0;
  602. }
  603. /* Initialize BGP packet dump functionality. */
  604. void
  605. bgp_dump_init ()
  606. {
  607.   memset (&bgp_dump_all, 0, sizeof (struct bgp_dump));
  608.   memset (&bgp_dump_updates, 0, sizeof (struct bgp_dump));
  609.   memset (&bgp_dump_routes, 0, sizeof (struct bgp_dump));
  610.   bgp_dump_obuf = stream_new (BGP_MAX_PACKET_SIZE + BGP_DUMP_HEADER_SIZE);
  611.   install_node (&bgp_dump_node, config_write_bgp_dump);
  612.   install_element (CONFIG_NODE, &dump_bgp_all_cmd);
  613.   install_element (CONFIG_NODE, &dump_bgp_all_interval_cmd);
  614.   install_element (CONFIG_NODE, &no_dump_bgp_all_cmd);
  615.   install_element (CONFIG_NODE, &dump_bgp_updates_cmd);
  616.   install_element (CONFIG_NODE, &dump_bgp_updates_interval_cmd);
  617.   install_element (CONFIG_NODE, &no_dump_bgp_updates_cmd);
  618.   install_element (CONFIG_NODE, &dump_bgp_routes_cmd);
  619.   install_element (CONFIG_NODE, &dump_bgp_routes_interval_cmd);
  620.   install_element (CONFIG_NODE, &no_dump_bgp_routes_cmd);
  621. }