summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpctl/mrtparser.c117
1 files changed, 57 insertions, 60 deletions
diff --git a/usr.sbin/bgpctl/mrtparser.c b/usr.sbin/bgpctl/mrtparser.c
index d1dcef51de1..f6b4602eaa8 100644
--- a/usr.sbin/bgpctl/mrtparser.c
+++ b/usr.sbin/bgpctl/mrtparser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrtparser.c,v 1.2 2012/03/06 07:52:32 claudio Exp $ */
+/* $OpenBSD: mrtparser.c,v 1.3 2012/03/26 20:40:32 claudio Exp $ */
/*
* Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org>
*
@@ -46,6 +46,7 @@ void mrt_free_bgp_state(struct mrt_bgp_state *);
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);
void *
mrt_read_msg(int fd, struct mrt_hdr *hdr)
@@ -125,6 +126,8 @@ mrt_parse(int fd, struct mrt_parser *p, int verbose)
switch (ntohs(h.subtype)) {
case MRT_DUMP_AFI_IP:
case MRT_DUMP_AFI_IPv6:
+ if (p->dump == NULL)
+ break;
if (mrt_parse_dump(&h, msg, &pctx, &r) == 0) {
p->dump(r, pctx, p->arg);
mrt_free_rib(r);
@@ -140,6 +143,8 @@ mrt_parse(int fd, struct mrt_parser *p, int verbose)
case MSG_TABLE_DUMP_V2:
switch (ntohs(h.subtype)) {
case MRT_DUMP_V2_PEER_INDEX_TABLE:
+ if (p->dump == NULL)
+ break;
if (pctx)
mrt_free_peers(pctx);
pctx = mrt_parse_v2_peer(&h, msg);
@@ -149,6 +154,8 @@ mrt_parse(int fd, struct mrt_parser *p, int verbose)
case MRT_DUMP_V2_RIB_IPV6_UNICAST:
case MRT_DUMP_V2_RIB_IPV6_MULTICAST:
case MRT_DUMP_V2_RIB_GENERIC:
+ if (p->dump == NULL)
+ break;
r = mrt_parse_v2_rib(&h, msg);
if (r) {
p->dump(r, pctx, p->arg);
@@ -182,6 +189,8 @@ mrt_parse(int fd, struct mrt_parser *p, int verbose)
errx(1, "BGP4MP subtype not yet implemented");
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);
@@ -273,22 +282,15 @@ mrt_parse_v2_peer(struct mrt_hdr *hdr, void *msg)
peers[i].bgp_id = ntohl(bid);
if (type & MRT_DUMP_V2_PEER_BIT_I) {
- if (len < sizeof(struct in6_addr))
+ if (mrt_extract_addr(b, len, &peers[i].addr,
+ AF_INET6) == -1)
goto fail;
- peers[i].addr.sin6.sin6_len =
- sizeof(struct sockaddr_in6);
- peers[i].addr.sin6.sin6_family = AF_INET6;
- memcpy(&peers[i].addr.sin6.sin6_addr, b,
- sizeof(struct in6_addr));
b += sizeof(struct in6_addr);
len -= sizeof(struct in6_addr);
} else {
- if (len < sizeof(struct in_addr))
+ if (mrt_extract_addr(b, len, &peers[i].addr,
+ AF_INET) == -1)
goto fail;
- peers[i].addr.sin.sin_len = sizeof(struct sockaddr_in);
- peers[i].addr.sin.sin_family = AF_INET;
- memcpy(&peers[i].addr.sin.sin_addr, b,
- sizeof(struct in_addr));
b += sizeof(struct in_addr);
len -= sizeof(struct in_addr);
}
@@ -466,20 +468,14 @@ mrt_parse_dump(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
switch (ntohs(hdr->subtype)) {
case MRT_DUMP_AFI_IP:
- if (len < sizeof(struct in_addr))
+ if (mrt_extract_addr(b, len, &r->prefix, AF_INET) == -1)
goto fail;
- r->prefix.sin.sin_family = AF_INET;
- r->prefix.sin.sin_len = sizeof(struct sockaddr_in);
- memcpy(&r->prefix.sin.sin_addr, b, sizeof(struct in_addr));
b += sizeof(struct in_addr);
len -= sizeof(struct in_addr);
break;
case MRT_DUMP_AFI_IPv6:
- if (len < sizeof(struct in6_addr))
+ if (mrt_extract_addr(b, len, &r->prefix, AF_INET6) == -1)
goto fail;
- r->prefix.sin6.sin6_family = AF_INET6;
- r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6);
- memcpy(&r->prefix.sin6.sin6_addr, b, sizeof(struct in6_addr));
b += sizeof(struct in6_addr);
len -= sizeof(struct in6_addr);
break;
@@ -499,21 +495,14 @@ mrt_parse_dump(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
/* peer ip */
switch (ntohs(hdr->subtype)) {
case MRT_DUMP_AFI_IP:
- if (len < sizeof(struct in_addr))
+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1)
goto fail;
- p->peers->addr.sin.sin_family = AF_INET;
- p->peers->addr.sin.sin_len = sizeof(struct sockaddr_in);
- memcpy(&p->peers->addr.sin.sin_addr, b, sizeof(struct in_addr));
b += sizeof(struct in_addr);
len -= sizeof(struct in_addr);
break;
case MRT_DUMP_AFI_IPv6:
- if (len < sizeof(struct in6_addr))
+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1)
goto fail;
- p->peers->addr.sin6.sin6_family = AF_INET6;
- p->peers->addr.sin6.sin6_len = sizeof(struct sockaddr_in6);
- memcpy(&p->peers->addr.sin6.sin6_addr, b,
- sizeof(struct in6_addr));
b += sizeof(struct in6_addr);
len -= sizeof(struct in6_addr);
break;
@@ -603,9 +592,8 @@ mrt_parse_dump_mp(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
b += sizeof(struct in_addr);
len -= sizeof(struct in_addr);
/* dest IP */
- p->peers->addr.sin.sin_family = AF_INET;
- p->peers->addr.sin.sin_len = sizeof(struct sockaddr_in);
- memcpy(&p->peers->addr.sin.sin_addr, b, sizeof(struct in_addr));
+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1)
+ goto fail;
b += sizeof(struct in_addr);
len -= sizeof(struct in_addr);
break;
@@ -616,10 +604,8 @@ mrt_parse_dump_mp(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
b += sizeof(struct in6_addr);
len -= sizeof(struct in6_addr);
/* dest IP */
- p->peers->addr.sin6.sin6_family = AF_INET6;
- p->peers->addr.sin6.sin6_len = sizeof(struct sockaddr_in6);
- memcpy(&p->peers->addr.sin6.sin6_addr, b,
- sizeof(struct in6_addr));
+ if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1)
+ goto fail;
b += sizeof(struct in6_addr);
len -= sizeof(struct in6_addr);
break;
@@ -670,30 +656,8 @@ mrt_parse_dump_mp(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp,
len -= 1;
/* nexthop */
- switch (af) {
- case AF_INET:
- if (len < sizeof(struct in_addr))
- goto fail;
- re->nexthop.sin.sin_family = AF_INET;
- re->nexthop.sin.sin_len = sizeof(struct sockaddr_in);
- memcpy(&re->nexthop.sin.sin_addr, b, sizeof(struct in_addr));
- break;
- case AF_INET6:
- if (len < sizeof(struct in6_addr))
- goto fail;
- re->nexthop.sin6.sin6_family = AF_INET6;
- re->nexthop.sin6.sin6_len = sizeof(struct sockaddr_in6);
- memcpy(&re->nexthop.sin6.sin6_addr, b, sizeof(struct in6_addr));
- break;
- case AF_VPNv4:
- if (len < sizeof(u_int64_t) + sizeof(struct in_addr))
- goto fail;
- re->nexthop.svpn4.sv_len = sizeof(struct sockaddr_vpn4);
- re->nexthop.svpn4.sv_family = AF_VPNv4;
- memcpy(&re->nexthop.svpn4.sv_addr, b + sizeof(u_int64_t),
- sizeof(struct in_addr));
- break;
- }
+ if (mrt_extract_addr(b, len, &re->nexthop, af) == -1)
+ goto fail;
if (len < nhlen)
goto fail;
b += nhlen;
@@ -971,3 +935,36 @@ mrt_aspath_inflate(void *data, u_int16_t len, u_int16_t *newlen)
return (ndata);
}
+
+int
+mrt_extract_addr(void *msg, u_int len, union mrt_addr *addr, sa_family_t af)
+{
+ u_int8_t *b = msg;
+
+ switch (af) {
+ case AF_INET:
+ if (len < sizeof(struct in_addr))
+ return (-1);
+ addr->sin.sin_family = AF_INET;
+ addr->sin.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&addr->sin.sin_addr, b, sizeof(struct in_addr));
+ return sizeof(struct in_addr);
+ case AF_INET6:
+ if (len < sizeof(struct in6_addr))
+ return (-1);
+ addr->sin6.sin6_family = AF_INET6;
+ addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&addr->sin6.sin6_addr, b, sizeof(struct in6_addr));
+ return sizeof(struct in6_addr);
+ case AF_VPNv4:
+ if (len < sizeof(u_int64_t) + sizeof(struct in_addr))
+ return (-1);
+ addr->svpn4.sv_len = sizeof(struct sockaddr_vpn4);
+ addr->svpn4.sv_family = AF_VPNv4;
+ memcpy(&addr->svpn4.sv_addr, b + sizeof(u_int64_t),
+ sizeof(struct in_addr));
+ return (sizeof(u_int64_t) + sizeof(struct in_addr));
+ default:
+ return (-1);
+ }
+}