]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_dump.c
Create override for quagga reinstall of originated routes
[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"
0b2aa3a0 29#include "linklist.h"
3f9c7369
DS
30#include "queue.h"
31
718e3744 32#include "bgpd/bgp_table.h"
33
34#include "bgpd/bgpd.h"
35#include "bgpd/bgp_route.h"
36#include "bgpd/bgp_attr.h"
37#include "bgpd/bgp_dump.h"
6b0655a2 38
718e3744 39enum bgp_dump_type
40{
41 BGP_DUMP_ALL,
42 BGP_DUMP_UPDATES,
43 BGP_DUMP_ROUTES
44};
45
46enum MRT_MSG_TYPES {
47 MSG_NULL,
48 MSG_START, /* sender is starting up */
49 MSG_DIE, /* receiver should shut down */
50 MSG_I_AM_DEAD, /* sender is shutting down */
51 MSG_PEER_DOWN, /* sender's peer is down */
52 MSG_PROTOCOL_BGP, /* msg is a BGP packet */
53 MSG_PROTOCOL_RIP, /* msg is a RIP packet */
54 MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */
55 MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */
56 MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */
57 MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */
58 MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */
0b2aa3a0
PJ
59 MSG_TABLE_DUMP, /* routing table dump */
60 MSG_TABLE_DUMP_V2 /* routing table dump, version 2 */
718e3744 61};
62
1f8ae70b 63static int bgp_dump_interval_func (struct thread *);
64
718e3744 65struct bgp_dump
66{
67 enum bgp_dump_type type;
68
69 char *filename;
70
71 FILE *fp;
72
73 unsigned int interval;
74
75 char *interval_str;
76
77 struct thread *t_interval;
78};
79
80/* BGP packet dump output buffer. */
81struct stream *bgp_dump_obuf;
82
83/* BGP dump strucuture for 'dump bgp all' */
84struct bgp_dump bgp_dump_all;
85
86/* BGP dump structure for 'dump bgp updates' */
87struct bgp_dump bgp_dump_updates;
88
89/* BGP dump structure for 'dump bgp routes' */
90struct bgp_dump bgp_dump_routes;
91
92/* Dump whole BGP table is very heavy process. */
93struct thread *t_bgp_dump_routes;
6b0655a2 94
718e3744 95/* Some define for BGP packet dump. */
94f2b392 96static FILE *
718e3744 97bgp_dump_open_file (struct bgp_dump *bgp_dump)
98{
99 int ret;
100 time_t clock;
101 struct tm *tm;
102 char fullpath[MAXPATHLEN];
103 char realpath[MAXPATHLEN];
aa593d5e 104 mode_t oldumask;
718e3744 105
106 time (&clock);
107 tm = localtime (&clock);
108
109 if (bgp_dump->filename[0] != DIRECTORY_SEP)
110 {
111 sprintf (fullpath, "%s/%s", vty_get_cwd (), bgp_dump->filename);
112 ret = strftime (realpath, MAXPATHLEN, fullpath, tm);
113 }
114 else
115 ret = strftime (realpath, MAXPATHLEN, bgp_dump->filename, tm);
116
117 if (ret == 0)
118 {
119 zlog_warn ("bgp_dump_open_file: strftime error");
120 return NULL;
121 }
122
123 if (bgp_dump->fp)
124 fclose (bgp_dump->fp);
125
126
aa593d5e 127 oldumask = umask(0777 & ~LOGFILE_MASK);
718e3744 128 bgp_dump->fp = fopen (realpath, "w");
129
130 if (bgp_dump->fp == NULL)
aa593d5e 131 {
45ad592e 132 zlog_warn ("bgp_dump_open_file: %s: %s", realpath, strerror (errno));
aa593d5e 133 umask(oldumask);
134 return NULL;
135 }
136 umask(oldumask);
718e3744 137
138 return bgp_dump->fp;
139}
140
94f2b392 141static int
718e3744 142bgp_dump_interval_add (struct bgp_dump *bgp_dump, int interval)
143{
45ad592e 144 int secs_into_day;
9834cd0f 145 time_t t;
146 struct tm *tm;
718e3744 147
45ad592e 148 if (interval > 0)
9834cd0f 149 {
45ad592e 150 /* Periodic dump every interval seconds */
9834cd0f 151 if ((interval < 86400) && ((86400 % interval) == 0))
152 {
45ad592e
PJ
153 /* Dump at predictable times: if a day has a whole number of
154 * intervals, dump every interval seconds starting from midnight
155 */
9834cd0f 156 (void) time(&t);
157 tm = localtime(&t);
158 secs_into_day = tm->tm_sec + 60*tm->tm_min + 60*60*tm->tm_hour;
45ad592e 159 interval = interval - secs_into_day % interval; /* always > 0 */
9834cd0f 160 }
161 bgp_dump->t_interval = thread_add_timer (master, bgp_dump_interval_func,
45ad592e 162 bgp_dump, interval);
9834cd0f 163 }
fba3d22b 164 else
9834cd0f 165 {
45ad592e 166 /* One-off dump: execute immediately, don't affect any scheduled dumps */
9834cd0f 167 bgp_dump->t_interval = thread_add_event (master, bgp_dump_interval_func,
168 bgp_dump, 0);
169 }
fba3d22b 170
718e3744 171 return 0;
172}
173
174/* Dump common header. */
94f2b392 175static void
718e3744 176bgp_dump_header (struct stream *obuf, int type, int subtype)
177{
178 time_t now;
179
180 /* Set header. */
181 time (&now);
182
183 /* Put dump packet header. */
184 stream_putl (obuf, now);
185 stream_putw (obuf, type);
186 stream_putw (obuf, subtype);
187
188 stream_putl (obuf, 0); /* len */
189}
190
94f2b392 191static void
718e3744 192bgp_dump_set_size (struct stream *s, int type)
193{
9985f83c 194 stream_putl_at (s, 8, stream_get_endp (s) - BGP_DUMP_HEADER_SIZE);
718e3744 195}
196
94f2b392 197static void
0b2aa3a0 198bgp_dump_routes_index_table(struct bgp *bgp)
718e3744 199{
718e3744 200 struct peer *peer;
0b2aa3a0
PJ
201 struct listnode *node;
202 uint16_t peerno = 0;
203 struct stream *obuf;
718e3744 204
718e3744 205 obuf = bgp_dump_obuf;
206 stream_reset (obuf);
207
0b2aa3a0
PJ
208 /* MRT header */
209 bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE);
718e3744 210
0b2aa3a0
PJ
211 /* Collector BGP ID */
212 stream_put_in_addr (obuf, &bgp->router_id);
213
214 /* View name */
215 if(bgp->name)
718e3744 216 {
0b2aa3a0
PJ
217 stream_putw (obuf, strlen(bgp->name));
218 stream_put(obuf, bgp->name, strlen(bgp->name));
718e3744 219 }
220 else
221 {
0b2aa3a0 222 stream_putw(obuf, 0);
718e3744 223 }
224
0b2aa3a0
PJ
225 /* Peer count */
226 stream_putw (obuf, listcount(bgp->peer));
718e3744 227
0b2aa3a0
PJ
228 /* Walk down all peers */
229 for(ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
718e3744 230 {
718e3744 231
0b2aa3a0
PJ
232 /* Peer's type */
233 if (sockunion_family(&peer->su) == AF_INET)
234 {
235 stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP);
236 }
237#ifdef HAVE_IPV6
238 else if (sockunion_family(&peer->su) == AF_INET6)
239 {
240 stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6);
241 }
242#endif /* HAVE_IPV6 */
718e3744 243
0b2aa3a0
PJ
244 /* Peer's BGP ID */
245 stream_put_in_addr (obuf, &peer->remote_id);
718e3744 246
0b2aa3a0
PJ
247 /* Peer's IP address */
248 if (sockunion_family(&peer->su) == AF_INET)
249 {
250 stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
251 }
252#ifdef HAVE_IPV6
253 else if (sockunion_family(&peer->su) == AF_INET6)
254 {
255 stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
256 IPV6_MAX_BYTELEN);
257 }
258#endif /* HAVE_IPV6 */
718e3744 259
0b2aa3a0
PJ
260 /* Peer's AS number. */
261 /* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */
262 stream_putl (obuf, peer->as);
718e3744 263
0b2aa3a0
PJ
264 /* Store the peer number for this peer */
265 peer->table_dump_index = peerno;
266 peerno++;
718e3744 267 }
718e3744 268
0b2aa3a0 269 bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
718e3744 270
a6694fe8 271 fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
718e3744 272 fflush (bgp_dump_routes.fp);
273}
274
0b2aa3a0 275
718e3744 276/* Runs under child process. */
0b2aa3a0
PJ
277static unsigned int
278bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
718e3744 279{
280 struct stream *obuf;
718e3744 281 struct bgp_info *info;
0b2aa3a0 282 struct bgp_node *rn;
718e3744 283 struct bgp *bgp;
284 struct bgp_table *table;
718e3744 285
286 bgp = bgp_get_default ();
287 if (!bgp)
0b2aa3a0 288 return seq;
718e3744 289
290 if (bgp_dump_routes.fp == NULL)
0b2aa3a0
PJ
291 return seq;
292
293 /* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers,
294 so this should only be done on the first call to bgp_dump_routes_func.
295 ( this function will be called once for ipv4 and once for ipv6 ) */
296 if(first_run)
297 bgp_dump_routes_index_table(bgp);
298
299 obuf = bgp_dump_obuf;
300 stream_reset(obuf);
718e3744 301
302 /* Walk down each BGP route. */
303 table = bgp->rib[afi][SAFI_UNICAST];
304
305 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
0b2aa3a0
PJ
306 {
307 if(!rn->info)
308 continue;
309
310 stream_reset(obuf);
311
312 /* MRT header */
313 if (afi == AFI_IP)
314 {
315 bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST);
316 }
317#ifdef HAVE_IPV6
318 else if (afi == AFI_IP6)
319 {
320 bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST);
321 }
322#endif /* HAVE_IPV6 */
323
324 /* Sequence number */
325 stream_putl(obuf, seq);
326
327 /* Prefix length */
328 stream_putc (obuf, rn->p.prefixlen);
329
330 /* Prefix */
331 if (afi == AFI_IP)
332 {
333 /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
334 stream_write(obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8);
335 }
336#ifdef HAVE_IPV6
337 else if (afi == AFI_IP6)
338 {
339 /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
340 stream_write (obuf, (u_char *)&rn->p.u.prefix6, (rn->p.prefixlen+7)/8);
341 }
342#endif /* HAVE_IPV6 */
343
344 /* Save where we are now, so we can overwride the entry count later */
345 int sizep = stream_get_endp(obuf);
346
347 /* Entry count */
348 uint16_t entry_count = 0;
349
350 /* Entry count, note that this is overwritten later */
351 stream_putw(obuf, 0);
352
353 for (info = rn->info; info; info = info->next)
354 {
355 entry_count++;
356
357 /* Peer index */
358 stream_putw(obuf, info->peer->table_dump_index);
359
360 /* Originated */
30b00176
JK
361#ifdef HAVE_CLOCK_MONOTONIC
362 stream_putl (obuf, time(NULL) - (bgp_clock() - info->uptime));
363#else
0b2aa3a0 364 stream_putl (obuf, info->uptime);
30b00176 365#endif /* HAVE_CLOCK_MONOTONIC */
0b2aa3a0
PJ
366
367 /* Dump attribute. */
368 /* Skip prefix & AFI/SAFI for MP_NLRI */
369 bgp_dump_routes_attr (obuf, info->attr, &rn->p);
370 }
371
372 /* Overwrite the entry count, now that we know the right number */
373 stream_putw_at (obuf, sizep, entry_count);
374
375 seq++;
376
377 bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
a6694fe8
DL
378 fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
379
0b2aa3a0
PJ
380 }
381
382 fflush (bgp_dump_routes.fp);
383
384 return seq;
718e3744 385}
386
94f2b392 387static int
718e3744 388bgp_dump_interval_func (struct thread *t)
389{
390 struct bgp_dump *bgp_dump;
718e3744 391 bgp_dump = THREAD_ARG (t);
392 bgp_dump->t_interval = NULL;
393
9834cd0f 394 /* Reschedule dump even if file couldn't be opened this time... */
395 if (bgp_dump_open_file (bgp_dump) != NULL)
718e3744 396 {
9834cd0f 397 /* In case of bgp_dump_routes, we need special route dump function. */
398 if (bgp_dump->type == BGP_DUMP_ROUTES)
399 {
0b2aa3a0 400 unsigned int seq = bgp_dump_routes_func (AFI_IP, 1, 0);
a384592f 401#ifdef HAVE_IPV6
0b2aa3a0 402 bgp_dump_routes_func (AFI_IP6, 0, seq);
a384592f 403#endif /* HAVE_IPV6 */
9834cd0f 404 /* Close the file now. For a RIB dump there's no point in leaving
405 * it open until the next scheduled dump starts. */
406 fclose(bgp_dump->fp); bgp_dump->fp = NULL;
407 }
718e3744 408 }
409
fba3d22b 410 /* if interval is set reschedule */
411 if (bgp_dump->interval > 0)
412 bgp_dump_interval_add (bgp_dump, bgp_dump->interval);
413
718e3744 414 return 0;
415}
416
417/* Dump common information. */
94f2b392 418static void
0b2aa3a0 419bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4)
718e3744 420{
421 char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
422
423 /* Source AS number and Destination AS number. */
0b2aa3a0
PJ
424 if (forceas4 || CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
425 {
426 stream_putl (obuf, peer->as);
427 stream_putl (obuf, peer->local_as);
428 }
429 else
430 {
431 stream_putw (obuf, peer->as);
432 stream_putw (obuf, peer->local_as);
433 }
718e3744 434
a384592f 435 if (peer->su.sa.sa_family == AF_INET)
718e3744 436 {
437 stream_putw (obuf, peer->ifindex);
438 stream_putw (obuf, AFI_IP);
439
440 stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN);
441
442 if (peer->su_local)
443 stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN);
444 else
445 stream_put (obuf, empty, IPV4_MAX_BYTELEN);
446 }
447#ifdef HAVE_IPV6
a384592f 448 else if (peer->su.sa.sa_family == AF_INET6)
718e3744 449 {
450 /* Interface Index and Address family. */
451 stream_putw (obuf, peer->ifindex);
452 stream_putw (obuf, AFI_IP6);
453
454 /* Source IP Address and Destination IP Address. */
455 stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN);
456
457 if (peer->su_local)
458 stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN);
459 else
460 stream_put (obuf, empty, IPV6_MAX_BYTELEN);
461 }
462#endif /* HAVE_IPV6 */
463}
464
465/* Dump BGP status change. */
466void
467bgp_dump_state (struct peer *peer, int status_old, int status_new)
468{
469 struct stream *obuf;
470
471 /* If dump file pointer is disabled return immediately. */
472 if (bgp_dump_all.fp == NULL)
473 return;
474
475 /* Make dump stream. */
476 obuf = bgp_dump_obuf;
477 stream_reset (obuf);
478
0b2aa3a0
PJ
479 bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4);
480 bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/
718e3744 481
482 stream_putw (obuf, status_old);
483 stream_putw (obuf, status_new);
484
485 /* Set length. */
486 bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
487
488 /* Write to the stream. */
a6694fe8 489 fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_all.fp);
718e3744 490 fflush (bgp_dump_all.fp);
491}
492
94f2b392 493static void
718e3744 494bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
495 struct stream *packet)
496{
497 struct stream *obuf;
498
499 /* If dump file pointer is disabled return immediately. */
500 if (bgp_dump->fp == NULL)
501 return;
502
503 /* Make dump stream. */
504 obuf = bgp_dump_obuf;
505 stream_reset (obuf);
506
507 /* Dump header and common part. */
0b2aa3a0
PJ
508 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
509 {
510 bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4);
511 }
512 else
513 {
514 bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE);
515 }
516 bgp_dump_common (obuf, peer, 0);
718e3744 517
518 /* Packet contents. */
519 stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet));
520
521 /* Set length. */
522 bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
523
524 /* Write to the stream. */
a6694fe8 525 fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump->fp);
718e3744 526 fflush (bgp_dump->fp);
527}
528
529/* Called from bgp_packet.c when BGP packet is received. */
530void
531bgp_dump_packet (struct peer *peer, int type, struct stream *packet)
532{
533 /* bgp_dump_all. */
534 bgp_dump_packet_func (&bgp_dump_all, peer, packet);
535
536 /* bgp_dump_updates. */
537 if (type == BGP_MSG_UPDATE)
538 bgp_dump_packet_func (&bgp_dump_updates, peer, packet);
539}
6b0655a2 540
94f2b392 541static unsigned int
fd79ac91 542bgp_dump_parse_time (const char *str)
718e3744 543{
544 int i;
545 int len;
546 int seen_h;
547 int seen_m;
548 int time;
549 unsigned int total;
550
551 time = 0;
552 total = 0;
553 seen_h = 0;
554 seen_m = 0;
555 len = strlen (str);
556
557 for (i = 0; i < len; i++)
558 {
559 if (isdigit ((int) str[i]))
560 {
561 time *= 10;
562 time += str[i] - '0';
563 }
564 else if (str[i] == 'H' || str[i] == 'h')
565 {
566 if (seen_h)
567 return 0;
568 if (seen_m)
569 return 0;
570 total += time * 60 *60;
571 time = 0;
572 seen_h = 1;
573 }
574 else if (str[i] == 'M' || str[i] == 'm')
575 {
576 if (seen_m)
577 return 0;
578 total += time * 60;
579 time = 0;
580 seen_h = 1;
581 }
582 else
583 return 0;
584 }
585 return total + time;
586}
587
94f2b392 588static int
45ad592e
PJ
589bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump,
590 enum bgp_dump_type type, const char *path,
591 const char *interval_str)
718e3744 592{
fba3d22b 593 unsigned int interval;
594
718e3744 595 if (interval_str)
596 {
fba3d22b 597
718e3744 598 /* Check interval string. */
599 interval = bgp_dump_parse_time (interval_str);
600 if (interval == 0)
601 {
602 vty_out (vty, "Malformed interval string%s", VTY_NEWLINE);
603 return CMD_WARNING;
604 }
45ad592e
PJ
605
606 /* Don't schedule duplicate dumps if the dump command is given twice */
607 if (interval == bgp_dump->interval &&
608 type == bgp_dump->type &&
609 path && bgp_dump->filename && !strcmp (path, bgp_dump->filename))
610 {
611 return CMD_SUCCESS;
612 }
613
718e3744 614 /* Set interval. */
615 bgp_dump->interval = interval;
616 if (bgp_dump->interval_str)
617 free (bgp_dump->interval_str);
618 bgp_dump->interval_str = strdup (interval_str);
fba3d22b 619
718e3744 620 }
fba3d22b 621 else
622 {
623 interval = 0;
624 }
625
626 /* Create interval thread. */
627 bgp_dump_interval_add (bgp_dump, interval);
718e3744 628
629 /* Set type. */
630 bgp_dump->type = type;
631
632 /* Set file name. */
633 if (bgp_dump->filename)
634 free (bgp_dump->filename);
635 bgp_dump->filename = strdup (path);
636
637 /* This should be called when interval is expired. */
638 bgp_dump_open_file (bgp_dump);
639
640 return CMD_SUCCESS;
641}
642
94f2b392 643static int
718e3744 644bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump)
645{
646 /* Set file name. */
647 if (bgp_dump->filename)
648 {
649 free (bgp_dump->filename);
650 bgp_dump->filename = NULL;
651 }
652
653 /* This should be called when interval is expired. */
654 if (bgp_dump->fp)
655 {
656 fclose (bgp_dump->fp);
657 bgp_dump->fp = NULL;
658 }
659
660 /* Create interval thread. */
661 if (bgp_dump->t_interval)
662 {
663 thread_cancel (bgp_dump->t_interval);
664 bgp_dump->t_interval = NULL;
665 }
666
667 bgp_dump->interval = 0;
668
669 if (bgp_dump->interval_str)
670 {
671 free (bgp_dump->interval_str);
672 bgp_dump->interval_str = NULL;
673 }
674
675
676 return CMD_SUCCESS;
677}
678
679DEFUN (dump_bgp_all,
680 dump_bgp_all_cmd,
681 "dump bgp all PATH",
682 "Dump packet\n"
683 "BGP packet dump\n"
684 "Dump all BGP packets\n"
685 "Output filename\n")
686{
687 return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], NULL);
688}
689
690DEFUN (dump_bgp_all_interval,
691 dump_bgp_all_interval_cmd,
692 "dump bgp all PATH INTERVAL",
693 "Dump packet\n"
694 "BGP packet dump\n"
695 "Dump all BGP packets\n"
696 "Output filename\n"
697 "Interval of output\n")
698{
699 return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], argv[1]);
700}
701
702DEFUN (no_dump_bgp_all,
703 no_dump_bgp_all_cmd,
704 "no dump bgp all [PATH] [INTERVAL]",
705 NO_STR
706 "Dump packet\n"
707 "BGP packet dump\n"
708 "Dump all BGP packets\n")
709{
710 return bgp_dump_unset (vty, &bgp_dump_all);
711}
712
713DEFUN (dump_bgp_updates,
714 dump_bgp_updates_cmd,
715 "dump bgp updates PATH",
716 "Dump packet\n"
717 "BGP packet dump\n"
718 "Dump BGP updates only\n"
719 "Output filename\n")
720{
721 return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], NULL);
722}
723
724DEFUN (dump_bgp_updates_interval,
725 dump_bgp_updates_interval_cmd,
726 "dump bgp updates PATH INTERVAL",
727 "Dump packet\n"
728 "BGP packet dump\n"
729 "Dump BGP updates only\n"
730 "Output filename\n"
731 "Interval of output\n")
732{
733 return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], argv[1]);
734}
735
736DEFUN (no_dump_bgp_updates,
737 no_dump_bgp_updates_cmd,
738 "no dump bgp updates [PATH] [INTERVAL]",
739 NO_STR
740 "Dump packet\n"
741 "BGP packet dump\n"
742 "Dump BGP updates only\n")
743{
744 return bgp_dump_unset (vty, &bgp_dump_updates);
745}
746
747DEFUN (dump_bgp_routes,
748 dump_bgp_routes_cmd,
749 "dump bgp routes-mrt PATH",
750 "Dump packet\n"
751 "BGP packet dump\n"
752 "Dump whole BGP routing table\n"
753 "Output filename\n")
754{
755 return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], NULL);
756}
757
758DEFUN (dump_bgp_routes_interval,
759 dump_bgp_routes_interval_cmd,
760 "dump bgp routes-mrt PATH INTERVAL",
761 "Dump packet\n"
762 "BGP packet dump\n"
763 "Dump whole BGP routing table\n"
764 "Output filename\n"
765 "Interval of output\n")
766{
767 return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], argv[1]);
768}
769
770DEFUN (no_dump_bgp_routes,
771 no_dump_bgp_routes_cmd,
772 "no dump bgp routes-mrt [PATH] [INTERVAL]",
773 NO_STR
774 "Dump packet\n"
775 "BGP packet dump\n"
776 "Dump whole BGP routing table\n")
777{
778 return bgp_dump_unset (vty, &bgp_dump_routes);
779}
780
781/* BGP node structure. */
7fc626de 782static struct cmd_node bgp_dump_node =
718e3744 783{
784 DUMP_NODE,
785 "",
501ba490 786 1
718e3744 787};
788
789#if 0
790char *
791config_time2str (unsigned int interval)
792{
793 static char buf[BUFSIZ];
794
795 buf[0] = '\0';
796
797 if (interval / 3600)
798 {
799 sprintf (buf, "%dh", interval / 3600);
800 interval %= 3600;
801 }
802 if (interval / 60)
803 {
804 sprintf (buf + strlen (buf), "%dm", interval /60);
805 interval %= 60;
806 }
807 if (interval)
808 {
809 sprintf (buf + strlen (buf), "%d", interval);
810 }
811 return buf;
812}
813#endif
814
94f2b392 815static int
718e3744 816config_write_bgp_dump (struct vty *vty)
817{
818 if (bgp_dump_all.filename)
819 {
820 if (bgp_dump_all.interval_str)
821 vty_out (vty, "dump bgp all %s %s%s",
822 bgp_dump_all.filename, bgp_dump_all.interval_str,
823 VTY_NEWLINE);
824 else
825 vty_out (vty, "dump bgp all %s%s",
826 bgp_dump_all.filename, VTY_NEWLINE);
827 }
828 if (bgp_dump_updates.filename)
829 {
830 if (bgp_dump_updates.interval_str)
831 vty_out (vty, "dump bgp updates %s %s%s",
832 bgp_dump_updates.filename, bgp_dump_updates.interval_str,
833 VTY_NEWLINE);
834 else
835 vty_out (vty, "dump bgp updates %s%s",
836 bgp_dump_updates.filename, VTY_NEWLINE);
837 }
838 if (bgp_dump_routes.filename)
839 {
840 if (bgp_dump_routes.interval_str)
841 vty_out (vty, "dump bgp routes-mrt %s %s%s",
842 bgp_dump_routes.filename, bgp_dump_routes.interval_str,
843 VTY_NEWLINE);
844 else
845 vty_out (vty, "dump bgp routes-mrt %s%s",
846 bgp_dump_routes.filename, VTY_NEWLINE);
847 }
848 return 0;
849}
6b0655a2 850
718e3744 851/* Initialize BGP packet dump functionality. */
852void
94f2b392 853bgp_dump_init (void)
718e3744 854{
855 memset (&bgp_dump_all, 0, sizeof (struct bgp_dump));
856 memset (&bgp_dump_updates, 0, sizeof (struct bgp_dump));
857 memset (&bgp_dump_routes, 0, sizeof (struct bgp_dump));
858
9834cd0f 859 bgp_dump_obuf = stream_new (BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
860 + BGP_DUMP_HEADER_SIZE);
718e3744 861
862 install_node (&bgp_dump_node, config_write_bgp_dump);
863
864 install_element (CONFIG_NODE, &dump_bgp_all_cmd);
865 install_element (CONFIG_NODE, &dump_bgp_all_interval_cmd);
866 install_element (CONFIG_NODE, &no_dump_bgp_all_cmd);
867 install_element (CONFIG_NODE, &dump_bgp_updates_cmd);
868 install_element (CONFIG_NODE, &dump_bgp_updates_interval_cmd);
869 install_element (CONFIG_NODE, &no_dump_bgp_updates_cmd);
870 install_element (CONFIG_NODE, &dump_bgp_routes_cmd);
871 install_element (CONFIG_NODE, &dump_bgp_routes_interval_cmd);
872 install_element (CONFIG_NODE, &no_dump_bgp_routes_cmd);
873}
228da428
CC
874
875void
876bgp_dump_finish (void)
877{
878 stream_free (bgp_dump_obuf);
879 bgp_dump_obuf = NULL;
880}