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