summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ChangeLog15
-rw-r--r--lib/if.c84
-rw-r--r--lib/if.h13
-rw-r--r--lib/prefix.c26
-rw-r--r--lib/prefix.h8
-rw-r--r--lib/zclient.c15
6 files changed, 102 insertions, 59 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog
index 31fb15be..d0a33d40 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 259b8423..5519b2ae 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -258,17 +258,13 @@ if_lookup_address (struct in_addr src)
{
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 @@ if_lookup_address (struct in_addr src)
{
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 @@ struct connected *
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 @@ connected_lookup_address (struct interface *ifp, struct in_addr dst)
{
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 @@ connected_add_by_prefix (struct interface *ifp, struct prefix *p,
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 218f1026..7afb2ae9 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -148,12 +148,23 @@ struct connected
/* 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 d9751e3f..3f3c4e8e 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -247,7 +247,7 @@ str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)
/* 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 @@ void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
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 @@ void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
}
}
+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 e4f17ab0..0546095b 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -153,6 +153,14 @@ void apply_classful_mask_ipv4 (struct prefix_ipv4 *);
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 98829f61..dfb2f2fc 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -644,6 +644,17 @@ zebra_interface_if_set_value (struct stream *s, struct interface *ifp)
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 @@ zebra_interface_address_read (int type, struct stream *s)
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;
}