From 3fb9cd6ef456959b6eff939d5c316f6785c2dda4 Mon Sep 17 00:00:00 2001 From: hasso Date: Tue, 19 Oct 2004 19:44:43 +0000 Subject: OK. Here it is - PtP patch from Andrew J. Schorr. No problems with ospfd, ripd might need some more testing though. --- lib/ChangeLog | 15 +++++++++++ lib/if.c | 84 +++++++++++++++++++++-------------------------------------- lib/if.h | 13 ++++++++- lib/prefix.c | 26 ++++++++++++++++-- lib/prefix.h | 8 ++++++ lib/zclient.c | 15 ++++++++++- 6 files changed, 102 insertions(+), 59 deletions(-) (limited to 'lib') 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 + + * 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 * 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; } -- cgit v1.2.1