diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2015-10-24 11:54:51 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2015-10-24 11:54:51 +0000 |
commit | feecf1b0734ee3a96775d9e0e9afd2a9642f02d9 (patch) | |
tree | a6ad1519f7587398ad62d6688c97d761b94ec8e3 /usr.sbin/bgpctl/mrtparser.c | |
parent | b6b7f2a359a0e1e2f9ab38ea790b64cc883f0f1e (diff) |
Implement the missing bits to parse the other MRT message types.
Printing bgp messages is still missing lots but at least it is a start.
I onced abused tcpdump's bgp protocol handler for this but that is an ugly hack.
Diffstat (limited to 'usr.sbin/bgpctl/mrtparser.c')
-rw-r--r-- | usr.sbin/bgpctl/mrtparser.c | 244 |
1 files changed, 232 insertions, 12 deletions
diff --git a/usr.sbin/bgpctl/mrtparser.c b/usr.sbin/bgpctl/mrtparser.c index d8f7cb8e89b..ed6fac41ad9 100644 --- a/usr.sbin/bgpctl/mrtparser.c +++ b/usr.sbin/bgpctl/mrtparser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mrtparser.c,v 1.6 2015/01/09 08:09:39 henning Exp $ */ +/* $OpenBSD: mrtparser.c,v 1.7 2015/10/24 11:54:50 claudio Exp $ */ /* * Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org> * @@ -48,6 +48,9 @@ void mrt_free_bgp_msg(struct mrt_bgp_msg *); u_char *mrt_aspath_inflate(void *, u_int16_t, u_int16_t *); int mrt_extract_addr(void *, u_int, union mrt_addr *, sa_family_t); +struct mrt_bgp_state *mrt_parse_state(struct mrt_hdr *, void *); +struct mrt_bgp_msg *mrt_parse_msg(struct mrt_hdr *, void *); + void * mrt_read_msg(int fd, struct mrt_hdr *hdr) { @@ -91,10 +94,12 @@ mrt_read_buf(int fd, void *buf, size_t len) void mrt_parse(int fd, struct mrt_parser *p, int verbose) { - struct mrt_hdr h; - struct mrt_peer *pctx = NULL; - struct mrt_rib *r; - void *msg; + struct mrt_hdr h; + struct mrt_peer *pctx = NULL; + struct mrt_rib *r; + struct mrt_bgp_state *s; + struct mrt_bgp_msg *m; + void *msg; while ((msg = mrt_read_msg(fd, &h))) { switch (ntohs(h.type)) { @@ -129,7 +134,8 @@ mrt_parse(int fd, struct mrt_parser *p, int verbose) if (p->dump == NULL) break; if (mrt_parse_dump(&h, msg, &pctx, &r) == 0) { - p->dump(r, pctx, p->arg); + if (p->dump) + p->dump(r, pctx, p->arg); mrt_free_rib(r); } break; @@ -158,7 +164,8 @@ mrt_parse(int fd, struct mrt_parser *p, int verbose) break; r = mrt_parse_v2_rib(&h, msg); if (r) { - p->dump(r, pctx, p->arg); + if (p->dump) + p->dump(r, pctx, p->arg); mrt_free_rib(r); } break; @@ -174,22 +181,30 @@ mrt_parse(int fd, struct mrt_parser *p, int verbose) switch (ntohs(h.subtype)) { case BGP4MP_STATE_CHANGE: case BGP4MP_STATE_CHANGE_AS4: - /* XXX p->state(s, p->arg); */ - errx(1, "BGP4MP subtype not yet implemented"); + if ((s = mrt_parse_state(&h, msg))) { + if (p->state) + p->state(s, p->arg); + free(s); + } break; case BGP4MP_MESSAGE: case BGP4MP_MESSAGE_AS4: case BGP4MP_MESSAGE_LOCAL: case BGP4MP_MESSAGE_AS4_LOCAL: - /* XXX p->message(m, p->arg); */ - errx(1, "BGP4MP subtype not yet implemented"); + if ((m = mrt_parse_msg(&h, msg))) { + if (p->message) + p->message(m, p->arg); + free(m->msg); + free(m); + } break; case BGP4MP_ENTRY: if (p->dump == NULL) break; if (mrt_parse_dump_mp(&h, msg, &pctx, &r) == 0) { - p->dump(r, pctx, p->arg); + if (p->dump) + p->dump(r, pctx, p->arg); mrt_free_rib(r); } break; @@ -972,3 +987,208 @@ mrt_extract_addr(void *msg, u_int len, union mrt_addr *addr, sa_family_t af) return (-1); } } + +struct mrt_bgp_state * +mrt_parse_state(struct mrt_hdr *hdr, void *msg) +{ + struct mrt_bgp_state *s; + u_int8_t *b = msg; + u_int len = ntohl(hdr->length); + u_int32_t sas, das; + u_int16_t tmp16, afi; + int r; + sa_family_t af; + + switch (ntohs(hdr->subtype)) { + case BGP4MP_STATE_CHANGE: + if (len < 8) + return (0); + /* source as */ + memcpy(&tmp16, b, sizeof(tmp16)); + b += sizeof(tmp16); + len -= sizeof(tmp16); + sas = ntohs(tmp16); + /* dest as */ + memcpy(&tmp16, b, sizeof(tmp16)); + b += sizeof(tmp16); + len -= sizeof(tmp16); + das = ntohs(tmp16); + /* if_index, ignored */ + b += sizeof(tmp16); + len -= sizeof(tmp16); + /* afi */ + memcpy(&tmp16, b, sizeof(tmp16)); + b += sizeof(tmp16); + len -= sizeof(tmp16); + afi = ntohs(tmp16); + break; + case BGP4MP_STATE_CHANGE_AS4: + if (len < 12) + return (0); + /* source as */ + memcpy(&sas, b, sizeof(sas)); + b += sizeof(sas); + len -= sizeof(sas); + sas = ntohl(sas); + /* dest as */ + memcpy(&das, b, sizeof(das)); + b += sizeof(das); + len -= sizeof(das); + das = ntohl(das); + /* if_index, ignored */ + b += sizeof(tmp16); + len -= sizeof(tmp16); + /* afi */ + memcpy(&tmp16, b, sizeof(tmp16)); + b += sizeof(tmp16); + len -= sizeof(tmp16); + afi = ntohs(tmp16); + break; + default: + errx(1, "mrt_parse_state: bad subtype"); + } + + /* src & dst addr */ + switch (afi) { + case MRT_DUMP_AFI_IP: + af = AF_INET; + break; + case MRT_DUMP_AFI_IPv6: + af = AF_INET6; + break; + default: + errx(1, "mrt_parse_state: bad afi"); + } + + if ((s = calloc(1, sizeof(struct mrt_bgp_state))) == NULL) + err(1, "calloc"); + s->src_as = sas; + s->dst_as = das; + + if ((r = mrt_extract_addr(b, len, &s->src, af)) == -1) + goto fail; + b += r; + len -= r; + if ((r = mrt_extract_addr(b, len, &s->dst, af)) == -1) + goto fail; + b += r; + len -= r; + + /* states */ + memcpy(&tmp16, b, sizeof(tmp16)); + b += sizeof(tmp16); + len -= sizeof(tmp16); + s->old_state = ntohs(tmp16); + memcpy(&tmp16, b, sizeof(tmp16)); + b += sizeof(tmp16); + len -= sizeof(tmp16); + s->new_state = ntohs(tmp16); + + return (s); + +fail: + free(s); + return (NULL); +} + +struct mrt_bgp_msg * +mrt_parse_msg(struct mrt_hdr *hdr, void *msg) +{ + struct mrt_bgp_msg *m; + u_int8_t *b = msg; + u_int len = ntohl(hdr->length); + u_int32_t sas, das; + u_int16_t tmp16, afi; + int r; + sa_family_t af; + + switch (ntohs(hdr->subtype)) { + case BGP4MP_MESSAGE: + if (len < 8) + return (0); + /* source as */ + memcpy(&tmp16, b, sizeof(tmp16)); + b += sizeof(tmp16); + len -= sizeof(tmp16); + sas = ntohs(tmp16); + /* dest as */ + memcpy(&tmp16, b, sizeof(tmp16)); + b += sizeof(tmp16); + len -= sizeof(tmp16); + das = ntohs(tmp16); + /* if_index, ignored */ + b += sizeof(tmp16); + len -= sizeof(tmp16); + /* afi */ + memcpy(&tmp16, b, sizeof(tmp16)); + b += sizeof(tmp16); + len -= sizeof(tmp16); + afi = ntohs(tmp16); + break; + case BGP4MP_MESSAGE_AS4: + if (len < 12) + return (0); + /* source as */ + memcpy(&sas, b, sizeof(sas)); + b += sizeof(sas); + len -= sizeof(sas); + sas = ntohl(sas); + /* dest as */ + memcpy(&das, b, sizeof(das)); + b += sizeof(das); + len -= sizeof(das); + das = ntohl(das); + /* if_index, ignored */ + b += sizeof(tmp16); + len -= sizeof(tmp16); + /* afi */ + memcpy(&tmp16, b, sizeof(tmp16)); + b += sizeof(tmp16); + len -= sizeof(tmp16); + afi = ntohs(tmp16); + break; + default: + errx(1, "mrt_parse_msg: bad subtype"); + } + + /* src & dst addr */ + switch (afi) { + case MRT_DUMP_AFI_IP: + af = AF_INET; + break; + case MRT_DUMP_AFI_IPv6: + af = AF_INET6; + break; + default: + errx(1, "mrt_parse_msg: bad afi"); + } + + if ((m = calloc(1, sizeof(struct mrt_bgp_msg))) == NULL) + err(1, "calloc"); + m->src_as = sas; + m->dst_as = das; + + if ((r = mrt_extract_addr(b, len, &m->src, af)) == -1) + goto fail; + b += r; + len -= r; + if ((r = mrt_extract_addr(b, len, &m->dst, af)) == -1) + goto fail; + b += r; + len -= r; + + /* msg */ + if (len > 0) { + m->msg_len = len; + if ((m->msg = malloc(len)) == NULL) + err(1, "malloc"); + memcpy(m->msg, b, len); + } + + return (m); + +fail: + free(m->msg); + free(m); + return (NULL); +} |