]> git.proxmox.com Git - mirror_frr.git/blobdiff - ripd/rip_interface.c
Fix alignment assumptions on non-RT_ROUNDUP platforms.
[mirror_frr.git] / ripd / rip_interface.c
index b47252253d4726df1915dfd48bb9913f69b7b247..23d90a616d93b4198ab82b3d2411b06fa0ed27ed 100644 (file)
 
 #include "ripd/ripd.h"
 #include "ripd/rip_debug.h"
+#include "ripd/rip_interface.h"
 
-void rip_enable_apply (struct interface *);
-void rip_passive_interface_apply (struct interface *);
-int rip_if_down(struct interface *ifp);
-int rip_enable_if_lookup (char *ifname);
-int rip_enable_network_lookup2 (struct connected *connected);
-void rip_enable_apply_all ();
+/* static prototypes */
+static void rip_enable_apply (struct interface *);
+static void rip_passive_interface_apply (struct interface *);
+static int rip_if_down(struct interface *ifp);
+static int rip_enable_if_lookup (const char *ifname);
+static int rip_enable_network_lookup2 (struct connected *connected);
+static void rip_enable_apply_all (void);
 
-
-struct message ri_version_msg[] = 
+const struct message ri_version_msg[] =
 {
   {RI_RIP_VERSION_1,       "1"},
   {RI_RIP_VERSION_2,       "2"},
   {RI_RIP_VERSION_1_AND_2, "1 2"},
-  {0,                      NULL}
 };
 
 extern struct zebra_privs_t ripd_privs;
@@ -68,9 +68,9 @@ struct route_table *rip_enable_network;
 /* Vector to store passive-interface name. */
 static int passive_default;    /* are we in passive-interface default mode? */
 vector Vrip_passive_nondefault;
-\f
+
 /* Join to the RIP version 2 multicast group. */
-int
+static int
 ipv4_multicast_join (int sock, 
                     struct in_addr group, 
                     struct in_addr ifa,
@@ -78,21 +78,20 @@ ipv4_multicast_join (int sock,
 {
   int ret;
 
-  ret = setsockopt_multicast_ipv4 (sock, 
+  ret = setsockopt_ipv4_multicast (sock,
                                   IP_ADD_MEMBERSHIP, 
-                                  ifa, 
                                   group.s_addr, 
                                   ifindex); 
 
   if (ret < 0) 
     zlog (NULL, LOG_INFO, "can't setsockopt IP_ADD_MEMBERSHIP %s",
-         strerror (errno));
+         safe_strerror (errno));
 
   return ret;
 }
 
 /* Leave from the RIP version 2 multicast group. */
-int
+static int
 ipv4_multicast_leave (int sock, 
                      struct in_addr group, 
                      struct in_addr ifa,
@@ -100,9 +99,8 @@ ipv4_multicast_leave (int sock,
 {
   int ret;
 
-  ret = setsockopt_multicast_ipv4 (sock, 
+  ret = setsockopt_ipv4_multicast (sock,
                                   IP_DROP_MEMBERSHIP, 
-                                  ifa, 
                                   group.s_addr, 
                                   ifindex);
 
@@ -111,20 +109,19 @@ ipv4_multicast_leave (int sock,
 
   return ret;
 }
-\f
+
 /* Allocate new RIP's interface configuration. */
-struct rip_interface *
-rip_interface_new ()
+static struct rip_interface *
+rip_interface_new (void)
 {
   struct rip_interface *ri;
 
-  ri = XMALLOC (MTYPE_RIP_INTERFACE, sizeof (struct rip_interface));
-  memset (ri, 0, sizeof (struct rip_interface));
+  ri = XCALLOC (MTYPE_RIP_INTERFACE, sizeof (struct rip_interface));
 
   /* Default authentication type is simple password for Cisco
      compatibility. */
-  /* ri->auth_type = RIP_NO_AUTH; */
-  ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD;
+  ri->auth_type = RIP_NO_AUTH;
+  ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE;
 
   /* Set default split-horizon behavior.  If the interface is Frame
      Relay or SMDS is enabled, the default value for split-horizon is
@@ -137,72 +134,23 @@ rip_interface_new ()
 }
 
 void
-rip_interface_multicast_set (int sock, struct interface *ifp)
+rip_interface_multicast_set (int sock, struct connected *connected)
 {
-  int ret;
-  listnode node;
-  struct servent *sp;
-  struct sockaddr_in from;
-
-  for (node = listhead (ifp->connected); node; nextnode (node))
+  assert (connected != NULL);
+  
+  if (setsockopt_ipv4_multicast_if (sock, connected->ifp->ifindex) < 0)
     {
-      struct prefix_ipv4 *p;
-      struct connected *connected;
-      struct in_addr addr;
-
-      connected = getdata (node);
-      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) 
-           {
-             zlog_warn ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock);
-             return;
-           }
-
-         /* 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);
-
-         /* Address shoud be any address. */
-         from.sin_family = AF_INET;
-         from.sin_addr = addr;
-#ifdef HAVE_SIN_LEN
-         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");
-      
-         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))
-        zlog_err ("rip_interface_multicast_set: could not lower privs");
-
-         return;
-
-       }
+      zlog_warn ("Can't setsockopt IP_MULTICAST_IF on fd %d to "
+                "ifindex %d for interface %s",
+                sock, connected->ifp->ifindex,
+                connected->ifp->name);
     }
+  
+  return;
 }
 
 /* Send RIP request packet to specified interface. */
-void
+static void
 rip_request_interface_send (struct interface *ifp, u_char version)
 {
   struct sockaddr_in to;
@@ -212,45 +160,50 @@ rip_request_interface_send (struct interface *ifp, u_char version)
     {
       
       if (IS_RIP_DEBUG_EVENT)
-       zlog_info ("multicast request on %s", ifp->name);
+       zlog_debug ("multicast request on %s", ifp->name);
 
-      rip_request_send (NULL, ifp, version);
+      rip_request_send (NULL, ifp, version, NULL);
       return;
     }
 
   /* RIPv1 and non multicast interface. */
   if (if_is_pointopoint (ifp) || if_is_broadcast (ifp))
     {
-      listnode cnode;
+      struct listnode *cnode, *cnnode;
+      struct connected *connected;
 
       if (IS_RIP_DEBUG_EVENT)
-       zlog_info ("broadcast request to %s", ifp->name);
+       zlog_debug ("broadcast request to %s", ifp->name);
 
-      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
+      for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, connected))
        {
-         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 peer destination addr */
+                to.sin_addr = connected->destination->u.prefix4;
+              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_info ("SEND request to %s", inet_ntoa (to.sin_addr));
+               zlog_debug ("SEND request to %s", inet_ntoa (to.sin_addr));
              
-             rip_request_send (&to, ifp, version);
+             rip_request_send (&to, ifp, version, connected);
            }
        }
     }
 }
 
 /* This will be executed when interface goes up. */
-void
+static void
 rip_request_interface (struct interface *ifp)
 {
   struct rip_interface *ri;
@@ -279,8 +232,9 @@ rip_request_interface (struct interface *ifp)
   }
 }
 
+#if 0
 /* Send RIP request to the neighbor. */
-void
+static void
 rip_request_neighbor (struct in_addr addr)
 {
   struct sockaddr_in to;
@@ -289,12 +243,12 @@ rip_request_neighbor (struct in_addr addr)
   to.sin_port = htons (RIP_PORT_DEFAULT);
   to.sin_addr = addr;
 
-  rip_request_send (&to, NULL, rip->version_send);
+  rip_request_send (&to, NULL, rip->version_send, NULL);
 }
 
 /* Request routes at all interfaces. */
-void
-rip_request_neighbor_all ()
+static void
+rip_request_neighbor_all (void)
 {
   struct route_node *rp;
 
@@ -302,33 +256,33 @@ rip_request_neighbor_all ()
     return;
 
   if (IS_RIP_DEBUG_EVENT)
-    zlog_info ("request to the all neighbor");
+    zlog_debug ("request to the all neighbor");
 
   /* Send request to all neighbor. */
   for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
     if (rp->info)
       rip_request_neighbor (rp->p.u.prefix4);
 }
+#endif
 
 /* Multicast packet receive socket. */
-int
+static int
 rip_multicast_join (struct interface *ifp, int sock)
 {
-  listnode cnode;
+  struct listnode *cnode;
+  struct connected *ifc;
 
   if (if_is_operative (ifp) && if_is_multicast (ifp))
     {
       if (IS_RIP_DEBUG_EVENT)
-       zlog_info ("multicast join at %s", ifp->name);
+       zlog_debug ("multicast join at %s", ifp->name);
 
-      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
+      for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc))
        {
          struct prefix_ipv4 *p;
-         struct connected *connected;
          struct in_addr group;
              
-         connected = getdata (cnode);
-         p = (struct prefix_ipv4 *) connected->address;
+         p = (struct prefix_ipv4 *) ifc->address;
       
          if (p->family != AF_INET)
            continue;
@@ -344,25 +298,24 @@ rip_multicast_join (struct interface *ifp, int sock)
 }
 
 /* Leave from multicast group. */
-void
+static void
 rip_multicast_leave (struct interface *ifp, int sock)
 {
-  listnode cnode;
+  struct listnode *cnode;
+  struct connected *connected;
 
   if (if_is_up (ifp) && if_is_multicast (ifp))
     {
       if (IS_RIP_DEBUG_EVENT)
-       zlog_info ("multicast leave from %s", ifp->name);
+       zlog_debug ("multicast leave from %s", ifp->name);
 
-      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
+      for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
        {
          struct prefix_ipv4 *p;
-         struct connected *connected;
          struct in_addr group;
-             
-         connected = getdata (cnode);
+          
          p = (struct prefix_ipv4 *) connected->address;
-      
+         
          if (p->family != AF_INET)
            continue;
       
@@ -374,32 +327,61 @@ rip_multicast_leave (struct interface *ifp, int sock)
 }
 
 /* Is there and address on interface that I could use ? */
-int
+static int
 rip_if_ipv4_address_check (struct interface *ifp)
 {
   struct listnode *nn;
   struct connected *connected;
   int count = 0;
 
-  for (nn = listhead (ifp->connected); nn; nextnode (nn))
-    if ((connected = getdata (nn)) != NULL)
-      {
-       struct prefix *p;
+  for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, connected))
+    {
+      struct prefix *p;
 
-       p = connected->address;
+      p = connected->address;
 
-       if (p->family == AF_INET)
-          {
-           count++;
-         }
-      }
+      if (p->family == AF_INET)
+        count++;
+    }
                                                
   return count;
 }
+                                               
+                                               
+                                               
+
+/* Does this address belongs to me ? */
+int
+if_check_address (struct in_addr addr)
+{
+  struct listnode *node;
+  struct interface *ifp;
+  
+  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
+    {
+      struct listnode *cnode;
+      struct connected *connected;
+
+      for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
+       {
+         struct prefix_ipv4 *p;
+
+         p = (struct prefix_ipv4 *) connected->address;
+
+         if (p->family != AF_INET)
+           continue;
+
+         if (IPV4_ADDR_CMP (&p->prefix, &addr) == 0)
+           return 1;
+       }
+    }
+  return 0;
+}
 
 /* Inteface link down message processing. */
 int
-rip_interface_down (int command, struct zclient *zclient, zebra_size_t length)
+rip_interface_down (int command, struct zclient *zclient, zebra_size_t length,
+    vrf_id_t vrf_id)
 {
   struct interface *ifp;
   struct stream *s;
@@ -408,7 +390,7 @@ rip_interface_down (int command, struct zclient *zclient, zebra_size_t length)
 
   /* zebra_interface_state_read() updates interface structure in
      iflist. */
-  ifp = zebra_interface_state_read(s);
+  ifp = zebra_interface_state_read (s, vrf_id);
 
   if (ifp == NULL)
     return 0;
@@ -416,28 +398,31 @@ rip_interface_down (int command, struct zclient *zclient, zebra_size_t length)
   rip_if_down(ifp);
  
   if (IS_RIP_DEBUG_ZEBRA)
-    zlog_info ("interface %s index %d flags %ld metric %d mtu %d is down",
-              ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+    zlog_debug ("interface %s index %d flags %llx metric %d mtu %d is down",
+              ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
+              ifp->metric, ifp->mtu);
 
   return 0;
 }
 
 /* Inteface link up message processing */
 int
-rip_interface_up (int command, struct zclient *zclient, zebra_size_t length)
+rip_interface_up (int command, struct zclient *zclient, zebra_size_t length,
+    vrf_id_t vrf_id)
 {
   struct interface *ifp;
 
   /* zebra_interface_state_read () updates interface structure in
      iflist. */
-  ifp = zebra_interface_state_read (zclient->ibuf);
+  ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
 
   if (ifp == NULL)
     return 0;
 
   if (IS_RIP_DEBUG_ZEBRA)
-    zlog_info ("interface %s index %d flags %ld metric %d mtu %d is up",
-              ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+    zlog_debug ("interface %s index %d flags %#llx metric %d mtu %d is up",
+              ifp->name, ifp->ifindex, (unsigned long long) ifp->flags,
+              ifp->metric, ifp->mtu);
 
   /* Check if this interface is RIP enabled or not.*/
   rip_enable_apply (ifp);
@@ -453,18 +438,23 @@ rip_interface_up (int command, struct zclient *zclient, zebra_size_t length)
 
 /* Inteface addition message from zebra. */
 int
-rip_interface_add (int command, struct zclient *zclient, zebra_size_t length)
+rip_interface_add (int command, struct zclient *zclient, zebra_size_t length,
+    vrf_id_t vrf_id)
 {
   struct interface *ifp;
 
-  ifp = zebra_interface_add_read (zclient->ibuf);
+  ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
 
   if (IS_RIP_DEBUG_ZEBRA)
-    zlog_info ("interface add %s index %d flags %ld metric %d mtu %d",
-              ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+    zlog_debug ("interface add %s index %d flags %#llx metric %d mtu %d",
+               ifp->name, ifp->ifindex, (unsigned long long) ifp->flags,
+               ifp->metric, ifp->mtu);
 
   /* Check if this interface is RIP enabled or not.*/
   rip_enable_apply (ifp);
+  /* Check for a passive interface */
+  rip_passive_interface_apply (ifp);
 
   /* Apply distribute list to the all interface. */
   rip_distribute_update_interface (ifp);
@@ -479,7 +469,7 @@ rip_interface_add (int command, struct zclient *zclient, zebra_size_t length)
 
 int
 rip_interface_delete (int command, struct zclient *zclient,
-                     zebra_size_t length)
+                     zebra_size_t length, vrf_id_t vrf_id)
 {
   struct interface *ifp;
   struct stream *s;
@@ -487,7 +477,7 @@ rip_interface_delete (int command, struct zclient *zclient,
 
   s = zclient->ibuf;  
   /* zebra_interface_state_read() updates interface structure in iflist */
-  ifp = zebra_interface_state_read(s);
+  ifp = zebra_interface_state_read (s, vrf_id);
 
   if (ifp == NULL)
     return 0;
@@ -496,25 +486,26 @@ rip_interface_delete (int command, struct zclient *zclient,
     rip_if_down(ifp);
   } 
   
-  zlog_info("interface delete %s index %d flags %ld metric %d mtu %d",
-           ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);  
+  zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d",
+           ifp->name, ifp->ifindex, (unsigned long long) ifp->flags,
+           ifp->metric, ifp->mtu);
   
   /* To support pseudo interface do not free interface structure.  */
   /* if_delete(ifp); */
+  ifp->ifindex = IFINDEX_DELETED;
 
   return 0;
 }
 
 void
-rip_interface_clean ()
+rip_interface_clean (void)
 {
-  listnode node;
+  struct listnode *node;
   struct interface *ifp;
   struct rip_interface *ri;
 
-  for (node = listhead (iflist); node; nextnode (node))
+  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
     {
-      ifp = getdata (node);
       ri = ifp->info;
 
       ri->enable_network = 0;
@@ -530,15 +521,14 @@ rip_interface_clean ()
 }
 
 void
-rip_interface_reset ()
+rip_interface_reset (void)
 {
-  listnode node;
+  struct listnode *node;
   struct interface *ifp;
   struct rip_interface *ri;
 
-  for (node = listhead (iflist); node; nextnode (node))
+  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
     {
-      ifp = getdata (node);
       ri = ifp->info;
 
       ri->enable_network = 0;
@@ -548,8 +538,7 @@ rip_interface_reset ()
       ri->ri_send = RI_RIP_UNSPEC;
       ri->ri_receive = RI_RIP_UNSPEC;
 
-      /* ri->auth_type = RIP_NO_AUTH; */
-      ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD;
+      ri->auth_type = RIP_NO_AUTH;
 
       if (ri->auth_str)
        {
@@ -603,7 +592,7 @@ rip_if_down(struct interface *ifp)
              {
                rip_zebra_ipv4_delete ((struct prefix_ipv4 *) &rp->p,
                                       &rinfo->nexthop,
-                                      rinfo->ifindex);
+                                      rinfo->metric);
 
                rip_redistribute_delete (rinfo->type,rinfo->sub_type,
                                         (struct prefix_ipv4 *)&rp->p,
@@ -627,7 +616,7 @@ rip_if_down(struct interface *ifp)
   if (ri->running)
    {
      if (IS_RIP_DEBUG_EVENT)
-       zlog_info ("turn off %s", ifp->name);
+       zlog_debug ("turn off %s", ifp->name);
 
      /* Leave from multicast group. */
      rip_multicast_leave (ifp, rip->sock);
@@ -643,17 +632,15 @@ void
 rip_if_down_all ()
 {
   struct interface *ifp;
-  listnode node;
+  struct listnode *node, *nnode;
 
-  for (node = listhead (iflist); node; nextnode (node))
-    {
-      ifp = getdata (node);
-      rip_if_down (ifp);
-    }
+  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp))
+    rip_if_down (ifp);
 }
 
 static void
-rip_apply_address_add (struct connected *ifc) {
+rip_apply_address_add (struct connected *ifc)
+{
   struct prefix_ipv4 address;
   struct prefix *p;
 
@@ -676,18 +663,19 @@ rip_apply_address_add (struct connected *ifc) {
   if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) ||
       (rip_enable_network_lookup2(ifc) >= 0))
     rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
-                         &address, ifc->ifp->ifindex, NULL);
+                         &address, ifc->ifp->ifindex, NULL, 0, 0);
 
 }
 
 int
 rip_interface_address_add (int command, struct zclient *zclient,
-                          zebra_size_t length)
+                          zebra_size_t length, vrf_id_t vrf_id)
 {
   struct connected *ifc;
   struct prefix *p;
 
-  ifc = zebra_interface_address_add_read (zclient->ibuf);
+  ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD, 
+                                      zclient->ibuf, vrf_id);
 
   if (ifc == NULL)
     return 0;
@@ -697,7 +685,7 @@ rip_interface_address_add (int command, struct zclient *zclient,
   if (p->family == AF_INET)
     {
       if (IS_RIP_DEBUG_ZEBRA)
-       zlog_info ("connected address %s/%d is added", 
+       zlog_debug ("connected address %s/%d is added", 
                   inet_ntoa (p->u.prefix4), p->prefixlen);
 
       rip_enable_apply(ifc->ifp);
@@ -737,12 +725,13 @@ rip_apply_address_del (struct connected *ifc) {
 
 int
 rip_interface_address_delete (int command, struct zclient *zclient,
-                             zebra_size_t length)
+                             zebra_size_t length, vrf_id_t vrf_id)
 {
   struct connected *ifc;
   struct prefix *p;
 
-  ifc = zebra_interface_address_delete_read (zclient->ibuf);
+  ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
+                                      zclient->ibuf, vrf_id);
   
   if (ifc)
     {
@@ -750,8 +739,7 @@ rip_interface_address_delete (int command, struct zclient *zclient,
       if (p->family == AF_INET)
        {
          if (IS_RIP_DEBUG_ZEBRA)
-
-           zlog_info ("connected address %s/%d is deleted",
+           zlog_debug ("connected address %s/%d is deleted",
                       inet_ntoa (p->u.prefix4), p->prefixlen);
 
 #ifdef HAVE_SNMP
@@ -769,40 +757,39 @@ rip_interface_address_delete (int command, struct zclient *zclient,
 
   return 0;
 }
-\f
+
 /* Check interface is enabled by network statement. */
 /* Check wether the interface has at least a connected prefix that
  * is within the ripng_enable_network table. */
-int
+static int
 rip_enable_network_lookup_if (struct interface *ifp)
 {
-  struct listnode *nn;
+  struct listnode *node, *nnode;
   struct connected *connected;
   struct prefix_ipv4 address;
 
-  for (nn = listhead (ifp->connected); nn; nextnode (nn))
-    if ((connected = getdata (nn)) != NULL)
-      {
-       struct prefix *p; 
-       struct route_node *node;
+  for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
+    {
+      struct prefix *p; 
+      struct route_node *node;
 
-       p = connected->address;
+      p = connected->address;
 
-       if (p->family == AF_INET)
-         {
-           address.family = AF_INET;
-           address.prefix = p->u.prefix4;
-           address.prefixlen = IPV4_MAX_BITLEN;
-           
-           node = route_node_match (rip_enable_network,
-                                    (struct prefix *)&address);
-           if (node)
-             {
-               route_unlock_node (node);
-               return 1;
-             }
-         }
-      }
+      if (p->family == AF_INET)
+        {
+          address.family = AF_INET;
+          address.prefix = p->u.prefix4;
+          address.prefixlen = IPV4_MAX_BITLEN;
+          
+          node = route_node_match (rip_enable_network,
+                                   (struct prefix *)&address);
+          if (node)
+            {
+              route_unlock_node (node);
+              return 1;
+            }
+        }
+    }
   return -1;
 }
 
@@ -835,7 +822,7 @@ rip_enable_network_lookup2 (struct connected *connected)
   return -1;
 }
 /* Add RIP enable network. */
-int
+static int
 rip_enable_network_add (struct prefix *p)
 {
   struct route_node *node;
@@ -848,7 +835,7 @@ rip_enable_network_add (struct prefix *p)
       return -1;
     }
   else
-    node->info = "enabled";
+    node->info = (void *)1;
 
   /* XXX: One should find a better solution than a generic one */
   rip_enable_apply_all();
@@ -857,7 +844,7 @@ rip_enable_network_add (struct prefix *p)
 }
 
 /* Delete RIP enable network. */
-int
+static int
 rip_enable_network_delete (struct prefix *p)
 {
   struct route_node *node;
@@ -882,13 +869,13 @@ rip_enable_network_delete (struct prefix *p)
 }
 
 /* Check interface is enabled by ifname statement. */
-int
-rip_enable_if_lookup (char *ifname)
+static int
+rip_enable_if_lookup (const char *ifname)
 {
-  int i;
+  unsigned int i;
   char *str;
 
-  for (i = 0; i < vector_max (rip_enable_interface); i++)
+  for (i = 0; i < vector_active (rip_enable_interface); i++)
     if ((str = vector_slot (rip_enable_interface, i)) != NULL)
       if (strcmp (str, ifname) == 0)
        return i;
@@ -896,8 +883,8 @@ rip_enable_if_lookup (char *ifname)
 }
 
 /* Add interface to rip_enable_if. */
-int
-rip_enable_if_add (char *ifname)
+static int
+rip_enable_if_add (const char *ifname)
 {
   int ret;
 
@@ -913,8 +900,8 @@ rip_enable_if_add (char *ifname)
 }
 
 /* Delete interface from rip_enable_if. */
-int
-rip_enable_if_delete (char *ifname)
+static int
+rip_enable_if_delete (const char *ifname)
 {
   int index;
   char *str;
@@ -933,7 +920,7 @@ rip_enable_if_delete (char *ifname)
 }
 
 /* Join to multicast group and send request to the interface. */
-int
+static int
 rip_interface_wakeup (struct thread *t)
 {
   struct interface *ifp;
@@ -961,44 +948,43 @@ rip_interface_wakeup (struct thread *t)
   return 0;
 }
 
-int rip_redistribute_check (int);
-
-void
+static void
 rip_connect_set (struct interface *ifp, int set)
 {
-  struct listnode *nn;
+  struct listnode *node, *nnode;
   struct connected *connected;
   struct prefix_ipv4 address;
 
-  for (nn = listhead (ifp->connected); nn; nextnode (nn))
-    if ((connected = getdata (nn)) != NULL)
-      {
-       struct prefix *p; 
-       p = connected->address;
-
-       if (p->family != AF_INET)
-         continue;
-
-       address.family = AF_INET;
-       address.prefix = p->u.prefix4;
-       address.prefixlen = p->prefixlen;
-       apply_mask_ipv4 (&address);
-
-       if (set) {
-          /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
-          if ((rip_enable_if_lookup(connected->ifp->name) >= 0) ||
-              (rip_enable_network_lookup2(connected) >= 0))
-           rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
-                                 &address, connected->ifp->ifindex, NULL);
-       } else
-         {
-           rip_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
-                                    &address, connected->ifp->ifindex);
-           if (rip_redistribute_check (ZEBRA_ROUTE_CONNECT))
-             rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_REDISTRIBUTE,
-                                   &address, connected->ifp->ifindex, NULL);
-         }
-      }
+  for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
+    {
+      struct prefix *p; 
+      p = connected->address;
+
+      if (p->family != AF_INET)
+        continue;
+
+      address.family = AF_INET;
+      address.prefix = p->u.prefix4;
+      address.prefixlen = p->prefixlen;
+      apply_mask_ipv4 (&address);
+
+      if (set) {
+        /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
+        if ((rip_enable_if_lookup(connected->ifp->name) >= 0) ||
+            (rip_enable_network_lookup2(connected) >= 0))
+          rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
+                                &address, connected->ifp->ifindex, 
+                                NULL, 0, 0);
+      } else
+        {
+          rip_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
+                                   &address, connected->ifp->ifindex);
+          if (rip_redistribute_check (ZEBRA_ROUTE_CONNECT))
+            rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_REDISTRIBUTE,
+                                  &address, connected->ifp->ifindex,
+                                  NULL, 0, 0);
+        }
+    }
 }
 
 /* Update interface status. */
@@ -1042,7 +1028,7 @@ rip_enable_apply (struct interface *ifp)
     {
        {
          if (IS_RIP_DEBUG_EVENT)
-           zlog_info ("turn on %s", ifp->name);
+           zlog_debug ("turn on %s", ifp->name);
 
          /* Add interface wake up thread. */
          if (! ri->t_wakeup)
@@ -1070,14 +1056,11 @@ void
 rip_enable_apply_all ()
 {
   struct interface *ifp;
-  listnode node;
+  struct listnode *node, *nnode;
 
   /* Check each interface. */
-  for (node = listhead (iflist); node; nextnode (node))
-    {
-      ifp = getdata (node);
-      rip_enable_apply (ifp);
-    }
+  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp))
+    rip_enable_apply (ifp);
 }
 
 int
@@ -1101,7 +1084,7 @@ rip_neighbor_lookup (struct sockaddr_in *from)
 }
 
 /* Add new RIP neighbor to the neighbor tree. */
-int
+static int
 rip_neighbor_add (struct prefix_ipv4 *p)
 {
   struct route_node *node;
@@ -1117,7 +1100,7 @@ rip_neighbor_add (struct prefix_ipv4 *p)
 }
 
 /* Delete RIP neighbor from the neighbor tree. */
-int
+static int
 rip_neighbor_delete (struct prefix_ipv4 *p)
 {
   struct route_node *node;
@@ -1142,7 +1125,7 @@ rip_neighbor_delete (struct prefix_ipv4 *p)
 void
 rip_clean_network ()
 {
-  int i;
+  unsigned int i;
   char *str;
   struct route_node *rn;
 
@@ -1155,22 +1138,22 @@ rip_clean_network ()
       }
 
   /* rip_enable_interface. */
-  for (i = 0; i < vector_max (rip_enable_interface); i++)
+  for (i = 0; i < vector_active (rip_enable_interface); i++)
     if ((str = vector_slot (rip_enable_interface, i)) != NULL)
       {
        free (str);
        vector_slot (rip_enable_interface, i) = NULL;
       }
 }
-\f
+
 /* Utility function for looking up passive interface settings. */
-int
-rip_passive_nondefault_lookup (char *ifname)
+static int
+rip_passive_nondefault_lookup (const char *ifname)
 {
-  int i;
+  unsigned int i;
   char *str;
 
-  for (i = 0; i < vector_max (Vrip_passive_nondefault); i++)
+  for (i = 0; i < vector_active (Vrip_passive_nondefault); i++)
     if ((str = vector_slot (Vrip_passive_nondefault, i)) != NULL)
       if (strcmp (str, ifname) == 0)
        return i;
@@ -1188,25 +1171,22 @@ rip_passive_interface_apply (struct interface *ifp)
                 passive_default : !passive_default);
 
   if (IS_RIP_DEBUG_ZEBRA)
-    zlog_info ("interface %s: passive = %d",ifp->name,ri->passive);
+    zlog_debug ("interface %s: passive = %d",ifp->name,ri->passive);
 }
 
-void
-rip_passive_interface_apply_all ()
+static void
+rip_passive_interface_apply_all (void)
 {
   struct interface *ifp;
-  listnode node;
+  struct listnode *node, *nnode;
 
-  for (node = listhead (iflist); node; nextnode (node))
-    {
-      ifp = getdata (node);
-      rip_passive_interface_apply (ifp);
-    }
+  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp))
+    rip_passive_interface_apply (ifp);
 }
 
 /* Passive interface. */
-int
-rip_passive_nondefault_set (struct vty *vty, char *ifname)
+static int
+rip_passive_nondefault_set (struct vty *vty, const char *ifname)
 {
   if (rip_passive_nondefault_lookup (ifname) >= 0)
     return CMD_WARNING;
@@ -1218,8 +1198,8 @@ rip_passive_nondefault_set (struct vty *vty, char *ifname)
   return CMD_SUCCESS;
 }
 
-int
-rip_passive_nondefault_unset (struct vty *vty, char *ifname)
+static int
+rip_passive_nondefault_unset (struct vty *vty, const char *ifname)
 {
   int i;
   char *str;
@@ -1239,12 +1219,12 @@ rip_passive_nondefault_unset (struct vty *vty, char *ifname)
 
 /* Free all configured RIP passive-interface settings. */
 void
-rip_passive_nondefault_clean ()
+rip_passive_nondefault_clean (void)
 {
-  int i;
+  unsigned int i;
   char *str;
 
-  for (i = 0; i < vector_max (Vrip_passive_nondefault); i++)
+  for (i = 0; i < vector_active (Vrip_passive_nondefault); i++)
     if ((str = vector_slot (Vrip_passive_nondefault, i)) != NULL)
       {
        free (str);
@@ -1252,7 +1232,7 @@ rip_passive_nondefault_clean ()
       }
   rip_passive_interface_apply_all ();
 }
-\f
+
 /* RIP enable network or interface configuration. */
 DEFUN (rip_network,
        rip_network_cmd,
@@ -1573,23 +1553,64 @@ DEFUN (ip_rip_authentication_mode,
 {
   struct interface *ifp;
   struct rip_interface *ri;
+  int auth_type;
 
   ifp = (struct interface *)vty->index;
   ri = ifp->info;
 
+  if ( (argc < 1) || (argc > 2) )
+    {
+      vty_out (vty, "incorrect argument count%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+    
   if (strncmp ("md5", argv[0], strlen (argv[0])) == 0)
-    ri->auth_type = RIP_AUTH_MD5;
+    auth_type = RIP_AUTH_MD5;
   else if (strncmp ("text", argv[0], strlen (argv[0])) == 0)
-    ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD;
+    auth_type = RIP_AUTH_SIMPLE_PASSWORD;
   else
     {
       vty_out (vty, "mode should be md5 or text%s", VTY_NEWLINE);
       return CMD_WARNING;
     }
 
+  if (argc == 1)
+    {
+      ri->auth_type = auth_type;
+      return CMD_SUCCESS;
+    }
+
+  if ( (argc == 2) && (auth_type != RIP_AUTH_MD5) )
+    {
+      vty_out (vty, "auth length argument only valid for md5%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (strncmp ("r", argv[1], 1) == 0)
+    ri->md5_auth_len = RIP_AUTH_MD5_SIZE;
+  else if (strncmp ("o", argv[1], 1) == 0)
+    ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE;
+  else 
+    return CMD_WARNING;
+    
+  ri->auth_type = auth_type;
+  
   return CMD_SUCCESS;
 }
 
+ALIAS (ip_rip_authentication_mode,
+       ip_rip_authentication_mode_authlen_cmd,
+       "ip rip authentication mode (md5|text) auth-length (rfc|old-ripd)",
+       IP_STR
+       "Routing Information Protocol\n"
+       "Authentication control\n"
+       "Authentication mode\n"
+       "Keyed message digest\n"
+       "Clear text authentication\n"
+       "MD5 authentication data length\n"
+       "RFC compatible\n"
+       "Old ripd compatible\n")
+
 DEFUN (no_ip_rip_authentication_mode,
        no_ip_rip_authentication_mode_cmd,
        "no ip rip authentication mode",
@@ -1605,8 +1626,8 @@ DEFUN (no_ip_rip_authentication_mode,
   ifp = (struct interface *)vty->index;
   ri = ifp->info;
 
-  /* ri->auth_type = RIP_NO_AUTH; */
-  ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD;
+  ri->auth_type = RIP_NO_AUTH;
+  ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE;
 
   return CMD_SUCCESS;
 }
@@ -1622,6 +1643,20 @@ ALIAS (no_ip_rip_authentication_mode,
        "Keyed message digest\n"
        "Clear text authentication\n")
 
+ALIAS (no_ip_rip_authentication_mode,
+       no_ip_rip_authentication_mode_type_authlen_cmd,
+       "no ip rip authentication mode (md5|text) auth-length (rfc|old-ripd)",
+       NO_STR
+       IP_STR
+       "Routing Information Protocol\n"
+       "Authentication control\n"
+       "Authentication mode\n"
+       "Keyed message digest\n"
+       "Clear text authentication\n"
+       "MD5 authentication data length\n"
+       "RFC compatible\n"
+       "Old ripd compatible\n")
+
 DEFUN (ip_rip_authentication_string,
        ip_rip_authentication_string_cmd,
        "ip rip authentication string LINE",
@@ -1815,7 +1850,7 @@ DEFUN (no_ip_rip_split_horizon,
   return CMD_SUCCESS;
 }
 
-ALIAS (no_ip_rip_split_horizon,
+DEFUN (no_ip_rip_split_horizon_poisoned_reverse,
        no_ip_rip_split_horizon_poisoned_reverse_cmd,
        "no ip rip split-horizon poisoned-reverse",
        NO_STR
@@ -1823,6 +1858,23 @@ ALIAS (no_ip_rip_split_horizon,
        "Routing Information Protocol\n"
        "Perform split horizon\n"
        "With poisoned-reverse\n")
+{
+  struct interface *ifp;
+  struct rip_interface *ri;
+
+  ifp = vty->index;
+  ri = ifp->info;
+
+  switch( ri->split_horizon )
+  {
+       case RIP_SPLIT_HORIZON_POISONED_REVERSE:
+               ri->split_horizon = RIP_SPLIT_HORIZON;
+       default:
+               break;
+  }
+
+  return CMD_SUCCESS;
+}
 
 DEFUN (rip_passive_interface,
        rip_passive_interface_cmd,
@@ -1831,7 +1883,7 @@ DEFUN (rip_passive_interface,
        "Interface name\n"
        "default for all interfaces\n")
 {
-  char *ifname = argv[0];
+  const char *ifname = argv[0];
 
   if (!strcmp(ifname,"default")) {
     passive_default = 1;
@@ -1852,7 +1904,7 @@ DEFUN (no_rip_passive_interface,
        "Interface name\n"
        "default for all interfaces\n")
 {
-  char *ifname = argv[0];
+  const char *ifname = argv[0];
 
   if (!strcmp(ifname,"default")) {
     passive_default = 0;
@@ -1864,19 +1916,21 @@ DEFUN (no_rip_passive_interface,
   else
     return rip_passive_nondefault_unset (vty, ifname);
 }
-\f
+
 /* Write rip configuration of each interface. */
-int
+static int
 rip_interface_config_write (struct vty *vty)
 {
-  listnode node;
+  struct listnode *node;
   struct interface *ifp;
 
-  for (node = listhead (iflist); node; nextnode (node))
+  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
     {
       struct rip_interface *ri;
 
-      ifp = getdata (node);
+      if (ifp->ifindex == IFINDEX_DELETED)
+        continue;
+
       ri = ifp->info;
 
       /* Do not display the interface if there is no
@@ -1887,6 +1941,7 @@ rip_interface_config_write (struct vty *vty)
           (ri->ri_send == RI_RIP_UNSPEC)                   &&
           (ri->ri_receive == RI_RIP_UNSPEC)                &&
           (ri->auth_type != RIP_AUTH_MD5)                  &&
+          (ri->md5_auth_len != RIP_AUTH_MD5_SIZE)          &&
           (!ri->auth_str)                                  &&
           (!ri->key_chain)                                 )
         continue;
@@ -1928,13 +1983,18 @@ rip_interface_config_write (struct vty *vty)
                 VTY_NEWLINE);
 
       /* RIP authentication. */
-#if 0 
-      /* RIP_AUTH_SIMPLE_PASSWORD becomes default mode. */
       if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
        vty_out (vty, " ip rip authentication mode text%s", VTY_NEWLINE);
-#endif /* 0 */
+
       if (ri->auth_type == RIP_AUTH_MD5)
-       vty_out (vty, " ip rip authentication mode md5%s", VTY_NEWLINE);
+        {
+          vty_out (vty, " ip rip authentication mode md5");
+          if (ri->md5_auth_len == RIP_AUTH_MD5_COMPAT_SIZE)
+            vty_out (vty, " auth-length old-ripd");
+          else 
+            vty_out (vty, " auth-length rfc");
+          vty_out (vty, "%s", VTY_NEWLINE);
+        }
 
       if (ri->auth_str)
        vty_out (vty, " ip rip authentication string %s%s",
@@ -1952,7 +2012,7 @@ rip_interface_config_write (struct vty *vty)
 int
 config_write_rip_network (struct vty *vty, int config_mode)
 {
-  int i;
+  unsigned int i;
   char *ifname;
   struct route_node *node;
 
@@ -1966,7 +2026,7 @@ config_write_rip_network (struct vty *vty, int config_mode)
               VTY_NEWLINE);
 
   /* Interface name RIP enable statement. */
-  for (i = 0; i < vector_max (rip_enable_interface); i++)
+  for (i = 0; i < vector_active (rip_enable_interface); i++)
     if ((ifname = vector_slot (rip_enable_interface, i)) != NULL)
       vty_out (vty, "%s%s%s",
               config_mode ? " network " : "    ",
@@ -1985,7 +2045,7 @@ config_write_rip_network (struct vty *vty, int config_mode)
   if (config_mode) {
     if (passive_default)
       vty_out (vty, " passive-interface default%s", VTY_NEWLINE);
-    for (i = 0; i < vector_max (Vrip_passive_nondefault); i++)
+    for (i = 0; i < vector_active (Vrip_passive_nondefault); i++)
       if ((ifname = vector_slot (Vrip_passive_nondefault, i)) != NULL)
        vty_out (vty, " %spassive-interface %s%s",
                 (passive_default ? "no " : ""), ifname, VTY_NEWLINE);
@@ -1994,7 +2054,7 @@ config_write_rip_network (struct vty *vty, int config_mode)
   return 0;
 }
 
-struct cmd_node interface_node =
+static struct cmd_node interface_node =
 {
   INTERFACE_NODE,
   "%s(config-if)# ",
@@ -2002,7 +2062,7 @@ struct cmd_node interface_node =
 };
 
 /* Called when interface structure allocated. */
-int
+static int
 rip_interface_new_hook (struct interface *ifp)
 {
   ifp->info = rip_interface_new ();
@@ -2010,7 +2070,7 @@ rip_interface_new_hook (struct interface *ifp)
 }
 
 /* Called when interface structure deleted. */
-int
+static int
 rip_interface_delete_hook (struct interface *ifp)
 {
   XFREE (MTYPE_RIP_INTERFACE, ifp->info);
@@ -2020,10 +2080,9 @@ rip_interface_delete_hook (struct interface *ifp)
 
 /* Allocate and initialize interface vector. */
 void
-rip_if_init ()
+rip_if_init (void)
 {
   /* Default initial size of interface vector. */
-  if_init();
   if_add_hook (IF_NEW_HOOK, rip_interface_new_hook);
   if_add_hook (IF_DELETE_HOOK, rip_interface_delete_hook);
   
@@ -2064,8 +2123,10 @@ rip_if_init ()
   install_element (INTERFACE_NODE, &no_ip_rip_receive_version_num_cmd);
 
   install_element (INTERFACE_NODE, &ip_rip_authentication_mode_cmd);
+  install_element (INTERFACE_NODE, &ip_rip_authentication_mode_authlen_cmd);
   install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd);
   install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_type_cmd);
+  install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_type_authlen_cmd);
 
   install_element (INTERFACE_NODE, &ip_rip_authentication_key_chain_cmd);
   install_element (INTERFACE_NODE, &no_ip_rip_authentication_key_chain_cmd);