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