blob: 7dc64c6a2235277dedf61183a6b2a393fcd8dacb [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* 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
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
59struct bgp_dump
60{
61 enum bgp_dump_type type;
62
63 char *filename;
64
65 FILE *fp;
66
67 unsigned int interval;
68
69 char *interval_str;
70
71 struct thread *t_interval;
72};
73
74/* BGP packet dump output buffer. */
75struct stream *bgp_dump_obuf;
76
77/* BGP dump strucuture for 'dump bgp all' */
78struct bgp_dump bgp_dump_all;
79
80/* BGP dump structure for 'dump bgp updates' */
81struct bgp_dump bgp_dump_updates;
82
83/* BGP dump structure for 'dump bgp routes' */
84struct bgp_dump bgp_dump_routes;
85
86/* Dump whole BGP table is very heavy process. */
87struct thread *t_bgp_dump_routes;
88
89/* Some define for BGP packet dump. */
90FILE *
91bgp_dump_open_file (struct bgp_dump *bgp_dump)
92{
93 int ret;
94 time_t clock;
95 struct tm *tm;
96 char fullpath[MAXPATHLEN];
97 char realpath[MAXPATHLEN];
98
99 time (&clock);
100 tm = localtime (&clock);
101
102 if (bgp_dump->filename[0] != DIRECTORY_SEP)
103 {
104 sprintf (fullpath, "%s/%s", vty_get_cwd (), bgp_dump->filename);
105 ret = strftime (realpath, MAXPATHLEN, fullpath, tm);
106 }
107 else
108 ret = strftime (realpath, MAXPATHLEN, bgp_dump->filename, tm);
109
110 if (ret == 0)
111 {
112 zlog_warn ("bgp_dump_open_file: strftime error");
113 return NULL;
114 }
115
116 if (bgp_dump->fp)
117 fclose (bgp_dump->fp);
118
119
120 bgp_dump->fp = fopen (realpath, "w");
121
122 if (bgp_dump->fp == NULL)
123 return NULL;
124
125 return bgp_dump->fp;
126}
127
128int
129bgp_dump_interval_add (struct bgp_dump *bgp_dump, int interval)
130{
131 int bgp_dump_interval_func (struct thread *);
paul9834cd02003-10-18 01:01:19 +0000132 int interval2, secs_into_day;
133 time_t t;
134 struct tm *tm;
paul718e3742002-12-13 20:15:29 +0000135
paulfba3d222003-05-10 18:33:28 +0000136 if (interval > 0 )
paul9834cd02003-10-18 01:01:19 +0000137 {
138 if ((interval < 86400) && ((86400 % interval) == 0))
139 {
140 (void) time(&t);
141 tm = localtime(&t);
142 secs_into_day = tm->tm_sec + 60*tm->tm_min + 60*60*tm->tm_hour;
143 interval2 = interval - secs_into_day % interval;
144 if(interval2 == 0) interval2 = interval;
145 }
146 else
147 {
148 interval2 = interval;
149 }
150 bgp_dump->t_interval = thread_add_timer (master, bgp_dump_interval_func,
151 bgp_dump, interval2);
152 }
paulfba3d222003-05-10 18:33:28 +0000153 else
paul9834cd02003-10-18 01:01:19 +0000154 {
155 bgp_dump->t_interval = thread_add_event (master, bgp_dump_interval_func,
156 bgp_dump, 0);
157 }
paulfba3d222003-05-10 18:33:28 +0000158
paul718e3742002-12-13 20:15:29 +0000159 return 0;
160}
161
162/* Dump common header. */
163void
164bgp_dump_header (struct stream *obuf, int type, int subtype)
165{
166 time_t now;
167
168 /* Set header. */
169 time (&now);
170
171 /* Put dump packet header. */
172 stream_putl (obuf, now);
173 stream_putw (obuf, type);
174 stream_putw (obuf, subtype);
175
176 stream_putl (obuf, 0); /* len */
177}
178
179void
180bgp_dump_set_size (struct stream *s, int type)
181{
182 stream_putl_at (s, 8, stream_get_putp (s) - BGP_DUMP_HEADER_SIZE);
183}
184
185void
186bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi,
187 int type, unsigned int seq)
188{
189 struct stream *obuf;
190 struct attr *attr;
191 struct peer *peer;
192 int plen;
193 int safi = 0;
194
195 /* Make dump stream. */
196 obuf = bgp_dump_obuf;
197 stream_reset (obuf);
198
199 attr = info->attr;
200 peer = info->peer;
201
202 /* We support MRT's old format. */
203 if (type == MSG_TABLE_DUMP)
204 {
205 bgp_dump_header (obuf, MSG_TABLE_DUMP, afi);
206 stream_putw (obuf, 0); /* View # */
207 stream_putw (obuf, seq); /* Sequence number. */
208 }
209 else
210 {
211 bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY);
212
213 stream_putl (obuf, info->uptime); /* Time Last Change */
214 stream_putw (obuf, afi); /* Address Family */
215 stream_putc (obuf, safi); /* SAFI */
216 }
217
218 if (afi == AFI_IP)
219 {
220 if (type == MSG_TABLE_DUMP)
221 {
222 /* Prefix */
223 stream_put_in_addr (obuf, &p->u.prefix4);
224 stream_putc (obuf, p->prefixlen);
225
226 /* Status */
227 stream_putc (obuf, 1);
228
229 /* Originated */
230 stream_putl (obuf, info->uptime);
231
232 /* Peer's IP address */
233 stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
234
235 /* Peer's AS number. */
236 stream_putw (obuf, peer->as);
237
238 /* Dump attribute. */
paul1302bdc2003-11-10 23:50:54 +0000239 bgp_dump_routes_attr (obuf, attr, p);
paul718e3742002-12-13 20:15:29 +0000240 }
241 else
242 {
243 /* Next-Hop-Len */
244 stream_putc (obuf, IPV4_MAX_BYTELEN);
245 stream_put_in_addr (obuf, &attr->nexthop);
246 stream_putc (obuf, p->prefixlen);
247 plen = PSIZE (p->prefixlen);
248 stream_put (obuf, &p->u.prefix4, plen);
paul1302bdc2003-11-10 23:50:54 +0000249 bgp_dump_routes_attr (obuf, attr, p);
paul718e3742002-12-13 20:15:29 +0000250 }
251 }
252#ifdef HAVE_IPV6
253 else if (afi == AFI_IP6)
254 {
255 if (type == MSG_TABLE_DUMP)
256 {
257 /* Prefix */
258 stream_write (obuf, (u_char *)&p->u.prefix6, IPV6_MAX_BYTELEN);
259 stream_putc (obuf, p->prefixlen);
260
261 /* Status */
262 stream_putc (obuf, 1);
263
264 /* Originated */
265 stream_putl (obuf, info->uptime);
266
267 /* Peer's IP address */
268 stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
269 IPV6_MAX_BYTELEN);
270
271 /* Peer's AS number. */
272 stream_putw (obuf, peer->as);
273
274 /* Dump attribute. */
paula3845922003-10-18 01:30:50 +0000275 bgp_dump_routes_attr (obuf, attr, p);
paul718e3742002-12-13 20:15:29 +0000276 }
277 else
278 {
279 ;
280 }
281 }
282#endif /* HAVE_IPV6 */
283
284 /* Set length. */
285 bgp_dump_set_size (obuf, type);
286
287 fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump_routes.fp);
288 fflush (bgp_dump_routes.fp);
289}
290
291/* Runs under child process. */
292void
293bgp_dump_routes_func (int afi)
294{
295 struct stream *obuf;
296 struct bgp_node *rn;
297 struct bgp_info *info;
298 struct bgp *bgp;
299 struct bgp_table *table;
300 unsigned int seq = 0;
301
302 obuf = bgp_dump_obuf;
303
304 bgp = bgp_get_default ();
305 if (!bgp)
306 return;
307
308 if (bgp_dump_routes.fp == NULL)
309 return;
310
311 /* Walk down each BGP route. */
312 table = bgp->rib[afi][SAFI_UNICAST];
313
314 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
315 for (info = rn->info; info; info = info->next)
316 bgp_dump_routes_entry (&rn->p, info, afi, MSG_TABLE_DUMP, seq++);
317}
318
319int
320bgp_dump_interval_func (struct thread *t)
321{
322 struct bgp_dump *bgp_dump;
paul718e3742002-12-13 20:15:29 +0000323 bgp_dump = THREAD_ARG (t);
324 bgp_dump->t_interval = NULL;
325
paul9834cd02003-10-18 01:01:19 +0000326 /* Reschedule dump even if file couldn't be opened this time... */
327 if (bgp_dump_open_file (bgp_dump) != NULL)
paul718e3742002-12-13 20:15:29 +0000328 {
paul9834cd02003-10-18 01:01:19 +0000329 /* In case of bgp_dump_routes, we need special route dump function. */
330 if (bgp_dump->type == BGP_DUMP_ROUTES)
331 {
332 bgp_dump_routes_func (AFI_IP);
paula3845922003-10-18 01:30:50 +0000333#ifdef HAVE_IPV6
paul9834cd02003-10-18 01:01:19 +0000334 bgp_dump_routes_func (AFI_IP6);
paula3845922003-10-18 01:30:50 +0000335#endif /* HAVE_IPV6 */
paul9834cd02003-10-18 01:01:19 +0000336 /* Close the file now. For a RIB dump there's no point in leaving
337 * it open until the next scheduled dump starts. */
338 fclose(bgp_dump->fp); bgp_dump->fp = NULL;
339 }
paul718e3742002-12-13 20:15:29 +0000340 }
341
paulfba3d222003-05-10 18:33:28 +0000342 /* if interval is set reschedule */
343 if (bgp_dump->interval > 0)
344 bgp_dump_interval_add (bgp_dump, bgp_dump->interval);
345
paul718e3742002-12-13 20:15:29 +0000346 return 0;
347}
348
349/* Dump common information. */
350void
351bgp_dump_common (struct stream *obuf, struct peer *peer)
352{
353 char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
354
355 /* Source AS number and Destination AS number. */
356 stream_putw (obuf, peer->as);
357 stream_putw (obuf, peer->local_as);
358
paula3845922003-10-18 01:30:50 +0000359 if (peer->su.sa.sa_family == AF_INET)
paul718e3742002-12-13 20:15:29 +0000360 {
361 stream_putw (obuf, peer->ifindex);
362 stream_putw (obuf, AFI_IP);
363
364 stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN);
365
366 if (peer->su_local)
367 stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN);
368 else
369 stream_put (obuf, empty, IPV4_MAX_BYTELEN);
370 }
371#ifdef HAVE_IPV6
paula3845922003-10-18 01:30:50 +0000372 else if (peer->su.sa.sa_family == AF_INET6)
paul718e3742002-12-13 20:15:29 +0000373 {
374 /* Interface Index and Address family. */
375 stream_putw (obuf, peer->ifindex);
376 stream_putw (obuf, AFI_IP6);
377
378 /* Source IP Address and Destination IP Address. */
379 stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN);
380
381 if (peer->su_local)
382 stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN);
383 else
384 stream_put (obuf, empty, IPV6_MAX_BYTELEN);
385 }
386#endif /* HAVE_IPV6 */
387}
388
389/* Dump BGP status change. */
390void
391bgp_dump_state (struct peer *peer, int status_old, int status_new)
392{
393 struct stream *obuf;
394
395 /* If dump file pointer is disabled return immediately. */
396 if (bgp_dump_all.fp == NULL)
397 return;
398
399 /* Make dump stream. */
400 obuf = bgp_dump_obuf;
401 stream_reset (obuf);
402
403 bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE);
404 bgp_dump_common (obuf, peer);
405
406 stream_putw (obuf, status_old);
407 stream_putw (obuf, status_new);
408
409 /* Set length. */
410 bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
411
412 /* Write to the stream. */
413 fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump_all.fp);
414 fflush (bgp_dump_all.fp);
415}
416
417void
418bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
419 struct stream *packet)
420{
421 struct stream *obuf;
422
423 /* If dump file pointer is disabled return immediately. */
424 if (bgp_dump->fp == NULL)
425 return;
426
427 /* Make dump stream. */
428 obuf = bgp_dump_obuf;
429 stream_reset (obuf);
430
431 /* Dump header and common part. */
432 bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE);
433 bgp_dump_common (obuf, peer);
434
435 /* Packet contents. */
436 stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet));
437
438 /* Set length. */
439 bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
440
441 /* Write to the stream. */
442 fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump->fp);
443 fflush (bgp_dump->fp);
444}
445
446/* Called from bgp_packet.c when BGP packet is received. */
447void
448bgp_dump_packet (struct peer *peer, int type, struct stream *packet)
449{
450 /* bgp_dump_all. */
451 bgp_dump_packet_func (&bgp_dump_all, peer, packet);
452
453 /* bgp_dump_updates. */
454 if (type == BGP_MSG_UPDATE)
455 bgp_dump_packet_func (&bgp_dump_updates, peer, packet);
456}
457
458unsigned int
459bgp_dump_parse_time (char *str)
460{
461 int i;
462 int len;
463 int seen_h;
464 int seen_m;
465 int time;
466 unsigned int total;
467
468 time = 0;
469 total = 0;
470 seen_h = 0;
471 seen_m = 0;
472 len = strlen (str);
473
474 for (i = 0; i < len; i++)
475 {
476 if (isdigit ((int) str[i]))
477 {
478 time *= 10;
479 time += str[i] - '0';
480 }
481 else if (str[i] == 'H' || str[i] == 'h')
482 {
483 if (seen_h)
484 return 0;
485 if (seen_m)
486 return 0;
487 total += time * 60 *60;
488 time = 0;
489 seen_h = 1;
490 }
491 else if (str[i] == 'M' || str[i] == 'm')
492 {
493 if (seen_m)
494 return 0;
495 total += time * 60;
496 time = 0;
497 seen_h = 1;
498 }
499 else
500 return 0;
501 }
502 return total + time;
503}
504
505int
506bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump, int type,
507 char *path, char *interval_str)
508{
paulfba3d222003-05-10 18:33:28 +0000509 unsigned int interval;
510
paul718e3742002-12-13 20:15:29 +0000511 if (interval_str)
512 {
paulfba3d222003-05-10 18:33:28 +0000513
paul718e3742002-12-13 20:15:29 +0000514 /* Check interval string. */
515 interval = bgp_dump_parse_time (interval_str);
516 if (interval == 0)
517 {
518 vty_out (vty, "Malformed interval string%s", VTY_NEWLINE);
519 return CMD_WARNING;
520 }
521 /* Set interval. */
522 bgp_dump->interval = interval;
523 if (bgp_dump->interval_str)
524 free (bgp_dump->interval_str);
525 bgp_dump->interval_str = strdup (interval_str);
paulfba3d222003-05-10 18:33:28 +0000526
paul718e3742002-12-13 20:15:29 +0000527 }
paulfba3d222003-05-10 18:33:28 +0000528 else
529 {
530 interval = 0;
531 }
532
533 /* Create interval thread. */
534 bgp_dump_interval_add (bgp_dump, interval);
paul718e3742002-12-13 20:15:29 +0000535
536 /* Set type. */
537 bgp_dump->type = type;
538
539 /* Set file name. */
540 if (bgp_dump->filename)
541 free (bgp_dump->filename);
542 bgp_dump->filename = strdup (path);
543
544 /* This should be called when interval is expired. */
545 bgp_dump_open_file (bgp_dump);
546
547 return CMD_SUCCESS;
548}
549
550int
551bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump)
552{
553 /* Set file name. */
554 if (bgp_dump->filename)
555 {
556 free (bgp_dump->filename);
557 bgp_dump->filename = NULL;
558 }
559
560 /* This should be called when interval is expired. */
561 if (bgp_dump->fp)
562 {
563 fclose (bgp_dump->fp);
564 bgp_dump->fp = NULL;
565 }
566
567 /* Create interval thread. */
568 if (bgp_dump->t_interval)
569 {
570 thread_cancel (bgp_dump->t_interval);
571 bgp_dump->t_interval = NULL;
572 }
573
574 bgp_dump->interval = 0;
575
576 if (bgp_dump->interval_str)
577 {
578 free (bgp_dump->interval_str);
579 bgp_dump->interval_str = NULL;
580 }
581
582
583 return CMD_SUCCESS;
584}
585
586DEFUN (dump_bgp_all,
587 dump_bgp_all_cmd,
588 "dump bgp all PATH",
589 "Dump packet\n"
590 "BGP packet dump\n"
591 "Dump all BGP packets\n"
592 "Output filename\n")
593{
594 return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], NULL);
595}
596
597DEFUN (dump_bgp_all_interval,
598 dump_bgp_all_interval_cmd,
599 "dump bgp all PATH INTERVAL",
600 "Dump packet\n"
601 "BGP packet dump\n"
602 "Dump all BGP packets\n"
603 "Output filename\n"
604 "Interval of output\n")
605{
606 return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], argv[1]);
607}
608
609DEFUN (no_dump_bgp_all,
610 no_dump_bgp_all_cmd,
611 "no dump bgp all [PATH] [INTERVAL]",
612 NO_STR
613 "Dump packet\n"
614 "BGP packet dump\n"
615 "Dump all BGP packets\n")
616{
617 return bgp_dump_unset (vty, &bgp_dump_all);
618}
619
620DEFUN (dump_bgp_updates,
621 dump_bgp_updates_cmd,
622 "dump bgp updates PATH",
623 "Dump packet\n"
624 "BGP packet dump\n"
625 "Dump BGP updates only\n"
626 "Output filename\n")
627{
628 return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], NULL);
629}
630
631DEFUN (dump_bgp_updates_interval,
632 dump_bgp_updates_interval_cmd,
633 "dump bgp updates PATH INTERVAL",
634 "Dump packet\n"
635 "BGP packet dump\n"
636 "Dump BGP updates only\n"
637 "Output filename\n"
638 "Interval of output\n")
639{
640 return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], argv[1]);
641}
642
643DEFUN (no_dump_bgp_updates,
644 no_dump_bgp_updates_cmd,
645 "no dump bgp updates [PATH] [INTERVAL]",
646 NO_STR
647 "Dump packet\n"
648 "BGP packet dump\n"
649 "Dump BGP updates only\n")
650{
651 return bgp_dump_unset (vty, &bgp_dump_updates);
652}
653
654DEFUN (dump_bgp_routes,
655 dump_bgp_routes_cmd,
656 "dump bgp routes-mrt PATH",
657 "Dump packet\n"
658 "BGP packet dump\n"
659 "Dump whole BGP routing table\n"
660 "Output filename\n")
661{
662 return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], NULL);
663}
664
665DEFUN (dump_bgp_routes_interval,
666 dump_bgp_routes_interval_cmd,
667 "dump bgp routes-mrt PATH INTERVAL",
668 "Dump packet\n"
669 "BGP packet dump\n"
670 "Dump whole BGP routing table\n"
671 "Output filename\n"
672 "Interval of output\n")
673{
674 return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], argv[1]);
675}
676
677DEFUN (no_dump_bgp_routes,
678 no_dump_bgp_routes_cmd,
679 "no dump bgp routes-mrt [PATH] [INTERVAL]",
680 NO_STR
681 "Dump packet\n"
682 "BGP packet dump\n"
683 "Dump whole BGP routing table\n")
684{
685 return bgp_dump_unset (vty, &bgp_dump_routes);
686}
687
688/* BGP node structure. */
689struct cmd_node bgp_dump_node =
690{
691 DUMP_NODE,
692 "",
693};
694
695#if 0
696char *
697config_time2str (unsigned int interval)
698{
699 static char buf[BUFSIZ];
700
701 buf[0] = '\0';
702
703 if (interval / 3600)
704 {
705 sprintf (buf, "%dh", interval / 3600);
706 interval %= 3600;
707 }
708 if (interval / 60)
709 {
710 sprintf (buf + strlen (buf), "%dm", interval /60);
711 interval %= 60;
712 }
713 if (interval)
714 {
715 sprintf (buf + strlen (buf), "%d", interval);
716 }
717 return buf;
718}
719#endif
720
721int
722config_write_bgp_dump (struct vty *vty)
723{
724 if (bgp_dump_all.filename)
725 {
726 if (bgp_dump_all.interval_str)
727 vty_out (vty, "dump bgp all %s %s%s",
728 bgp_dump_all.filename, bgp_dump_all.interval_str,
729 VTY_NEWLINE);
730 else
731 vty_out (vty, "dump bgp all %s%s",
732 bgp_dump_all.filename, VTY_NEWLINE);
733 }
734 if (bgp_dump_updates.filename)
735 {
736 if (bgp_dump_updates.interval_str)
737 vty_out (vty, "dump bgp updates %s %s%s",
738 bgp_dump_updates.filename, bgp_dump_updates.interval_str,
739 VTY_NEWLINE);
740 else
741 vty_out (vty, "dump bgp updates %s%s",
742 bgp_dump_updates.filename, VTY_NEWLINE);
743 }
744 if (bgp_dump_routes.filename)
745 {
746 if (bgp_dump_routes.interval_str)
747 vty_out (vty, "dump bgp routes-mrt %s %s%s",
748 bgp_dump_routes.filename, bgp_dump_routes.interval_str,
749 VTY_NEWLINE);
750 else
751 vty_out (vty, "dump bgp routes-mrt %s%s",
752 bgp_dump_routes.filename, VTY_NEWLINE);
753 }
754 return 0;
755}
756
757/* Initialize BGP packet dump functionality. */
758void
759bgp_dump_init ()
760{
761 memset (&bgp_dump_all, 0, sizeof (struct bgp_dump));
762 memset (&bgp_dump_updates, 0, sizeof (struct bgp_dump));
763 memset (&bgp_dump_routes, 0, sizeof (struct bgp_dump));
764
paul9834cd02003-10-18 01:01:19 +0000765 bgp_dump_obuf = stream_new (BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
766 + BGP_DUMP_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +0000767
768 install_node (&bgp_dump_node, config_write_bgp_dump);
769
770 install_element (CONFIG_NODE, &dump_bgp_all_cmd);
771 install_element (CONFIG_NODE, &dump_bgp_all_interval_cmd);
772 install_element (CONFIG_NODE, &no_dump_bgp_all_cmd);
773 install_element (CONFIG_NODE, &dump_bgp_updates_cmd);
774 install_element (CONFIG_NODE, &dump_bgp_updates_interval_cmd);
775 install_element (CONFIG_NODE, &no_dump_bgp_updates_cmd);
776 install_element (CONFIG_NODE, &dump_bgp_routes_cmd);
777 install_element (CONFIG_NODE, &dump_bgp_routes_interval_cmd);
778 install_element (CONFIG_NODE, &no_dump_bgp_routes_cmd);
779}