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