blob: edc80b2fe616781c3d9a93d64ee8e8a93765969f [file] [log] [blame]
/* 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_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;
}