[zebra] Routemap support on received routes, with 'set src' command (linux)

2007-05-01 David L Stevens <dlstevens@us.ibm.com>

	* (general) These changes collectively add route-map and
	  prefix-list support to zebra and fix a bug in "show
	  route-map" (with no argument).
	* doc/main.texi: added route-map, prefix-list, ip protocol
	  and set src documentation
	* lib/command.h: added PROTOCOL_NODE type
	* lib/log.c: (proto_name2num) new function, protocol name to
	  number translation.
	* lib/routemap.c: (vty_show_route_map) fixed "show route-map"
	  without route-map name
	* lib/routemap.h: added RMAP_ZEBRA type
	* lib/zebra.h: added proto_name2num() prototype
	* vtysh/extract.pl.in: added VTYSH_ZEBRA flag for route-map and
	  plist
	* vtysh/Makefile.am: added zebra_routemap.c
	* vtysh/vtysh.h: added VTYSH_ZEBRA flag to VTYSH_RMAP
	* zebra/connected.c: (connected_up_ipv4) added src preference argument
	  to rib_add_ipv4()
	* zebra/kernel_socket.c: (rtm_read) ditto
	* zebra/main.c: added prefix list initialization
	* zebra/Makefile.am: added zebra_routemap.c source file
	* zebra/rib.h: added generic address union "g_addr" and use in
	  existing places that had an explicit union.
	  Added "src" to struct nexthop.
	  Added preferred src arg to nexthop_ipv4_add and rib_add_ipv4.
	* zebra/rt_netlink.c: (netlink_routing_table) set preferred source on
	  netlink messages.
	  (netlink_route_change) ditto
	  (netlink_route_multipath) ditto.
	* zebra/rtread_getmsg.c: (handle_route_entry) added (NULL) src to
	  rib_add_ipv4() call.
	* zebra/rtread_proc.c: (proc_route_read) ditto
	* zebra/zebra_rib.c: (nexthop_ipv4_add) add src argument.
	  (nexthop_ipv4_ifindex_add) ditto
	  (rib_add_ipv4) ditto
	  (nexthop_active_check) Add route-map processing.
	* zebra/zebra_routemap.c: new file for zebra route-map commands.
	* zebra/zebra_vty.c: (ip_protocol_cmd) Apply route-map to protocol
	  (vty_show_ip_route_detail) added "src" printing
	  (vty_show_ip_route) ditto
	  (show_ip_protocol_cmd) new command, list routemaps.
	  (config_write_protocol) write out routemap protocl config.
	  (zebra_vty_init) Install the new routemap protocol commands.
	* zebra/zserv.c: (zread_ipv4_add) added (NULL) src arg
	  (zebra_init) init zebra route-maps.
	* zebra/zserv.h: add zebra_route_map_init
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 68e6f92..1487745 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -21,6 +21,7 @@
 
 #include <zebra.h>
 
+#include "memory.h"
 #include "if.h"
 #include "prefix.h"
 #include "command.h"
@@ -474,6 +475,59 @@
   return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]);
 }
 
+char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];	/* "any" == ZEBRA_ROUTE_MAX */
+
+DEFUN (ip_protocol,
+       ip_protocol_cmd,
+       "ip protocol PROTO route-map ROUTE-MAP",
+       NO_STR
+       "Apply route map to PROTO\n"
+       "Protocol name\n"
+       "Route map name\n")
+{
+  int i;
+
+  if (strcasecmp(argv[0], "any") == 0)
+    i = ZEBRA_ROUTE_MAX;
+  else
+    i = proto_name2num(argv[0]);
+  if (i < 0)
+    {
+      vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
+               VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  if (proto_rm[AFI_IP][i])
+    XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
+  proto_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_protocol,
+       no_ip_protocol_cmd,
+       "no ip protocol PROTO",
+       NO_STR
+       "Remove route map from PROTO\n"
+       "Protocol name\n")
+{
+  int i;
+
+  if (strcasecmp(argv[0], "any") == 0)
+    i = ZEBRA_ROUTE_MAX;
+  else
+    i = proto_name2num(argv[0]);
+  if (i < 0)
+    {
+      vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
+               VTY_NEWLINE);
+     return CMD_WARNING;
+    }
+  if (proto_rm[AFI_IP][i])
+    XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]);
+  proto_rm[AFI_IP][i] = NULL;
+  return CMD_SUCCESS;
+}
+
 /* New RIB.  Detailed information for IPv4 route. */
 static void
 vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
@@ -529,6 +583,8 @@
 
       for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
 	{
+          char addrstr[32];
+
 	  vty_out (vty, "  %c",
 		   CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
 
@@ -575,6 +631,31 @@
 		  break;
 		}
 	    }
+	  switch (nexthop->type)
+            {
+            case NEXTHOP_TYPE_IPV4:
+            case NEXTHOP_TYPE_IPV4_IFINDEX:
+            case NEXTHOP_TYPE_IPV4_IFNAME:
+              if (nexthop->src.ipv4.s_addr)
+                {
+		  if (inet_ntop(AF_INET, &nexthop->src.ipv4, addrstr,
+		      sizeof addrstr))
+                    vty_out (vty, ", src %s", addrstr);
+                }
+              break;
+            case NEXTHOP_TYPE_IPV6:
+            case NEXTHOP_TYPE_IPV6_IFINDEX:
+            case NEXTHOP_TYPE_IPV6_IFNAME:
+              if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
+                {
+		  if (inet_ntop(AF_INET6, &nexthop->src.ipv6, addrstr,
+		      sizeof addrstr))
+                    vty_out (vty, ", src %s", addrstr);
+                }
+              break;
+            default:
+	       break;
+            }
 	  vty_out (vty, "%s", VTY_NEWLINE);
 	}
       vty_out (vty, "%s", VTY_NEWLINE);
@@ -658,6 +739,29 @@
 	      break;
 	    }
 	}
+      switch (nexthop->type)
+        {
+          case NEXTHOP_TYPE_IPV4:
+          case NEXTHOP_TYPE_IPV4_IFINDEX:
+          case NEXTHOP_TYPE_IPV4_IFNAME:
+            if (nexthop->src.ipv4.s_addr)
+              {
+		if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf))
+                  vty_out (vty, ", src %s", buf);
+              }
+            break;
+          case NEXTHOP_TYPE_IPV6:
+          case NEXTHOP_TYPE_IPV6_IFINDEX:
+          case NEXTHOP_TYPE_IPV6_IFNAME:
+            if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
+              {
+		if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf))
+                  vty_out (vty, ", src %s", buf);
+              }
+            break;
+          default:
+	    break;
+        }
 
       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
                vty_out (vty, ", bh");
@@ -1805,6 +1909,34 @@
   return CMD_SUCCESS;
 }
 
+DEFUN (show_ip_protocol,
+       show_ip_protocol_cmd,
+       "show ip protocol",
+        SHOW_STR
+        IP_STR
+       "IP protocol filtering status\n")
+{
+    int i; 
+
+    vty_out(vty, "Protocol    : route-map %s", VTY_NEWLINE);
+    vty_out(vty, "------------------------%s", VTY_NEWLINE);
+    for (i=0;i<ZEBRA_ROUTE_MAX;i++)
+    {
+        if (proto_rm[AFI_IP][i])
+          vty_out (vty, "%-10s  : %-10s%s", zebra_route_string(i),
+					proto_rm[AFI_IP][i],
+					VTY_NEWLINE);
+        else
+          vty_out (vty, "%-10s  : none%s", zebra_route_string(i), VTY_NEWLINE);
+    }
+    if (proto_rm[AFI_IP][i])
+      vty_out (vty, "%-10s  : %-10s%s", "any", proto_rm[AFI_IP][i],
+					VTY_NEWLINE);
+    else
+      vty_out (vty, "%-10s  : none%s", "any", VTY_NEWLINE);
+
+    return CMD_SUCCESS;
+}
 
 /* Write IPv6 static route configuration. */
 static int
@@ -1874,6 +2006,27 @@
   return write;
 }
 
+/* ip protocol configuration write function */
+static int config_write_protocol(struct vty *vty)
+{  
+  int i;
+
+  for (i=0;i<ZEBRA_ROUTE_MAX;i++)
+    {
+      if (proto_rm[AFI_IP][i])
+        vty_out (vty, "ip protocol %s route-map %s%s", zebra_route_string(i),
+                 proto_rm[AFI_IP][i], VTY_NEWLINE);
+    }
+  if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX])
+      vty_out (vty, "ip protocol %s route-map %s%s", "any",
+               proto_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
+
+  return 1;
+}   
+
+/* table node for protocol filtering */
+struct cmd_node protocol_node = { PROTOCOL_NODE, "", 1 };
+
 /* IP node for static routes. */
 struct cmd_node ip_node = { IP_NODE,  "",  1 };
 
@@ -1882,7 +2035,12 @@
 zebra_vty_init (void)
 {
   install_node (&ip_node, zebra_ip_config);
+  install_node (&protocol_node, config_write_protocol);
 
+  install_element (CONFIG_NODE, &ip_protocol_cmd);
+  install_element (CONFIG_NODE, &no_ip_protocol_cmd);
+  install_element (VIEW_NODE, &show_ip_protocol_cmd);
+  install_element (ENABLE_NODE, &show_ip_protocol_cmd);
   install_element (CONFIG_NODE, &ip_route_cmd);
   install_element (CONFIG_NODE, &ip_route_flags_cmd);
   install_element (CONFIG_NODE, &ip_route_flags2_cmd);