aboutsummaryrefslogtreecommitdiffstats
path: root/net/zebra
diff options
context:
space:
mode:
authorsumikawa <sumikawa@FreeBSD.org>2003-05-21 06:39:03 +0800
committersumikawa <sumikawa@FreeBSD.org>2003-05-21 06:39:03 +0800
commitbca649808a15c3af98da680305f9cedd4aa5a2e9 (patch)
tree6ecfd256dd38ea7af7a92bbaa41771ad7d643694 /net/zebra
parent769ad4dff352ad44fb1e6fb586988232680f9739 (diff)
downloadfreebsd-ports-graphics-bca649808a15c3af98da680305f9cedd4aa5a2e9.tar.gz
freebsd-ports-graphics-bca649808a15c3af98da680305f9cedd4aa5a2e9.tar.zst
freebsd-ports-graphics-bca649808a15c3af98da680305f9cedd4aa5a2e9.zip
Fix RIPv1 subnet bugs
Submitted by: jonny@jonny.eng.br (Joao Carlos Mendes Luis) Obtained from: http://www.geocrawler.com/archives/3/372/2002/10/0/9918592/
Diffstat (limited to 'net/zebra')
-rw-r--r--net/zebra/Makefile2
-rw-r--r--net/zebra/files/patch-ripd301
2 files changed, 302 insertions, 1 deletions
diff --git a/net/zebra/Makefile b/net/zebra/Makefile
index 5751661f153..08da8b2631e 100644
--- a/net/zebra/Makefile
+++ b/net/zebra/Makefile
@@ -7,7 +7,7 @@
PORTNAME= zebra
PORTVERSION= 0.93b
-PORTREVISION= 5
+PORTREVISION= 6
CATEGORIES= net ipv6
MASTER_SITES= ftp://ftp.zebra.org/pub/zebra/ \
ftp://ftp.ripe.net/mirrors/sites/ftp.zebra.org/pub/zebra/ \
diff --git a/net/zebra/files/patch-ripd b/net/zebra/files/patch-ripd
new file mode 100644
index 00000000000..4178aaac23c
--- /dev/null
+++ b/net/zebra/files/patch-ripd
@@ -0,0 +1,301 @@
+--- lib/if.c.orig Fri Jun 21 23:49:50 2002
++++ lib/if.c Mon Oct 14 17:25:42 2002
+@@ -553,6 +553,65 @@
+ return NULL;
+ }
+
++/* Find the IPv4 address on our side that will be used when packets
++ are sent to dst. */
++struct connected *
++connected_lookup_address (struct interface *ifp, struct in_addr dst)
++{
++ struct prefix addr;
++ struct prefix best;
++ listnode cnode;
++ struct prefix *p;
++ struct connected *c;
++ struct connected *match;
++
++ /* Zero structures - get rid of rubbish from stack */
++ memset(&addr, 0, sizeof(addr));
++ memset(&best, 0, sizeof(best));
++
++ addr.family = AF_INET;
++ addr.u.prefix4 = dst;
++ addr.prefixlen = IPV4_MAX_BITLEN;
++
++ match = NULL;
++
++ for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
++ {
++ c = getdata (cnode);
++
++ if (if_is_pointopoint (ifp))
++ {
++ p = c->address;
++
++ if (p && p->family == AF_INET)
++ {
++#ifdef OLD_RIB /* PTP links are conventionally identified
++ by the address of the far end - MAG */
++ if (IPV4_ADDR_SAME (&p->u.prefix4, &dst))
++ return c;
++#endif
++ p = c->destination;
++ if (p && IPV4_ADDR_SAME (&p->u.prefix4, &dst))
++ return c;
++ }
++ }
++ else
++ {
++ p = c->address;
++
++ if (p->family == AF_INET)
++ {
++ if (prefix_match (p, &addr) && p->prefixlen > best.prefixlen)
++ {
++ best = *p;
++ match = c;
++ }
++ }
++ }
++ }
++ return match;
++}
++
+ /* Check the connected information is PtP style or not. */
+ int
+ ifc_pointopoint (struct connected *ifc)
+--- ./lib/if.h.orig Fri Jun 21 23:49:50 2002
++++ ./lib/if.h Mon Oct 14 17:25:42 2002
+@@ -202,6 +202,7 @@
+ void connected_free (struct connected *);
+ void connected_add (struct interface *, struct connected *);
+ struct connected *connected_delete_by_prefix (struct interface *, struct prefix *);
++struct connected *connected_lookup_address (struct interface *, struct in_addr);
+ int ifc_pointopoint (struct connected *);
+
+ #ifndef HAVE_IF_NAMETOINDEX
+--- ./ripd/ripd.c.orig Mon Jul 1 02:57:22 2002
++++ ./ripd/ripd.c Tue Oct 15 10:02:11 2002
+@@ -55,8 +55,8 @@
+ /* Prototypes. */
+ void rip_event (enum rip_event, int);
+
+-void rip_output_process (struct interface *, struct sockaddr_in *,
+- int, u_char);
++void rip_output_process (struct interface *, struct prefix *,
++ struct sockaddr_in *, int, u_char);
+
+ /* RIP output routes type. */
+ enum
+@@ -955,7 +955,14 @@
+ {
+ caddr_t lim;
+ struct rte *rte;
++ struct prefix_ipv4 ifaddr;
++ struct prefix_ipv4 ifaddrclass;
++ struct connected *c;
++ int subnetted;
+
++ /* We don't know yet. */
++ subnetted = -1;
++
+ /* The Response must be ignored if it is not from the RIP
+ port. (RFC2453 - Sec. 3.9.2)*/
+ if (ntohs (from->sin_port) != RIP_PORT_DEFAULT)
+@@ -1108,23 +1115,51 @@
+ {
+ u_int32_t destination;
+
+- destination = ntohl (rte->prefix.s_addr);
+-
+- if (destination & 0xff)
++ if (subnetted == -1)
+ {
+- masklen2ip (32, &rte->mask);
++ c = connected_lookup_address (ifp, from->sin_addr);
++ if (c != NULL)
++ {
++ memcpy (&ifaddr, c->address, sizeof (struct prefix_ipv4));
++ memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
++ apply_classful_mask_ipv4 (&ifaddrclass);
++ subnetted = 0;
++ if (ifaddr.prefixlen > ifaddrclass.prefixlen)
++ subnetted = 1;
++ }
+ }
+- else if ((destination & 0xff00) || IN_CLASSC (destination))
+- {
++
++ destination = ntohl (rte->prefix.s_addr);
++
++ if (IN_CLASSA (destination))
++ masklen2ip (8, &rte->mask);
++ else if (IN_CLASSB (destination))
++ masklen2ip (16, &rte->mask);
++ else if (IN_CLASSC (destination))
+ masklen2ip (24, &rte->mask);
++
++ if (subnetted == 1)
++ masklen2ip (ifaddrclass.prefixlen,
++ (struct in_addr *) &destination);
++ if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
++ ifaddrclass.prefix.s_addr))
++ {
++ masklen2ip (ifaddr.prefixlen, &rte->mask);
++ if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
++ masklen2ip (32, &rte->mask);
++ if (IS_RIP_DEBUG_EVENT)
++ zlog_info ("Subnetted route %s", inet_ntoa (rte->prefix));
+ }
+- else if ((destination & 0xff0000) || IN_CLASSB (destination))
++ else
+ {
+- masklen2ip (16, &rte->mask);
++ if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
++ continue;
+ }
+- else
++
++ if (IS_RIP_DEBUG_EVENT)
+ {
+- masklen2ip (8, &rte->mask);
++ zlog_info ("Resultant route %s", inet_ntoa (rte->prefix));
++ zlog_info ("Resultant mask %s", inet_ntoa (rte->mask));
+ }
+ }
+
+@@ -1353,7 +1388,7 @@
+ ntohl (rte->metric) == RIP_METRIC_INFINITY)
+ {
+ /* All route with split horizon */
+- rip_output_process (ifp, from, rip_all_route, packet->version);
++ rip_output_process (ifp, NULL, from, rip_all_route, packet->version);
+ }
+ else
+ {
+@@ -1884,8 +1919,8 @@
+
+ /* Send update to the ifp or spcified neighbor. */
+ void
+-rip_output_process (struct interface *ifp, struct sockaddr_in *to,
+- int route_type, u_char version)
++rip_output_process (struct interface *ifp, struct prefix *ifaddr,
++ struct sockaddr_in *to, int route_type, u_char version)
+ {
+ int ret;
+ struct stream *s;
+@@ -1894,8 +1929,11 @@
+ struct rip_interface *ri;
+ struct prefix_ipv4 *p;
+ struct prefix_ipv4 classfull;
++ struct prefix_ipv4 ifaddrclass;
++ struct connected *c;
+ int num;
+ int rtemax;
++ int subnetted;
+
+ /* Logging output event. */
+ if (IS_RIP_DEBUG_EVENT)
+@@ -1946,29 +1984,60 @@
+ rtemax -=1;
+ }
+
++ if (version == RIPv1)
++ {
++ if (ifaddr == NULL)
++ {
++ c = connected_lookup_address (ifp, to->sin_addr);
++ if (c != NULL)
++ ifaddr = c->address;
++ }
++ if (ifaddr == NULL)
++ {
++ zlog_warn ("cannot find source address for packets to neighbor %s",
++ inet_ntoa (to->sin_addr));
++ return;
++ }
++ memcpy (&ifaddrclass, ifaddr, sizeof (struct prefix_ipv4));
++ apply_classful_mask_ipv4 (&ifaddrclass);
++ subnetted = 0;
++ if (ifaddr->prefixlen > ifaddrclass.prefixlen)
++ subnetted = 1;
++ }
++
+ for (rp = route_top (rip->table); rp; rp = route_next (rp))
+ if ((rinfo = rp->info) != NULL)
+ {
+- /* Some inheritance stuff: */
+- /* Before we process with ipv4 prefix we should mask it */
+- /* with Classful mask if we send RIPv1 packet.That's because */
+- /* user could set non-classful mask or we could get it by RIPv2 */
+- /* or other protocol. checked with Cisco's way of life :) */
++ /* For RIPv1, if we are subnetted, output subnets in our network */
++ /* that have the same mask as the output "interface". For other */
++ /* networks, only the classfull version is output. */
+
+ if (version == RIPv1)
+ {
+- memcpy (&classfull, &rp->p, sizeof (struct prefix_ipv4));
++ p = (struct prefix_ipv4 *) &rp->p;
+
+ if (IS_RIP_DEBUG_PACKET)
+- zlog_info("%s/%d before RIPv1 mask check ",
+- inet_ntoa (classfull.prefix), classfull.prefixlen);
+-
+- apply_classful_mask_ipv4 (&classfull);
+- p = &classfull;
++ zlog_info("RIPv1 mask check, %s/%d considered for output",
++ inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
+
++ if (subnetted &&
++ prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
++ {
++ if ((ifaddr->prefixlen != rp->p.prefixlen) &&
++ (rp->p.prefixlen != 32))
++ continue;
++ }
++ else
++ {
++ memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
++ apply_classful_mask_ipv4(&classfull);
++ if (rp->p.u.prefix4.s_addr != 0 &&
++ classfull.prefixlen != rp->p.prefixlen)
++ continue;
++ }
+ if (IS_RIP_DEBUG_PACKET)
+- zlog_info("%s/%d after RIPv1 mask check",
+- inet_ntoa (p->prefix), p->prefixlen);
++ zlog_info("RIPv1 mask check, %s/%d made it through",
++ inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
+ }
+ else
+ p = (struct prefix_ipv4 *) &rp->p;
+@@ -2109,7 +2178,7 @@
+ if (IS_RIP_DEBUG_EVENT)
+ zlog_info ("multicast announce on %s ", ifp->name);
+
+- rip_output_process (ifp, NULL, route_type, version);
++ rip_output_process (ifp, NULL, NULL, route_type, version);
+ return;
+ }
+
+@@ -2136,7 +2205,8 @@
+ if_is_pointopoint (ifp) ? "unicast" : "broadcast",
+ inet_ntoa (to.sin_addr), ifp->name);
+
+- rip_output_process (ifp, &to, route_type, version);
++ rip_output_process (ifp, connected->address, &to, route_type,
++ version);
+ }
+ }
+ }
+@@ -2224,7 +2294,7 @@
+ to.sin_port = htons (RIP_PORT_DEFAULT);
+
+ /* RIP version is rip's configuration. */
+- rip_output_process (ifp, &to, route_type, rip->version);
++ rip_output_process (ifp, NULL, &to, route_type, rip->version);
+ }
+ }