[zebra 14631] Generic PtP and RFC3021 interface addressing support
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 24a113d..ad932b5 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -663,7 +663,7 @@
p.family = AF_INET;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp))
+ if (ifc_pointopoint (ifc))
p.u.prefix4 = dest->u.prefix4;
else
p.u.prefix4 = addr->u.prefix4;
@@ -694,7 +694,7 @@
p.family = AF_INET6;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp))
+ if (ifc_pointopoint (ifc))
p.u.prefix6 = dest->u.prefix6;
else
p.u.prefix6 = addr->u.prefix6;
@@ -748,7 +748,7 @@
p.family = AF_INET;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp))
+ if (ifc_pointopoint (ifc))
p.u.prefix4 = dest->u.prefix4;
else
p.u.prefix4 = addr->u.prefix4;
@@ -779,7 +779,7 @@
p.family = AF_INET6;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp))
+ if (ifc_pointopoint (ifc))
p.u.prefix6 = dest->u.prefix6;
else
p.u.prefix6 = addr->u.prefix6;
diff --git a/lib/if.c b/lib/if.c
index ce3595d..e1a1839 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -189,11 +189,13 @@
listnode node;
struct prefix addr;
struct prefix best;
+ struct prefix peer;
listnode cnode;
struct interface *ifp;
struct prefix *p;
struct connected *c;
struct interface *match;
+ int prefixlen;
/* Zero structures - get rid of rubbish from stack */
memset(&addr, 0, sizeof(addr));
@@ -212,34 +214,24 @@
for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
{
c = getdata (cnode);
+ p = c->address;
- if (if_is_pointopoint (ifp))
+ if (p->family == AF_INET)
{
- p = c->address;
+ prefixlen = p->prefixlen;
- if (p && p->family == AF_INET)
+ if (if_is_pointopoint (ifp) ||
+ prefixlen >= IPV4_MAX_PREFIXLEN - 1)
{
-#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))
- return ifp;
+ peer = *c->destination;
+ peer.prefixlen = prefixlen;
+ p = &peer;
}
- }
- else
- {
- p = c->address;
- if (p->family == AF_INET)
+ if (prefix_match (p, &addr) && prefixlen > best.prefixlen)
{
- if (prefix_match (p, &addr) && p->prefixlen > best.prefixlen)
- {
- best = *p;
- match = ifp;
- }
+ best = *p;
+ match = ifp;
}
}
}
diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c
index 6187977..4ed0ecd 100644
--- a/ospfd/ospf_snmp.c
+++ b/ospfd/ospf_snmp.c
@@ -1413,7 +1413,7 @@
/* Lookup first IPv4 address entry. */
LIST_LOOP (ifp->connected, ifc, nn)
{
- if (if_is_pointopoint (ifp))
+ if (ifc_pointopoint (ifc))
p = ifc->destination;
else
p = ifc->address;
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index e8bd360..19bc1e5 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -699,17 +699,17 @@
struct connected *co = getdata (cn);
struct prefix *addr;
- if (if_is_pointopoint (ifp))
+ if (ifc_pointopoint (co))
addr = co->destination;
else
addr = co->address;
if (p->family == co->address->family &&
! ospf_if_is_configured (&(addr->u.prefix4)))
- if ((if_is_pointopoint (ifp) &&
+ if ((ifc_pointopoint (co) &&
IPV4_ADDR_SAME (&(addr->u.prefix4), &(p->u.prefix4))) ||
prefix_match (p, addr))
- {
+ {
struct ospf_interface *oi;
oi = ospf_if_new (ifp, co->address);
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index bdfca57..9432717 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -391,106 +391,6 @@
return count;
}
-
-
-
-
-/* Does this address belongs to me ? */
-int
-if_check_address (struct in_addr addr)
-{
- listnode node;
-
- for (node = listhead (iflist); node; nextnode (node))
- {
- listnode cnode;
- struct interface *ifp;
-
- ifp = getdata (node);
-
- for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
- {
- struct connected *connected;
- struct prefix_ipv4 *p;
-
- connected = getdata (cnode);
- p = (struct prefix_ipv4 *) connected->address;
-
- if (p->family != AF_INET)
- continue;
-
- if (IPV4_ADDR_CMP (&p->prefix, &addr) == 0)
- return 1;
- }
- }
- return 0;
-}
-
-/* is this address from a valid neighbor? (RFC2453 - Sec. 3.9.2) */
-int
-if_valid_neighbor (struct in_addr addr)
-{
- listnode node;
- struct connected *connected = NULL;
- struct prefix_ipv4 *p;
-
- for (node = listhead (iflist); node; nextnode (node))
- {
- listnode cnode;
- struct interface *ifp;
-
- ifp = getdata (node);
-
- 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))
- {
- p = (struct prefix_ipv4 *) connected->address;
-
- if (p && p->family == AF_INET)
- {
- if (IPV4_ADDR_SAME (&p->prefix, &addr))
- return 1;
-
- p = (struct prefix_ipv4 *) connected->destination;
- if (p && IPV4_ADDR_SAME (&p->prefix, &addr))
- 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);
- }
- }
- }
- return 0;
-}
/* Inteface link down message processing. */
int
diff --git a/ripd/ripd.c b/ripd/ripd.c
index c63bf10..62ebd47 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -976,7 +976,7 @@
/* The datagram's IPv4 source address should be checked to see
whether the datagram is from a valid neighbor; the source of the
datagram must be on a directly connected network */
- if (! if_valid_neighbor (from->sin_addr))
+ if (if_lookup_address (from->sin_addr) == NULL)
{
zlog_info ("This datagram doesn't came from a valid neighbor: %s",
inet_ntoa (from->sin_addr));
@@ -1535,7 +1535,7 @@
}
/* Check is this packet comming from myself? */
- if (if_check_address (from.sin_addr))
+ if (if_lookup_exact_address (from.sin_addr))
{
if (IS_RIP_DEBUG_PACKET)
zlog_warn ("ignore packet comes from myself");
diff --git a/ripd/ripd.h b/ripd/ripd.h
index 2545db0..17301c3 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -359,8 +359,6 @@
void rip_zclient_start ();
void rip_zclient_reset ();
void rip_offset_init ();
-int if_check_address (struct in_addr addr);
-int if_valid_neighbor (struct in_addr addr);
int rip_request_send (struct sockaddr_in *, struct interface *, u_char);
int rip_neighbor_lookup (struct sockaddr_in *);
diff --git a/zebra/connected.c b/zebra/connected.c
index cb43074..22c9a1f 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -69,7 +69,7 @@
p.prefixlen = addr->prefixlen;
/* Point-to-point check. */
- if (if_is_pointopoint (ifp))
+ if (ifc_pointopoint (ifc))
p.prefix = dest->prefix;
else
p.prefix = addr->prefix;
@@ -162,7 +162,7 @@
p.family = AF_INET;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp))
+ if (ifc_pointopoint (ifc))
p.prefix = dest->prefix;
else
p.prefix = addr->prefix;
@@ -249,7 +249,7 @@
p.family = AF_INET6;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp) && dest)
+ if (ifc_pointopoint (ifc) && dest)
{
if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
p.prefix = addr->prefix;
@@ -339,7 +339,7 @@
p.family = AF_INET6;
p.prefixlen = addr->prefixlen;
- if (if_is_pointopoint (ifp) && dest)
+ if (ifc_pointopoint (ifc) && dest)
{
if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
p.prefix = addr->prefix;
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index fa4dc54..1e39d8a 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -388,6 +388,7 @@
void *broad = NULL;
u_char flags = 0;
char *label = NULL;
+ int peeronly = 0;
ifa = NLMSG_DATA (h);
@@ -416,40 +417,51 @@
return -1;
}
- if (tb[IFA_ADDRESS] == NULL)
- tb[IFA_ADDRESS] = tb[IFA_LOCAL];
-
- if (ifp->flags & IFF_POINTOPOINT)
+ if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
{
+ char buf[BUFSIZ];
+ zlog_info ("netlink_interface_addr %s %s/%d:",
+ lookup (nlmsg_str, h->nlmsg_type),
+ ifp->name, ifa->ifa_prefixlen);
if (tb[IFA_LOCAL])
- {
- addr = RTA_DATA (tb[IFA_LOCAL]);
- if (tb[IFA_ADDRESS])
- broad = RTA_DATA (tb[IFA_ADDRESS]);
- else
- broad = NULL;
- }
- else
- {
- if (tb[IFA_ADDRESS])
- addr = RTA_DATA (tb[IFA_ADDRESS]);
- else
- addr = NULL;
- }
- }
- else
- {
+ zlog_info (" IFA_LOCAL %s", inet_ntop (ifa->ifa_family,
+ RTA_DATA (tb[IFA_LOCAL]), buf, BUFSIZ));
if (tb[IFA_ADDRESS])
- addr = RTA_DATA (tb[IFA_ADDRESS]);
- else
- addr = NULL;
-
+ zlog_info (" IFA_ADDRESS %s", inet_ntop (ifa->ifa_family,
+ RTA_DATA (tb[IFA_ADDRESS]), buf, BUFSIZ));
if (tb[IFA_BROADCAST])
- broad = RTA_DATA(tb[IFA_BROADCAST]);
- else
- broad = NULL;
+ zlog_info (" IFA_BROADCAST %s", inet_ntop (ifa->ifa_family,
+ RTA_DATA (tb[IFA_BROADCAST]), buf, BUFSIZ));
+ if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
+ zlog_info (" IFA_LABEL %s", RTA_DATA (tb[IFA_LABEL]));
}
+ /* peer or broadcast network? */
+ if (ifa->ifa_family == AF_INET)
+ peeronly = if_is_pointopoint (ifp) ||
+ ifa->ifa_prefixlen >= IPV4_MAX_PREFIXLEN - 1;
+#ifdef HAVE_IPV6
+ if (ifa->ifa_family == AF_INET6)
+ peeronly = if_is_pointopoint (ifp) ||
+ ifa->ifa_prefixlen >= IPV6_MAX_PREFIXLEN - 1;
+#endif /* HAVE_IPV6*/
+
+ /* network. prefixlen applies to IFA_ADDRESS rather than IFA_LOCAL */
+ if (tb[IFA_ADDRESS] && !peeronly)
+ addr = RTA_DATA (tb[IFA_ADDRESS]);
+ else if (tb[IFA_LOCAL])
+ addr = RTA_DATA (tb[IFA_LOCAL]);
+ else
+ addr = NULL;
+
+ /* broadcast/peer */
+ if (tb[IFA_BROADCAST])
+ broad = RTA_DATA (tb[IFA_BROADCAST]);
+ else if (tb[IFA_ADDRESS] && peeronly)
+ broad = RTA_DATA (tb[IFA_ADDRESS]); /* peer address specified */
+ else
+ broad = NULL;
+
/* Flags. */
if (ifa->ifa_flags & IFA_F_SECONDARY)
SET_FLAG (flags, ZEBRA_IFA_SECONDARY);