Annotation of embedaddon/quagga/bgpd/bgp_dump.c, revision 1.1
1.1 ! misho 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: 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: time (&clock);
! 105: tm = localtime (&clock);
! 106:
! 107: if (bgp_dump->filename[0] != DIRECTORY_SEP)
! 108: {
! 109: sprintf (fullpath, "%s/%s", vty_get_cwd (), bgp_dump->filename);
! 110: ret = strftime (realpath, MAXPATHLEN, fullpath, tm);
! 111: }
! 112: else
! 113: ret = strftime (realpath, MAXPATHLEN, bgp_dump->filename, tm);
! 114:
! 115: if (ret == 0)
! 116: {
! 117: zlog_warn ("bgp_dump_open_file: strftime error");
! 118: return NULL;
! 119: }
! 120:
! 121: if (bgp_dump->fp)
! 122: fclose (bgp_dump->fp);
! 123:
! 124:
! 125: oldumask = umask(0777 & ~LOGFILE_MASK);
! 126: bgp_dump->fp = fopen (realpath, "w");
! 127:
! 128: if (bgp_dump->fp == NULL)
! 129: {
! 130: zlog_warn ("bgp_dump_open_file: %s: %s", realpath, strerror (errno));
! 131: umask(oldumask);
! 132: return NULL;
! 133: }
! 134: umask(oldumask);
! 135:
! 136: return bgp_dump->fp;
! 137: }
! 138:
! 139: static int
! 140: 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: if (interval > 0)
! 147: {
! 148: /* Periodic dump every interval seconds */
! 149: 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: (void) time(&t);
! 155: tm = localtime(&t);
! 156: secs_into_day = tm->tm_sec + 60*tm->tm_min + 60*60*tm->tm_hour;
! 157: interval = interval - secs_into_day % interval; /* always > 0 */
! 158: }
! 159: 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: bgp_dump->t_interval = thread_add_event (master, bgp_dump_interval_func,
! 166: bgp_dump, 0);
! 167: }
! 168:
! 169: return 0;
! 170: }
! 171:
! 172: /* Dump common header. */
! 173: static void
! 174: bgp_dump_header (struct stream *obuf, int type, int subtype)
! 175: {
! 176: time_t now;
! 177:
! 178: /* Set header. */
! 179: time (&now);
! 180:
! 181: /* Put dump packet header. */
! 182: stream_putl (obuf, now);
! 183: stream_putw (obuf, type);
! 184: stream_putw (obuf, subtype);
! 185:
! 186: stream_putl (obuf, 0); /* len */
! 187: }
! 188:
! 189: static void
! 190: bgp_dump_set_size (struct stream *s, int type)
! 191: {
! 192: stream_putl_at (s, 8, stream_get_endp (s) - BGP_DUMP_HEADER_SIZE);
! 193: }
! 194:
! 195: static void
! 196: bgp_dump_routes_index_table(struct bgp *bgp)
! 197: {
! 198: struct peer *peer;
! 199: struct listnode *node;
! 200: uint16_t peerno = 0;
! 201: struct stream *obuf;
! 202:
! 203: obuf = bgp_dump_obuf;
! 204: stream_reset (obuf);
! 205:
! 206: /* MRT header */
! 207: bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE);
! 208:
! 209: /* Collector BGP ID */
! 210: stream_put_in_addr (obuf, &bgp->router_id);
! 211:
! 212: /* View name */
! 213: if(bgp->name)
! 214: {
! 215: stream_putw (obuf, strlen(bgp->name));
! 216: stream_put(obuf, bgp->name, strlen(bgp->name));
! 217: }
! 218: else
! 219: {
! 220: stream_putw(obuf, 0);
! 221: }
! 222:
! 223: /* Peer count */
! 224: stream_putw (obuf, listcount(bgp->peer));
! 225:
! 226: /* Walk down all peers */
! 227: for(ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
! 228: {
! 229:
! 230: /* Peer's type */
! 231: if (sockunion_family(&peer->su) == AF_INET)
! 232: {
! 233: stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP);
! 234: }
! 235: #ifdef HAVE_IPV6
! 236: else if (sockunion_family(&peer->su) == AF_INET6)
! 237: {
! 238: 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: stream_put_in_addr (obuf, &peer->remote_id);
! 244:
! 245: /* Peer's IP address */
! 246: if (sockunion_family(&peer->su) == AF_INET)
! 247: {
! 248: stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
! 249: }
! 250: #ifdef HAVE_IPV6
! 251: else if (sockunion_family(&peer->su) == AF_INET6)
! 252: {
! 253: 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: stream_putl (obuf, peer->as);
! 261:
! 262: /* Store the peer number for this peer */
! 263: peer->table_dump_index = peerno;
! 264: peerno++;
! 265: }
! 266:
! 267: bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
! 268:
! 269: fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
! 270: fflush (bgp_dump_routes.fp);
! 271: }
! 272:
! 273:
! 274: /* Runs under child process. */
! 275: static unsigned int
! 276: 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: bgp = bgp_get_default ();
! 285: if (!bgp)
! 286: return seq;
! 287:
! 288: if (bgp_dump_routes.fp == NULL)
! 289: 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: if(first_run)
! 295: bgp_dump_routes_index_table(bgp);
! 296:
! 297: obuf = bgp_dump_obuf;
! 298: stream_reset(obuf);
! 299:
! 300: /* Walk down each BGP route. */
! 301: table = bgp->rib[afi][SAFI_UNICAST];
! 302:
! 303: for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
! 304: {
! 305: if(!rn->info)
! 306: continue;
! 307:
! 308: stream_reset(obuf);
! 309:
! 310: /* MRT header */
! 311: if (afi == AFI_IP)
! 312: {
! 313: bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST);
! 314: }
! 315: #ifdef HAVE_IPV6
! 316: else if (afi == AFI_IP6)
! 317: {
! 318: bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST);
! 319: }
! 320: #endif /* HAVE_IPV6 */
! 321:
! 322: /* Sequence number */
! 323: stream_putl(obuf, seq);
! 324:
! 325: /* Prefix length */
! 326: stream_putc (obuf, rn->p.prefixlen);
! 327:
! 328: /* Prefix */
! 329: if (afi == AFI_IP)
! 330: {
! 331: /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */
! 332: stream_write(obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8);
! 333: }
! 334: #ifdef HAVE_IPV6
! 335: 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: 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: int sizep = stream_get_endp(obuf);
! 344:
! 345: /* Entry count */
! 346: uint16_t entry_count = 0;
! 347:
! 348: /* Entry count, note that this is overwritten later */
! 349: stream_putw(obuf, 0);
! 350:
! 351: for (info = rn->info; info; info = info->next)
! 352: {
! 353: entry_count++;
! 354:
! 355: /* Peer index */
! 356: stream_putw(obuf, info->peer->table_dump_index);
! 357:
! 358: /* Originated */
! 359: #ifdef HAVE_CLOCK_MONOTONIC
! 360: 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: bgp_dump_routes_attr (obuf, info->attr, &rn->p);
! 368: }
! 369:
! 370: /* Overwrite the entry count, now that we know the right number */
! 371: stream_putw_at (obuf, sizep, entry_count);
! 372:
! 373: seq++;
! 374:
! 375: bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);
! 376: fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
! 377:
! 378: }
! 379:
! 380: fflush (bgp_dump_routes.fp);
! 381:
! 382: return seq;
! 383: }
! 384:
! 385: static int
! 386: bgp_dump_interval_func (struct thread *t)
! 387: {
! 388: struct bgp_dump *bgp_dump;
! 389: bgp_dump = THREAD_ARG (t);
! 390: bgp_dump->t_interval = NULL;
! 391:
! 392: /* Reschedule dump even if file couldn't be opened this time... */
! 393: if (bgp_dump_open_file (bgp_dump) != NULL)
! 394: {
! 395: /* In case of bgp_dump_routes, we need special route dump function. */
! 396: if (bgp_dump->type == BGP_DUMP_ROUTES)
! 397: {
! 398: unsigned int seq = bgp_dump_routes_func (AFI_IP, 1, 0);
! 399: #ifdef HAVE_IPV6
! 400: 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: fclose(bgp_dump->fp); bgp_dump->fp = NULL;
! 405: }
! 406: }
! 407:
! 408: /* if interval is set reschedule */
! 409: if (bgp_dump->interval > 0)
! 410: bgp_dump_interval_add (bgp_dump, bgp_dump->interval);
! 411:
! 412: return 0;
! 413: }
! 414:
! 415: /* Dump common information. */
! 416: static void
! 417: bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4)
! 418: {
! 419: 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: if (forceas4 || CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
! 423: {
! 424: stream_putl (obuf, peer->as);
! 425: stream_putl (obuf, peer->local_as);
! 426: }
! 427: else
! 428: {
! 429: stream_putw (obuf, peer->as);
! 430: stream_putw (obuf, peer->local_as);
! 431: }
! 432:
! 433: if (peer->su.sa.sa_family == AF_INET)
! 434: {
! 435: stream_putw (obuf, peer->ifindex);
! 436: stream_putw (obuf, AFI_IP);
! 437:
! 438: stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN);
! 439:
! 440: if (peer->su_local)
! 441: stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN);
! 442: else
! 443: stream_put (obuf, empty, IPV4_MAX_BYTELEN);
! 444: }
! 445: #ifdef HAVE_IPV6
! 446: else if (peer->su.sa.sa_family == AF_INET6)
! 447: {
! 448: /* Interface Index and Address family. */
! 449: stream_putw (obuf, peer->ifindex);
! 450: stream_putw (obuf, AFI_IP6);
! 451:
! 452: /* Source IP Address and Destination IP Address. */
! 453: stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN);
! 454:
! 455: if (peer->su_local)
! 456: stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN);
! 457: else
! 458: stream_put (obuf, empty, IPV6_MAX_BYTELEN);
! 459: }
! 460: #endif /* HAVE_IPV6 */
! 461: }
! 462:
! 463: /* Dump BGP status change. */
! 464: void
! 465: 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: if (bgp_dump_all.fp == NULL)
! 471: return;
! 472:
! 473: /* Make dump stream. */
! 474: obuf = bgp_dump_obuf;
! 475: stream_reset (obuf);
! 476:
! 477: bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4);
! 478: bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/
! 479:
! 480: stream_putw (obuf, status_old);
! 481: stream_putw (obuf, status_new);
! 482:
! 483: /* Set length. */
! 484: bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
! 485:
! 486: /* Write to the stream. */
! 487: fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_all.fp);
! 488: fflush (bgp_dump_all.fp);
! 489: }
! 490:
! 491: static void
! 492: 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: if (bgp_dump->fp == NULL)
! 499: return;
! 500:
! 501: /* Make dump stream. */
! 502: obuf = bgp_dump_obuf;
! 503: stream_reset (obuf);
! 504:
! 505: /* Dump header and common part. */
! 506: if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
! 507: {
! 508: bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4);
! 509: }
! 510: else
! 511: {
! 512: bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE);
! 513: }
! 514: bgp_dump_common (obuf, peer, 0);
! 515:
! 516: /* Packet contents. */
! 517: stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet));
! 518:
! 519: /* Set length. */
! 520: bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
! 521:
! 522: /* Write to the stream. */
! 523: fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump->fp);
! 524: fflush (bgp_dump->fp);
! 525: }
! 526:
! 527: /* Called from bgp_packet.c when BGP packet is received. */
! 528: void
! 529: bgp_dump_packet (struct peer *peer, int type, struct stream *packet)
! 530: {
! 531: /* bgp_dump_all. */
! 532: bgp_dump_packet_func (&bgp_dump_all, peer, packet);
! 533:
! 534: /* bgp_dump_updates. */
! 535: if (type == BGP_MSG_UPDATE)
! 536: bgp_dump_packet_func (&bgp_dump_updates, peer, packet);
! 537: }
! 538:
! 539: static unsigned int
! 540: 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: time = 0;
! 550: total = 0;
! 551: seen_h = 0;
! 552: seen_m = 0;
! 553: len = strlen (str);
! 554:
! 555: for (i = 0; i < len; i++)
! 556: {
! 557: if (isdigit ((int) str[i]))
! 558: {
! 559: time *= 10;
! 560: time += str[i] - '0';
! 561: }
! 562: else if (str[i] == 'H' || str[i] == 'h')
! 563: {
! 564: if (seen_h)
! 565: return 0;
! 566: if (seen_m)
! 567: return 0;
! 568: total += time * 60 *60;
! 569: time = 0;
! 570: seen_h = 1;
! 571: }
! 572: else if (str[i] == 'M' || str[i] == 'm')
! 573: {
! 574: if (seen_m)
! 575: return 0;
! 576: total += time * 60;
! 577: time = 0;
! 578: seen_h = 1;
! 579: }
! 580: else
! 581: return 0;
! 582: }
! 583: return total + time;
! 584: }
! 585:
! 586: static int
! 587: 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: if (interval_str)
! 594: {
! 595:
! 596: /* Check interval string. */
! 597: interval = bgp_dump_parse_time (interval_str);
! 598: if (interval == 0)
! 599: {
! 600: vty_out (vty, "Malformed interval string%s", VTY_NEWLINE);
! 601: return CMD_WARNING;
! 602: }
! 603:
! 604: /* Don't schedule duplicate dumps if the dump command is given twice */
! 605: if (interval == bgp_dump->interval &&
! 606: type == bgp_dump->type &&
! 607: path && bgp_dump->filename && !strcmp (path, bgp_dump->filename))
! 608: {
! 609: return CMD_SUCCESS;
! 610: }
! 611:
! 612: /* Set interval. */
! 613: bgp_dump->interval = interval;
! 614: if (bgp_dump->interval_str)
! 615: free (bgp_dump->interval_str);
! 616: bgp_dump->interval_str = strdup (interval_str);
! 617:
! 618: }
! 619: else
! 620: {
! 621: interval = 0;
! 622: }
! 623:
! 624: /* Create interval thread. */
! 625: bgp_dump_interval_add (bgp_dump, interval);
! 626:
! 627: /* Set type. */
! 628: bgp_dump->type = type;
! 629:
! 630: /* Set file name. */
! 631: if (bgp_dump->filename)
! 632: free (bgp_dump->filename);
! 633: bgp_dump->filename = strdup (path);
! 634:
! 635: /* This should be called when interval is expired. */
! 636: bgp_dump_open_file (bgp_dump);
! 637:
! 638: return CMD_SUCCESS;
! 639: }
! 640:
! 641: static int
! 642: bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump)
! 643: {
! 644: /* Set file name. */
! 645: if (bgp_dump->filename)
! 646: {
! 647: free (bgp_dump->filename);
! 648: bgp_dump->filename = NULL;
! 649: }
! 650:
! 651: /* This should be called when interval is expired. */
! 652: if (bgp_dump->fp)
! 653: {
! 654: fclose (bgp_dump->fp);
! 655: bgp_dump->fp = NULL;
! 656: }
! 657:
! 658: /* Create interval thread. */
! 659: if (bgp_dump->t_interval)
! 660: {
! 661: thread_cancel (bgp_dump->t_interval);
! 662: bgp_dump->t_interval = NULL;
! 663: }
! 664:
! 665: bgp_dump->interval = 0;
! 666:
! 667: if (bgp_dump->interval_str)
! 668: {
! 669: free (bgp_dump->interval_str);
! 670: bgp_dump->interval_str = NULL;
! 671: }
! 672:
! 673:
! 674: return CMD_SUCCESS;
! 675: }
! 676:
! 677: 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: return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], NULL);
! 686: }
! 687:
! 688: 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: return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], argv[1]);
! 698: }
! 699:
! 700: 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: return bgp_dump_unset (vty, &bgp_dump_all);
! 709: }
! 710:
! 711: 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: return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], NULL);
! 720: }
! 721:
! 722: 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: return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], argv[1]);
! 732: }
! 733:
! 734: 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: return bgp_dump_unset (vty, &bgp_dump_updates);
! 743: }
! 744:
! 745: 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: return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], NULL);
! 754: }
! 755:
! 756: 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: return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], argv[1]);
! 766: }
! 767:
! 768: 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: 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: config_write_bgp_dump (struct vty *vty)
! 815: {
! 816: if (bgp_dump_all.filename)
! 817: {
! 818: if (bgp_dump_all.interval_str)
! 819: vty_out (vty, "dump bgp all %s %s%s",
! 820: bgp_dump_all.filename, bgp_dump_all.interval_str,
! 821: VTY_NEWLINE);
! 822: else
! 823: vty_out (vty, "dump bgp all %s%s",
! 824: bgp_dump_all.filename, VTY_NEWLINE);
! 825: }
! 826: if (bgp_dump_updates.filename)
! 827: {
! 828: if (bgp_dump_updates.interval_str)
! 829: vty_out (vty, "dump bgp updates %s %s%s",
! 830: bgp_dump_updates.filename, bgp_dump_updates.interval_str,
! 831: VTY_NEWLINE);
! 832: else
! 833: vty_out (vty, "dump bgp updates %s%s",
! 834: bgp_dump_updates.filename, VTY_NEWLINE);
! 835: }
! 836: if (bgp_dump_routes.filename)
! 837: {
! 838: if (bgp_dump_routes.interval_str)
! 839: vty_out (vty, "dump bgp routes-mrt %s %s%s",
! 840: bgp_dump_routes.filename, bgp_dump_routes.interval_str,
! 841: VTY_NEWLINE);
! 842: else
! 843: vty_out (vty, "dump bgp routes-mrt %s%s",
! 844: bgp_dump_routes.filename, VTY_NEWLINE);
! 845: }
! 846: return 0;
! 847: }
! 848:
! 849: /* Initialize BGP packet dump functionality. */
! 850: void
! 851: bgp_dump_init (void)
! 852: {
! 853: memset (&bgp_dump_all, 0, sizeof (struct bgp_dump));
! 854: memset (&bgp_dump_updates, 0, sizeof (struct bgp_dump));
! 855: memset (&bgp_dump_routes, 0, sizeof (struct bgp_dump));
! 856:
! 857: bgp_dump_obuf = stream_new (BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
! 858: + BGP_DUMP_HEADER_SIZE);
! 859:
! 860: install_node (&bgp_dump_node, config_write_bgp_dump);
! 861:
! 862: install_element (CONFIG_NODE, &dump_bgp_all_cmd);
! 863: install_element (CONFIG_NODE, &dump_bgp_all_interval_cmd);
! 864: install_element (CONFIG_NODE, &no_dump_bgp_all_cmd);
! 865: install_element (CONFIG_NODE, &dump_bgp_updates_cmd);
! 866: install_element (CONFIG_NODE, &dump_bgp_updates_interval_cmd);
! 867: install_element (CONFIG_NODE, &no_dump_bgp_updates_cmd);
! 868: install_element (CONFIG_NODE, &dump_bgp_routes_cmd);
! 869: install_element (CONFIG_NODE, &dump_bgp_routes_interval_cmd);
! 870: install_element (CONFIG_NODE, &no_dump_bgp_routes_cmd);
! 871: }
! 872:
! 873: void
! 874: bgp_dump_finish (void)
! 875: {
! 876: stream_free (bgp_dump_obuf);
! 877: bgp_dump_obuf = NULL;
! 878: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>