]> git.puffer.fish Git - matthieu/frr.git/commitdiff
OK. Here it is - PtP patch from Andrew J. Schorr. No problems with ospfd,
authorhasso <hasso>
Tue, 19 Oct 2004 19:44:43 +0000 (19:44 +0000)
committerhasso <hasso>
Tue, 19 Oct 2004 19:44:43 +0000 (19:44 +0000)
ripd might need some more testing though.

22 files changed:
ChangeLog
bgpd/ChangeLog
bgpd/bgp_nexthop.c
lib/ChangeLog
lib/if.c
lib/if.h
lib/prefix.c
lib/prefix.h
lib/zclient.c
ospfd/ChangeLog
ospfd/ospf_interface.c
ospfd/ospf_lsa.c
ospfd/ospf_snmp.c
ospfd/ospf_vty.c
ospfd/ospfd.c
ripd/ChangeLog
ripd/rip_interface.c
ripd/ripd.c
zebra/ChangeLog
zebra/connected.c
zebra/interface.c
zebra/rt_netlink.c

index e46bb112c6c56f9d75829232d5cbb7e0d3ad4ce3..e732bca5f48cc9d0028fab5adc8fb2d606476755 100644 (file)
--- 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.
index 37ab163b431639cfd034936e5c57b93d96747672..e82843beb4aa370682db7e264d4bf897fa4f3b75 100644 (file)
@@ -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.
index 4100e3df35347db864e7d63a6dc59502a9d7252a..c50eeedd634e3840b0971d39f5c92bb108cca23b 100644 (file)
@@ -666,7 +666,7 @@ bgp_connected_add (struct connected *ifc)
       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 @@ bgp_connected_add (struct connected *ifc)
       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 @@ bgp_connected_delete (struct connected *ifc)
       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 @@ bgp_connected_delete (struct connected *ifc)
       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;
index 31fb15be77a0287455b3b88dce57f92a2e924739..d0a33d40ae495bd0d7c069bf8acecb8bb14d7c1f 100644 (file)
@@ -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
index 259b84231ca4c01ed6d6dd51843afa40e1810db5..5519b2ae44e96dae8b2e1efcbc77906ccf9a6c2d 100644 (file)
--- 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);
index 218f10266af5f77865d45cbd41e676641eb3cfc4..7afb2ae9e0be51c937fbeaad60642702cd698c93 100644 (file)
--- 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
index d9751e3ff48cfffde7721c5e36d8e308da32d1b6..3f3c4e8e3ee9e9ac68feb33f1b51f7ca21cb42e5 100644 (file)
@@ -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"                   */
index e4f17ab02ab048763b8f19409b62fabdd0cb0f87..0546095b49d1282a80be5919a14bdfd44ad2aea9 100644 (file)
@@ -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
index 98829f611685e16e181949a6711ba0e3d78fbfe9..dfb2f2fc79b956f17f885048f620fdeb2d8664c2 100644 (file)
@@ -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;
     }
index 914ed930ee0d1001c6f0bb4ae76b16a509e4f1ba..31ee303d8cfab5c25d9320ad86dc68c115bd1093 100644 (file)
@@ -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.
index 277d508b45611cdc6fa6d8a54deca6d685ebfffd..e74c375ad16dcb76ba7c2f172bd7910c1d1c294b 100644 (file)
@@ -338,27 +338,45 @@ ospf_if_free (struct ospf_interface *oi)
 \f
 /*
 *  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 @@ ospf_if_lookup_by_prefix (struct ospf *ospf, struct prefix_ipv4 *p)
     {
       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 @@ ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src)
       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;
index 3ad6ddf04507fc287a089eaaf5d1221c7c603fb1..f1478a3d74f6bfb60bd77da5d88d895486b37370 100644 (file)
@@ -517,7 +517,7 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
        links++;
       }
 
-  if (oi->connected->destination != NULL)
+  if (CONNECTED_DEST_HOST(oi->connected))
     {
       /* Option 1:
         link_type = LSA_LINK_TYPE_STUB;
index db0aaf6e204c024917ada395fa08cd939922adcc..0cf257da4dee0f726307240d39fc1ffbe23fcdf3 100644 (file)
@@ -1435,7 +1435,7 @@ ospf_snmp_if_update (struct interface *ifp)
   /* 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;
index 0ecb6fb48a30f1ce19dd845f7be55d8c1697f3c3..c84da747cf13d5bde3c5685fd06db0879017bb13 100644 (file)
@@ -2550,6 +2550,11 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf,
       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);
 
index 0a988e0fafa225f989263bc69041b5f37f0bb06b..054c3316c3dc323e7032a92bf10829ec44e6b577 100644 (file)
@@ -686,31 +686,17 @@ ospf_network_match_iface(struct connected *co, struct prefix *net)
    *   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 @@ ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
           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;
index ee878ff6a2169ebf11980811285408ed1afe6db1..ae67e72d4a6e81b8cb67157de5280cbf429cd48e 100644 (file)
@@ -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
index 509d5ed5d0085a92dd6eba2c3643d9f669db296d..19f6f114cf3b18a70c5ce2d152f5dc4583c2e488 100644 (file)
@@ -143,16 +143,16 @@ rip_interface_multicast_set (int sock, struct connected *connected)
   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 @@ rip_interface_multicast_set (int sock, struct connected *connected)
 
   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 (ripd_privs.change (ZPRIVS_LOWER))
-        zlog_err ("rip_interface_multicast_set: could not lower privs");
+  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));
+    }
 
-         return;
+  if (ripd_privs.change (ZPRIVS_LOWER))
+    zlog_err ("rip_interface_multicast_set: could not lower privs");
 
-       }
+  return;
+}
 
 /* Send RIP request packet to specified interface. */
 void
@@ -229,17 +235,22 @@ rip_request_interface_send (struct interface *ifp, u_char version)
 
       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 @@ if_valid_neighbor (struct in_addr addr)
   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 @@ if_valid_neighbor (struct in_addr addr)
 
       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 @@ if_valid_neighbor (struct in_addr addr)
                    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;
            }
        }
     }
index 2b4e1b2f79e15ba1efa3da43f72b2616b3e9329d..94324f03ab03861859d5e2488850e7f1b99e2c8a 100644 (file)
@@ -2391,7 +2391,6 @@ void
 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 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type,
        {           
          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)
index 506e3ae35a621f9897b648e4b454dd5bab0f9a7b..e3774706eaab61eaf19c2bc7c91a860fe91ffe06 100644 (file)
@@ -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.
index a043ef48e567f9d27088b677e5c6a248d23b6e36..9a6fd6693e90de7ec7c12a8650df01d27b76525b 100644 (file)
@@ -70,7 +70,7 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
   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 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
       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 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
   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;
index 5664f41a41e4fbef0a3b37ecc7e5c7890040226b..a1d0332a72de37eba65e640befaad12eb485537a 100644 (file)
@@ -1107,7 +1107,6 @@ ip_address_install (struct vty *vty, struct interface *ifp,
   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 @@ ip_address_install (struct vty *vty, struct interface *ifp,
       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;
        }
 
index ee61cb27f2115f3673f716a897acf38d3f571c1b..50e83b77c110cfed9c04e674aedc02d68ffe61d5 100644 (file)
@@ -596,7 +596,9 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
       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;