123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893 |
- /* BGP-4 dump routine
- Copyright (C) 1999 Kunihiro Ishiguro
- This file is part of GNU Zebra.
- GNU Zebra is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
- GNU Zebra is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNU Zebra; see the file COPYING. If not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
- #include <zebra.h>
- #include "log.h"
- #include "stream.h"
- #include "sockunion.h"
- #include "command.h"
- #include "prefix.h"
- #include "thread.h"
- #include "linklist.h"
- #include "filter.h"
- #include "bgpd/bgp_table.h"
- #include "bgpd/bgpd.h"
- #include "bgpd/bgp_route.h"
- #include "bgpd/bgp_attr.h"
- #include "bgpd/bgp_dump.h"
- enum bgp_dump_type
- {
- BGP_DUMP_ALL,
- BGP_DUMP_ALL_ET,
- BGP_DUMP_UPDATES,
- BGP_DUMP_UPDATES_ET,
- BGP_DUMP_ROUTES
- };
- static const struct bgp_dump_type_map {
- enum bgp_dump_type type;
- const char *str;
- } bgp_dump_type_map[] =
- {
- {BGP_DUMP_ALL, "all"},
- {BGP_DUMP_ALL_ET, "all-et"},
- {BGP_DUMP_UPDATES, "updates"},
- {BGP_DUMP_UPDATES_ET, "updates-et"},
- {BGP_DUMP_ROUTES, "routes-mrt"},
- {0, NULL},
- };
- enum MRT_MSG_TYPES {
- MSG_NULL,
- MSG_START, /* sender is starting up */
- MSG_DIE, /* receiver should shut down */
- MSG_I_AM_DEAD, /* sender is shutting down */
- MSG_PEER_DOWN, /* sender's peer is down */
- MSG_PROTOCOL_BGP, /* msg is a BGP packet */
- MSG_PROTOCOL_RIP, /* msg is a RIP packet */
- MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */
- MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */
- MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */
- MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */
- MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */
- MSG_TABLE_DUMP, /* routing table dump */
- MSG_TABLE_DUMP_V2 /* routing table dump, version 2 */
- };
- struct bgp_dump
- {
- enum bgp_dump_type type;
- char *filename;
- FILE *fp;
- unsigned int interval;
- char *interval_str;
- struct thread *t_interval;
- };
- static int bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump);
- static int bgp_dump_interval_func (struct thread *);
- /* BGP packet dump output buffer. */
- struct stream *bgp_dump_obuf;
- /* BGP dump strucuture for 'dump bgp all' */
- struct bgp_dump bgp_dump_all;
- /* BGP dump structure for 'dump bgp updates' */
- struct bgp_dump bgp_dump_updates;
- /* BGP dump structure for 'dump bgp routes' */
- struct bgp_dump bgp_dump_routes;
- static FILE *
- bgp_dump_open_file (struct bgp_dump *bgp_dump)
- {
- int ret;
- time_t clock;
- struct tm *tm;
- char fullpath[MAXPATHLEN];
- char realpath[MAXPATHLEN];
- mode_t oldumask;
- time (&clock);
- tm = localtime (&clock);
- if (bgp_dump->filename[0] != DIRECTORY_SEP)
- {
- sprintf (fullpath, "%s/%s", vty_get_cwd (), bgp_dump->filename);
- ret = strftime (realpath, MAXPATHLEN, fullpath, tm);
- }
- else
- ret = strftime (realpath, MAXPATHLEN, bgp_dump->filename, tm);
- if (ret == 0)
- {
- zlog_warn ("bgp_dump_open_file: strftime error");
- return NULL;
- }
- if (bgp_dump->fp)
- fclose (bgp_dump->fp);
- oldumask = umask(0777 & ~LOGFILE_MASK);
- bgp_dump->fp = fopen (realpath, "w");
- if (bgp_dump->fp == NULL)
- {
- zlog_warn ("bgp_dump_open_file: %s: %s", realpath, strerror (errno));
- umask(oldumask);
- return NULL;
- }
- umask(oldumask);
- return bgp_dump->fp;
- }
- static int
- bgp_dump_interval_add (struct bgp_dump *bgp_dump, int interval)
- {
- int secs_into_day;
- time_t t;
- struct tm *tm;
- if (interval > 0)
- {
- /* Periodic dump every interval seconds */
- if ((interval < 86400) && ((86400 % interval) == 0))
- {
- /* Dump at predictable times: if a day has a whole number of
- * intervals, dump every interval seconds starting from midnight
- */
- (void) time(&t);
- tm = localtime(&t);
- secs_into_day = tm->tm_sec + 60*tm->tm_min + 60*60*tm->tm_hour;
- interval = interval - secs_into_day % interval; /* always > 0 */
- }
- bgp_dump->t_interval = thread_add_timer (bm->master, bgp_dump_interval_func,
- bgp_dump, interval);
- }
- else
- {
- /* One-off dump: execute immediately, don't affect any scheduled dumps */
- bgp_dump->t_interval = thread_add_event (bm->master, bgp_dump_interval_func,
- bgp_dump, 0);
- }
- return 0;
- }
- /* Dump common header. */
- static void
- bgp_dump_header (struct stream *obuf, int type, int subtype, int dump_type)
- {
- struct timeval clock;
- long msecs;
- time_t secs;
- if ((dump_type == BGP_DUMP_ALL_ET || dump_type == BGP_DUMP_UPDATES_ET)
- && type == MSG_PROTOCOL_BGP4MP)
- type = MSG_PROTOCOL_BGP4MP_ET;
- gettimeofday(&clock, NULL);
- secs = clock.tv_sec;
- msecs = clock.tv_usec;
- /* Put dump packet header. */
- stream_putl (obuf, secs);
- stream_putw (obuf, type);
- stream_putw (obuf, subtype);
- stream_putl (obuf, 0); /* len */
- /* Adding microseconds for the MRT Extended Header */
- if (type == MSG_PROTOCOL_BGP4MP_ET)
- stream_putl (obuf, msecs);
- }
- static void
- bgp_dump_set_size (struct stream *s, int type)
- {
- /*
- * The BGP_DUMP_HEADER_SIZE stay at 12 event when ET:
- * "The Microsecond Timestamp is included in the computation
- * of the Length field value." (RFC6396 2011)
- */
- stream_putl_at (s, 8, stream_get_endp (s) - BGP_DUMP_HEADER_SIZE);
- }
- static void
- bgp_dump_routes_index_table(struct bgp *bgp)
- {
- struct peer *peer;
- struct listnode *node;
- uint16_t peerno = 1;
- struct stream *obuf;
- obuf = bgp_dump_obuf;
- stream_reset (obuf);
- /* MRT header */
- bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE,
- BGP_DUMP_ROUTES);
- /* Collector BGP ID */
- stream_put_in_addr (obuf, &bgp->router_id);
- /* View name */
- if(bgp->name)
- {
- stream_putw (obuf, strlen(bgp->name));
- stream_put(obuf, bgp->name, strlen(bgp->name));
- }
- else
- {
- stream_putw(obuf, 0);
- }
- /* Peer count ( plus one extra internal peer ) */
- stream_putw (obuf, listcount(bgp->peer) + 1);
- /* Populate fake peer at index 0, for locally originated routes */
- /* Peer type (IPv4) */
- stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP);
- /* Peer BGP ID (0.0.0.0) */
- stream_putl (obuf, 0);
- /* Peer IP address (0.0.0.0) */
- stream_putl (obuf, 0);
- /* Peer ASN (0) */
- stream_putl (obuf, 0);
- /* Walk down all peers */
- for(ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
- {
- /* Peer's type */
- if (sockunion_family(&peer->su) == AF_INET)
- {
- stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP);
- }
- else if (sockunion_family(&peer->su) == AF_INET6)
- {
- stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6);
- }
- /* Peer's BGP ID */
- stream_put_in_addr (obuf, &peer->remote_id);
- /* Peer's IP address */
- if (sockunion_family(&peer->su) == AF_INET)
- {
- stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
- }
- else if (sockunion_family(&peer->su) == AF_INET6)
- {
- stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
- IPV6_MAX_BYTELEN);
- }
- /* Peer's AS number. */
- /* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */
- stream_putl (obuf, peer->as);
- /* Store the peer number for this peer */
- peer->table_dump_index = peerno;
- peerno++;
- }
- bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
- fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
- fflush (bgp_dump_routes.fp);
- }
- static struct bgp_info *
- bgp_dump_route_node_record (int afi, struct bgp_node *rn,
- struct bgp_info *info, unsigned int seq)
- {
- struct stream *obuf;
- size_t sizep;
- size_t endp;
- obuf = bgp_dump_obuf;
- stream_reset (obuf);
- /* MRT header */
- if (afi == AFI_IP)
- bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST,
- BGP_DUMP_ROUTES);
- else if (afi == AFI_IP6)
- bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST,
- BGP_DUMP_ROUTES);
- /* Sequence number */
- stream_putl (obuf, seq);
- /* Prefix length */
- stream_putc (obuf, rn->p.prefixlen);
- /* Prefix */
- if (afi == AFI_IP)
- {
- /* We'll dump only the useful bits (those not 0), but have to
- * align on 8 bits */
- stream_write (obuf, (u_char *) &rn->p.u.prefix4,
- (rn->p.prefixlen + 7) / 8);
- }
- else if (afi == AFI_IP6)
- {
- /* We'll dump only the useful bits (those not 0), but have to
- * align on 8 bits */
- stream_write (obuf, (u_char *) &rn->p.u.prefix6,
- (rn->p.prefixlen + 7) / 8);
- }
- /* Save where we are now, so we can overwride the entry count later */
- sizep = stream_get_endp (obuf);
- /* Entry count */
- uint16_t entry_count = 0;
- /* Entry count, note that this is overwritten later */
- stream_putw (obuf, 0);
- endp = stream_get_endp (obuf);
- for (; info; info = info->next)
- {
- size_t cur_endp;
- /* Peer index */
- stream_putw (obuf, info->peer->table_dump_index);
- /* Originated */
- #ifdef HAVE_CLOCK_MONOTONIC
- stream_putl (obuf, time (NULL) - (bgp_clock () - info->uptime));
- #else
- stream_putl (obuf, info->uptime);
- #endif /* HAVE_CLOCK_MONOTONIC */
- /* Dump attribute. */
- /* Skip prefix & AFI/SAFI for MP_NLRI */
- bgp_dump_routes_attr (obuf, info->attr, &rn->p);
- cur_endp = stream_get_endp (obuf);
- if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
- + BGP_DUMP_HEADER_SIZE)
- {
- stream_set_endp (obuf, endp);
- break;
- }
- entry_count++;
- endp = cur_endp;
- }
- /* Overwrite the entry count, now that we know the right number */
- stream_putw_at (obuf, sizep, entry_count);
- bgp_dump_set_size (obuf, MSG_TABLE_DUMP_V2);
- fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
- return info;
- }
- /* Runs under child process. */
- static unsigned int
- bgp_dump_routes_func (int afi, int first_run, unsigned int seq)
- {
- struct bgp_info *info;
- struct bgp_node *rn;
- struct bgp *bgp;
- struct bgp_table *table;
- bgp = bgp_get_default ();
- if (!bgp)
- return seq;
- if (bgp_dump_routes.fp == NULL)
- return seq;
- /* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers,
- so this should only be done on the first call to bgp_dump_routes_func.
- ( this function will be called once for ipv4 and once for ipv6 ) */
- if(first_run)
- bgp_dump_routes_index_table(bgp);
- /* Walk down each BGP route. */
- table = bgp->rib[afi][SAFI_UNICAST];
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
- {
- info = rn->info;
- while (info)
- {
- info = bgp_dump_route_node_record(afi, rn, info, seq);
- seq++;
- }
- }
- fflush (bgp_dump_routes.fp);
- return seq;
- }
- static int
- bgp_dump_interval_func (struct thread *t)
- {
- struct bgp_dump *bgp_dump;
- bgp_dump = THREAD_ARG (t);
- bgp_dump->t_interval = NULL;
- /* Reschedule dump even if file couldn't be opened this time... */
- if (bgp_dump_open_file (bgp_dump) != NULL)
- {
- /* In case of bgp_dump_routes, we need special route dump function. */
- if (bgp_dump->type == BGP_DUMP_ROUTES)
- {
- unsigned int seq = bgp_dump_routes_func (AFI_IP, 1, 0);
- bgp_dump_routes_func (AFI_IP6, 0, seq);
- /* Close the file now. For a RIB dump there's no point in leaving
- * it open until the next scheduled dump starts. */
- fclose(bgp_dump->fp); bgp_dump->fp = NULL;
- }
- }
- /* if interval is set reschedule */
- if (bgp_dump->interval > 0)
- bgp_dump_interval_add (bgp_dump, bgp_dump->interval);
- return 0;
- }
- /* Dump common information. */
- static void
- bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4)
- {
- char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- /* Source AS number and Destination AS number. */
- if (forceas4 || CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
- {
- stream_putl (obuf, peer->as);
- stream_putl (obuf, peer->local_as);
- }
- else
- {
- stream_putw (obuf, peer->as);
- stream_putw (obuf, peer->local_as);
- }
- if (peer->su.sa.sa_family == AF_INET)
- {
- stream_putw (obuf, peer->ifindex);
- stream_putw (obuf, AFI_IP);
- stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN);
- if (peer->su_local)
- stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN);
- else
- stream_put (obuf, empty, IPV4_MAX_BYTELEN);
- }
- else if (peer->su.sa.sa_family == AF_INET6)
- {
- /* Interface Index and Address family. */
- stream_putw (obuf, peer->ifindex);
- stream_putw (obuf, AFI_IP6);
- /* Source IP Address and Destination IP Address. */
- stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN);
- if (peer->su_local)
- stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN);
- else
- stream_put (obuf, empty, IPV6_MAX_BYTELEN);
- }
- }
- /* Dump BGP status change. */
- void
- bgp_dump_state (struct peer *peer, int status_old, int status_new)
- {
- struct stream *obuf;
- /* If dump file pointer is disabled return immediately. */
- if (bgp_dump_all.fp == NULL)
- return;
- /* Make dump stream. */
- obuf = bgp_dump_obuf;
- stream_reset (obuf);
- bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4,
- bgp_dump_all.type);
- bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/
- stream_putw (obuf, status_old);
- stream_putw (obuf, status_new);
- /* Set length. */
- bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
- /* Write to the stream. */
- fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_all.fp);
- fflush (bgp_dump_all.fp);
- }
- static void
- bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
- struct stream *packet)
- {
- struct stream *obuf;
- /* If dump file pointer is disabled return immediately. */
- if (bgp_dump->fp == NULL)
- return;
- /* Make dump stream. */
- obuf = bgp_dump_obuf;
- stream_reset (obuf);
- /* Dump header and common part. */
- if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
- {
- bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4,
- bgp_dump->type);
- }
- else
- {
- bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE,
- bgp_dump->type);
- }
- bgp_dump_common (obuf, peer, 0);
- /* Packet contents. */
- stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet));
-
- /* Set length. */
- bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
- /* Write to the stream. */
- fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump->fp);
- fflush (bgp_dump->fp);
- }
- /* Called from bgp_packet.c when BGP packet is received. */
- void
- bgp_dump_packet (struct peer *peer, int type, struct stream *packet)
- {
- /* bgp_dump_all. */
- bgp_dump_packet_func (&bgp_dump_all, peer, packet);
- /* bgp_dump_updates. */
- if (type == BGP_MSG_UPDATE)
- bgp_dump_packet_func (&bgp_dump_updates, peer, packet);
- }
- static unsigned int
- bgp_dump_parse_time (const char *str)
- {
- int i;
- int len;
- int seen_h;
- int seen_m;
- int time;
- unsigned int total;
- time = 0;
- total = 0;
- seen_h = 0;
- seen_m = 0;
- len = strlen (str);
- for (i = 0; i < len; i++)
- {
- if (isdigit ((int) str[i]))
- {
- time *= 10;
- time += str[i] - '0';
- }
- else if (str[i] == 'H' || str[i] == 'h')
- {
- if (seen_h)
- return 0;
- if (seen_m)
- return 0;
- total += time * 60 *60;
- time = 0;
- seen_h = 1;
- }
- else if (str[i] == 'M' || str[i] == 'm')
- {
- if (seen_m)
- return 0;
- total += time * 60;
- time = 0;
- seen_h = 1;
- }
- else
- return 0;
- }
- return total + time;
- }
- static int
- bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump,
- enum bgp_dump_type type, const char *path,
- const char *interval_str)
- {
- unsigned int interval;
-
- /* Don't schedule duplicate dumps if the dump command is given twice */
- if (bgp_dump->filename && strcmp(path, bgp_dump->filename) == 0
- && type == bgp_dump->type)
- {
- if (interval_str)
- {
- if (bgp_dump->interval_str &&
- strcmp(bgp_dump->interval_str, interval_str) == 0)
- return CMD_SUCCESS;
- }
- else
- {
- if (!bgp_dump->interval_str)
- return CMD_SUCCESS;
- }
- }
- /* Removing previous config */
- bgp_dump_unset(vty, bgp_dump);
- if (interval_str)
- {
- /* Check interval string. */
- interval = bgp_dump_parse_time (interval_str);
- if (interval == 0)
- {
- vty_out (vty, "Malformed interval string%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- /* Setting interval string */
- bgp_dump->interval_str = strdup (interval_str);
- }
- else
- {
- interval = 0;
- }
- /* Set type. */
- bgp_dump->type = type;
- /* Set interval */
- bgp_dump->interval = interval;
- /* Set file name. */
- bgp_dump->filename = strdup (path);
- /* Create interval thread. */
- bgp_dump_interval_add (bgp_dump, interval);
- /* This should be called when interval is expired. */
- bgp_dump_open_file (bgp_dump);
- return CMD_SUCCESS;
- }
- static int
- bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump)
- {
- /* Removing file name. */
- if (bgp_dump->filename)
- {
- free (bgp_dump->filename);
- bgp_dump->filename = NULL;
- }
- /* Closing file. */
- if (bgp_dump->fp)
- {
- fclose (bgp_dump->fp);
- bgp_dump->fp = NULL;
- }
- /* Removing interval thread. */
- if (bgp_dump->t_interval)
- {
- thread_cancel (bgp_dump->t_interval);
- bgp_dump->t_interval = NULL;
- }
- bgp_dump->interval = 0;
- /* Removing interval string. */
- if (bgp_dump->interval_str)
- {
- free (bgp_dump->interval_str);
- bgp_dump->interval_str = NULL;
- }
-
- return CMD_SUCCESS;
- }
- DEFUN (dump_bgp_all,
- dump_bgp_all_cmd,
- "dump bgp (all|all-et|updates|updates-et|routes-mrt) PATH [INTERVAL]",
- "Dump packet\n"
- "BGP packet dump\n"
- "Dump all BGP packets\nDump all BGP packets (Extended Tiemstamp Header)\n"
- "Dump BGP updates only\nDump BGP updates only (Extended Tiemstamp Header)\n"
- "Dump whole BGP routing table\n"
- "Output filename\n"
- "Interval of output\n")
- {
- int bgp_dump_type = 0;
- const char *interval = NULL;
- struct bgp_dump *bgp_dump_struct = NULL;
- const struct bgp_dump_type_map *map = NULL;
- for (map = bgp_dump_type_map; map->str; map++)
- if (strcmp(argv[0], map->str) == 0)
- bgp_dump_type = map->type;
- switch (bgp_dump_type)
- {
- case BGP_DUMP_ALL:
- case BGP_DUMP_ALL_ET:
- bgp_dump_struct = &bgp_dump_all;
- break;
- case BGP_DUMP_UPDATES:
- case BGP_DUMP_UPDATES_ET:
- bgp_dump_struct = &bgp_dump_updates;
- break;
- case BGP_DUMP_ROUTES:
- default:
- bgp_dump_struct = &bgp_dump_routes;
- break;
- }
- /* When an interval is given */
- if (argc == 3)
- interval = argv[2];
- return bgp_dump_set (vty, bgp_dump_struct, bgp_dump_type,
- argv[1], interval);
- }
- DEFUN (no_dump_bgp_all,
- no_dump_bgp_all_cmd,
- "no dump bgp (all|updates|routes-mrt) [PATH] [INTERVAL]",
- NO_STR
- "Stop dump packet\n"
- "Stop BGP packet dump\n"
- "Stop dump process all/all-et\n"
- "Stop dump process updates/updates-et\n"
- "Stop dump process route-mrt\n")
- {
- return bgp_dump_unset (vty, &bgp_dump_all);
- }
- /* BGP node structure. */
- static struct cmd_node bgp_dump_node =
- {
- DUMP_NODE,
- "",
- 1
- };
- #if 0
- char *
- config_time2str (unsigned int interval)
- {
- static char buf[BUFSIZ];
- buf[0] = '\0';
- if (interval / 3600)
- {
- sprintf (buf, "%dh", interval / 3600);
- interval %= 3600;
- }
- if (interval / 60)
- {
- sprintf (buf + strlen (buf), "%dm", interval /60);
- interval %= 60;
- }
- if (interval)
- {
- sprintf (buf + strlen (buf), "%d", interval);
- }
- return buf;
- }
- #endif
- static int
- config_write_bgp_dump (struct vty *vty)
- {
- if (bgp_dump_all.filename)
- {
- const char *type_str = "all";
- if (bgp_dump_all.type == BGP_DUMP_ALL_ET)
- type_str = "all-et";
- if (bgp_dump_all.interval_str)
- vty_out (vty, "dump bgp %s %s %s%s", type_str,
- bgp_dump_all.filename, bgp_dump_all.interval_str,
- VTY_NEWLINE);
- else
- vty_out (vty, "dump bgp %s %s%s", type_str,
- bgp_dump_all.filename, VTY_NEWLINE);
- }
- if (bgp_dump_updates.filename)
- {
- const char *type_str = "updates";
- if (bgp_dump_updates.type == BGP_DUMP_UPDATES_ET)
- type_str = "updates-et";
- if (bgp_dump_updates.interval_str)
- vty_out (vty, "dump bgp %s %s %s%s", type_str,
- bgp_dump_updates.filename, bgp_dump_updates.interval_str,
- VTY_NEWLINE);
- else
- vty_out (vty, "dump bgp updates %s%s",
- bgp_dump_updates.filename, VTY_NEWLINE);
- }
- if (bgp_dump_routes.filename)
- {
- if (bgp_dump_routes.interval_str)
- vty_out (vty, "dump bgp routes-mrt %s %s%s",
- bgp_dump_routes.filename, bgp_dump_routes.interval_str,
- VTY_NEWLINE);
- }
- return 0;
- }
- /* Initialize BGP packet dump functionality. */
- void
- bgp_dump_init (void)
- {
- memset (&bgp_dump_all, 0, sizeof (struct bgp_dump));
- memset (&bgp_dump_updates, 0, sizeof (struct bgp_dump));
- memset (&bgp_dump_routes, 0, sizeof (struct bgp_dump));
- bgp_dump_obuf = stream_new ((BGP_MAX_PACKET_SIZE << 1)
- + BGP_DUMP_MSG_HEADER + BGP_DUMP_HEADER_SIZE);
- install_node (&bgp_dump_node, config_write_bgp_dump);
- install_element (CONFIG_NODE, &dump_bgp_all_cmd);
- install_element (CONFIG_NODE, &no_dump_bgp_all_cmd);
- }
- void
- bgp_dump_finish (void)
- {
- stream_free (bgp_dump_obuf);
- bgp_dump_obuf = NULL;
- }
|