[quagga-dev 4166] Re: bgpd and pointopoint links

Andrew J. Schorr aschorr at telemetry-investments.com
Mon Jun 19 16:11:27 BST 2006


On Sat, Apr 15, 2006 at 03:31:02PM -0400, Andrew J. Schorr wrote:
> Anyway, I'm attaching my latest version of the patch.  I know that I need to
> test in particular with ospfd (which I'll try to do within the next week), but
> I'd be interested in feedback.  I think it's a big elegance win, and it
> generally simplifies/removes code.  The basic idea is that the CONNECTED_PREFIX
> macro gives the prefix to insert into the RIB, and the CONNECTED_ID macro
> tries to give a unique identifying address for the interface.  With those
> 2 macros in place, it's very rare to access the destination address directly.

OK, after much delay, I finally tested with ospfd and fixed a bug
in ospf_if_is_configured.  I tested on linux with regular PtP links (over
a GRE tunnel), and the new code seems to work just like the old
code.  If somebody could test with PtP over ethernet, that would be great.
Note that I have not tested the other routing protocols, but OSPF
had the trickiest changes.  But ripd should also certainly be tested...

Anyway, I'm happy with this patch and plan to deploy it in production.
One other issue is that we should revisit the logic in
ospfd/ospfd.c:ospf_network_match_iface.  The current code has some strange
behavior that we've been locked into for compatibility reasons (or so
it seems to me).  The patch continues to support that strange behavior,
but I've added an ifdef for COMPATIBILITY_MODE, and if this is
not defined, it would behave more sensibly (in my opinion).  Here's
the new implementation of that function:

/* Check whether interface matches given network
 * returns: 1, true. 0, false
 */
int 
ospf_network_match_iface(struct connected *co, struct prefix *net)
{
#define COMPATIBILITY_MODE
  /* The old code used to have a special case for PtP interfaces:

     if (if_is_pointopoint (co->ifp) && co->destination &&
	 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
       return 1;

     The new approach is much more general.  If a peer address is supplied,
     then we are routing to that prefix, so that's the address to compare
     against (not the local address, which may not be unique).
  */
#ifndef COMPATIBILITY_MODE
  /* new approach: more elegant and conceptually clean */
  return prefix_match(net, CONNECTED_PREFIX(co));
#else /* COMPATIBILITY_MODE */
  /* match old (strange?) behavior */

  /* Behaviour to match both Cisco where:
   *   iface address lies within network specified -> ospf
   * and zebra 0.9[2ish-3]:
   *   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
   * test is solely for compatibility with zebra.
   */
  if (CONNECTED_PEER(co) &&
      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 (prefix_match (net, co->address))
    return 1;

  return 0;			/* no match */

#endif /* COMPATIBILITY_MODE */
}

Does anybody else agree that the old logic is strange and should
be abandoned in favor of the cleaner and simpler
prefix_match(net, CONNECTED_PREFIX(co)) test?  If so, when, if ever,
could we make such a change in behavior?

Feedback on the patch is welcome.

Regards,
Andy
-------------- next part --------------
Index: bgpd/bgp_nexthop.c
===================================================================
RCS file: /var/cvsroot/quagga/bgpd/bgp_nexthop.c,v
retrieving revision 1.16
diff -b -u -p -r1.16 bgp_nexthop.c
--- bgpd/bgp_nexthop.c	21 Feb 2006 01:09:01 -0000	1.16
+++ bgpd/bgp_nexthop.c	19 Jun 2006 14:29:00 -0000
@@ -543,7 +543,6 @@ bgp_connected_add (struct connected *ifc
 {
   struct prefix p;
   struct prefix *addr;
-  struct prefix *dest;
   struct interface *ifp;
   struct bgp_node *rn;
   struct bgp_connected_ref *bc;
@@ -557,19 +556,10 @@ bgp_connected_add (struct connected *ifc
     return;
 
   addr = ifc->address;
-  dest = ifc->destination;
 
   if (addr->family == AF_INET)
     {
-      memset (&p, 0, sizeof (struct prefix));
-      p.family = AF_INET;
-      p.prefixlen = addr->prefixlen;
-
-      if (CONNECTED_POINTOPOINT_HOST(ifc))
-	p.u.prefix4 = dest->u.prefix4;
-      else
-	p.u.prefix4 = addr->u.prefix4;
-
+      PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
 
       if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
@@ -590,17 +580,9 @@ bgp_connected_add (struct connected *ifc
 	}
     }
 #ifdef HAVE_IPV6
-  if (addr->family == AF_INET6)
+  else if (addr->family == AF_INET6)
     {
-      memset (&p, 0, sizeof (struct prefix));
-      p.family = AF_INET6;
-      p.prefixlen = addr->prefixlen;
-
-      if (if_is_pointopoint (ifp) && dest)
-	p.u.prefix6 = dest->u.prefix6;
-      else
-	p.u.prefix6 = addr->u.prefix6;
-
+      PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
 
       if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
@@ -631,7 +613,6 @@ bgp_connected_delete (struct connected *
 {
   struct prefix p;
   struct prefix *addr;
-  struct prefix *dest;
   struct interface *ifp;
   struct bgp_node *rn;
   struct bgp_connected_ref *bc;
@@ -642,19 +623,10 @@ bgp_connected_delete (struct connected *
     return;
 
   addr = ifc->address;
-  dest = ifc->destination;
 
   if (addr->family == AF_INET)
     {
-      memset (&p, 0, sizeof (struct prefix));
-      p.family = AF_INET;
-      p.prefixlen = addr->prefixlen;
-
-      if (CONNECTED_POINTOPOINT_HOST(ifc))
-	p.u.prefix4 = dest->u.prefix4;
-      else
-	p.u.prefix4 = addr->u.prefix4;
-
+      PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
 
       if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
@@ -677,15 +649,7 @@ bgp_connected_delete (struct connected *
 #ifdef HAVE_IPV6
   else if (addr->family == AF_INET6)
     {
-      memset (&p, 0, sizeof (struct prefix));
-      p.family = AF_INET6;
-      p.prefixlen = addr->prefixlen;
-
-      if (if_is_pointopoint (ifp) && dest)
-	p.u.prefix6 = dest->u.prefix6;
-      else
-	p.u.prefix6 = addr->u.prefix6;
-
+      PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
 
       if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
Index: lib/if.c
===================================================================
RCS file: /var/cvsroot/quagga/lib/if.c,v
retrieving revision 1.34
diff -b -u -p -r1.34 if.c
--- lib/if.c	15 Jun 2006 12:48:17 -0000	1.34
+++ lib/if.c	19 Jun 2006 14:29:01 -0000
@@ -275,7 +275,6 @@ if_lookup_address (struct in_addr src)
   int bestlen = 0;
   struct listnode *cnode;
   struct interface *ifp;
-  struct prefix *p;
   struct connected *c;
   struct interface *match;
 
@@ -289,28 +288,15 @@ if_lookup_address (struct in_addr src)
     {
       for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
 	{
-	  if (c->address && (c->address->family == AF_INET))
-	    {
-	      if (CONNECTED_POINTOPOINT_HOST(c))
-		{
-		 /* 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 (prefix_match (p, &addr) && p->prefixlen > bestlen)
+	  if (c->address && (c->address->family == AF_INET) &&
+	      prefix_match(CONNECTED_PREFIX(c), &addr) &&
+	      (c->address->prefixlen > bestlen))
 		    {
-		      bestlen = p->prefixlen;
+	      bestlen = c->address->prefixlen;
 		      match = ifp;
 		    }
 		}
 	    }
-	}
-    }
   return match;
 }
 
@@ -684,7 +670,6 @@ connected_lookup_address (struct interfa
 {
   struct prefix addr;
   struct listnode *cnode;
-  struct prefix *p;
   struct connected *c;
   struct connected *match;
 
@@ -696,25 +681,11 @@ connected_lookup_address (struct interfa
 
   for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
     {
-      if (c->address && (c->address->family == AF_INET))
-        {
-	  if (CONNECTED_POINTOPOINT_HOST(c))
-	    {
-		     /* 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 (prefix_match (p, &addr) &&
-	      	  (!match || (p->prefixlen > match->address->prefixlen)))
+      if (c->address && (c->address->family == AF_INET) &&
+	  prefix_match(CONNECTED_PREFIX(c), &addr) &&
+	  (!match || (c->address->prefixlen > match->address->prefixlen)))
 		match = c;
 	    }
-        }
-    }
   return match;
 }
 
Index: lib/if.h
===================================================================
RCS file: /var/cvsroot/quagga/lib/if.h,v
retrieving revision 1.24
diff -b -u -p -r1.24 if.h
--- lib/if.h	21 May 2006 04:04:50 -0000	1.24
+++ lib/if.h	19 Jun 2006 14:29:01 -0000
@@ -155,25 +155,37 @@ struct connected
   /* Flags for connected address. */
   u_char flags;
 #define ZEBRA_IFA_SECONDARY   (1 << 0)
+#define ZEBRA_IFA_PEER         (1 << 1)
+  /* N.B. the ZEBRA_IFA_PEER flag should be set if and only if
+     a peer address has been configured.  If this flag is set,
+     the destination field must contain the peer address.  
+     Otherwise, if this flag is not set, the destination address
+     will either contain a broadcast address or be NULL.
+   */
 
   /* Address of connected network. */
   struct prefix *address;
-  struct prefix *destination; /* broadcast or peer address; may be NULL */
+
+  /* Peer or Broadcast address, depending on whether ZEBRA_IFA_PEER is set.
+     Note: destination may be NULL if ZEBRA_IFA_PEER is not set. */
+  struct prefix *destination;
 
   /* 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))
+/* Does the destination field contain a peer address? */
+#define CONNECTED_PEER(C) CHECK_FLAG((C)->flags, ZEBRA_IFA_PEER)
+
+/* Prefix to insert into the RIB */
+#define CONNECTED_PREFIX(C) \
+	(CONNECTED_PEER(C) ? (C)->destination : (C)->address)
+
+/* Identifying address.  We guess that if there's a peer address, but the
+   local address is in the same prefix, then the local address may be unique. */
+#define CONNECTED_ID(C)	\
+	((CONNECTED_PEER(C) && !prefix_match((C)->destination, (C)->address)) ?\
+	 (C)->destination : (C)->address)
 
 /* Interface hook sort. */
 #define IF_NEW_HOOK   0
Index: lib/prefix.h
===================================================================
RCS file: /var/cvsroot/quagga/lib/prefix.h,v
retrieving revision 1.7
diff -b -u -p -r1.7 prefix.h
--- lib/prefix.h	6 May 2005 21:25:49 -0000	1.7
+++ lib/prefix.h	19 Jun 2006 14:29:01 -0000
@@ -151,6 +151,9 @@ extern void prefix_ipv4_free (struct pre
 extern int str2prefix_ipv4 (const char *, struct prefix_ipv4 *);
 extern void apply_mask_ipv4 (struct prefix_ipv4 *);
 
+#define PREFIX_COPY_IPV4(DST, SRC)	\
+	*((struct prefix_ipv4 *)(DST)) = *((const struct prefix_ipv4 *)(SRC));
+
 extern int prefix_ipv4_any (const struct prefix_ipv4 *);
 extern void apply_classful_mask_ipv4 (struct prefix_ipv4 *);
 
@@ -172,6 +175,9 @@ extern void prefix_ipv6_free (struct pre
 extern int str2prefix_ipv6 (const char *, struct prefix_ipv6 *);
 extern void apply_mask_ipv6 (struct prefix_ipv6 *);
 
+#define PREFIX_COPY_IPV6(DST, SRC)	\
+	*((struct prefix_ipv6 *)(DST)) = *((const struct prefix_ipv6 *)(SRC));
+
 extern int ip6_masklen (struct in6_addr);
 extern void masklen2ip6 (int, struct in6_addr *);
 
Index: lib/zclient.c
===================================================================
RCS file: /var/cvsroot/quagga/lib/zclient.c,v
retrieving revision 1.21
diff -b -u -p -r1.21 zclient.c
--- lib/zclient.c	17 Jan 2006 17:43:18 -0000	1.21
+++ lib/zclient.c	19 Jun 2006 14:29:01 -0000
@@ -780,7 +780,11 @@ zebra_interface_address_read (int type, 
        ifc = connected_add_by_prefix(ifp, &p,(memconstant(&d.u.prefix,0,plen) ?
 					      NULL : &d));
        if (ifc != NULL)
+	 {
        ifc->flags = ifc_flags;
+	   if (ifc->destination)
+	     ifc->destination->prefixlen = ifc->address->prefixlen;
+	 }
     }
   else
     {
Index: ospfd/ospf_interface.c
===================================================================
RCS file: /var/cvsroot/quagga/ospfd/ospf_interface.c,v
retrieving revision 1.44
diff -b -u -p -r1.44 ospf_interface.c
--- ospfd/ospf_interface.c	15 Jun 2006 18:40:49 -0000	1.44
+++ ospfd/ospf_interface.c	19 Jun 2006 14:29:01 -0000
@@ -360,23 +360,13 @@ ospf_if_is_configured (struct ospf *ospf
       {
 	if (oi->type == OSPF_IFTYPE_POINTOPOINT)
 	  {
-	    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))
+	    /* special leniency: match if addr is anywhere on peer subnet */
+	    if (prefix_match(CONNECTED_PREFIX(oi->connected),
+			     (struct prefix *)&addr))
 		return oi;
 	      }
 	    else
 	      {
-		/* special leniency: match if addr is anywhere on PtP subnet */
-		if (prefix_match(oi->address,(struct prefix *)&addr))
-		  return oi;
-	      }
-	  }
-	else
-	  {
 	    if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4))
 	      return oi;
 	  }
@@ -432,22 +422,15 @@ ospf_if_lookup_by_prefix (struct ospf *o
 {
   struct listnode *node;
   struct ospf_interface *oi;
-  struct prefix ptmp;
   
   /* Check each Interface. */
   for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
     {
       if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
 	{
-	  if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
-	      CONNECTED_DEST_HOST(oi->connected))
-	    {
-	      prefix_copy (&ptmp, oi->connected->destination);
-	      ptmp.prefixlen = IPV4_MAX_BITLEN;
-	    }
-	  else
-	    prefix_copy (&ptmp, oi->address);
+	  struct prefix ptmp;
 	
+	  prefix_copy (&ptmp, CONNECTED_PREFIX(oi->connected));
 	  apply_mask (&ptmp);
 	  if (prefix_same (&ptmp, (struct prefix *) p))
 	    return oi;
@@ -478,15 +461,8 @@ ospf_if_lookup_recv_if (struct ospf *osp
       if (if_is_loopback (oi->ifp))
         continue;
       
-      if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
-	  CONNECTED_DEST_HOST(oi->connected))
-	{
-	  if (IPV4_ADDR_SAME (&oi->connected->destination->u.prefix4, &src))
-	    return oi;
-	}
-      else
-	{
-	  if (prefix_match (oi->address, (struct prefix *) &addr))
+      if (prefix_match (CONNECTED_PREFIX(oi->connected),
+      			(struct prefix *) &addr))
 	    {
 	      if ( (match == NULL) || 
 	           (match->address->prefixlen < oi->address->prefixlen)
@@ -494,7 +470,6 @@ ospf_if_lookup_recv_if (struct ospf *osp
 	        match = oi;
 	    }
 	}
-    }
 
   return match;
 }
Index: ospfd/ospf_lsa.c
===================================================================
RCS file: /var/cvsroot/quagga/ospfd/ospf_lsa.c,v
retrieving revision 1.49
diff -b -u -p -r1.49 ospf_lsa.c
--- ospfd/ospf_lsa.c	15 Jun 2006 12:04:57 -0000	1.49
+++ ospfd/ospf_lsa.c	19 Jun 2006 14:29:02 -0000
@@ -542,7 +542,7 @@ link_info_set (struct stream *s, struct 
   return 1;
 }
 
-/* Describe Point-to-Point link. */
+/* Describe Point-to-Point link (Section 12.4.1.1). */
 static int
 lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
 {
@@ -563,28 +563,13 @@ lsa_link_ptop_set (struct stream *s, str
 		                LSA_LINK_TYPE_POINTOPOINT, 0, cost);
       }
 
-  if (CONNECTED_DEST_HOST(oi->connected))
-    {
-      /* Option 1:
-	 link_type = LSA_LINK_TYPE_STUB;
-	 link_id = nbr->address.u.prefix4;
-	 link_data.s_addr = 0xffffffff;
-	 link_cost = o->output_cost; */
-      
-      id.s_addr = oi->connected->destination->u.prefix4.s_addr;
-      mask.s_addr = 0xffffffff;
-      links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
-                              oi->output_cost);
-    }
-  else
-    {
-       /* Option 2:  We need to include link to a stub
-	 network regardless of the state of the neighbor */
+  /* Regardless of the state of the neighboring router, we must
+     add a Type 3 link (stub network).
+     N.B. Options 1 & 2 share basically the same logic. */
       masklen2ip (oi->address->prefixlen, &mask);
-      id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
+  id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr & mask.s_addr;
       links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 
                               oi->output_cost);
-    }
   return links;
 }
 
Index: ospfd/ospf_snmp.c
===================================================================
RCS file: /var/cvsroot/quagga/ospfd/ospf_snmp.c,v
retrieving revision 1.17
diff -b -u -p -r1.17 ospf_snmp.c
--- ospfd/ospf_snmp.c	6 Oct 2005 07:46:22 -0000	1.17
+++ ospfd/ospf_snmp.c	19 Jun 2006 14:29:03 -0000
@@ -1438,10 +1438,7 @@ ospf_snmp_if_update (struct interface *i
   /* Lookup first IPv4 address entry. */
   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
     {
-      if (CONNECTED_POINTOPOINT_HOST(ifc))
-	p = ifc->destination;
-      else
-	p = ifc->address;
+      p = CONNECTED_ID(ifc);
 
       if (p->family == AF_INET)
 	{
@@ -1491,19 +1488,13 @@ ospf_snmp_if_update (struct interface *i
 int
 ospf_snmp_is_if_have_addr (struct interface *ifp)
 {
-  struct prefix *p;
   struct listnode *nn;
   struct connected *ifc;
 
   /* Is this interface having any connected IPv4 address ? */
   for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, ifc))
   {
-    if (if_is_pointopoint (ifp))
-      p = ifc->destination;
-    else
-      p = ifc->address;
-
-    if (p->family == AF_INET)
+    if (CONNECTED_PREFIX(ifc)->family == AF_INET)
       return 1;
   }
   
Index: ospfd/ospf_vty.c
===================================================================
RCS file: /var/cvsroot/quagga/ospfd/ospf_vty.c,v
retrieving revision 1.55
diff -b -u -p -r1.55 ospf_vty.c
--- ospfd/ospf_vty.c	18 Jun 2006 00:45:48 -0000	1.55
+++ ospfd/ospf_vty.c	19 Jun 2006 14:29:04 -0000
@@ -2731,7 +2731,7 @@ show_ip_ospf_interface_sub (struct vty *
           struct in_addr *dest;
           const char *dstr;
           
-          if ((ifp->flags & IFF_POINTOPOINT)
+          if (CONNECTED_PEER(oi->connected)
               || oi->type == OSPF_IFTYPE_VIRTUALLINK)
             dstr = "Peer";
           else
Index: ospfd/ospfd.c
===================================================================
RCS file: /var/cvsroot/quagga/ospfd/ospfd.c,v
retrieving revision 1.41
diff -b -u -p -r1.41 ospfd.c
--- ospfd/ospfd.c	12 May 2006 22:55:41 -0000	1.41
+++ ospfd/ospfd.c	19 Jun 2006 14:29:05 -0000
@@ -783,6 +783,23 @@ ospf_network_unset (struct ospf *ospf, s
 int 
 ospf_network_match_iface(struct connected *co, struct prefix *net)
 {
+#define COMPATIBILITY_MODE
+  /* The old code used to have a special case for PtP interfaces:
+
+     if (if_is_pointopoint (co->ifp) && co->destination &&
+	 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
+       return 1;
+
+     The new approach is much more general.  If a peer address is supplied,
+     then we are routing to that prefix, so that's the address to compare
+     against (not the local address, which may not be unique).
+  */
+#ifndef COMPATIBILITY_MODE
+  /* new approach: more elegant and conceptually clean */
+  return prefix_match(net, CONNECTED_PREFIX(co));
+#else /* COMPATIBILITY_MODE */
+  /* match old (strange?) behavior */
+
   /* Behaviour to match both Cisco where:
    *   iface address lies within network specified -> ospf
    * and zebra 0.9[2ish-3]:
@@ -794,7 +811,7 @@ ospf_network_match_iface(struct connecte
    * exactly; this is not a test for falling within the prefix.  This
    * test is solely for compatibility with zebra.
    */
-  if (if_is_pointopoint (co->ifp) && co->destination &&
+  if (CONNECTED_PEER(co) &&
       IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
     return 1;
 
@@ -814,6 +831,8 @@ ospf_network_match_iface(struct connecte
     return 1;
 
   return 0;			/* no match */
+
+#endif /* COMPATIBILITY_MODE */
 }
 
 void
@@ -844,10 +863,7 @@ ospf_network_run (struct ospf *ospf, str
           if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
             continue;
 
-	  if (CONNECTED_POINTOPOINT_HOST(co))
-	    addr = co->destination;
-	  else 
-	    addr = co->address;
+	  addr = CONNECTED_ID(co);
 
 	  if (p->family == co->address->family 
 	      && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
Index: ripd/rip_interface.c
===================================================================
RCS file: /var/cvsroot/quagga/ripd/rip_interface.c,v
retrieving revision 1.35
diff -b -u -p -r1.35 rip_interface.c
--- ripd/rip_interface.c	4 May 2006 07:36:34 -0000	1.35
+++ ripd/rip_interface.c	19 Jun 2006 14:29:05 -0000
@@ -141,16 +141,10 @@ void
 rip_interface_multicast_set (int sock, struct connected *connected)
 {
   struct in_addr addr;
-  struct prefix_ipv4 *p;
   
   assert (connected != NULL);
   
-  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;
+  addr = CONNECTED_ID(connected)->u.prefix4;
 
   if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, 0, 
                                  connected->ifp->ifindex) < 0) 
@@ -197,13 +191,16 @@ rip_request_interface_send (struct inter
 	      memset (&to, 0, sizeof (struct sockaddr_in));
 	      to.sin_port = htons (RIP_PORT_DEFAULT);
               if (connected->destination)
-                /* use specified broadcast or point-to-point destination addr */
+                /* use specified broadcast or peer destination addr */
                 to.sin_addr = connected->destination->u.prefix4;
-              else
+              else if (connected->address->prefixlen < IPV4_MAX_PREFIXLEN)
 	        /* calculate the appropriate broadcast address */
                 to.sin_addr.s_addr =
 		  ipv4_broadcast_addr(connected->address->u.prefix4.s_addr,
 				      connected->address->prefixlen);
+	      else
+		/* do not know where to send the packet */
+	        continue;
 
 	      if (IS_RIP_DEBUG_EVENT)
 		zlog_debug ("SEND request to %s", inet_ntoa (to.sin_addr));
Index: ripd/ripd.c
===================================================================
RCS file: /var/cvsroot/quagga/ripd/ripd.c,v
retrieving revision 1.57
diff -b -u -p -r1.57 ripd.c
--- ripd/ripd.c	4 May 2006 07:36:34 -0000	1.57
+++ ripd/ripd.c	19 Jun 2006 14:29:06 -0000
@@ -2448,18 +2448,21 @@ rip_update_interface (struct connected *
           /* Destination address and port setting. */
           memset (&to, 0, sizeof (struct sockaddr_in));
           if (ifc->destination)
-            /* use specified broadcast or point-to-point destination addr */
+            /* use specified broadcast or peer destination addr */
             to.sin_addr = ifc->destination->u.prefix4;
-          else
+          else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN)
             /* calculate the appropriate broadcast address */
             to.sin_addr.s_addr =
               ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
                                   ifc->address->prefixlen);
+	  else
+	    /* do not know where to send the packet */
+	    return;
           to.sin_port = htons (RIP_PORT_DEFAULT);
 
           if (IS_RIP_DEBUG_EVENT)
-            zlog_debug ("%s announce to %s on %s",
-                       if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
+            zlog_debug("%s announce to %s on %s",
+		       CONNECTED_PEER(ifc) ? "unicast" : "broadcast",
                        inet_ntoa (to.sin_addr), ifc->ifp->name);
 
           rip_output_process (ifc, &to, route_type, version);
Index: zebra/connected.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/connected.c,v
retrieving revision 1.24
diff -b -u -p -r1.24 connected.c
--- zebra/connected.c	15 Jun 2006 18:10:47 -0000	1.24
+++ zebra/connected.c	19 Jun 2006 14:29:06 -0000
@@ -173,24 +173,11 @@ void
 connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
 {
   struct prefix_ipv4 p;
-  struct prefix_ipv4 *addr;
-  struct prefix_ipv4 *dest;
 
   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
     return;
 
-  addr = (struct prefix_ipv4 *) ifc->address;
-  dest = (struct prefix_ipv4 *) ifc->destination;
-
-  memset (&p, 0, sizeof (struct prefix_ipv4));
-  p.family = AF_INET;
-  p.prefixlen = addr->prefixlen;
-
-  /* Point-to-point check. */
-  if (CONNECTED_POINTOPOINT_HOST(ifc))
-    p.prefix = dest->prefix;
-  else
-    p.prefix = addr->prefix;
+  PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
 
   /* Apply mask to the network. */
   apply_mask_ipv4 (&p);
@@ -227,33 +214,22 @@ connected_add_ipv4 (struct interface *if
   p->prefixlen = prefixlen;
   ifc->address = (struct prefix *) p;
   
-  /* If there is broadcast or pointopoint address. */
+  /* If there is broadcast or peer address. */
   if (broad)
     {
       p = prefix_ipv4_new ();
       p->family = AF_INET;
       p->prefix = *broad;
+      p->prefixlen = prefixlen;
       ifc->destination = (struct prefix *) p;
 
       /* validate the destination address */
-      if (ifp->flags & IFF_POINTOPOINT)
+      if (CONNECTED_PEER(ifc))
         {
 	  if (IPV4_ADDR_SAME(addr,broad))
-	    zlog_warn("warning: PtP interface %s has same local and peer "
+	    zlog_warn("warning: 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
         {
@@ -273,10 +249,20 @@ connected_add_ipv4 (struct interface *if
 
     }
   else
+    {
+      if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
+        {
+	  zlog_warn("warning: %s called for interface %s "
+		    "with peer flag set, but no peer address supplied",
+		    __func__, ifp->name);
+	  UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
+	}
+
     /* no broadcast or destination address was supplied */
     if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
       zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
       		"peer address",ifp->name,inet_ntoa(*addr),prefixlen);
+    }
 
   /* Label of this address. */
   if (label)
@@ -293,24 +279,11 @@ void
 connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
 {
   struct prefix_ipv4 p;
-  struct prefix_ipv4 *addr;
-  struct prefix_ipv4 *dest;
 
   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
     return;
 
-  addr = (struct prefix_ipv4 *)ifc->address;
-  dest = (struct prefix_ipv4 *)ifc->destination;
-
-  memset (&p, 0, sizeof (struct prefix_ipv4));
-  p.family = AF_INET;
-  p.prefixlen = addr->prefixlen;
-
-  /* Point-to-point check. */
-  if (CONNECTED_POINTOPOINT_HOST(ifc))
-    p.prefix = dest->prefix;
-  else
-    p.prefix = addr->prefix;
+  PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
 
   /* Apply mask to the network. */
   apply_mask_ipv4 (&p);
@@ -350,28 +323,11 @@ void
 connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
 {
   struct prefix_ipv6 p;
-  struct prefix_ipv6 *addr;
-  struct prefix_ipv6 *dest;
 
   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
     return;
 
-  addr = (struct prefix_ipv6 *) ifc->address;
-  dest = (struct prefix_ipv6 *) ifc->destination;
-
-  memset (&p, 0, sizeof (struct prefix_ipv6));
-  p.family = AF_INET6;
-  p.prefixlen = addr->prefixlen;
-
-  if (if_is_pointopoint (ifp) && dest)
-    {
-      if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
-	p.prefix = addr->prefix;
-      else
-	p.prefix = dest->prefix;
-    }
-  else
-    p.prefix = addr->prefix;
+  PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
 
   /* Apply mask to the network. */
   apply_mask_ipv6 (&p);
@@ -390,7 +346,7 @@ connected_up_ipv6 (struct interface *ifp
 
 /* Add connected IPv6 route to the interface. */
 void
-connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
+connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
 		    u_char prefixlen, struct in6_addr *broad,
 		    const char *label)
 {
@@ -400,6 +356,7 @@ connected_add_ipv6 (struct interface *if
   /* Make connected structure. */
   ifc = connected_new ();
   ifc->ifp = ifp;
+  ifc->flags = flags;
 
   /* Allocate new connected address. */
   p = prefix_ipv6_new ();
@@ -408,14 +365,28 @@ connected_add_ipv6 (struct interface *if
   p->prefixlen = prefixlen;
   ifc->address = (struct prefix *) p;
 
-  /* If there is broadcast or pointopoint address. */
+  /* If there is broadcast or peer address. */
   if (broad)
     {
+      if (IN6_IS_ADDR_UNSPECIFIED(broad))
+	zlog_warn("warning: %s called for interface %s with unspecified "
+		  "destination address; ignoring!", __func__, ifp->name);
+      else
+	{
       p = prefix_ipv6_new ();
       p->family = AF_INET6;
       IPV6_ADDR_COPY (&p->prefix, broad);
+	  p->prefixlen = prefixlen;
       ifc->destination = (struct prefix *) p;
     }
+    }
+  if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination)
+    {
+      zlog_warn("warning: %s called for interface %s "
+		"with peer flag set, but no peer address supplied",
+		__func__, ifp->name);
+      UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
+    }
 
   /* Label of this address. */
   if (label)
@@ -431,28 +402,11 @@ void
 connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
 {
   struct prefix_ipv6 p;
-  struct prefix_ipv6 *addr;
-  struct prefix_ipv6 *dest;
 
   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
     return;
 
-  addr = (struct prefix_ipv6 *) ifc->address;
-  dest = (struct prefix_ipv6 *) ifc->destination;
-
-  memset (&p, 0, sizeof (struct prefix_ipv6));
-  p.family = AF_INET6;
-  p.prefixlen = addr->prefixlen;
-
-  if (if_is_pointopoint (ifp) && dest)
-    {
-      if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
-	p.prefix = addr->prefix;
-      else
-	p.prefix = dest->prefix;
-    }
-  else
-    p.prefix = addr->prefix;
+  PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
 
   apply_mask_ipv6 (&p);
 
Index: zebra/connected.h
===================================================================
RCS file: /var/cvsroot/quagga/zebra/connected.h,v
retrieving revision 1.6
diff -b -u -p -r1.6 connected.h
--- zebra/connected.h	26 Nov 2005 09:14:07 -0000	1.6
+++ zebra/connected.h	19 Jun 2006 14:29:06 -0000
@@ -40,7 +40,7 @@ extern void connected_down_ipv4 (struct 
 
 #ifdef HAVE_IPV6
 extern void
-connected_add_ipv6 (struct interface *ifp, struct in6_addr *address,
+connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *address,
 		    u_char prefixlen, struct in6_addr *broad,
 		    const char *label);
 extern void
Index: zebra/if_ioctl.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/if_ioctl.c,v
retrieving revision 1.10
diff -b -u -p -r1.10 if_ioctl.c
--- zebra/if_ioctl.c	17 Jan 2006 17:59:11 -0000	1.10
+++ zebra/if_ioctl.c	19 Jun 2006 14:29:06 -0000
@@ -249,6 +249,7 @@ if_getaddrs (void)
 	  struct sockaddr_in *mask;
 	  struct sockaddr_in *dest;
 	  struct in_addr *dest_pnt;
+	  int flags = 0;
 
 	  addr = (struct sockaddr_in *) ifap->ifa_addr;
 	  mask = (struct sockaddr_in *) ifap->ifa_netmask;
@@ -256,19 +257,25 @@ if_getaddrs (void)
 
 	  dest_pnt = NULL;
 
-	  if (ifap->ifa_flags & IFF_POINTOPOINT) 
+	  if (ifap->ifa_dstaddr &&
+	      !IPV4_ADDR_SAME(&addr->sin_addr,
+			      &((struct sockaddr_in *)
+			      	ifap->ifa_dstaddr)->sin_addr))
 	    {
 	      dest = (struct sockaddr_in *) ifap->ifa_dstaddr;
 	      dest_pnt = &dest->sin_addr;
+	      flags = ZEBRA_IFA_PEER;
 	    }
-
-	  if (ifap->ifa_flags & IFF_BROADCAST)
+	  else if (ifap->ifa_broadaddr &&
+		   !IPV4_ADDR_SAME(&addr->sin_addr,
+				   &((struct sockaddr_in *)
+				     ifap->ifa_broadaddr)->sin_addr))
 	    {
 	      dest = (struct sockaddr_in *) ifap->ifa_broadaddr;
 	      dest_pnt = &dest->sin_addr;
 	    }
 
-	  connected_add_ipv4 (ifp, 0, &addr->sin_addr,
+	  connected_add_ipv4 (ifp, flags, &addr->sin_addr,
 			      prefixlen, dest_pnt, NULL);
 	}
 #ifdef HAVE_IPV6
@@ -278,6 +285,7 @@ if_getaddrs (void)
 	  struct sockaddr_in6 *mask;
 	  struct sockaddr_in6 *dest;
 	  struct in6_addr *dest_pnt;
+	  int flags = 0;
 
 	  addr = (struct sockaddr_in6 *) ifap->ifa_addr;
 	  mask = (struct sockaddr_in6 *) ifap->ifa_netmask;
@@ -285,23 +293,23 @@ if_getaddrs (void)
 
 	  dest_pnt = NULL;
 
-	  if (ifap->ifa_flags & IFF_POINTOPOINT) 
-	    {
-	      if (ifap->ifa_dstaddr)
+	  if (ifap->ifa_dstaddr &&
+	      !IPV6_ADDR_SAME(&addr->sin6_addr,
+			      &((struct sockaddr_in6 *)
+			      	ifap->ifa_dstaddr)->sin6_addr))
 		{
 		  dest = (struct sockaddr_in6 *) ifap->ifa_dstaddr;
 		  dest_pnt = &dest->sin6_addr;
+	      flags = ZEBRA_IFA_PEER;
 		}
-	    }
-
-	  if (ifap->ifa_flags & IFF_BROADCAST)
-	    {
-	      if (ifap->ifa_broadaddr)
+	  else if (ifap->ifa_broadaddr &&
+		   !IPV6_ADDR_SAME(&addr->sin6_addr,
+				   &((struct sockaddr_in6 *)
+				     ifap->ifa_broadaddr)->sin6_addr))
 		{
 		  dest = (struct sockaddr_in6 *) ifap->ifa_broadaddr;
 		  dest_pnt = &dest->sin6_addr;
 		}
-	    }
 
 #if defined(KAME)
 	  if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) 
@@ -312,7 +320,7 @@ if_getaddrs (void)
 	    }	
 #endif          
 
-	  connected_add_ipv6 (ifp, &addr->sin6_addr, prefixlen, 
+	  connected_add_ipv6 (ifp, flags, &addr->sin6_addr, prefixlen, 
 	                      dest_pnt, NULL);
 	}
 #endif /* HAVE_IPV6 */
@@ -335,6 +343,7 @@ if_get_addr (struct interface *ifp)
   struct sockaddr_in dest;
   struct in_addr *dest_pnt;
   u_char prefixlen;
+  int flags = 0;
 
   /* Interface's name and address family. */
   strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ);
@@ -374,40 +383,36 @@ if_get_addr (struct interface *ifp)
   /* Point to point or borad cast address pointer init. */
   dest_pnt = NULL;
 
-  if (ifp->flags & IFF_POINTOPOINT) 
-    {
       ret = if_ioctl (SIOCGIFDSTADDR, (caddr_t) &ifreq);
       if (ret < 0) 
 	{
 	  if (errno != EADDRNOTAVAIL) 
-	    {
 	      zlog_warn ("SIOCGIFDSTADDR fail: %s", safe_strerror (errno));
-	      return ret;
-	    }
-	  return 0;
 	}
+  else if (!IPV4_ADDR_SAME(&addr.sin_addr, &ifreq.ifr_dstaddr.sin_addr))
+    {
       memcpy (&dest, &ifreq.ifr_dstaddr, sizeof (struct sockaddr_in));
       dest_pnt = &dest.sin_addr;
+      flags = ZEBRA_IFA_PEER;
     }
-  if (ifp->flags & IFF_BROADCAST)
+  if (!dest_pnt)
     {
       ret = if_ioctl (SIOCGIFBRDADDR, (caddr_t) &ifreq);
       if (ret < 0) 
 	{
 	  if (errno != EADDRNOTAVAIL) 
-	    {
 	      zlog_warn ("SIOCGIFBRDADDR fail: %s", safe_strerror (errno));
-	      return ret;
-	    }
-	  return 0;
 	}
+      else if (!IPV4_ADDR_SAME(&addr.sin_addr, &ifreq.ifr_broadaddr.sin_addr))
+        {
       memcpy (&dest, &ifreq.ifr_broadaddr, sizeof (struct sockaddr_in));
       dest_pnt = &dest.sin_addr;
     }
+    }
 
 
   /* Set address to the interface. */
-  connected_add_ipv4 (ifp, 0, &addr.sin_addr, prefixlen, dest_pnt, NULL);
+  connected_add_ipv4 (ifp, flags, &addr.sin_addr, prefixlen, dest_pnt, NULL);
 
   return 0;
 }
Index: zebra/if_ioctl_solaris.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/if_ioctl_solaris.c,v
retrieving revision 1.12
diff -b -u -p -r1.12 if_ioctl_solaris.c
--- zebra/if_ioctl_solaris.c	25 Jan 2006 04:31:40 -0000	1.12
+++ zebra/if_ioctl_solaris.c	19 Jun 2006 14:29:06 -0000
@@ -258,6 +258,7 @@ if_get_addr (struct interface *ifp, stru
   char *dest_pnt = NULL;
   u_char prefixlen = 0;
   afi_t af;
+  int flags = 0;
 
   /* Interface's name and address family.
    * We need to use the logical interface name / label, if we've been
@@ -272,21 +273,14 @@ if_get_addr (struct interface *ifp, stru
   /* Point to point or broad cast address pointer init. */
   dest_pnt = NULL;
 
-  if (ifp->flags & IFF_POINTOPOINT)
-    {
-      ret = AF_IOCTL (af, SIOCGLIFDSTADDR, (caddr_t) & lifreq);
-        
-      if (ret < 0)
+  if (AF_IOCTL (af, SIOCGLIFDSTADDR, (caddr_t) & lifreq) >= 0)
         {
-          zlog_warn ("SIOCGLIFDSTADDR (%s) fail: %s",
-                     ifp->name, safe_strerror (errno));
-          return ret;
-        }
       memcpy (&dest, &lifreq.lifr_dstaddr, ADDRLEN (addr));
       if (af == AF_INET)
         dest_pnt = (char *) &(SIN (&dest)->sin_addr);
       else
         dest_pnt = (char *) &(SIN6 (&dest)->sin6_addr);
+      flags = ZEBRA_IFA_PEER;
     }
 
   if (af == AF_INET)
@@ -306,19 +300,8 @@ if_get_addr (struct interface *ifp, stru
       memcpy (&mask, &lifreq.lifr_addr, ADDRLEN (addr));
 
       prefixlen = ip_masklen (SIN (&mask)->sin_addr);
-      if (ifp->flags & IFF_BROADCAST)
-        {
-          ret = if_ioctl (SIOCGLIFBRDADDR, (caddr_t) & lifreq);
-          if (ret < 0)
-            {
-              if (errno != EADDRNOTAVAIL)
+      if (!dest_pnt && (if_ioctl (SIOCGLIFBRDADDR, (caddr_t) & lifreq) >= 0))
                 {
-                  zlog_warn ("SIOCGLIFBRDADDR (%s) fail: %s",
-                             ifp->name, safe_strerror (errno));
-                  return ret;
-                }
-              return 0;
-            }
           memcpy (&dest, &lifreq.lifr_broadaddr, sizeof (struct sockaddr_in));
           dest_pnt = (char *) &SIN (&dest)->sin_addr;
         }
@@ -348,11 +331,11 @@ if_get_addr (struct interface *ifp, stru
 
   /* Set address to the interface. */
   if (af == AF_INET)
-    connected_add_ipv4 (ifp, 0, &SIN (addr)->sin_addr, prefixlen,
+    connected_add_ipv4 (ifp, flags, &SIN (addr)->sin_addr, prefixlen,
                         (struct in_addr *) dest_pnt, label);
 #ifdef HAVE_IPV6
   else if (af == AF_INET6)
-    connected_add_ipv6 (ifp, &SIN6 (addr)->sin6_addr, prefixlen,
+    connected_add_ipv6 (ifp, flags, &SIN6 (addr)->sin6_addr, prefixlen,
                         (struct in6_addr *) dest_pnt, label);
 #endif /* HAVE_IPV6 */
 
Index: zebra/if_proc.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/if_proc.c,v
retrieving revision 1.6
diff -b -u -p -r1.6 if_proc.c
--- zebra/if_proc.c	3 Nov 2005 12:35:21 -0000	1.6
+++ zebra/if_proc.c	19 Jun 2006 14:29:06 -0000
@@ -240,7 +240,7 @@ ifaddr_proc_ipv6 ()
       str2in6_addr (addr, &p.prefix);
       p.prefixlen = plen;
 
-      connected_add_ipv6 (ifp, &p.prefix, p.prefixlen, NULL, ifname);
+      connected_add_ipv6 (ifp, 0, &p.prefix, p.prefixlen, NULL, ifname);
     }
   fclose (fp);
   return 0;
Index: zebra/interface.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/interface.c,v
retrieving revision 1.35
diff -b -u -p -r1.35 interface.c
--- zebra/interface.c	15 Jun 2006 18:10:47 -0000	1.35
+++ zebra/interface.c	19 Jun 2006 14:29:07 -0000
@@ -564,10 +564,6 @@ static void
 connected_dump_vty (struct vty *vty, struct connected *connected)
 {
   struct prefix *p;
-  struct interface *ifp;
-
-  /* Set interface pointer. */
-  ifp = connected->ifp;
 
   /* Print interface address. */
   p = connected->address;
@@ -576,21 +572,10 @@ connected_dump_vty (struct vty *vty, str
   vty_out (vty, "/%d", p->prefixlen);
 
   /* If there is destination address, print it. */
-  p = connected->destination;
-  if (p)
-    {
-      if (p->family == AF_INET)
-	if (ifp->flags & IFF_BROADCAST)
+  if (connected->destination)
 	  {
-	    vty_out (vty, " broadcast ");
-	    prefix_vty_out (vty, p);
-	  }
-
-      if (ifp->flags & IFF_POINTOPOINT)
-	{
-	  vty_out (vty, " pointopoint ");
-	  prefix_vty_out (vty, p);
-	}
+      vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
+      prefix_vty_out (vty, connected->destination);
     }
 
   if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
Index: zebra/kernel_socket.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/kernel_socket.c,v
retrieving revision 1.38
diff -b -u -p -r1.38 kernel_socket.c
--- zebra/kernel_socket.c	17 May 2006 15:04:59 -0000	1.38
+++ zebra/kernel_socket.c	19 Jun 2006 14:29:07 -0000
@@ -605,7 +605,7 @@ ifam_read (struct ifa_msghdr *ifam)
 	SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);
 
       if (ifam->ifam_type == RTM_NEWADDR)
-	connected_add_ipv6 (ifp,
+	connected_add_ipv6 (ifp, 0,
 			    &addr.sin6.sin6_addr, 
 			    ip6_masklen (mask.sin6.sin6_addr),
 			    &brd.sin6.sin6_addr,
Index: zebra/rt_netlink.c
===================================================================
RCS file: /var/cvsroot/quagga/zebra/rt_netlink.c,v
retrieving revision 1.42
diff -b -u -p -r1.42 rt_netlink.c
--- zebra/rt_netlink.c	17 Jan 2006 18:03:04 -0000	1.42
+++ zebra/rt_netlink.c	19 Jun 2006 14:29:07 -0000
@@ -577,8 +577,8 @@ netlink_interface_addr (struct sockaddr_
   struct ifaddrmsg *ifa;
   struct rtattr *tb[IFA_MAX + 1];
   struct interface *ifp;
-  void *addr = NULL;
-  void *broad = NULL;
+  void *addr;
+  void *broad;
   u_char flags = 0;
   char *label = NULL;
 
@@ -637,41 +637,29 @@ netlink_interface_addr (struct sockaddr_
         }
     }
   
+  /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
+  if (tb[IFA_LOCAL] == NULL)
+    tb[IFA_LOCAL] = tb[IFA_ADDRESS];
   if (tb[IFA_ADDRESS] == NULL)
     tb[IFA_ADDRESS] = tb[IFA_LOCAL];
   
-  if (ifp->flags & IFF_POINTOPOINT)
-    {
-      if (tb[IFA_LOCAL])
-        {
-          addr = RTA_DATA (tb[IFA_LOCAL]);
+  /* local interface address */
+  addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
+
+  /* is there a peer address? */
+  /* N.B. I do not understand why the memcmp compares 4 bytes regardless
+     of address family, but this is exactly how it appears in
+     print_addrinfo.  I wonder if it should be RTA_PAYLOAD(tb[IFA_ADDRESS])
+     instead of 4... */
           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;
-        }
-      else
+      memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), 4))
         {
-          if (tb[IFA_ADDRESS])
-            addr = RTA_DATA (tb[IFA_ADDRESS]);
-          else
-            addr = NULL;
+      broad = RTA_DATA(tb[IFA_ADDRESS]);
+      SET_FLAG (flags, ZEBRA_IFA_PEER);
         }
-    }
-  else
-    {
-      if (tb[IFA_ADDRESS])
-        addr = RTA_DATA (tb[IFA_ADDRESS]);
       else
-        addr = NULL;
-      
-      if (tb[IFA_BROADCAST])
-        broad = RTA_DATA(tb[IFA_BROADCAST]);
-      else
-        broad = NULL;
-    }
+    /* seeking a broadcast address */
+    broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL);
 
   /* Flags. */
   if (ifa->ifa_flags & IFA_F_SECONDARY)
@@ -700,7 +688,7 @@ netlink_interface_addr (struct sockaddr_
   if (ifa->ifa_family == AF_INET6)
     {
       if (h->nlmsg_type == RTM_NEWADDR)
-        connected_add_ipv6 (ifp,
+        connected_add_ipv6 (ifp, flags,
                             (struct in6_addr *) addr, ifa->ifa_prefixlen,
                             (struct in6_addr *) broad, label);
       else
@@ -1842,7 +1830,7 @@ netlink_address (int cmd, int family, st
 
   if (family == AF_INET && cmd == RTM_NEWADDR)
     {
-      if (if_is_broadcast (ifp) && ifc->destination)
+      if (!CONNECTED_PEER(ifc) && ifc->destination)
         {
           p = ifc->destination;
           addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,


More information about the Quagga-dev mailing list