mirror of
https://git.freebsd.org/ports.git
synced 2025-05-31 10:26:28 -04:00
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/
This commit is contained in:
parent
5ab03702b2
commit
42adb65dc1
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=81566
6 changed files with 906 additions and 3 deletions
|
@ -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/ \
|
||||
|
|
301
net/zebra-devel/files/patch-ripd
Normal file
301
net/zebra-devel/files/patch-ripd
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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/ \
|
||||
|
|
301
net/zebra-pj/files/patch-ripd
Normal file
301
net/zebra-pj/files/patch-ripd
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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/ \
|
||||
|
|
301
net/zebra/files/patch-ripd
Normal file
301
net/zebra/files/patch-ripd
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue