OK. Here it is - PtP patch from Andrew J. Schorr. No problems with ospfd,
ripd might need some more testing though.
diff --git a/ChangeLog b/ChangeLog
index e46bb11..e732bca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * lib, zebra, ripd, ospfd, bgpd: Support NULL connected destination
+ pointers properly everywhere. Fix point-to-point logic to
+ support links where a dedicated subnet has been assigned.
+ PtP links with /31 subnets should now work where supported by O/S.
+
2004-10-11 Paul Jakma <paul@dishone.st>
* bump version to 0.97.1, release imminent.
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index 37ab163..e82843b 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -1,3 +1,9 @@
+2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * bgp_nexthop.c: (bgp_connected_add) Connected destination pointer
+ may be NULL.
+ (bgp_connected_delete) ditto.
+
2004-10-14 Hasso Tepper <hasso at quagga.net>
* bgp_dump.c: Make dump configuration appear in vtysh.
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 4100e3d..c50eeed 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -666,7 +666,7 @@
p.family = AF_INET;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp))
+ if (CONNECTED_POINTOPOINT_HOST(ifc))
p.u.prefix4 = dest->u.prefix4;
else
p.u.prefix4 = addr->u.prefix4;
@@ -697,7 +697,7 @@
p.family = AF_INET6;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp))
+ if (if_is_pointopoint (ifp) && dest)
p.u.prefix6 = dest->u.prefix6;
else
p.u.prefix6 = addr->u.prefix6;
@@ -751,7 +751,7 @@
p.family = AF_INET;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp))
+ if (CONNECTED_POINTOPOINT_HOST(ifc))
p.u.prefix4 = dest->u.prefix4;
else
p.u.prefix4 = addr->u.prefix4;
@@ -782,7 +782,7 @@
p.family = AF_INET6;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp))
+ if (if_is_pointopoint (ifp) && dest)
p.u.prefix6 = dest->u.prefix6;
else
p.u.prefix6 = addr->u.prefix6;
diff --git a/lib/ChangeLog b/lib/ChangeLog
index 31fb15b..d0a33d4 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,18 @@
+2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * zclient.c: (zebra_interface_address_read) If the destination address
+ is encoded as all zeroes, load it as a NULL pointer.
+ * if.h: Add comment describing struct connected destination field
+ and indicating that it may be NULL. Define macros
+ CONNECTED_DEST_HOST and CONNECTED_POINTOPOINT_HOST to help
+ with PtP logic (distinguish between host and subnet addressing).
+ * if.c: (if_lookup_address) Fix PtP logic to handle subnet addressing
+ properly,
+ (connected_lookup_address) ditto.
+ (connected_add_by_prefix) Handle case where destination is NULL,
+ * prefix.[c|h]: New functions ipv4_network_addr and
+ ipv4_broadcast_addr.
+
2004-10-13 Hasso Tepper <hasso at quagga.net>
* command.c: Make CMD_ERR_NOTHING_TODO nonfatal if reading
diff --git a/lib/if.c b/lib/if.c
index 259b842..5519b2a 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -258,17 +258,13 @@
{
struct listnode *node;
struct prefix addr;
- struct prefix best;
+ int bestlen = 0;
struct listnode *cnode;
struct interface *ifp;
struct prefix *p;
struct connected *c;
struct interface *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 = src;
addr.prefixlen = IPV4_MAX_BITLEN;
@@ -283,31 +279,22 @@
{
c = getdata (cnode);
- if (if_is_pointopoint (ifp))
+ if (c->address && (c->address->family == AF_INET))
{
- p = c->address;
-
- if (p && p->family == AF_INET)
+ if (CONNECTED_POINTOPOINT_HOST(c))
{
-#ifdef OLD_RIB /* PTP links are conventionally identified
- by the address of the far end - MAG */
- if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
- return ifp;
-#endif
- p = c->destination;
- if (p && IPV4_ADDR_SAME (&p->u.prefix4, &src))
+ /* PTP links are conventionally identified
+ by the address of the far end - MAG */
+ if (IPV4_ADDR_SAME (&c->destination->u.prefix4, &src))
return ifp;
}
- }
- else
- {
- p = c->address;
-
- if (p->family == AF_INET)
+ else
{
- if (prefix_match (p, &addr) && p->prefixlen > best.prefixlen)
+ p = c->address;
+
+ if (prefix_match (p, &addr) && p->prefixlen > bestlen)
{
- best = *p;
+ bestlen = p->prefixlen;
match = ifp;
}
}
@@ -680,16 +667,11 @@
connected_lookup_address (struct interface *ifp, struct in_addr dst)
{
struct prefix addr;
- struct prefix best;
struct 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;
@@ -700,35 +682,24 @@
{
c = getdata (cnode);
- if (if_is_pointopoint (ifp))
- {
- p = c->address;
-
- if (p && p->family == AF_INET)
+ if (c->address && (c->address->family == AF_INET))
+ {
+ if (CONNECTED_POINTOPOINT_HOST(c))
{
-#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))
+ /* PTP links are conventionally identified
+ by the address of the far end - MAG */
+ if (IPV4_ADDR_SAME (&c->destination->u.prefix4, &dst))
return c;
}
- }
- else
- {
- p = c->address;
-
- if (p->family == AF_INET)
+ else
{
- if (prefix_match (p, &addr) && p->prefixlen > best.prefixlen)
- {
- best = *p;
- match = c;
- }
+ p = c->address;
+
+ if (prefix_match (p, &addr) &&
+ (!match || (p->prefixlen > match->address->prefixlen)))
+ match = c;
}
- }
+ }
}
return match;
}
@@ -748,8 +719,11 @@
memcpy (ifc->address, p, sizeof(struct prefix));
/* Fetch dest address */
- ifc->destination = prefix_new();
- memcpy (ifc->destination, destination, sizeof(struct prefix));
+ if (destination)
+ {
+ ifc->destination = prefix_new();
+ memcpy (ifc->destination, destination, sizeof(struct prefix));
+ }
/* Add connected address to the interface. */
listnode_add (ifp->connected, ifc);
diff --git a/lib/if.h b/lib/if.h
index 218f102..7afb2ae 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -148,12 +148,23 @@
/* Address of connected network. */
struct prefix *address;
- struct prefix *destination;
+ struct prefix *destination; /* broadcast or peer address; may be NULL */
/* Label for Linux 2.2.X and upper. */
char *label;
};
+/* Given an IPV4 struct connected, this macro determines whether a /32
+ peer address has been supplied (i.e. there is no subnet assigned) */
+#define CONNECTED_DEST_HOST(C) \
+ ((C)->destination && ((C)->address->prefixlen == IPV4_MAX_PREFIXLEN))
+
+/* Given an IPV4 struct connected, this macro determins whether it is
+ a point-to-point link with a /32 peer address (i.e. there
+ is no dedicated subnet for the PtP link) */
+#define CONNECTED_POINTOPOINT_HOST(C) \
+ (((C)->ifp->flags & IFF_POINTOPOINT) && CONNECTED_DEST_HOST(C))
+
/* Interface hook sort. */
#define IF_NEW_HOOK 0
#define IF_DELETE_HOOK 1
diff --git a/lib/prefix.c b/lib/prefix.c
index d9751e3..3f3c4e8 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -247,7 +247,7 @@
/* Get prefix length. */
plen = (u_char) atoi (++pnt);
- if (plen > 32)
+ if (plen > IPV4_MAX_PREFIXLEN)
return 0;
p->family = AF_INET;
@@ -648,7 +648,7 @@
destination = ntohl (p->prefix.s_addr);
- if (p->prefixlen == 32);
+ if (p->prefixlen == IPV4_MAX_PREFIXLEN);
/* do nothing for host routes */
else if (IN_CLASSC (destination))
{
@@ -667,6 +667,28 @@
}
}
+in_addr_t
+ipv4_network_addr (in_addr_t hostaddr, int masklen)
+{
+ struct in_addr mask;
+
+ masklen2ip (masklen, &mask);
+ return hostaddr & mask.s_addr;
+}
+
+in_addr_t
+ipv4_broadcast_addr (in_addr_t hostaddr, int masklen)
+{
+ struct in_addr mask;
+
+ masklen2ip (masklen, &mask);
+ return (masklen != IPV4_MAX_PREFIXLEN-1) ?
+ /* normal case */
+ (hostaddr | ~mask.s_addr) :
+ /* special case for /31 */
+ (hostaddr ^ ~mask.s_addr);
+}
+
/* Utility function to convert ipv4 netmask to prefixes
ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
diff --git a/lib/prefix.h b/lib/prefix.h
index e4f17ab..0546095 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -153,6 +153,14 @@
u_char ip_masklen (struct in_addr);
void masklen2ip (int, struct in_addr *);
+/* returns the network portion of the host address */
+in_addr_t ipv4_network_addr (in_addr_t hostaddr, int masklen);
+/* given the address of a host on a network and the network mask length,
+ * calculate the broadcast address for that network;
+ * special treatment for /31: returns the address of the other host
+ * on the network by flipping the host bit */
+in_addr_t ipv4_broadcast_addr (in_addr_t hostaddr, int masklen);
+
int netmask_str2prefix_str (const char *, const char *, char *);
#ifdef HAVE_IPV6
diff --git a/lib/zclient.c b/lib/zclient.c
index 98829f6..dfb2f2f 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -644,6 +644,17 @@
ifp->bandwidth = stream_getl (s);
}
+static int
+memconstant(const void *s, int c, size_t n)
+{
+ const u_char *p = s;
+
+ while (n-- > 0)
+ if (*p++ != c)
+ return 0;
+ return 1;
+}
+
struct connected *
zebra_interface_address_read (int type, struct stream *s)
{
@@ -688,7 +699,9 @@
if (type == ZEBRA_INTERFACE_ADDRESS_ADD)
{
- ifc = connected_add_by_prefix(ifp, &p, &d);
+ /* N.B. NULL destination pointers are encoded as all zeroes */
+ ifc = connected_add_by_prefix(ifp, &p,(memconstant(&d.u.prefix,0,plen) ?
+ NULL : &d));
if (ifc != NULL)
ifc->flags = ifc_flags;
}
diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog
index 914ed93..31ee303 100644
--- a/ospfd/ChangeLog
+++ b/ospfd/ChangeLog
@@ -1,3 +1,16 @@
+2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * ospf_snmp.c: (ospf_snmp_if_update) Fix logic to handle PtP links
+ with dedicated subnets properly.
+ * ospf_lsa.c: (lsa_link_ptop_set) ditto.
+ * ospfd.c: (ospf_network_match_iface) ditto.
+ (ospf_network_run) ditto.
+ * ospf_interface.c: (ospf_if_is_configured) ditto.
+ (ospf_if_lookup_by_prefix) ditto.
+ (ospf_if_lookup_recv_if) ditto.
+ * ospf_vty.c: (show_ip_ospf_interface_sub) Display the peer or
+ broadcast address if present.
+
2004-10-13 Hasso Tepper <hasso at quagga.net>
* ospf_main.c: Unbreak compilation with ospfapi disabled.
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 277d508..e74c375 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -338,27 +338,45 @@
/*
* check if interface with given address is configured and
-* return it if yes.
+* return it if yes. special treatment for PtP networks.
*/
struct ospf_interface *
ospf_if_is_configured (struct ospf *ospf, struct in_addr *address)
{
struct listnode *node;
struct ospf_interface *oi;
- struct prefix *addr;
+ struct prefix_ipv4 addr;
+
+ addr.family = AF_INET;
+ addr.prefix = *address;
+ addr.prefixlen = IPV4_MAX_PREFIXLEN;
for (node = listhead (ospf->oiflist); node; nextnode (node))
if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
{
if (oi->type == OSPF_IFTYPE_POINTOPOINT)
- addr = oi->connected->destination;
+ {
+ if (CONNECTED_DEST_HOST(oi->connected))
+ {
+ /* match only destination addr, since local addr is most likely
+ * not unique (borrowed from another interface) */
+ if (IPV4_ADDR_SAME (address,
+ &oi->connected->destination->u.prefix4))
+ return oi;
+ }
+ else
+ {
+ /* special leniency: match if addr is anywhere on PtP subnet */
+ if (prefix_match(oi->address,(struct prefix *)&addr))
+ return oi;
+ }
+ }
else
- addr = oi->address;
-
- if (IPV4_ADDR_SAME (address, &addr->u.prefix4))
- return oi;
+ {
+ if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4))
+ return oi;
+ }
}
-
return NULL;
}
@@ -417,7 +435,8 @@
{
if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
{
- if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
+ CONNECTED_DEST_HOST(oi->connected))
{
prefix_copy (&ptmp, oi->connected->destination);
ptmp.prefixlen = IPV4_MAX_BITLEN;
@@ -454,7 +473,8 @@
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
continue;
- if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
+ CONNECTED_DEST_HOST(oi->connected))
{
if (IPV4_ADDR_SAME (&oi->connected->destination->u.prefix4, &src))
return oi;
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 3ad6ddf..f1478a3 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -517,7 +517,7 @@
links++;
}
- if (oi->connected->destination != NULL)
+ if (CONNECTED_DEST_HOST(oi->connected))
{
/* Option 1:
link_type = LSA_LINK_TYPE_STUB;
diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c
index db0aaf6..0cf257d 100644
--- a/ospfd/ospf_snmp.c
+++ b/ospfd/ospf_snmp.c
@@ -1435,7 +1435,7 @@
/* Lookup first IPv4 address entry. */
LIST_LOOP (ifp->connected, ifc, nn)
{
- if (if_is_pointopoint (ifp))
+ if (CONNECTED_POINTOPOINT_HOST(ifc))
p = ifc->destination;
else
p = ifc->address;
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 0ecb6fb..c84da74 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -2550,6 +2550,11 @@
vty_out (vty, " Internet Address %s/%d,",
inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen);
+ if (oi->connected->destination)
+ vty_out (vty, " %s %s,",
+ ((ifp->flags & IFF_POINTOPOINT) ? "Peer" : "Broadcast"),
+ inet_ntoa (oi->connected->destination->u.prefix4));
+
vty_out (vty, " Area %s%s", ospf_area_desc_string (oi->area),
VTY_NEWLINE);
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 0a988e0..054c331 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -686,31 +686,17 @@
* PtP special case: network specified == iface peer addr -> ospf
*/
- /* For PtP, match if peer address matches network address exactly.
- * This can be addr/32 or addr/p for p < 32, but the addr must match
- * exactly; this is not a test for falling within the prefix. This
+ /* For PtP, match if peer address matches network address exactly
+ * in situations where the peer address is available and the prefix
+ * length is 32 (i.e. a dedicated subnet has not been assigned).
+ * This is not a test for falling within the prefix. This
* test is solely for compatibility with zebra.
- */
- if (if_is_pointopoint (co->ifp) &&
- IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
- return 1;
-
-#if 0
- /* Decline to accept PtP if dst address does not match the
- * prefix. (ifdefed out because this is a workaround, not the
- * desired behavior.) */
- if (if_is_pointopoint (co->ifp) &&
- ! prefix_match (net, co->destination))
- return 0;
-#endif
-
- /* If the address is within the prefix, accept. Note that this
- * applies to PtP as well as other types.
+ *
+ * If not PtP, accept if the address is within the prefix.
*/
- if (prefix_match (net, co->address))
- return 1;
-
- return 0; /* no match */
+ return CONNECTED_POINTOPOINT_HOST(co) ?
+ IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)) :
+ prefix_match (net, co->address);
}
void
@@ -748,7 +734,7 @@
if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
continue;
- if (if_is_pointopoint (co->ifp))
+ if (CONNECTED_POINTOPOINT_HOST(co))
addr = co->destination;
else
addr = co->address;
diff --git a/ripd/ChangeLog b/ripd/ChangeLog
index ee878ff..ae67e72 100644
--- a/ripd/ChangeLog
+++ b/ripd/ChangeLog
@@ -1,3 +1,15 @@
+2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * ripd.c: (rip_update_interface) if connected->destination is NULL,
+ get the broadcast address with ipv4_broadcast_addr()
+ * rip_interface.c: (rip_interface_multicast_set)
+ connected->destination may be NULL. Improve message if
+ setsockopt_multicast_ipv4 fails. Improve message if bind fails.
+ (rip_request_interface_send) If connected->destination is NULL,
+ get the broadcast address with ipv4_broadcast_addr().
+ (if_valid_neighbor) Handle PtP subnet addressing properly.
+ Speed up code by using prefix_match properly.
+
2004-10-13 Hasso Tepper <hasso at quagga.net>
* ripd_snmp.c: Remove defaults used to initialize smux connection to
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 509d5ed..19f6f11 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -143,16 +143,16 @@
int ret;
struct servent *sp;
struct sockaddr_in from;
- struct in_addr addr;
+ struct in_addr addr;
struct prefix_ipv4 *p;
if (connected != NULL)
{
- if (if_is_pointopoint(connected->ifp))
- p = (struct prefix_ipv4 *) connected->destination;
- else
- p = (struct prefix_ipv4 *) connected->address;
- addr = p->prefix;
+ if (if_is_pointopoint(connected->ifp) && CONNECTED_DEST_HOST(connected))
+ p = (struct prefix_ipv4 *) connected->destination;
+ else
+ p = (struct prefix_ipv4 *) connected->address;
+ addr = p->prefix;
}
else
{
@@ -161,46 +161,52 @@
if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, 0,
connected->ifp->ifindex) < 0)
- {
- zlog_warn ("Can't setsockopt IP_MULTICAST_IF to fd %d, ifindex %d",
- sock, connected->ifp->ifindex);
- return;
- }
+ {
+ zlog_warn ("Can't setsockopt IP_MULTICAST_IF on fd %d to "
+ "source address %s for interface %s",
+ sock, inet_ntoa(addr),
+ (connected ? connected->ifp->name : "(unknown)"));
+ return;
+ }
- /* Bind myself. */
- memset (&from, 0, sizeof (struct sockaddr_in));
+ /* Bind myself. */
+ memset (&from, 0, sizeof (struct sockaddr_in));
- /* Set RIP port. */
- sp = getservbyname ("router", "udp");
- if (sp)
- from.sin_port = sp->s_port;
- else
- from.sin_port = htons (RIP_PORT_DEFAULT);
+ /* Set RIP port. */
+ sp = getservbyname ("router", "udp");
+ if (sp)
+ from.sin_port = sp->s_port;
+ else
+ from.sin_port = htons (RIP_PORT_DEFAULT);
/* Address should be any address. */
- from.sin_family = AF_INET;
+ from.sin_family = AF_INET;
if (connected)
- addr = ((struct prefix_ipv4 *) connected->address)->prefix;
- from.sin_addr = addr;
+ addr = ((struct prefix_ipv4 *) connected->address)->prefix;
+ from.sin_addr = addr;
#ifdef HAVE_SIN_LEN
- from.sin_len = sizeof (struct sockaddr_in);
+ from.sin_len = sizeof (struct sockaddr_in);
#endif /* HAVE_SIN_LEN */
- if (ripd_privs.change (ZPRIVS_RAISE))
- zlog_err ("rip_interface_multicast_set: could not raise privs");
+ if (ripd_privs.change (ZPRIVS_RAISE))
+ zlog_err ("rip_interface_multicast_set: could not raise privs");
ret = bind (sock, (struct sockaddr *) & from, sizeof (struct sockaddr_in));
- if (ret < 0)
- {
- zlog_warn ("Can't bind socket: %s", strerror (errno));
- }
+ if (ret < 0)
+ {
+ zlog_warn ("Can't bind socket fd %d to %s port %d for "
+ "interface %s: %s",
+ sock,inet_ntoa(from.sin_addr),
+ (int)ntohs(from.sin_port),
+ (connected ? connected->ifp->name : "(unknown)"),
+ strerror (errno));
+ }
- if (ripd_privs.change (ZPRIVS_LOWER))
- zlog_err ("rip_interface_multicast_set: could not lower privs");
+ if (ripd_privs.change (ZPRIVS_LOWER))
+ zlog_err ("rip_interface_multicast_set: could not lower privs");
- return;
-
- }
+ return;
+}
/* Send RIP request packet to specified interface. */
void
@@ -229,17 +235,22 @@
for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
{
- struct prefix_ipv4 *p;
struct connected *connected;
connected = getdata (cnode);
- p = (struct prefix_ipv4 *) connected->destination;
- if (p->family == AF_INET)
+ if (connected->address->family == AF_INET)
{
memset (&to, 0, sizeof (struct sockaddr_in));
to.sin_port = htons (RIP_PORT_DEFAULT);
- to.sin_addr = p->prefix;
+ if (connected->destination)
+ /* use specified broadcast or point-to-point destination addr */
+ to.sin_addr = connected->destination->u.prefix4;
+ else
+ /* calculate the appropriate broadcast address */
+ to.sin_addr.s_addr =
+ ipv4_broadcast_addr(connected->address->u.prefix4.s_addr,
+ connected->address->prefixlen);
if (IS_RIP_DEBUG_EVENT)
zlog_info ("SEND request to %s", inet_ntoa (to.sin_addr));
@@ -439,6 +450,11 @@
struct listnode *node;
struct connected *connected = NULL;
struct prefix_ipv4 *p;
+ struct prefix_ipv4 pa;
+
+ pa.family = AF_INET;
+ pa.prefix = addr;
+ pa.prefixlen = IPV4_MAX_PREFIXLEN;
for (node = listhead (iflist); node; nextnode (node))
{
@@ -449,9 +465,6 @@
for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
{
- struct prefix *pxn = NULL; /* Prefix of the neighbor */
- struct prefix *pxc = NULL; /* Prefix of the connected network */
-
connected = getdata (cnode);
if (if_is_pointopoint (ifp))
@@ -464,34 +477,23 @@
return 1;
p = (struct prefix_ipv4 *) connected->destination;
- if (p && IPV4_ADDR_SAME (&p->prefix, &addr))
- return 1;
+ if (p)
+ {
+ if (IPV4_ADDR_SAME (&p->prefix, &addr))
+ return 1;
+ }
+ else
+ {
+ if (prefix_match(connected->address,(struct prefix *)&pa))
+ return 1;
+ }
}
}
else
{
- p = (struct prefix_ipv4 *) connected->address;
-
- if (p->family != AF_INET)
- continue;
-
- pxn = prefix_new();
- pxn->family = AF_INET;
- pxn->prefixlen = 32;
- pxn->u.prefix4 = addr;
-
- pxc = prefix_new();
- prefix_copy(pxc, (struct prefix *) p);
- apply_mask(pxc);
-
- if (prefix_match (pxc, pxn))
- {
- prefix_free (pxn);
- prefix_free (pxc);
- return 1;
- }
- prefix_free(pxc);
- prefix_free(pxn);
+ if ((connected->address->family == AF_INET) &&
+ prefix_match(connected->address,(struct prefix *)&pa))
+ return 1;
}
}
}
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 2b4e1b2..94324f0 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -2391,7 +2391,6 @@
rip_update_interface (struct interface *ifp, u_char version, int route_type,
struct connected *sconn)
{
- struct prefix_ipv4 *p;
struct connected *connected;
struct listnode *node;
struct sockaddr_in to;
@@ -2415,15 +2414,18 @@
{
connected = getdata (node);
- /* Fetch broadcast address or poin-to-point destination
- address . */
- p = (struct prefix_ipv4 *) connected->destination;
-
- if (p->family == AF_INET)
+ if (connected->address->family == AF_INET)
{
/* Destination address and port setting. */
memset (&to, 0, sizeof (struct sockaddr_in));
- to.sin_addr = p->prefix;
+ if (connected->destination)
+ /* use specified broadcast or point-to-point destination addr */
+ to.sin_addr = connected->destination->u.prefix4;
+ else
+ /* calculate the appropriate broadcast address */
+ to.sin_addr.s_addr =
+ ipv4_broadcast_addr(connected->address->u.prefix4.s_addr,
+ connected->address->prefixlen);
to.sin_port = htons (RIP_PORT_DEFAULT);
if (IS_RIP_DEBUG_EVENT)
diff --git a/zebra/ChangeLog b/zebra/ChangeLog
index 506e3ae..e377470 100644
--- a/zebra/ChangeLog
+++ b/zebra/ChangeLog
@@ -1,3 +1,15 @@
+2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * rt_netlink.c: (netlink_interface_addr) For PtP interfaces, ignore
+ tb[IFA_ADDRESS] if it's the same as tb[IFA_LOCAL].
+ * interface.c: (ip_address_install) Use new ipv4_broadcast_addr
+ function.
+ * connected.c: (connected_up_ipv4) Use CONNECTED_POINTOPOINT_HOST
+ macro.
+ (connected_down_ipv4) ditto.
+ (connected_add_ipv4) Validate destination address, print warnings
+ if it does not make sense.
+
2004-10-19 Hasso Tepper <hasso at quagga.net>
* zserv.c: Fix regression introduced with zserv cleanup.
diff --git a/zebra/connected.c b/zebra/connected.c
index a043ef4..9a6fd66 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -70,7 +70,7 @@
p.prefixlen = addr->prefixlen;
/* Point-to-point check. */
- if (if_is_pointopoint (ifp) && dest)
+ if (CONNECTED_POINTOPOINT_HOST(ifc))
p.prefix = dest->prefix;
else
p.prefix = addr->prefix;
@@ -116,7 +116,49 @@
p->family = AF_INET;
p->prefix = *broad;
ifc->destination = (struct prefix *) p;
+
+ /* validate the destination address */
+ if (ifp->flags & IFF_POINTOPOINT)
+ {
+ if (IPV4_ADDR_SAME(addr,broad))
+ zlog_warn("warning: PtP interface %s has same local and peer "
+ "address %s, routing protocols may malfunction",
+ ifp->name,inet_ntoa(*addr));
+ else if ((prefixlen != IPV4_MAX_PREFIXLEN) &&
+ (ipv4_network_addr(addr->s_addr,prefixlen) !=
+ ipv4_network_addr(broad->s_addr,prefixlen)))
+ {
+ char buf[2][INET_ADDRSTRLEN];
+ zlog_warn("warning: PtP interface %s network mismatch: local "
+ "%s/%d vs. peer %s, routing protocols may malfunction",
+ ifp->name,
+ inet_ntop (AF_INET, addr, buf[0], sizeof(buf[0])),
+ prefixlen,
+ inet_ntop (AF_INET, broad, buf[1], sizeof(buf[1])));
+ }
+ }
+ else
+ {
+ if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
+ {
+ char buf[2][INET_ADDRSTRLEN];
+ struct in_addr bcalc;
+ bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
+ zlog_warn("warning: interface %s broadcast addr %s/%d != "
+ "calculated %s, routing protocols may malfunction",
+ ifp->name,
+ inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
+ prefixlen,
+ inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
+ }
+ }
+
}
+ else
+ /* no broadcast or destination address was supplied */
+ if (prefixlen == IPV4_MAX_PREFIXLEN)
+ zlog_warn("warning: interface %s with addr %s/%d needs a peer address",
+ ifp->name,inet_ntoa(*addr),prefixlen);
/* Label of this address. */
if (label)
@@ -166,7 +208,7 @@
p.prefixlen = addr->prefixlen;
/* Point-to-point check. */
- if (dest && if_is_pointopoint (ifp))
+ if (CONNECTED_POINTOPOINT_HOST(ifc))
p.prefix = dest->prefix;
else
p.prefix = addr->prefix;
diff --git a/zebra/interface.c b/zebra/interface.c
index 5664f41..a1d0332 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1107,7 +1107,6 @@
struct prefix_ipv4 cp;
struct connected *ifc;
struct prefix_ipv4 *p;
- struct in_addr mask;
int ret;
ret = str2prefix_ipv4 (addr_str, &cp);
@@ -1129,12 +1128,11 @@
ifc->address = (struct prefix *) p;
/* Broadcast. */
- if (p->prefixlen <= 30)
+ if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
{
p = prefix_ipv4_new ();
*p = cp;
- masklen2ip (p->prefixlen, &mask);
- p->prefix.s_addr |= ~mask.s_addr;
+ p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
ifc->destination = (struct prefix *) p;
}
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index ee61cb2..50e83b7 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -596,7 +596,9 @@
if (tb[IFA_LOCAL])
{
addr = RTA_DATA (tb[IFA_LOCAL]);
- if (tb[IFA_ADDRESS])
+ if (tb[IFA_ADDRESS] &&
+ memcmp(RTA_DATA(tb[IFA_ADDRESS]),RTA_DATA(tb[IFA_LOCAL]),4))
+ /* if IFA_ADDRESS != IFA_LOCAL, then it's the peer address */
broad = RTA_DATA (tb[IFA_ADDRESS]);
else
broad = NULL;