diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/ChangeLog | 15 | ||||
| -rw-r--r-- | lib/if.c | 84 | ||||
| -rw-r--r-- | lib/if.h | 13 | ||||
| -rw-r--r-- | lib/prefix.c | 26 | ||||
| -rw-r--r-- | lib/prefix.h | 8 | ||||
| -rw-r--r-- | lib/zclient.c | 15 | 
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 @@ -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); @@ -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;      }  | 
