| /* BGP dump to ascii converter |
| 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 "zebra.h" |
| #include "stream.h" |
| #include "log.h" |
| #include "prefix.h" |
| #include "command.h" |
| #include "memory.h" |
| #include "privs.h" |
| |
| #include "bgpd/bgpd.h" |
| #include "bgpd/bgp_dump.h" |
| #include "bgpd/bgp_attr.h" |
| #include "bgpd/bgp_aspath.h" |
| |
| /* privileges */ |
| static zebra_capabilities_t _caps_p [] = |
| { |
| ZCAP_BIND, |
| ZCAP_NET_RAW, |
| ZCAP_NET_ADMIN, |
| }; |
| |
| struct zebra_privs_t bgpd_privs = |
| { |
| #if defined(QUAGGA_USER) && defined(QUAGGA_GROUP) |
| .user = QUAGGA_USER, |
| .group = QUAGGA_GROUP, |
| #endif |
| #ifdef VTY_GROUP |
| .vty_group = VTY_GROUP, |
| #endif |
| .caps_p = _caps_p, |
| .cap_num_p = array_size(_caps_p), |
| .cap_num_i = 0, |
| }; |
| |
| 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 */ |
| }; |
| |
| static int |
| attr_parse (struct stream *s, u_int16_t len) |
| { |
| u_int flag; |
| u_int type; |
| u_int16_t length; |
| u_int16_t lim; |
| |
| lim = s->getp + len; |
| |
| printf ("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim); |
| |
| while (s->getp < lim) |
| { |
| flag = stream_getc (s); |
| type = stream_getc (s); |
| |
| if (flag & BGP_ATTR_FLAG_EXTLEN) |
| length = stream_getw (s); |
| else |
| length = stream_getc (s); |
| |
| printf ("FLAG: %d\n", flag); |
| printf ("TYPE: %d\n", type); |
| printf ("Len: %d\n", length); |
| |
| switch (type) |
| { |
| case BGP_ATTR_ORIGIN: |
| { |
| u_char origin; |
| origin = stream_getc (s); |
| printf ("ORIGIN: %d\n", origin); |
| } |
| break; |
| case BGP_ATTR_AS_PATH: |
| { |
| struct aspath *aspath; |
| |
| aspath = aspath_parse (s, length, 1); |
| printf ("ASPATH: %s\n", aspath->str); |
| aspath_free(aspath); |
| } |
| break; |
| case BGP_ATTR_NEXT_HOP: |
| { |
| struct in_addr nexthop; |
| nexthop.s_addr = stream_get_ipv4 (s); |
| printf ("NEXTHOP: %s\n", inet_ntoa (nexthop)); |
| } |
| break; |
| default: |
| stream_getw_from (s, length); |
| break; |
| } |
| } |
| |
| return 0; |
| } |
| |
| int |
| main (int argc, char **argv) |
| { |
| int ret; |
| FILE *fp; |
| struct stream *s; |
| time_t now; |
| int type; |
| int subtype; |
| size_t len; |
| int source_as; |
| int dest_as; |
| int ifindex; |
| int family; |
| struct in_addr sip; |
| struct in_addr dip; |
| u_int16_t viewno, seq_num; |
| struct prefix_ipv4 p; |
| |
| s = stream_new (10000); |
| |
| if (argc != 2) |
| { |
| fprintf (stderr, "Usage: %s FILENAME\n", argv[0]); |
| exit (1); |
| } |
| fp = fopen (argv[1], "r"); |
| if (!fp) |
| { |
| perror ("fopen"); |
| exit (1); |
| } |
| |
| while (1) |
| { |
| stream_reset (s); |
| |
| ret = fread (s->data, 12, 1, fp); |
| if (!ret || feof (fp)) |
| { |
| printf ("END OF FILE\n"); |
| break; |
| } |
| if (ferror (fp)) |
| { |
| printf ("ERROR OF FREAD\n"); |
| break; |
| } |
| |
| /* Extract header. */ |
| now = stream_getl (s); |
| type = stream_getw (s); |
| subtype = stream_getw (s); |
| len = stream_getl (s); |
| |
| printf ("TIME: %s", ctime (&now)); |
| |
| /* printf ("TYPE: %d/%d\n", type, subtype); */ |
| |
| if (type == MSG_PROTOCOL_BGP4MP) |
| printf ("TYPE: BGP4MP"); |
| else if (type == MSG_PROTOCOL_BGP4MP_ET) |
| printf ("TYPE: BGP4MP_ET"); |
| else if (type == MSG_TABLE_DUMP) |
| printf ("TYPE: MSG_TABLE_DUMP"); |
| else |
| printf ("TYPE: Unknown %d", type); |
| |
| if (type == MSG_TABLE_DUMP) |
| switch (subtype) |
| { |
| case AFI_IP: |
| printf ("/AFI_IP\n"); |
| break; |
| case AFI_IP6: |
| printf ("/AFI_IP6\n"); |
| break; |
| default: |
| printf ("/UNKNOWN %d", subtype); |
| break; |
| } |
| else |
| { |
| switch (subtype) |
| { |
| case BGP4MP_STATE_CHANGE: |
| printf ("/CHANGE\n"); |
| break; |
| case BGP4MP_MESSAGE: |
| printf ("/MESSAGE\n"); |
| break; |
| case BGP4MP_ENTRY: |
| printf ("/ENTRY\n"); |
| break; |
| case BGP4MP_SNAPSHOT: |
| printf ("/SNAPSHOT\n"); |
| break; |
| default: |
| printf ("/UNKNOWN %d", subtype); |
| break; |
| } |
| } |
| |
| printf ("len: %zd\n", len); |
| |
| ret = fread (s->data + 12, len, 1, fp); |
| if (feof (fp)) |
| { |
| printf ("ENDOF FILE 2\n"); |
| break; |
| } |
| if (ferror (fp)) |
| { |
| printf ("ERROR OF FREAD 2\n"); |
| break; |
| } |
| |
| /* printf ("now read %d\n", len); */ |
| |
| if (type == MSG_TABLE_DUMP) |
| { |
| u_char status; |
| time_t originated; |
| struct in_addr peer; |
| u_int16_t attrlen; |
| |
| viewno = stream_getw (s); |
| seq_num = stream_getw (s); |
| printf ("VIEW: %d\n", viewno); |
| printf ("SEQUENCE: %d\n", seq_num); |
| |
| /* start */ |
| while (s->getp < len - 16) |
| { |
| p.prefix.s_addr = stream_get_ipv4 (s); |
| p.prefixlen = stream_getc (s); |
| printf ("PREFIX: %s/%d\n", inet_ntoa (p.prefix), p.prefixlen); |
| |
| status = stream_getc (s); |
| originated = stream_getl (s); |
| peer.s_addr = stream_get_ipv4 (s); |
| source_as = stream_getw(s); |
| |
| printf ("FROM: %s AS%d\n", inet_ntoa (peer), source_as); |
| printf ("ORIGINATED: %s", ctime (&originated)); |
| |
| attrlen = stream_getw (s); |
| printf ("ATTRLEN: %d\n", attrlen); |
| |
| attr_parse (s, attrlen); |
| |
| printf ("STATUS: 0x%x\n", status); |
| } |
| } |
| else |
| { |
| source_as = stream_getw (s); |
| dest_as = stream_getw (s); |
| printf ("source_as: %d\n", source_as); |
| printf ("dest_as: %d\n", dest_as); |
| |
| ifindex = stream_getw (s); |
| family = stream_getw (s); |
| |
| printf ("ifindex: %d\n", ifindex); |
| printf ("family: %d\n", family); |
| |
| sip.s_addr = stream_get_ipv4 (s); |
| dip.s_addr = stream_get_ipv4 (s); |
| |
| printf ("saddr: %s\n", inet_ntoa (sip)); |
| printf ("daddr: %s\n", inet_ntoa (dip)); |
| |
| printf ("\n"); |
| } |
| } |
| fclose (fp); |
| return 0; |
| } |