diff options
Diffstat (limited to 'bgpd/bgp_btoa.c')
-rw-r--r-- | bgpd/bgp_btoa.c | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c new file mode 100644 index 0000000..8e27d97 --- /dev/null +++ b/bgpd/bgp_btoa.c @@ -0,0 +1,276 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* BGP dump to ascii converter + * Copyright (C) 1999 Kunihiro Ishiguro + */ + +#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 "filter.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(FRR_USER) && defined(FRR_GROUP) + .user = FRR_USER, + .group = FRR_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 void attr_parse(struct stream *s, uint16_t len) +{ + unsigned int flag; + unsigned int type; + uint16_t length; + uint16_t lim; + + lim = s->getp + len; + + printf("%s s->getp %zd, len %d, lim %d\n", __func__, 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: { + uint8_t 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, + bgp_get_asnotation(NULL)); + 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: %pI4\n", &nexthop); + } break; + default: + stream_getw_from(s, length); + break; + } + } +} + +int main(int argc, char **argv) +{ + int ret; + int fd; + struct stream *s; + time_t now; + int type; + int subtype; + size_t len; + int source_as; + int dest_as; + ifindex_t ifindex; + int family; + struct in_addr sip; + struct in_addr dip; + uint16_t viewno, seq_num; + struct prefix_ipv4 p; + char tbuf[32]; + + s = stream_new(10000); + + if (argc != 2) { + fprintf(stderr, "Usage: %s FILENAME\n", argv[0]); + exit(1); + } + fd = open(argv[1], O_RDONLY); + if (fd < 0) { + fprintf(stdout, + "%% Can't open configuration file %s due to '%s'.\n", + argv[1], safe_strerror(errno)); + exit(1); + } + + while (1) { + stream_reset(s); + + ret = stream_read(s, fd, 12); + if (ret != 12) { + if (!ret) + printf("END OF FILE\n"); + else if (ret < 0) + printf("ERROR OF READ\n"); + else + printf("UNDERFLOW\n"); + break; + } + + /* Extract header. */ + now = stream_getl(s); + type = stream_getw(s); + subtype = stream_getw(s); + len = stream_getl(s); + + printf("TIME: %s", ctime_r(&now, tbuf)); + + /* 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 = stream_read(s, fd, len); + if (ret != (int)len) { + if (!ret) + printf("END OF FILE 2\n"); + else if (ret < 0) + printf("ERROR OF READ 2\n"); + else + printf("UNDERFLOW 2\n"); + break; + } + + /* printf ("now read %d\n", len); */ + + if (type == MSG_TABLE_DUMP) { + uint8_t status; + time_t originated; + struct in_addr peer; + uint16_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: %pI4/%d\n", &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: %pI4 AS%d\n", &peer, source_as); + printf("ORIGINATED: %s", ctime_r(&originated, + tbuf)); + + 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: %pI4\n", &sip); + printf("daddr: %pI4\n", &dip); + + printf("\n"); + } + } + close(fd); + return 0; +} |