]> git.proxmox.com Git - mirror_frr.git/commitdiff
2003-10-15 sowmini.varadhan@sun.com
authorpaul <paul>
Wed, 15 Oct 2003 23:20:17 +0000 (23:20 +0000)
committerpaul <paul>
Wed, 15 Oct 2003 23:20:17 +0000 (23:20 +0000)
        * ripd/ripd.c: (rip_send_packet) use rip->sock for mcast sends,
          instead of creating one socket per send. send source addr to
          rip_update_interface.
          (rip_update_process) should send an update on every connected
          network for each interface.
          (rip_request_send) should send a request on every connected
          network for each interface.
        * ripd/ripd.h: update prototype for rip_interface_multicast_set
        * ripd/rip_interface.c: (rip_interface_multicast_set) reorganized
          so that it can be called repeatedly for aliased interfaces (on
          multiple networks).

ripd/rip_interface.c
ripd/ripd.c
ripd/ripd.h

index 2668e7dcb7ecdb9961928eff2a232c1cf668aad4..e3aea186f1f85cdf7f142d0a3a0c405c32270e30 100644 (file)
@@ -137,28 +137,25 @@ rip_interface_new ()
 }
 
 void
-rip_interface_multicast_set (int sock, struct interface *ifp)
+rip_interface_multicast_set (int sock, struct connected *connected, 
+                             int if_pointopoint)
 {
   int ret;
-  listnode node;
   struct servent *sp;
   struct sockaddr_in from;
-
-  for (node = listhead (ifp->connected); node; nextnode (node))
-    {
-      struct prefix_ipv4 *p;
-      struct connected *connected;
       struct in_addr addr;
+  struct prefix_ipv4 *p;
 
-      connected = getdata (node);
+  if (if_pointopoint)
+    p = (struct prefix_ipv4 *) connected->destination;
+  else
       p = (struct prefix_ipv4 *) connected->address;
 
-      if (p->family == AF_INET)
-       {
          addr = p->prefix;
 
+
          if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF,
-                                        addr, 0, ifp->ifindex) < 0) 
+                                addr, 0, 0) < 0) 
            {
              zlog_warn ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock);
              return;
@@ -176,6 +173,7 @@ rip_interface_multicast_set (int sock, struct interface *ifp)
 
          /* Address shoud be any address. */
          from.sin_family = AF_INET;
+  addr = ((struct prefix_ipv4 *) connected->address)->prefix;
          from.sin_addr = addr;
 #ifdef HAVE_SIN_LEN
          from.sin_len = sizeof (struct sockaddr_in);
@@ -184,12 +182,11 @@ rip_interface_multicast_set (int sock, struct interface *ifp)
     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));
+  bind (sock, NULL, 0); /* unbind any previous association */
+  ret = bind (sock, (struct sockaddr *) & from, sizeof (struct sockaddr_in));
          if (ret < 0)
            {
              zlog_warn ("Can't bind socket: %s", strerror (errno));
-             return;
            }
 
     if (ripd_privs.change (ZPRIVS_LOWER))
@@ -198,8 +195,6 @@ rip_interface_multicast_set (int sock, struct interface *ifp)
          return;
 
        }
-    }
-}
 
 /* Send RIP request packet to specified interface. */
 void
index 68f49ac223bc77b311c148eb0c93666e7a2a087b..accac5e9c5836d658d13bbda2410e84bd4ca032a 100644 (file)
@@ -60,7 +60,8 @@ long rip_global_queries = 0;
 void rip_event (enum rip_event, int);
 
 void rip_output_process (struct interface *, struct prefix *,
-                        struct sockaddr_in *, int, u_char);
+                        struct sockaddr_in *, int, u_char, 
+                         struct prefix_ipv4 *);
 
 /* RIP output routes type. */
 enum
@@ -1238,7 +1239,6 @@ rip_send_packet (caddr_t buf, int size, struct sockaddr_in *to,
 {
   int ret;
   struct sockaddr_in sin;
-  int sock;
 
   /* Make destination address. */
   memset (&sin, 0, sizeof (struct sockaddr_in));
@@ -1250,39 +1250,29 @@ rip_send_packet (caddr_t buf, int size, struct sockaddr_in *to,
   /* When destination is specified, use it's port and address. */
   if (to)
     {
-      sock = rip->sock;
-
       sin.sin_port = to->sin_port;
       sin.sin_addr = to->sin_addr;
     }
   else
     {
-      sock = socket (AF_INET, SOCK_DGRAM, 0);
-      
-      sockopt_broadcast (sock);
-      sockopt_reuseaddr (sock);
-      sockopt_reuseport (sock);
 
       sin.sin_port = htons (RIP_PORT_DEFAULT);
       sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
 
-      /* Set multicast interface. */
-      rip_interface_multicast_set (sock, ifp);
+      /* caller has set multicast interface */
+
     }
 
-  ret = sendto (sock, buf, size, 0, (struct sockaddr *)&sin,
+  ret = sendto (rip->sock, buf, size, 0, (struct sockaddr *)&sin,
                sizeof (struct sockaddr_in));
 
   if (IS_RIP_DEBUG_EVENT)
-      zlog_info ("SEND to socket %d port %d addr %s",
-                 sock, ntohs (sin.sin_port), inet_ntoa(sin.sin_addr));
+      zlog_info ("SEND to  %s.%d", inet_ntoa(sin.sin_addr), 
+                  ntohs (sin.sin_port));
 
   if (ret < 0)
     zlog_warn ("can't send packet : %s", strerror (errno));
 
-  if (! to)
-    close (sock);
-
   return ret;
 }
 
@@ -1454,8 +1444,19 @@ rip_request_process (struct rip_packet *packet, int size,
       ntohs (rte->family) == 0 &&
       ntohl (rte->metric) == RIP_METRIC_INFINITY)
     {  
+      struct prefix_ipv4 saddr;
+
+      /* saddr will be used for determining which routes to split-horizon.
+         Since the source address we'll pick will be on the same subnet as the
+         destination, for the purpose of split-horizoning, we'll
+         pretend that "from" is our source address.  */
+      saddr.family = AF_INET;
+      saddr.prefixlen = IPV4_MAX_BITLEN;
+      saddr.prefix = from->sin_addr;
+
       /* All route with split horizon */
-      rip_output_process (ifp, NULL, from, rip_all_route, packet->version);
+      rip_output_process (ifp, NULL, from, rip_all_route, packet->version, 
+                          &saddr);
     }
   else
     {
@@ -1979,7 +1980,8 @@ rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
 /* Send update to the ifp or spcified neighbor. */
 void
 rip_output_process (struct interface *ifp, struct prefix *ifaddr,
-                   struct sockaddr_in *to, int route_type, u_char version)
+                   struct sockaddr_in *to, int route_type, u_char version,
+                    struct prefix_ipv4 *saddr)
 {
   int ret;
   struct stream *s;
@@ -2118,7 +2120,7 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr,
            /* We perform split horizon for RIP and connected route. */
            if ((rinfo->type == ZEBRA_ROUTE_RIP ||
                 rinfo->type == ZEBRA_ROUTE_CONNECT) &&
-               rinfo->ifindex == ifp->ifindex)
+                 prefix_match((struct prefix *)p, (struct prefix *)saddr))
              continue;
          }
 
@@ -2247,7 +2249,8 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr,
 
 /* Send RIP packet to the interface. */
 void
-rip_update_interface (struct interface *ifp, u_char version, int route_type)
+rip_update_interface (struct interface *ifp, u_char version, int route_type,
+                      struct prefix_ipv4 *saddr)
 {
   struct prefix_ipv4 *p;
   struct connected *connected;
@@ -2260,7 +2263,8 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type)
       if (IS_RIP_DEBUG_EVENT)
        zlog_info ("multicast announce on %s ", ifp->name);
 
-      rip_output_process (ifp, NULL, NULL, route_type, rip->version_send);
+      rip_output_process (ifp, NULL, NULL, route_type, rip->version_send, 
+                          saddr);
       return;
     }
 
@@ -2288,7 +2292,7 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type)
                           inet_ntoa (to.sin_addr), ifp->name);
 
              rip_output_process (ifp, connected->address, &to, route_type,
-                                rip->version_send);
+                                rip->version_send, saddr);
            }
        }
     }
@@ -2298,7 +2302,8 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type)
 void
 rip_update_process (int route_type)
 {
-  listnode node;
+  listnode node, ifnode;
+  struct connected *connected;
   struct interface *ifp;
   struct rip_interface *ri;
   struct route_node *rp;
@@ -2336,15 +2341,29 @@ rip_update_process (int route_type)
                           ifp->ifindex);
            }
 
+          /* send update on each connected network */
+
+         LIST_LOOP(ifp->connected, connected, ifnode)
+           {
+             struct prefix_ipv4 *ifaddr;
+          
+
          /* If there is no version configuration in the interface,
              use rip's version setting. */
-         {
              int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
                           rip->version_send : ri->ri_send);
+
+              ifaddr = (struct prefix_ipv4 *) connected->address;
+
+             if (ifaddr->family != AF_INET)
+               continue;
+
+             rip_interface_multicast_set(rip->sock, connected,
+                                         if_is_pointopoint(ifp));
              if (vsend & RIPv1)
-               rip_update_interface (ifp, RIPv1, route_type);
+               rip_update_interface (ifp, RIPv1, route_type, ifaddr);
              if (vsend & RIPv2)
-               rip_update_interface (ifp, RIPv2, route_type);
+               rip_update_interface (ifp, RIPv2, route_type, ifaddr);
          }
        }
     }
@@ -2369,7 +2388,7 @@ rip_update_process (int route_type)
        to.sin_port = htons (RIP_PORT_DEFAULT);
 
        /* RIP version is rip's configuration. */
-       rip_output_process (ifp, NULL, &to, route_type, rip->version_send);
+       rip_output_process (ifp, NULL, &to, route_type, rip->version_send, p);
       }
 }
 
@@ -2549,6 +2568,8 @@ rip_request_send (struct sockaddr_in *to, struct interface *ifp,
 {
   struct rte *rte;
   struct rip_packet rip_packet;
+  listnode node;
+  struct connected *connected;
 
   memset (&rip_packet, 0, sizeof (rip_packet));
 
@@ -2557,7 +2578,23 @@ rip_request_send (struct sockaddr_in *to, struct interface *ifp,
   rte = rip_packet.rte;
   rte->metric = htonl (RIP_METRIC_INFINITY);
 
-  return rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet), to, ifp);
+  /* send request on each connected network */
+  LIST_LOOP(ifp->connected, connected, node)
+    {
+      struct prefix_ipv4 *p;
+
+      p = (struct prefix_ipv4 *) connected->address;
+
+      if (p->family != AF_INET)
+        continue;
+
+      rip_interface_multicast_set(rip->sock, connected,
+                                 if_is_pointopoint(ifp));
+      if (rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet), 
+                            to, ifp) != sizeof (rip_packet))
+        return -1;
+    }
+  return sizeof (rip_packet);
 }
 \f
 int
index dc2f64d04931cb3e5d3f2d3cd5f0f87b3aaa8048..29e4f67c2b3272150e0811872531fb1e36b737df 100644 (file)
@@ -385,7 +385,7 @@ void rip_redistribute_delete (int, int, struct prefix_ipv4 *, unsigned int);
 void rip_redistribute_withdraw (int);
 void rip_zebra_ipv4_add (struct prefix_ipv4 *, struct in_addr *, u_int32_t, u_char);
 void rip_zebra_ipv4_delete (struct prefix_ipv4 *, struct in_addr *, u_int32_t);
-void rip_interface_multicast_set (int, struct interface *);
+void rip_interface_multicast_set (int, struct connected *, int);
 void rip_distribute_update_interface (struct interface *);
 void rip_if_rmap_update_interface (struct interface *);