summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRenato Westphal <renato@cvs.openbsd.org>2016-02-21 18:38:38 +0000
committerRenato Westphal <renato@cvs.openbsd.org>2016-02-21 18:38:38 +0000
commit1cbfe68ea7152e4613f97d7fe87368802a2a0837 (patch)
treee1e39fbbbc8b13d6e31bc774d77fc20cefb8310e
parenta905bfc8fb2d1b635885537cc2ed1726c12b53e0 (diff)
Make eigrpd work against newer IOS routers.
Different versions of IOS can use a different number of bytes to encode the same IPv6 prefix inside route TLVs. This sucks but we have to deal with it. Instead of calculating the number of bytes based on the value of the prefixlen field, let's get this number by subtracting the size of all other fields from the total size of the TLV. It works because all the other fields have a fixed length. For reference, the EIGRP draft says that length of the prefix field should be obtained according to this function: ((Bit Count - 1) / 8) + 1 But older IOS versions use this for IPv6 (obtained through reverse engineering): ((Bit Count == 128) ? 16 : ((Bit Count / 8) + 1)) Now, the new IOS-XR apparently uses the first formula for both IPv4 and IPv6. With this patch, eigrpd will work against both older and newer versions of IOS.
-rw-r--r--usr.sbin/eigrpd/tlv.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/usr.sbin/eigrpd/tlv.c b/usr.sbin/eigrpd/tlv.c
index ef5df135b76..0992f215edb 100644
--- a/usr.sbin/eigrpd/tlv.c
+++ b/usr.sbin/eigrpd/tlv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tlv.c,v 1.6 2016/01/15 12:29:29 renato Exp $ */
+/* $OpenBSD: tlv.c,v 1.7 2016/02/21 18:38:37 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
@@ -364,16 +364,18 @@ tlv_decode_mcast_seq(struct tlv *tlv, char *buf)
int
tlv_decode_route(int af, struct tlv *tlv, char *buf, struct rinfo *ri)
{
- int tlv_len, min_len, plen, offset;
+ unsigned int tlv_len, min_len, max_plen, plen, offset;
in_addr_t ipv4;
ri->af = af;
switch (ri->af) {
case AF_INET:
min_len = TLV_TYPE_IPV4_INT_MIN_LEN;
+ max_plen = sizeof(ri->prefix.v4);
break;
case AF_INET6:
min_len = TLV_TYPE_IPV6_INT_MIN_LEN;
+ max_plen = sizeof(ri->prefix.v6);
break;
default:
fatalx("tlv_decode_route: unknown af");
@@ -433,21 +435,19 @@ tlv_decode_route(int af, struct tlv *tlv, char *buf, struct rinfo *ri)
memcpy(&ri->prefixlen, buf + offset, sizeof(ri->prefixlen));
offset += sizeof(ri->prefixlen);
- switch (af) {
- case AF_INET:
- plen = PREFIX_SIZE4(ri->prefixlen);
- break;
- case AF_INET6:
- plen = PREFIX_SIZE6(ri->prefixlen);
- break;
- default:
- fatalx("tlv_decode_route: unknown af");
- }
+ /*
+ * Different versions of IOS can use a different number of bytes to
+ * encode the same IPv6 prefix. This sucks but we have to deal with it.
+ * Instead of calculating the number of bytes based on the value of the
+ * prefixlen field, let's get this number by subtracting the size of all
+ * other fields from the total size of the TLV. It works because all
+ * the other fields have a fixed length.
+ */
+ plen = tlv_len - min_len;
/* safety check */
- if (plen != (tlv_len - min_len)) {
- log_debug("%s: malformed tlv (invalid prefix length)",
- __func__);
+ if (plen > max_plen) {
+ log_debug("%s: malformed tlv", __func__);
return (-1);
}