LCOV - code coverage report
Current view: top level - bgpd - bgp_dump.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 291 0.0 %
Date: 2015-11-19 Functions: 0 26 0.0 %

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

Generated by: LCOV version 1.10