Merge RIP part of 6Wind patch.
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 23c9cb0..8ec96ae 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -43,6 +43,10 @@
 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 ();
+
 
 struct message ri_version_msg[] = 
 {
@@ -122,7 +126,7 @@
      Relay or SMDS is enabled, the default value for split-horizon is
      off.  But currently Zebra does detect Frame Relay or SMDS
      interface.  So all interface is set to split horizon.  */
-  ri->split_horizon_default = 1;
+  ri->split_horizon_default = RIP_SPLIT_HORIZON;
   ri->split_horizon = ri->split_horizon_default;
 
   return ri;
@@ -226,10 +230,8 @@
 	      to.sin_port = htons (RIP_PORT_DEFAULT);
 	      to.sin_addr = p->prefix;
 
-#if 0
 	      if (IS_RIP_DEBUG_EVENT)
 		zlog_info ("SEND request to %s", inet_ntoa (to.sin_addr));
-#endif /* 0 */
 	      
 	      rip_request_send (&to, ifp, version);
 	    }
@@ -466,6 +468,9 @@
 
   /* rip_request_neighbor_all (); */
 
+  /* Check interface routemap. */
+  rip_if_rmap_update_interface (ifp);
+
   return 0;
 }
 
@@ -554,8 +559,8 @@
 	  ri->key_chain = NULL;
 	}
 
-      ri->split_horizon = 0;
-      ri->split_horizon_default = 0;
+      ri->split_horizon = RIP_NO_SPLIT_HORIZON;
+      ri->split_horizon_default = RIP_NO_SPLIT_HORIZON;
 
       ri->list[RIP_FILTER_IN] = NULL;
       ri->list[RIP_FILTER_OUT] = NULL;
@@ -644,6 +649,34 @@
     }
 }
 
+static void
+rip_apply_address_add (struct connected *ifc) {
+  struct prefix_ipv4 address;
+  struct prefix *p;
+
+  if (!rip)
+    return;
+
+  if (! if_is_up(ifc->ifp))
+    return;
+
+  p = ifc->address;
+
+  memset (&address, 0, sizeof (address));
+  address.family = p->family;
+  address.prefix = p->u.prefix4;
+  address.prefixlen = p->prefixlen;
+  apply_mask_ipv4(&address);
+
+  /* Check if this interface is RIP enabled or not
+     or  Check if this address's prefix is RIP enabled */
+  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);
+
+}
+
 int
 rip_interface_address_add (int command, struct zclient *zclient,
 			   zebra_size_t length)
@@ -663,9 +696,9 @@
       if (IS_RIP_DEBUG_ZEBRA)
 	zlog_info ("connected address %s/%d is added", 
 		   inet_ntoa (p->u.prefix4), p->prefixlen);
-      
-      /* Check is this interface is RIP enabled or not.*/
-      rip_enable_apply (ifc->ifp);
+
+      /* Check if this prefix needs to be redistributed */
+      rip_apply_address_add(ifc);
 
 #ifdef HAVE_SNMP
       rip_ifaddr_add (ifc->ifp, ifc);
@@ -675,6 +708,29 @@
   return 0;
 }
 
+static void
+rip_apply_address_del (struct connected *ifc) {
+  struct prefix_ipv4 address;
+  struct prefix *p;
+
+  if (!rip)
+    return;
+
+  if (! if_is_up(ifc->ifp))
+    return;
+
+  p = ifc->address;
+
+  memset (&address, 0, sizeof (address));
+  address.family = p->family;
+  address.prefix = p->u.prefix4;
+  address.prefixlen = p->prefixlen;
+  apply_mask_ipv4(&address);
+
+  rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
+                          &address, ifc->ifp->ifindex);
+}
+
 int
 rip_interface_address_delete (int command, struct zclient *zclient,
 			      zebra_size_t length)
@@ -698,8 +754,9 @@
 	  rip_ifaddr_delete (ifc->ifp, ifc);
 #endif /* HAVE_SNMP */
 
-	  /* Check if this interface is RIP enabled or not.*/
-	  rip_enable_apply (ifc->ifp);
+	  /* Chech wether this prefix needs to be removed */
+          rip_apply_address_del(ifc);
+
 	}
 
       connected_free (ifc);
@@ -710,8 +767,10 @@
 }
 
 /* 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
-rip_enable_network_lookup (struct interface *ifp)
+rip_enable_network_lookup_if (struct interface *ifp)
 {
   struct listnode *nn;
   struct connected *connected;
@@ -743,6 +802,34 @@
   return -1;
 }
 
+/* Check wether connected is within the ripng_enable_network table. */
+int
+rip_enable_network_lookup2 (struct connected *connected)
+{
+  struct prefix_ipv4 address;
+  struct prefix *p;
+
+  p = connected->address;
+
+  if (p->family == AF_INET) {
+    struct route_node *node;
+
+    address.family = p->family;
+    address.prefix = p->u.prefix4;
+    address.prefixlen = IPV4_MAX_BITLEN;
+
+    /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within rip_enable_network */
+    node = route_node_match (rip_enable_network,
+                             (struct prefix *)&address);
+
+    if (node) {
+      route_unlock_node (node);
+      return 1;
+    }
+  }
+
+  return -1;
+}
 /* Add RIP enable network. */
 int
 rip_enable_network_add (struct prefix *p)
@@ -759,6 +846,9 @@
   else
     node->info = "enabled";
 
+  /* XXX: One should find a better solution than a generic one */
+  rip_enable_apply_all();
+
   return 1;
 }
 
@@ -779,6 +869,9 @@
       /* Unlock lookup lock. */
       route_unlock_node (node);
 
+      /* XXX: One should find a better solution than a generic one */
+      rip_enable_apply_all ();
+
       return 1;
     }
   return -1;
@@ -810,6 +903,8 @@
 
   vector_set (rip_enable_interface, strdup (ifname));
 
+  rip_enable_apply_all(); /* TODOVJ */
+
   return 1;
 }
 
@@ -828,6 +923,8 @@
   free (str);
   vector_unset (rip_enable_interface, index);
 
+  rip_enable_apply_all(); /* TODOVJ */
+
   return 1;
 }
 
@@ -883,10 +980,13 @@
 	address.prefixlen = p->prefixlen;
 	apply_mask_ipv4 (&address);
 
-	if (set)
-	  rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
-				&address, connected->ifp->ifindex, NULL);
-	else
+	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);
@@ -905,16 +1005,13 @@
   struct rip_interface *ri = NULL;
 
   /* Check interface. */
-  if (if_is_loopback (ifp))
-    return;
-
   if (! if_is_operative (ifp))
     return;
 
   ri = ifp->info;
 
   /* Check network configuration. */
-  ret = rip_enable_network_lookup (ifp);
+  ret = rip_enable_network_lookup_if (ifp);
 
   /* If the interface is matched. */
   if (ret > 0)
@@ -939,7 +1036,6 @@
   /* Update running status of the interface. */
   if (ri->enable_network || ri->enable_interface)
     {
-      if (! ri->running)
 	{
 	  if (IS_RIP_DEBUG_EVENT)
 	    zlog_info ("turn on %s", ifp->name);
@@ -955,13 +1051,11 @@
     {
       if (ri->running)
 	{
-	  if (IS_RIP_DEBUG_EVENT)
-	    zlog_info ("turn off %s", ifp->name);
-
-	  /* Might as well clean up the route table as well */ 
+	  /* Might as well clean up the route table as well
+	   * rip_if_down sets to 0 ri->running, and displays "turn off %s"
+	   **/ 
 	  rip_if_down(ifp);
 
-	  ri->running = 0;
           rip_connect_set (ifp, 0);
 	}
     }
@@ -1181,8 +1275,6 @@
       return CMD_WARNING;
     }
 
-  rip_enable_apply_all ();
-
   return CMD_SUCCESS;
 }
 
@@ -1212,8 +1304,6 @@
       return CMD_WARNING;
     }
 
-  rip_enable_apply_all ();
-
   return CMD_SUCCESS;
 }
 
@@ -1661,10 +1751,15 @@
        "Authentication key-chain\n"
        "name of key-chain\n")
 
-DEFUN (rip_split_horizon,
-       rip_split_horizon_cmd,
-       "ip split-horizon",
+/* CHANGED: ip rip split-horizon
+   Cisco and Zebra's command is
+   ip split-horizon
+ */
+DEFUN (ip_rip_split_horizon,
+       ip_rip_split_horizon_cmd,
+       "ip rip split-horizon",
        IP_STR
+       "Routing Information Protocol\n"
        "Perform split horizon\n")
 {
   struct interface *ifp;
@@ -1673,15 +1768,38 @@
   ifp = vty->index;
   ri = ifp->info;
 
-  ri->split_horizon = 1;
+  ri->split_horizon = RIP_SPLIT_HORIZON;
   return CMD_SUCCESS;
 }
 
-DEFUN (no_rip_split_horizon,
-       no_rip_split_horizon_cmd,
-       "no ip split-horizon",
+DEFUN (ip_rip_split_horizon_poisoned_reverse,
+       ip_rip_split_horizon_poisoned_reverse_cmd,
+       "ip rip split-horizon poisoned-reverse",
+       IP_STR
+       "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;
+
+  ri->split_horizon = RIP_SPLIT_HORIZON_POISONED_REVERSE;
+  return CMD_SUCCESS;
+}
+
+/* CHANGED: no ip rip split-horizon
+   Cisco and Zebra's command is
+   no ip split-horizon
+ */
+DEFUN (no_ip_rip_split_horizon,
+       no_ip_rip_split_horizon_cmd,
+       "no ip rip split-horizon",
        NO_STR
        IP_STR
+       "Routing Information Protocol\n"
        "Perform split horizon\n")
 {
   struct interface *ifp;
@@ -1690,10 +1808,19 @@
   ifp = vty->index;
   ri = ifp->info;
 
-  ri->split_horizon = 0;
+  ri->split_horizon = RIP_NO_SPLIT_HORIZON;
   return CMD_SUCCESS;
 }
 
+ALIAS (no_ip_rip_split_horizon,
+       no_ip_rip_split_horizon_poisoned_reverse_cmd,
+       "no ip rip split-horizon poisoned-reverse",
+       NO_STR
+       IP_STR
+       "Routing Information Protocol\n"
+       "Perform split horizon\n"
+       "With poisoned-reverse\n")
+
 DEFUN (rip_passive_interface,
        rip_passive_interface_cmd,
        "passive-interface IFNAME",
@@ -1727,6 +1854,18 @@
       ifp = getdata (node);
       ri = ifp->info;
 
+      /* Do not display the interface if there is no
+       * configuration about it.
+       **/
+      if ((!ifp->desc)                                     &&
+          (ri->split_horizon == ri->split_horizon_default) &&
+          (ri->ri_send == RI_RIP_UNSPEC)                   &&
+          (ri->ri_receive == RI_RIP_UNSPEC)                &&
+          (ri->auth_type != RIP_AUTH_MD5)                  &&
+          (!ri->auth_str)                                  &&
+          (!ri->key_chain)                                 )
+        continue;
+
       vty_out (vty, "interface %s%s", ifp->name,
 	       VTY_NEWLINE);
 
@@ -1737,10 +1876,19 @@
       /* Split horizon. */
       if (ri->split_horizon != ri->split_horizon_default)
 	{
-	  if (ri->split_horizon)
-	    vty_out (vty, " ip split-horizon%s", VTY_NEWLINE);
-	  else
-	    vty_out (vty, " no ip split-horizon%s", VTY_NEWLINE);
+          switch (ri->split_horizon) {
+          case RIP_SPLIT_HORIZON:
+            vty_out (vty, " ip rip split-horizon%s", VTY_NEWLINE);
+            break;
+          case RIP_SPLIT_HORIZON_POISONED_REVERSE:
+            vty_out (vty, " ip rip split-horizon poisoned-reverse%s",
+                          VTY_NEWLINE);
+            break;
+          case RIP_NO_SPLIT_HORIZON:
+          default:
+            vty_out (vty, " no ip rip split-horizon%s", VTY_NEWLINE);
+            break;
+          }
 	}
 
       /* RIP version setting. */
@@ -1837,6 +1985,7 @@
 rip_interface_delete_hook (struct interface *ifp)
 {
   XFREE (MTYPE_RIP_INTERFACE, ifp->info);
+  ifp->info = NULL;
   return 0;
 }
 
@@ -1897,6 +2046,8 @@
   install_element (INTERFACE_NODE, &no_ip_rip_authentication_string_cmd);
   install_element (INTERFACE_NODE, &no_ip_rip_authentication_string2_cmd);
 
-  install_element (INTERFACE_NODE, &rip_split_horizon_cmd);
-  install_element (INTERFACE_NODE, &no_rip_split_horizon_cmd);
+  install_element (INTERFACE_NODE, &ip_rip_split_horizon_cmd);
+  install_element (INTERFACE_NODE, &ip_rip_split_horizon_poisoned_reverse_cmd);
+  install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_cmd);
+  install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_poisoned_reverse_cmd);
 }