OK. Here it is - PtP patch from Andrew J. Schorr. No problems with ospfd,
ripd might need some more testing though.
diff --git a/ChangeLog b/ChangeLog
index e46bb11..e732bca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+	* lib, zebra, ripd, ospfd, bgpd: Support NULL connected destination
+	  pointers properly everywhere.  Fix point-to-point logic to
+	  support links where a dedicated subnet has been assigned.
+	  PtP links with /31 subnets should now work where supported by O/S.
+
 2004-10-11 Paul Jakma <paul@dishone.st>
 
 	* bump version to 0.97.1, release imminent.
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index 37ab163..e82843b 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -1,3 +1,9 @@
+2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+	* bgp_nexthop.c: (bgp_connected_add) Connected destination pointer
+	  may be NULL.
+	  (bgp_connected_delete) ditto.
+
 2004-10-14 Hasso Tepper <hasso at quagga.net>
 
 	* bgp_dump.c: Make dump configuration appear in vtysh.
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 4100e3d..c50eeed 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -666,7 +666,7 @@
       p.family = AF_INET;
       p.prefixlen = addr->prefixlen;
 
-      if (if_is_pointopoint (ifp))
+      if (CONNECTED_POINTOPOINT_HOST(ifc))
 	p.u.prefix4 = dest->u.prefix4;
       else
 	p.u.prefix4 = addr->u.prefix4;
@@ -697,7 +697,7 @@
       p.family = AF_INET6;
       p.prefixlen = addr->prefixlen;
 
-      if (if_is_pointopoint (ifp))
+      if (if_is_pointopoint (ifp) && dest)
 	p.u.prefix6 = dest->u.prefix6;
       else
 	p.u.prefix6 = addr->u.prefix6;
@@ -751,7 +751,7 @@
       p.family = AF_INET;
       p.prefixlen = addr->prefixlen;
 
-      if (if_is_pointopoint (ifp))
+      if (CONNECTED_POINTOPOINT_HOST(ifc))
 	p.u.prefix4 = dest->u.prefix4;
       else
 	p.u.prefix4 = addr->u.prefix4;
@@ -782,7 +782,7 @@
       p.family = AF_INET6;
       p.prefixlen = addr->prefixlen;
 
-      if (if_is_pointopoint (ifp))
+      if (if_is_pointopoint (ifp) && dest)
 	p.u.prefix6 = dest->u.prefix6;
       else
 	p.u.prefix6 = addr->u.prefix6;
diff --git a/lib/ChangeLog b/lib/ChangeLog
index 31fb15b..d0a33d4 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 259b842..5519b2a 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -258,17 +258,13 @@
 {
   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 @@
 	{
 	  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 @@
 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 @@
     {
       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 @@
   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 218f102..7afb2ae 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -148,12 +148,23 @@
 
   /* 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 d9751e3..3f3c4e8 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -247,7 +247,7 @@
 
       /* 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 @@
   
   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 @@
     }
 }
 
+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 e4f17ab..0546095 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -153,6 +153,14 @@
 
 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 98829f6..dfb2f2f 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -644,6 +644,17 @@
   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 @@
 
   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;
     }
diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog
index 914ed93..31ee303 100644
--- a/ospfd/ChangeLog
+++ b/ospfd/ChangeLog
@@ -1,3 +1,16 @@
+2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+	* ospf_snmp.c: (ospf_snmp_if_update) Fix logic to handle PtP links
+	  with dedicated subnets properly.
+	* ospf_lsa.c: (lsa_link_ptop_set) ditto.
+	* ospfd.c: (ospf_network_match_iface) ditto.
+	  (ospf_network_run) ditto.
+	* ospf_interface.c: (ospf_if_is_configured) ditto.
+	  (ospf_if_lookup_by_prefix) ditto.
+	  (ospf_if_lookup_recv_if) ditto.
+	* ospf_vty.c: (show_ip_ospf_interface_sub) Display the peer or
+	  broadcast address if present.
+
 2004-10-13 Hasso Tepper <hasso at quagga.net>
 
 	* ospf_main.c: Unbreak compilation with ospfapi disabled.
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 277d508..e74c375 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -338,27 +338,45 @@
 
 /*
 *  check if interface with given address is configured and
-*  return it if yes.
+*  return it if yes.  special treatment for PtP networks.
 */
 struct ospf_interface *
 ospf_if_is_configured (struct ospf *ospf, struct in_addr *address)
 {
   struct listnode *node;
   struct ospf_interface *oi;
-  struct prefix *addr;
+  struct prefix_ipv4 addr;
+
+  addr.family = AF_INET;
+  addr.prefix = *address;
+  addr.prefixlen = IPV4_MAX_PREFIXLEN;
   
   for (node = listhead (ospf->oiflist); node; nextnode (node))
     if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
       {
 	if (oi->type == OSPF_IFTYPE_POINTOPOINT)
-	  addr = oi->connected->destination;
+	  {
+	    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))
+		return oi;
+	      }
+	    else
+	      {
+		/* special leniency: match if addr is anywhere on PtP subnet */
+		if (prefix_match(oi->address,(struct prefix *)&addr))
+		  return oi;
+	      }
+	  }
 	else
-	  addr = oi->address;
-	
-	if (IPV4_ADDR_SAME (address, &addr->u.prefix4))
-	  return oi;
+	  {
+	    if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4))
+	      return oi;
+	  }
       }
-
   return NULL;
 }
 
@@ -417,7 +435,8 @@
     {
       if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
 	{
-	  if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+	  if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
+	      CONNECTED_DEST_HOST(oi->connected))
 	    {
 	      prefix_copy (&ptmp, oi->connected->destination);
 	      ptmp.prefixlen = IPV4_MAX_BITLEN;
@@ -454,7 +473,8 @@
       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
 	continue;
       
-      if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+      if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
+	  CONNECTED_DEST_HOST(oi->connected))
 	{
 	  if (IPV4_ADDR_SAME (&oi->connected->destination->u.prefix4, &src))
 	    return oi;
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 3ad6ddf..f1478a3 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -517,7 +517,7 @@
 	links++;
       }
 
-  if (oi->connected->destination != NULL)
+  if (CONNECTED_DEST_HOST(oi->connected))
     {
       /* Option 1:
 	 link_type = LSA_LINK_TYPE_STUB;
diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c
index db0aaf6..0cf257d 100644
--- a/ospfd/ospf_snmp.c
+++ b/ospfd/ospf_snmp.c
@@ -1435,7 +1435,7 @@
   /* Lookup first IPv4 address entry. */
   LIST_LOOP (ifp->connected, ifc, nn)
     {
-      if (if_is_pointopoint (ifp))
+      if (CONNECTED_POINTOPOINT_HOST(ifc))
 	p = ifc->destination;
       else
 	p = ifc->address;
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 0ecb6fb..c84da74 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -2550,6 +2550,11 @@
       vty_out (vty, "  Internet Address %s/%d,",
 	       inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen);
 
+      if (oi->connected->destination)
+	 vty_out (vty, " %s %s,",
+		  ((ifp->flags & IFF_POINTOPOINT) ? "Peer" : "Broadcast"),
+		  inet_ntoa (oi->connected->destination->u.prefix4));
+
       vty_out (vty, " Area %s%s", ospf_area_desc_string (oi->area),
 	       VTY_NEWLINE);
 
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 0a988e0..054c331 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -686,31 +686,17 @@
    *   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
+  /* For PtP, match if peer address matches network address exactly
+   * in situations where the peer address is available and the prefix
+   * length is 32 (i.e. a dedicated subnet has not been assigned).
+   * This is not a test for falling within the prefix.  This
    * test is solely for compatibility with zebra.
-  */
-  if (if_is_pointopoint (co->ifp) && 
-      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 not PtP, accept if the address is within the prefix.
    */
-  if (prefix_match (net, co->address))
-    return 1;
-
-  return 0;			/* no match */
+  return CONNECTED_POINTOPOINT_HOST(co) ?
+	 IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)) :
+	 prefix_match (net, co->address);
 }
 
 void
@@ -748,7 +734,7 @@
           if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
             continue;
 
-	  if (if_is_pointopoint (co->ifp))
+	  if (CONNECTED_POINTOPOINT_HOST(co))
 	    addr = co->destination;
 	  else 
 	    addr = co->address;
diff --git a/ripd/ChangeLog b/ripd/ChangeLog
index ee878ff..ae67e72 100644
--- a/ripd/ChangeLog
+++ b/ripd/ChangeLog
@@ -1,3 +1,15 @@
+2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+	* ripd.c: (rip_update_interface) if connected->destination is NULL,
+	  get the broadcast address with ipv4_broadcast_addr()
+	* rip_interface.c: (rip_interface_multicast_set)
+	  connected->destination may be NULL. Improve message if
+	  setsockopt_multicast_ipv4 fails. Improve message if bind fails.
+	  (rip_request_interface_send) If connected->destination is NULL,
+	  get the broadcast address with ipv4_broadcast_addr().
+	  (if_valid_neighbor) Handle PtP subnet addressing properly.
+	  Speed up code by using prefix_match properly.
+
 2004-10-13 Hasso Tepper <hasso at quagga.net>
 
 	* ripd_snmp.c: Remove defaults used to initialize smux connection to
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 509d5ed..19f6f11 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -143,16 +143,16 @@
   int ret;
   struct servent *sp;
   struct sockaddr_in from;
-      struct in_addr addr;
+  struct in_addr addr;
   struct prefix_ipv4 *p;
 
   if (connected != NULL) 
     {
-  if (if_is_pointopoint(connected->ifp))
-    p = (struct prefix_ipv4 *) connected->destination;
-  else
-      p = (struct prefix_ipv4 *) connected->address;
-	  addr = p->prefix;
+      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;
     }
   else 
     {
@@ -161,46 +161,52 @@
 
   if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, 0, 
                                  connected->ifp->ifindex) < 0) 
-	    {
-	      zlog_warn ("Can't setsockopt IP_MULTICAST_IF to fd %d, ifindex %d", 
-	                 sock, connected->ifp->ifindex);
-	      return;
-	    }
+    {
+      zlog_warn ("Can't setsockopt IP_MULTICAST_IF on fd %d to "
+		 "source address %s for interface %s",
+		 sock, inet_ntoa(addr),
+		 (connected ? connected->ifp->name : "(unknown)"));
+      return;
+    }
 
-	  /* Bind myself. */
-	  memset (&from, 0, sizeof (struct sockaddr_in));
+  /* Bind myself. */
+  memset (&from, 0, sizeof (struct sockaddr_in));
 
-	  /* Set RIP port. */
-	  sp = getservbyname ("router", "udp");
-	  if (sp) 
-	    from.sin_port = sp->s_port;
-	  else 
-	    from.sin_port = htons (RIP_PORT_DEFAULT);
+  /* Set RIP port. */
+  sp = getservbyname ("router", "udp");
+  if (sp) 
+    from.sin_port = sp->s_port;
+  else 
+    from.sin_port = htons (RIP_PORT_DEFAULT);
 
   /* Address should be any address. */
-	  from.sin_family = AF_INET;
+  from.sin_family = AF_INET;
   if (connected)
-  addr = ((struct prefix_ipv4 *) connected->address)->prefix;
-	  from.sin_addr = addr;
+    addr = ((struct prefix_ipv4 *) connected->address)->prefix;
+  from.sin_addr = addr;
 #ifdef HAVE_SIN_LEN
-	  from.sin_len = sizeof (struct sockaddr_in);
+  from.sin_len = sizeof (struct sockaddr_in);
 #endif /* HAVE_SIN_LEN */
 
-    if (ripd_privs.change (ZPRIVS_RAISE))
-      zlog_err ("rip_interface_multicast_set: could not raise privs");
+  if (ripd_privs.change (ZPRIVS_RAISE))
+    zlog_err ("rip_interface_multicast_set: could not raise privs");
       
   ret = bind (sock, (struct sockaddr *) & from, sizeof (struct sockaddr_in));
-	  if (ret < 0)
-	    {
-	      zlog_warn ("Can't bind socket: %s", strerror (errno));
-	    }
+  if (ret < 0)
+    {
+      zlog_warn ("Can't bind socket fd %d to %s port %d for "
+		 "interface %s: %s",
+	      	 sock,inet_ntoa(from.sin_addr),
+		 (int)ntohs(from.sin_port),
+		 (connected ? connected->ifp->name : "(unknown)"),
+		  strerror (errno));
+    }
 
-    if (ripd_privs.change (ZPRIVS_LOWER))
-        zlog_err ("rip_interface_multicast_set: could not lower privs");
+  if (ripd_privs.change (ZPRIVS_LOWER))
+    zlog_err ("rip_interface_multicast_set: could not lower privs");
 
-	  return;
-
-	}
+  return;
+}
 
 /* Send RIP request packet to specified interface. */
 void
@@ -229,17 +235,22 @@
 
       for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
 	{
-	  struct prefix_ipv4 *p;
 	  struct connected *connected;
 
 	  connected = getdata (cnode);
-	  p = (struct prefix_ipv4 *) connected->destination;
 
-	  if (p->family == AF_INET)
+	  if (connected->address->family == AF_INET)
 	    {
 	      memset (&to, 0, sizeof (struct sockaddr_in));
 	      to.sin_port = htons (RIP_PORT_DEFAULT);
-	      to.sin_addr = p->prefix;
+              if (connected->destination)
+                /* use specified broadcast or point-to-point destination addr */
+                to.sin_addr = connected->destination->u.prefix4;
+              else
+	        /* calculate the appropriate broadcast address */
+                to.sin_addr.s_addr =
+		  ipv4_broadcast_addr(connected->address->u.prefix4.s_addr,
+				      connected->address->prefixlen);
 
 	      if (IS_RIP_DEBUG_EVENT)
 		zlog_info ("SEND request to %s", inet_ntoa (to.sin_addr));
@@ -439,6 +450,11 @@
   struct listnode *node;
   struct connected *connected = NULL;
   struct prefix_ipv4 *p;
+  struct prefix_ipv4 pa;
+
+  pa.family = AF_INET;
+  pa.prefix = addr;
+  pa.prefixlen = IPV4_MAX_PREFIXLEN;
 
   for (node = listhead (iflist); node; nextnode (node))
     {
@@ -449,9 +465,6 @@
 
       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))
@@ -464,34 +477,23 @@
 		    return 1;
 
 		  p = (struct prefix_ipv4 *) connected->destination;
-		  if (p && IPV4_ADDR_SAME (&p->prefix, &addr))
-		    return 1;
+		  if (p)
+		    {
+		      if (IPV4_ADDR_SAME (&p->prefix, &addr))
+			return 1;
+		    }
+		  else
+		    {
+		      if (prefix_match(connected->address,(struct prefix *)&pa))
+			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);
+	      if ((connected->address->family == AF_INET) &&
+		  prefix_match(connected->address,(struct prefix *)&pa))
+		return 1;
 	    }
 	}
     }
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 2b4e1b2..94324f0 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -2391,7 +2391,6 @@
 rip_update_interface (struct interface *ifp, u_char version, int route_type,
                       struct connected *sconn)
 {
-  struct prefix_ipv4 *p;
   struct connected *connected;
   struct listnode *node;
   struct sockaddr_in to;
@@ -2415,15 +2414,18 @@
 	{	    
 	  connected = getdata (node);
 
-	  /* Fetch broadcast address or poin-to-point destination
-             address . */
-	  p = (struct prefix_ipv4 *) connected->destination;
-
-	  if (p->family == AF_INET)
+	  if (connected->address->family == AF_INET)
 	    {
 	      /* Destination address and port setting. */
 	      memset (&to, 0, sizeof (struct sockaddr_in));
-	      to.sin_addr = p->prefix;
+	      if (connected->destination)
+		/* use specified broadcast or point-to-point destination addr */
+	        to.sin_addr = connected->destination->u.prefix4;
+	      else
+		/* calculate the appropriate broadcast address */
+	        to.sin_addr.s_addr =
+		  ipv4_broadcast_addr(connected->address->u.prefix4.s_addr,
+				      connected->address->prefixlen);
 	      to.sin_port = htons (RIP_PORT_DEFAULT);
 
 	      if (IS_RIP_DEBUG_EVENT)
diff --git a/zebra/ChangeLog b/zebra/ChangeLog
index 506e3ae..e377470 100644
--- a/zebra/ChangeLog
+++ b/zebra/ChangeLog
@@ -1,3 +1,15 @@
+2004-10-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+	* rt_netlink.c: (netlink_interface_addr) For PtP interfaces, ignore
+	  tb[IFA_ADDRESS] if it's the same as tb[IFA_LOCAL].
+	* interface.c: (ip_address_install) Use new ipv4_broadcast_addr
+	  function.
+	* connected.c: (connected_up_ipv4) Use CONNECTED_POINTOPOINT_HOST
+	  macro.
+	  (connected_down_ipv4) ditto.
+	  (connected_add_ipv4) Validate destination address, print warnings
+	  if it does not make sense.
+
 2004-10-19 Hasso Tepper <hasso at quagga.net>
 
 	* zserv.c: Fix regression introduced with zserv cleanup.
diff --git a/zebra/connected.c b/zebra/connected.c
index a043ef4..9a6fd66 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -70,7 +70,7 @@
   p.prefixlen = addr->prefixlen;
 
   /* Point-to-point check. */
-  if (if_is_pointopoint (ifp) && dest)
+  if (CONNECTED_POINTOPOINT_HOST(ifc))
     p.prefix = dest->prefix;
   else
     p.prefix = addr->prefix;
@@ -116,7 +116,49 @@
       p->family = AF_INET;
       p->prefix = *broad;
       ifc->destination = (struct prefix *) p;
+
+      /* validate the destination address */
+      if (ifp->flags & IFF_POINTOPOINT)
+        {
+	  if (IPV4_ADDR_SAME(addr,broad))
+	    zlog_warn("warning: PtP 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
+        {
+	  if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
+	    {
+	      char buf[2][INET_ADDRSTRLEN];
+	      struct in_addr bcalc;
+	      bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
+	      zlog_warn("warning: interface %s broadcast addr %s/%d != "
+	       		"calculated %s, routing protocols may malfunction",
+	    		ifp->name,
+			inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
+			prefixlen,
+			inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
+	    }
+        }
+
     }
+  else
+    /* no broadcast or destination address was supplied */
+    if (prefixlen == IPV4_MAX_PREFIXLEN)
+      zlog_warn("warning: interface %s with addr %s/%d needs a peer address",
+		ifp->name,inet_ntoa(*addr),prefixlen);
 
   /* Label of this address. */
   if (label)
@@ -166,7 +208,7 @@
   p.prefixlen = addr->prefixlen;
 
   /* Point-to-point check. */
-  if (dest && if_is_pointopoint (ifp))
+  if (CONNECTED_POINTOPOINT_HOST(ifc))
     p.prefix = dest->prefix;
   else
     p.prefix = addr->prefix;
diff --git a/zebra/interface.c b/zebra/interface.c
index 5664f41..a1d0332 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1107,7 +1107,6 @@
   struct prefix_ipv4 cp;
   struct connected *ifc;
   struct prefix_ipv4 *p;
-  struct in_addr mask;
   int ret;
 
   ret = str2prefix_ipv4 (addr_str, &cp);
@@ -1129,12 +1128,11 @@
       ifc->address = (struct prefix *) p;
 
       /* Broadcast. */
-      if (p->prefixlen <= 30)
+      if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
 	{
 	  p = prefix_ipv4_new ();
 	  *p = cp;
-	  masklen2ip (p->prefixlen, &mask);
-	  p->prefix.s_addr |= ~mask.s_addr;
+	  p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
 	  ifc->destination = (struct prefix *) p;
 	}
 
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index ee61cb2..50e83b7 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -596,7 +596,9 @@
       if (tb[IFA_LOCAL])
         {
           addr = RTA_DATA (tb[IFA_LOCAL]);
-          if (tb[IFA_ADDRESS])
+          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;