Initial revision
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
new file mode 100644
index 0000000..498a600
--- /dev/null
+++ b/bgpd/bgp_routemap.c
@@ -0,0 +1,3207 @@
+/* Route map function of bgpd.
+   Copyright (C) 1998, 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "prefix.h"
+#include "filter.h"
+#include "routemap.h"
+#include "command.h"
+#include "linklist.h"
+#include "plist.h"
+#include "memory.h"
+#include "log.h"
+#ifdef HAVE_GNU_REGEX
+#include <regex.h>
+#else
+#include "regex-gnu.h"
+#endif /* HAVE_GNU_REGEX */
+#include "buffer.h"
+#include "sockunion.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_regex.h"
+#include "bgpd/bgp_community.h"
+#include "bgpd/bgp_clist.h"
+#include "bgpd/bgp_filter.h"
+#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_ecommunity.h"
+
+/* Memo of route-map commands.
+
+o Cisco route-map
+
+ match as-path          :  Done
+       community        :  Done
+       interface        :  Not yet
+       ip address       :  Done
+       ip next-hop      :  Done
+       ip route-source  :  (This will not be implemented by bgpd)
+       ip prefix-list   :  Done
+       ipv6 address     :  Done
+       ipv6 next-hop    :  Done
+       ipv6 route-source:  (This will not be implemented by bgpd)
+       ipv6 prefix-list :  Done
+       length           :  (This will not be implemented by bgpd)
+       metric           :  Done
+       route-type       :  (This will not be implemented by bgpd)
+       tag              :  (This will not be implemented by bgpd)
+
+ set  as-path prepend   :  Done
+      as-path tag       :  Not yet
+      automatic-tag     :  (This will not be implemented by bgpd)
+      community         :  Done
+      comm-list         :  Not yet
+      dampning          :  Not yet
+      default           :  (This will not be implemented by bgpd)
+      interface         :  (This will not be implemented by bgpd)
+      ip default        :  (This will not be implemented by bgpd)
+      ip next-hop       :  Done
+      ip precedence     :  (This will not be implemented by bgpd)
+      ip tos            :  (This will not be implemented by bgpd)
+      level             :  (This will not be implemented by bgpd)
+      local-preference  :  Done
+      metric            :  Done
+      metric-type       :  Not yet
+      origin            :  Done
+      tag               :  (This will not be implemented by bgpd)
+      weight            :  Done
+
+o Local extention
+
+  set ipv6 next-hop global: Done
+  set ipv6 next-hop local : Done
+
+*/ 
+
+/* `match ip address IP_ACCESS_LIST' */
+
+/* Match function should return 1 if match is success else return
+   zero. */
+route_map_result_t
+route_match_ip_address (void *rule, struct prefix *prefix, 
+			route_map_object_t type, void *object)
+{
+  struct access_list *alist;
+  /* struct prefix_ipv4 match; */
+
+  if (type == RMAP_BGP)
+    {
+      alist = access_list_lookup (AFI_IP, (char *) rule);
+      if (alist == NULL)
+	return RMAP_NOMATCH;
+    
+      return (access_list_apply (alist, prefix) == FILTER_DENY ?
+	      RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Route map `ip address' match statement.  `arg' should be
+   access-list name. */
+void *
+route_match_ip_address_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `ip address' value. */
+void
+route_match_ip_address_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip address matching. */
+struct route_map_rule_cmd route_match_ip_address_cmd =
+{
+  "ip address",
+  route_match_ip_address,
+  route_match_ip_address_compile,
+  route_match_ip_address_free
+};
+
+/* `match ip next-hop IP_ADDRESS' */
+
+/* Match function return 1 if match is success else return zero. */
+route_map_result_t
+route_match_ip_next_hop (void *rule, struct prefix *prefix, 
+			 route_map_object_t type, void *object)
+{
+  struct access_list *alist;
+  struct bgp_info *bgp_info;
+  struct prefix_ipv4 p;
+
+  if (type == RMAP_BGP)
+    {
+      bgp_info = object;
+      p.family = AF_INET;
+      p.prefix = bgp_info->attr->nexthop;
+      p.prefixlen = IPV4_MAX_BITLEN;
+
+      alist = access_list_lookup (AFI_IP, (char *) rule);
+      if (alist == NULL)
+	return RMAP_NOMATCH;
+
+      return (access_list_apply (alist, &p) == FILTER_DENY ?
+              RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Route map `ip next-hop' match statement. `arg' is
+   access-list name. */
+void *
+route_match_ip_next_hop_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `ip address' value. */
+void
+route_match_ip_next_hop_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip next-hop matching. */
+struct route_map_rule_cmd route_match_ip_next_hop_cmd =
+{
+  "ip next-hop",
+  route_match_ip_next_hop,
+  route_match_ip_next_hop_compile,
+  route_match_ip_next_hop_free
+};
+
+/* `match ip address prefix-list PREFIX_LIST' */
+
+route_map_result_t
+route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, 
+				    route_map_object_t type, void *object)
+{
+  struct prefix_list *plist;
+
+  if (type == RMAP_BGP)
+    {
+      plist = prefix_list_lookup (AFI_IP, (char *) rule);
+      if (plist == NULL)
+	return RMAP_NOMATCH;
+    
+      return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
+	      RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ip_address_prefix_list_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+route_match_ip_address_prefix_list_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
+{
+  "ip address prefix-list",
+  route_match_ip_address_prefix_list,
+  route_match_ip_address_prefix_list_compile,
+  route_match_ip_address_prefix_list_free
+};
+
+/* `match ip next-hop prefix-list PREFIX_LIST' */
+
+route_map_result_t
+route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
+                                    route_map_object_t type, void *object)
+{
+  struct prefix_list *plist;
+  struct bgp_info *bgp_info;
+  struct prefix_ipv4 p;
+
+  if (type == RMAP_BGP)
+    {
+      bgp_info = object;
+      p.family = AF_INET;
+      p.prefix = bgp_info->attr->nexthop;
+      p.prefixlen = IPV4_MAX_BITLEN;
+
+      plist = prefix_list_lookup (AFI_IP, (char *) rule);
+      if (plist == NULL)
+        return RMAP_NOMATCH;
+
+      return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
+              RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ip_next_hop_prefix_list_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+route_match_ip_next_hop_prefix_list_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
+{
+  "ip next-hop prefix-list",
+  route_match_ip_next_hop_prefix_list,
+  route_match_ip_next_hop_prefix_list_compile,
+  route_match_ip_next_hop_prefix_list_free
+};
+
+/* `match metric METRIC' */
+
+/* Match function return 1 if match is success else return zero. */
+route_map_result_t
+route_match_metric (void *rule, struct prefix *prefix, 
+		    route_map_object_t type, void *object)
+{
+  u_int32_t *med;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      med = rule;
+      bgp_info = object;
+    
+      if (bgp_info->attr->med == *med)
+	return RMAP_MATCH;
+      else
+	return RMAP_NOMATCH;
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Route map `match metric' match statement. `arg' is MED value */
+void *
+route_match_metric_compile (char *arg)
+{
+  u_int32_t *med;
+  char *endptr = NULL;
+
+  med = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
+  *med = strtoul (arg, &endptr, 10);
+  if (*endptr != '\0' || *med == ULONG_MAX)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, med);
+      return NULL;
+    }
+  return med;
+}
+
+/* Free route map's compiled `match metric' value. */
+void
+route_match_metric_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for metric matching. */
+struct route_map_rule_cmd route_match_metric_cmd =
+{
+  "metric",
+  route_match_metric,
+  route_match_metric_compile,
+  route_match_metric_free
+};
+
+/* `match as-path ASPATH' */
+
+/* Match function for as-path match.  I assume given object is */
+route_map_result_t
+route_match_aspath (void *rule, struct prefix *prefix, 
+		    route_map_object_t type, void *object)
+{
+  
+  struct as_list *as_list;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      as_list = as_list_lookup ((char *) rule);
+      if (as_list == NULL)
+	return RMAP_NOMATCH;
+    
+      bgp_info = object;
+    
+      /* Perform match. */
+      return ((as_list_apply (as_list, bgp_info->attr->aspath) == AS_FILTER_DENY) ? RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Compile function for as-path match. */
+void *
+route_match_aspath_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Compile function for as-path match. */
+void
+route_match_aspath_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for aspath matching. */
+struct route_map_rule_cmd route_match_aspath_cmd = 
+{
+  "as-path",
+  route_match_aspath,
+  route_match_aspath_compile,
+  route_match_aspath_free
+};
+
+#if ROUTE_MATCH_ASPATH_OLD
+/* `match as-path ASPATH' */
+
+/* Match function for as-path match.  I assume given object is */
+int
+route_match_aspath (void *rule, struct prefix *prefix, void *object)
+{
+  regex_t *regex;
+  struct bgp_info *bgp_info;
+
+  regex = rule;
+  bgp_info = object;
+  
+  /* Perform match. */
+  return bgp_regexec (regex, bgp_info->attr->aspath);
+}
+
+/* Compile function for as-path match. */
+void *
+route_match_aspath_compile (char *arg)
+{
+  regex_t *regex;
+
+  regex = bgp_regcomp (arg);
+  if (! regex)
+    return NULL;
+
+  return regex;
+}
+
+/* Compile function for as-path match. */
+void
+route_match_aspath_free (void *rule)
+{
+  regex_t *regex = rule;
+
+  bgp_regex_free (regex);
+}
+
+/* Route map commands for aspath matching. */
+struct route_map_rule_cmd route_match_aspath_cmd = 
+{
+  "as-path",
+  route_match_aspath,
+  route_match_aspath_compile,
+  route_match_aspath_free
+};
+#endif /* ROUTE_MATCH_ASPATH_OLD */
+
+/* `match community COMMUNIY' */
+struct rmap_community
+{
+  char *name;
+  int exact;
+};
+
+/* Match function for community match. */
+route_map_result_t
+route_match_community (void *rule, struct prefix *prefix, 
+		       route_map_object_t type, void *object)
+{
+  struct community_list *list;
+  struct bgp_info *bgp_info;
+  struct rmap_community *rcom;
+
+  if (type == RMAP_BGP) 
+    {
+      bgp_info = object;
+      rcom = rule;
+
+      list = community_list_lookup (bgp_clist, rcom->name, COMMUNITY_LIST_AUTO);
+      if (! list)
+	return RMAP_NOMATCH;
+
+      if (rcom->exact)
+	{
+	  if (community_list_exact_match (bgp_info->attr->community, list))
+	    return RMAP_MATCH;
+	}
+      else
+	{
+	  if (community_list_match (bgp_info->attr->community, list))
+	    return RMAP_MATCH;
+	}
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Compile function for community match. */
+void *
+route_match_community_compile (char *arg)
+{
+  struct rmap_community *rcom;
+  int len;
+  char *p;
+
+  rcom = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_community));
+
+  p = strchr (arg, ' ');
+  if (p)
+    {
+      len = p - arg;
+      rcom->name = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
+      memcpy (rcom->name, arg, len);
+      rcom->exact = 1;
+    }
+  else
+    {
+      rcom->name = XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+      rcom->exact = 0;
+    }
+  return rcom;
+}
+
+/* Compile function for community match. */
+void
+route_match_community_free (void *rule)
+{
+  struct rmap_community *rcom = rule;
+
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name); 
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom);
+}
+
+/* Route map commands for community matching. */
+struct route_map_rule_cmd route_match_community_cmd = 
+{
+  "community",
+  route_match_community,
+  route_match_community_compile,
+  route_match_community_free
+};
+
+/* `match nlri` and `set nlri` are replaced by `address-family ipv4`
+   and `address-family vpnv4'.  */
+
+/* `match origin' */
+route_map_result_t
+route_match_origin (void *rule, struct prefix *prefix, 
+		    route_map_object_t type, void *object)
+{
+  u_char *origin;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      origin = rule;
+      bgp_info = object;
+    
+      if (bgp_info->attr->origin == *origin)
+	return RMAP_MATCH;
+    }
+
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_origin_compile (char *arg)
+{
+  u_char *origin;
+
+  origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char));
+
+  if (strcmp (arg, "igp") == 0)
+    *origin = 0;
+  else if (strcmp (arg, "egp") == 0)
+    *origin = 1;
+  else
+    *origin = 2;
+
+  return origin;
+}
+
+/* Free route map's compiled `ip address' value. */
+void
+route_match_origin_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for origin matching. */
+struct route_map_rule_cmd route_match_origin_cmd =
+{
+  "origin",
+  route_match_origin,
+  route_match_origin_compile,
+  route_match_origin_free
+};
+/* `set ip next-hop IP_ADDRESS' */
+
+/* Set nexthop to object.  ojbect must be pointer to struct attr. */
+route_map_result_t
+route_set_ip_nexthop (void *rule, struct prefix *prefix,
+		      route_map_object_t type, void *object)
+{
+  struct in_addr *address;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      address = rule;
+      bgp_info = object;
+    
+      /* Set next hop value. */ 
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
+      bgp_info->attr->nexthop = *address;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Route map `ip nexthop' compile function.  Given string is converted
+   to struct in_addr structure. */
+void *
+route_set_ip_nexthop_compile (char *arg)
+{
+  int ret;
+  struct in_addr *address;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
+
+  ret = inet_aton (arg, address);
+
+  if (ret == 0)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+/* Free route map's compiled `ip nexthop' value. */
+void
+route_set_ip_nexthop_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip nexthop set. */
+struct route_map_rule_cmd route_set_ip_nexthop_cmd =
+{
+  "ip next-hop",
+  route_set_ip_nexthop,
+  route_set_ip_nexthop_compile,
+  route_set_ip_nexthop_free
+};
+
+/* `set local-preference LOCAL_PREF' */
+
+/* Set local preference. */
+route_map_result_t
+route_set_local_pref (void *rule, struct prefix *prefix,
+		      route_map_object_t type, void *object)
+{
+  u_int32_t *local_pref;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      local_pref = rule;
+      bgp_info = object;
+    
+      /* Set local preference value. */ 
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
+      bgp_info->attr->local_pref = *local_pref;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* set local preference compilation. */
+void *
+route_set_local_pref_compile (char *arg)
+{
+  u_int32_t *local_pref;
+  char *endptr = NULL;
+
+  /* Local preference value shoud be integer. */
+  if (! all_digit (arg))
+    return NULL;
+
+  local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
+  *local_pref = strtoul (arg, &endptr, 10);
+  if (*endptr != '\0' || *local_pref == ULONG_MAX)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, local_pref);
+      return NULL;
+    }
+  return local_pref;
+}
+
+/* Free route map's local preference value. */
+void
+route_set_local_pref_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set local preference rule structure. */
+struct route_map_rule_cmd route_set_local_pref_cmd = 
+{
+  "local-preference",
+  route_set_local_pref,
+  route_set_local_pref_compile,
+  route_set_local_pref_free,
+};
+
+/* `set weight WEIGHT' */
+
+/* Set weight. */
+route_map_result_t
+route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
+		  void *object)
+{
+  u_int32_t *weight;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      weight = rule;
+      bgp_info = object;
+    
+      /* Set weight value. */ 
+      bgp_info->attr->weight = *weight;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* set local preference compilation. */
+void *
+route_set_weight_compile (char *arg)
+{
+  u_int32_t *weight;
+  char *endptr = NULL;
+
+  /* Local preference value shoud be integer. */
+  if (! all_digit (arg))
+    return NULL;
+
+  weight = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
+  *weight = strtoul (arg, &endptr, 10);
+  if (*endptr != '\0' || *weight == ULONG_MAX)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, weight);
+      return NULL;
+    }
+  return weight;
+}
+
+/* Free route map's local preference value. */
+void
+route_set_weight_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set local preference rule structure. */
+struct route_map_rule_cmd route_set_weight_cmd = 
+{
+  "weight",
+  route_set_weight,
+  route_set_weight_compile,
+  route_set_weight_free,
+};
+
+/* `set metric METRIC' */
+
+/* Set metric to attribute. */
+route_map_result_t
+route_set_metric (void *rule, struct prefix *prefix, 
+		  route_map_object_t type, void *object)
+{
+  char *metric;
+  u_int32_t metric_val;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      metric = rule;
+      bgp_info = object;
+
+      if (! (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)))
+	bgp_info->attr->med = 0;
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+
+      if (all_digit (metric))
+	{
+	  metric_val = strtoul (metric, (char **)NULL, 10);
+	  bgp_info->attr->med = metric_val;
+	}
+      else
+	{
+	  metric_val = strtoul (metric+1, (char **)NULL, 10);
+
+	  if (strncmp (metric, "+", 1) == 0)
+	    {
+	      if (bgp_info->attr->med/2 + metric_val/2 > ULONG_MAX/2)
+		bgp_info->attr->med = ULONG_MAX-1;
+	      else
+		bgp_info->attr->med += metric_val;
+	    }
+	  else if (strncmp (metric, "-", 1) == 0)
+	    {
+	      if (bgp_info->attr->med <= metric_val) 
+		bgp_info->attr->med = 0;
+	      else
+		bgp_info->attr->med -= metric_val;
+	    }
+	}
+    }
+  return RMAP_OKAY;
+}
+
+/* set metric compilation. */
+void *
+route_set_metric_compile (char *arg)
+{
+  u_int32_t metric;
+  char *endptr = NULL;
+
+  if (all_digit (arg))
+    {
+      /* set metric value check*/
+      metric = strtoul (arg, &endptr, 10);
+      if (*endptr != '\0' || metric == ULONG_MAX)
+        return NULL;
+    }
+  else
+    {
+      /* set metric +/-value check */
+      if ((strncmp (arg, "+", 1) != 0
+	   && strncmp (arg, "-", 1) != 0)
+	   || (! all_digit (arg+1)))
+	return NULL;
+
+      metric = strtoul (arg+1, &endptr, 10);
+      if (*endptr != '\0' || metric == ULONG_MAX)
+	return NULL;
+    }
+
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `set metric' value. */
+void
+route_set_metric_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set metric rule structure. */
+struct route_map_rule_cmd route_set_metric_cmd = 
+{
+  "metric",
+  route_set_metric,
+  route_set_metric_compile,
+  route_set_metric_free,
+};
+
+/* `set as-path prepend ASPATH' */
+
+/* For AS path prepend mechanism. */
+route_map_result_t
+route_set_aspath_prepend (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
+{
+  struct aspath *aspath;
+  struct aspath *new;
+  struct bgp_info *binfo;
+
+  if (type == RMAP_BGP)
+    {
+      aspath = rule;
+      binfo = object;
+    
+      if (binfo->attr->aspath->refcnt)
+	new = aspath_dup (binfo->attr->aspath);
+      else
+	new = binfo->attr->aspath;
+
+      aspath_prepend (aspath, new);
+      binfo->attr->aspath = new;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for as-path prepend. */
+void *
+route_set_aspath_prepend_compile (char *arg)
+{
+  struct aspath *aspath;
+
+  aspath = aspath_str2aspath (arg);
+  if (! aspath)
+    return NULL;
+  return aspath;
+}
+
+/* Compile function for as-path prepend. */
+void
+route_set_aspath_prepend_free (void *rule)
+{
+  struct aspath *aspath = rule;
+  aspath_free (aspath);
+}
+
+/* Set metric rule structure. */
+struct route_map_rule_cmd route_set_aspath_prepend_cmd = 
+{
+  "as-path prepend",
+  route_set_aspath_prepend,
+  route_set_aspath_prepend_compile,
+  route_set_aspath_prepend_free,
+};
+
+/* `set community COMMUNITY' */
+struct rmap_com_set
+{
+  struct community *com;
+  int additive;
+  int none;
+};
+
+/* For community set mechanism. */
+route_map_result_t
+route_set_community (void *rule, struct prefix *prefix,
+		     route_map_object_t type, void *object)
+{
+  struct rmap_com_set *rcs;
+  struct bgp_info *binfo;
+  struct attr *attr;
+  struct community *new = NULL;
+  struct community *old;
+  struct community *merge;
+
+  if (type == RMAP_BGP)
+    {
+      rcs = rule;
+      binfo = object;
+      attr = binfo->attr;
+      old = attr->community;
+
+      /* "none" case.  */
+      if (rcs->none)
+	{
+	  attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
+	  attr->community = NULL;
+	  return RMAP_OKAY;
+	}
+
+      /* "additive" case.  */
+      if (rcs->additive && old)
+	{
+	  merge = community_merge (community_dup (old), rcs->com);
+	  new = community_uniq_sort (merge);
+	  community_free (merge);
+	}
+      else
+	new = community_dup (rcs->com);
+
+      attr->community = new;
+      attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for set community. */
+void *
+route_set_community_compile (char *arg)
+{
+  struct rmap_com_set *rcs;
+  struct community *com = NULL;
+  char *sp;
+  int additive = 0;
+  int none = 0;
+  
+  if (strcmp (arg, "none") == 0)
+    none = 1;
+  else
+    {
+      sp = strstr (arg, "additive");
+
+      if (sp && sp > arg)
+  	{
+	  /* "additive" keyworkd is included.  */
+	  additive = 1;
+	  *(sp - 1) = '\0';
+	}
+
+      com = community_str2com (arg);
+
+      if (additive)
+	*(sp - 1) = ' ';
+
+      if (! com)
+	return NULL;
+    }
+  
+  rcs = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set));
+  memset (rcs, 0, sizeof (struct rmap_com_set));
+  
+  rcs->com = com;
+  rcs->additive = additive;
+  rcs->none = none;
+  
+  return rcs;
+}
+
+/* Free function for set community. */
+void
+route_set_community_free (void *rule)
+{
+  struct rmap_com_set *rcs = rule;
+
+  if (rcs->com)
+    community_free (rcs->com);
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs);
+}
+
+/* Set community rule structure. */
+struct route_map_rule_cmd route_set_community_cmd = 
+{
+  "community",
+  route_set_community,
+  route_set_community_compile,
+  route_set_community_free,
+};
+
+/* `set comm-list (<1-99>|<100-199>|WORD) delete' */
+
+/* For community set mechanism. */
+route_map_result_t
+route_set_community_delete (void *rule, struct prefix *prefix,
+			    route_map_object_t type, void *object)
+{
+  struct community_list *list;
+  struct community *merge;
+  struct community *new;
+  struct community *old;
+  struct bgp_info *binfo;
+
+  if (type == RMAP_BGP)
+    {
+      if (! rule)
+	return RMAP_OKAY;
+
+      binfo = object;
+      list = community_list_lookup (bgp_clist, rule, COMMUNITY_LIST_AUTO);
+      old = binfo->attr->community;
+
+      if (list && old)
+	{
+	  merge = community_list_match_delete (community_dup (old), list);
+	  new = community_uniq_sort (merge);
+	  community_free (merge);
+
+	  if (new->size == 0)
+	    {
+	      binfo->attr->community = NULL;
+	      binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
+	      community_free (new);
+	    }
+	  else
+	    {
+	      binfo->attr->community = new;
+	      binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
+	    }
+	}
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for set community. */
+void *
+route_set_community_delete_compile (char *arg)
+{
+  char *p;
+  char *str;
+  int len;
+
+  p = strchr (arg, ' ');
+  if (p)
+    {
+      len = p - arg;
+      str = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
+      memcpy (str, arg, len);
+    }
+  else
+    str = NULL;
+
+  return str;
+}
+
+/* Free function for set community. */
+void
+route_set_community_delete_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set community rule structure. */
+struct route_map_rule_cmd route_set_community_delete_cmd =
+{
+  "comm-list",
+  route_set_community_delete,
+  route_set_community_delete_compile,
+  route_set_community_delete_free,
+};
+
+/* `set extcommunity rt COMMUNITY' */
+
+/* For community set mechanism. */
+route_map_result_t
+route_set_ecommunity_rt (void *rule, struct prefix *prefix, 
+			 route_map_object_t type, void *object)
+{
+  struct ecommunity *ecom;
+  struct ecommunity *new_ecom;
+  struct ecommunity *old_ecom;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      ecom = rule;
+      bgp_info = object;
+    
+      if (! ecom)
+	return RMAP_OKAY;
+    
+      /* We assume additive for Extended Community. */
+      old_ecom = bgp_info->attr->ecommunity;
+
+      if (old_ecom)
+	new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
+      else
+	new_ecom = ecommunity_dup (ecom);
+
+      bgp_info->attr->ecommunity = new_ecom;
+
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
+    }
+  return RMAP_OKAY;
+}
+
+/* Compile function for set community. */
+void *
+route_set_ecommunity_rt_compile (char *arg)
+{
+  struct ecommunity *ecom;
+
+  ecom = ecommunity_str2com (arg, ECOMMUNITY_ROUTE_TARGET, 0);
+  if (! ecom)
+    return NULL;
+  return ecom;
+}
+
+/* Free function for set community. */
+void
+route_set_ecommunity_rt_free (void *rule)
+{
+  struct ecommunity *ecom = rule;
+  ecommunity_free (ecom);
+}
+
+/* Set community rule structure. */
+struct route_map_rule_cmd route_set_ecommunity_rt_cmd = 
+{
+  "extcommunity rt",
+  route_set_ecommunity_rt,
+  route_set_ecommunity_rt_compile,
+  route_set_ecommunity_rt_free,
+};
+
+/* `set extcommunity soo COMMUNITY' */
+
+/* For community set mechanism. */
+route_map_result_t
+route_set_ecommunity_soo (void *rule, struct prefix *prefix, 
+			 route_map_object_t type, void *object)
+{
+  struct ecommunity *ecom;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      ecom = rule;
+      bgp_info = object;
+    
+      if (! ecom)
+	return RMAP_OKAY;
+    
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
+      bgp_info->attr->ecommunity = ecommunity_dup (ecom);
+    }
+  return RMAP_OKAY;
+}
+
+/* Compile function for set community. */
+void *
+route_set_ecommunity_soo_compile (char *arg)
+{
+  struct ecommunity *ecom;
+
+  ecom = ecommunity_str2com (arg, ECOMMUNITY_SITE_ORIGIN, 0);
+  if (! ecom)
+    return NULL;
+  
+  return ecom;
+}
+
+/* Free function for set community. */
+void
+route_set_ecommunity_soo_free (void *rule)
+{
+  struct ecommunity *ecom = rule;
+  ecommunity_free (ecom);
+}
+
+/* Set community rule structure. */
+struct route_map_rule_cmd route_set_ecommunity_soo_cmd = 
+{
+  "extcommunity soo",
+  route_set_ecommunity_soo,
+  route_set_ecommunity_soo_compile,
+  route_set_ecommunity_soo_free,
+};
+
+/* `set origin ORIGIN' */
+
+/* For origin set. */
+route_map_result_t
+route_set_origin (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
+{
+  u_char *origin;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      origin = rule;
+      bgp_info = object;
+    
+      bgp_info->attr->origin = *origin;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for origin set. */
+void *
+route_set_origin_compile (char *arg)
+{
+  u_char *origin;
+
+  origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char));
+
+  if (strcmp (arg, "igp") == 0)
+    *origin = 0;
+  else if (strcmp (arg, "egp") == 0)
+    *origin = 1;
+  else
+    *origin = 2;
+
+  return origin;
+}
+
+/* Compile function for origin set. */
+void
+route_set_origin_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set metric rule structure. */
+struct route_map_rule_cmd route_set_origin_cmd = 
+{
+  "origin",
+  route_set_origin,
+  route_set_origin_compile,
+  route_set_origin_free,
+};
+
+/* `set atomic-aggregate' */
+
+/* For atomic aggregate set. */
+route_map_result_t
+route_set_atomic_aggregate (void *rule, struct prefix *prefix,
+			    route_map_object_t type, void *object)
+{
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      bgp_info = object;
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for atomic aggregate. */
+void *
+route_set_atomic_aggregate_compile (char *arg)
+{
+  return (void *)1;
+}
+
+/* Compile function for atomic aggregate. */
+void
+route_set_atomic_aggregate_free (void *rule)
+{
+  return;
+}
+
+/* Set atomic aggregate rule structure. */
+struct route_map_rule_cmd route_set_atomic_aggregate_cmd = 
+{
+  "atomic-aggregate",
+  route_set_atomic_aggregate,
+  route_set_atomic_aggregate_compile,
+  route_set_atomic_aggregate_free,
+};
+
+/* `set aggregator as AS A.B.C.D' */
+struct aggregator
+{
+  as_t as;
+  struct in_addr address;
+};
+
+route_map_result_t
+route_set_aggregator_as (void *rule, struct prefix *prefix, 
+			 route_map_object_t type, void *object)
+{
+  struct bgp_info *bgp_info;
+  struct aggregator *aggregator;
+
+  if (type == RMAP_BGP)
+    {
+      bgp_info = object;
+      aggregator = rule;
+    
+      bgp_info->attr->aggregator_as = aggregator->as;
+      bgp_info->attr->aggregator_addr = aggregator->address;
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
+    }
+
+  return RMAP_OKAY;
+}
+
+void *
+route_set_aggregator_as_compile (char *arg)
+{
+  struct aggregator *aggregator;
+  char as[10];
+  char address[20];
+
+  aggregator = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct aggregator));
+  memset (aggregator, 0, sizeof (struct aggregator));
+
+  sscanf (arg, "%s %s", as, address);
+
+  aggregator->as = strtoul (as, NULL, 10);
+  inet_aton (address, &aggregator->address);
+
+  return aggregator;
+}
+
+void
+route_set_aggregator_as_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_set_aggregator_as_cmd = 
+{
+  "aggregator as",
+  route_set_aggregator_as,
+  route_set_aggregator_as_compile,
+  route_set_aggregator_as_free,
+};
+
+#ifdef HAVE_IPV6
+/* `match ipv6 address IP_ACCESS_LIST' */
+
+route_map_result_t
+route_match_ipv6_address (void *rule, struct prefix *prefix, 
+			  route_map_object_t type, void *object)
+{
+  struct access_list *alist;
+
+  if (type == RMAP_BGP)
+    {
+      alist = access_list_lookup (AFI_IP6, (char *) rule);
+      if (alist == NULL)
+	return RMAP_NOMATCH;
+    
+      return (access_list_apply (alist, prefix) == FILTER_DENY ?
+	      RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ipv6_address_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+route_match_ipv6_address_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip address matching. */
+struct route_map_rule_cmd route_match_ipv6_address_cmd =
+{
+  "ipv6 address",
+  route_match_ipv6_address,
+  route_match_ipv6_address_compile,
+  route_match_ipv6_address_free
+};
+
+/* `match ipv6 next-hop IP_ADDRESS' */
+
+route_map_result_t
+route_match_ipv6_next_hop (void *rule, struct prefix *prefix, 
+			   route_map_object_t type, void *object)
+{
+  struct in6_addr *addr;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      addr = rule;
+      bgp_info = object;
+    
+      if (IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_global, rule))
+	return RMAP_MATCH;
+
+      if (bgp_info->attr->mp_nexthop_len == 32 &&
+	  IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_local, rule))
+	return RMAP_MATCH;
+
+      return RMAP_NOMATCH;
+    }
+
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ipv6_next_hop_compile (char *arg)
+{
+  struct in6_addr *address;
+  int ret;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
+
+  ret = inet_pton (AF_INET6, arg, address);
+  if (!ret)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+void
+route_match_ipv6_next_hop_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ipv6_next_hop_cmd =
+{
+  "ipv6 next-hop",
+  route_match_ipv6_next_hop,
+  route_match_ipv6_next_hop_compile,
+  route_match_ipv6_next_hop_free
+};
+
+/* `match ipv6 address prefix-list PREFIX_LIST' */
+
+route_map_result_t
+route_match_ipv6_address_prefix_list (void *rule, struct prefix *prefix, 
+			      route_map_object_t type, void *object)
+{
+  struct prefix_list *plist;
+
+  if (type == RMAP_BGP)
+    {
+      plist = prefix_list_lookup (AFI_IP6, (char *) rule);
+      if (plist == NULL)
+	return RMAP_NOMATCH;
+    
+      return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
+	      RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ipv6_address_prefix_list_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+route_match_ipv6_address_prefix_list_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd =
+{
+  "ipv6 address prefix-list",
+  route_match_ipv6_address_prefix_list,
+  route_match_ipv6_address_prefix_list_compile,
+  route_match_ipv6_address_prefix_list_free
+};
+
+/* `set ipv6 nexthop global IP_ADDRESS' */
+
+/* Set nexthop to object.  ojbect must be pointer to struct attr. */
+route_map_result_t
+route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix, 
+			       route_map_object_t type, void *object)
+{
+  struct in6_addr *address;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      address = rule;
+      bgp_info = object;
+    
+      /* Set next hop value. */ 
+      bgp_info->attr->mp_nexthop_global = *address;
+    
+      /* Set nexthop length. */
+      if (bgp_info->attr->mp_nexthop_len == 0)
+	bgp_info->attr->mp_nexthop_len = 16;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Route map `ip next-hop' compile function.  Given string is converted
+   to struct in_addr structure. */
+void *
+route_set_ipv6_nexthop_global_compile (char *arg)
+{
+  int ret;
+  struct in6_addr *address;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
+
+  ret = inet_pton (AF_INET6, arg, address);
+
+  if (ret == 0)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+/* Free route map's compiled `ip next-hop' value. */
+void
+route_set_ipv6_nexthop_global_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip nexthop set. */
+struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd =
+{
+  "ipv6 next-hop global",
+  route_set_ipv6_nexthop_global,
+  route_set_ipv6_nexthop_global_compile,
+  route_set_ipv6_nexthop_global_free
+};
+
+/* `set ipv6 nexthop local IP_ADDRESS' */
+
+/* Set nexthop to object.  ojbect must be pointer to struct attr. */
+route_map_result_t
+route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix, 
+			      route_map_object_t type, void *object)
+{
+  struct in6_addr *address;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      address = rule;
+      bgp_info = object;
+    
+      /* Set next hop value. */ 
+      bgp_info->attr->mp_nexthop_local = *address;
+    
+      /* Set nexthop length. */
+      if (bgp_info->attr->mp_nexthop_len != 32)
+	bgp_info->attr->mp_nexthop_len = 32;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Route map `ip nexthop' compile function.  Given string is converted
+   to struct in_addr structure. */
+void *
+route_set_ipv6_nexthop_local_compile (char *arg)
+{
+  int ret;
+  struct in6_addr *address;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
+
+  ret = inet_pton (AF_INET6, arg, address);
+
+  if (ret == 0)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+/* Free route map's compiled `ip nexthop' value. */
+void
+route_set_ipv6_nexthop_local_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip nexthop set. */
+struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd =
+{
+  "ipv6 next-hop local",
+  route_set_ipv6_nexthop_local,
+  route_set_ipv6_nexthop_local_compile,
+  route_set_ipv6_nexthop_local_free
+};
+#endif /* HAVE_IPV6 */
+
+/* `set vpnv4 nexthop A.B.C.D' */
+
+route_map_result_t
+route_set_vpnv4_nexthop (void *rule, struct prefix *prefix, 
+			 route_map_object_t type, void *object)
+{
+  struct in_addr *address;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      address = rule;
+      bgp_info = object;
+    
+      /* Set next hop value. */ 
+      bgp_info->attr->mp_nexthop_global_in = *address;
+    }
+
+  return RMAP_OKAY;
+}
+
+void *
+route_set_vpnv4_nexthop_compile (char *arg)
+{
+  int ret;
+  struct in_addr *address;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
+
+  ret = inet_aton (arg, address);
+
+  if (ret == 0)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+void
+route_set_vpnv4_nexthop_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip nexthop set. */
+struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd =
+{
+  "vpnv4 next-hop",
+  route_set_vpnv4_nexthop,
+  route_set_vpnv4_nexthop_compile,
+  route_set_vpnv4_nexthop_free
+};
+
+/* `set originator-id' */
+
+/* For origin set. */
+route_map_result_t
+route_set_originator_id (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
+{
+  struct in_addr *address;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP) 
+    {
+      address = rule;
+      bgp_info = object;
+    
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
+      bgp_info->attr->originator_id = *address;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for originator-id set. */
+void *
+route_set_originator_id_compile (char *arg)
+{
+  int ret;
+  struct in_addr *address;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
+
+  ret = inet_aton (arg, address);
+
+  if (ret == 0)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+/* Compile function for originator_id set. */
+void
+route_set_originator_id_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set metric rule structure. */
+struct route_map_rule_cmd route_set_originator_id_cmd = 
+{
+  "originator-id",
+  route_set_originator_id,
+  route_set_originator_id_compile,
+  route_set_originator_id_free,
+};
+
+/* Add bgp route map rule. */
+int
+bgp_route_match_add (struct vty *vty, struct route_map_index *index,
+		    char *command, char *arg)
+{
+  int ret;
+
+  ret = route_map_add_match (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+	{
+	case RMAP_RULE_MISSING:
+	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	case RMAP_COMPILE_ERROR:
+	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	}
+    }
+  return CMD_SUCCESS;
+}
+
+/* Delete bgp route map rule. */
+int
+bgp_route_match_delete (struct vty *vty, struct route_map_index *index,
+			char *command, char *arg)
+{
+  int ret;
+
+  ret = route_map_delete_match (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+	{
+	case RMAP_RULE_MISSING:
+	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	case RMAP_COMPILE_ERROR:
+	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	}
+    }
+  return CMD_SUCCESS;
+}
+
+/* Add bgp route map rule. */
+int
+bgp_route_set_add (struct vty *vty, struct route_map_index *index,
+		   char *command, char *arg)
+{
+  int ret;
+
+  ret = route_map_add_set (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+	{
+	case RMAP_RULE_MISSING:
+	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	case RMAP_COMPILE_ERROR:
+	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	}
+    }
+  return CMD_SUCCESS;
+}
+
+/* Delete bgp route map rule. */
+int
+bgp_route_set_delete (struct vty *vty, struct route_map_index *index,
+		      char *command, char *arg)
+{
+  int ret;
+
+  ret = route_map_delete_set (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+	{
+	case RMAP_RULE_MISSING:
+	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	case RMAP_COMPILE_ERROR:
+	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	}
+    }
+  return CMD_SUCCESS;
+}
+
+/* Hook function for updating route_map assignment. */
+void
+bgp_route_map_update ()
+{
+  int i;
+  afi_t afi;
+  safi_t safi;
+  int direct;
+  struct listnode *nn, *nm;
+  struct bgp *bgp;
+  struct peer *peer;
+  struct peer_group *group;
+  struct bgp_filter *filter;
+  struct bgp_node *bn;
+  struct bgp_static *bgp_static;
+
+  /* For neighbor route-map updates. */
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      LIST_LOOP (bgp->peer, peer, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		filter = &peer->filter[afi][safi];
+	  
+		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
+		  {
+		    if (filter->map[direct].name)
+		      filter->map[direct].map = 
+			route_map_lookup_by_name (filter->map[direct].name);
+		    else
+		      filter->map[direct].map = NULL;
+		  }
+
+		if (filter->usmap.name)
+		  filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
+		else
+		  filter->usmap.map = NULL;
+	      }
+	}
+      LIST_LOOP (bgp->group, group, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		filter = &group->conf->filter[afi][safi];
+	  
+		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
+		  {
+		    if (filter->map[direct].name)
+		      filter->map[direct].map = 
+			route_map_lookup_by_name (filter->map[direct].name);
+		    else
+		      filter->map[direct].map = NULL;
+		  }
+
+		if (filter->usmap.name)
+		  filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
+		else
+		  filter->usmap.map = NULL;
+	      }
+	}
+    }
+
+  /* For default-originate route-map updates. */
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      LIST_LOOP (bgp->peer, peer, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		if (peer->default_rmap[afi][safi].name)
+		  peer->default_rmap[afi][safi].map =
+		    route_map_lookup_by_name (peer->default_rmap[afi][safi].name);
+		else
+		  peer->default_rmap[afi][safi].map = NULL;
+	      }
+	}
+    }
+
+  /* For network route-map updates. */
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	  for (bn = bgp_table_top (bgp->route[afi][safi]); bn;
+	       bn = bgp_route_next (bn))
+	    if ((bgp_static = bn->info) != NULL)
+	      {
+		if (bgp_static->rmap.name)
+		  bgp_static->rmap.map =
+			 route_map_lookup_by_name (bgp_static->rmap.name);
+		else
+		  bgp_static->rmap.map = NULL;
+	      }
+    }
+
+  /* For redistribute route-map updates. */
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+	{
+	  if (bgp->rmap[ZEBRA_FAMILY_IPV4][i].name)
+	    bgp->rmap[ZEBRA_FAMILY_IPV4][i].map = 
+	      route_map_lookup_by_name (bgp->rmap[ZEBRA_FAMILY_IPV4][i].name);
+#ifdef HAVE_IPV6
+	  if (bgp->rmap[ZEBRA_FAMILY_IPV6][i].name)
+	    bgp->rmap[ZEBRA_FAMILY_IPV6][i].map =
+	      route_map_lookup_by_name (bgp->rmap[ZEBRA_FAMILY_IPV6][i].name);
+#endif /* HAVE_IPV6 */
+	}
+    }
+}
+
+DEFUN (match_ip_address, 
+       match_ip_address_cmd,
+       "match ip address (<1-199>|<1300-2699>|WORD)",
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP Access-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ip address", argv[0]);
+}
+
+DEFUN (no_match_ip_address, 
+       no_match_ip_address_cmd,
+       "no match ip address",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n")
+{
+  if (argc == 0)
+    return bgp_route_match_delete (vty, vty->index, "ip address", NULL);
+
+  return bgp_route_match_delete (vty, vty->index, "ip address", argv[0]);
+}
+
+ALIAS (no_match_ip_address, 
+       no_match_ip_address_val_cmd,
+       "no match ip address (<1-199>|<1300-2699>|WORD)",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP Access-list name\n")
+
+DEFUN (match_ip_next_hop, 
+       match_ip_next_hop_cmd,
+       "match ip next-hop (<1-199>|<1300-2699>|WORD)",
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP Access-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
+}
+
+DEFUN (no_match_ip_next_hop,
+       no_match_ip_next_hop_cmd,
+       "no match ip next-hop",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n")
+{
+  if (argc == 0)
+    return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL);
+
+  return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
+}
+
+ALIAS (no_match_ip_next_hop,
+       no_match_ip_next_hop_val_cmd,
+       "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP Access-list name\n")
+
+DEFUN (match_ip_address_prefix_list, 
+       match_ip_address_prefix_list_cmd,
+       "match ip address prefix-list WORD",
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]);
+}
+
+DEFUN (no_match_ip_address_prefix_list,
+       no_match_ip_address_prefix_list_cmd,
+       "no match ip address prefix-list",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n")
+{
+  if (argc == 0)
+    return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
+
+  return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
+}
+
+ALIAS (no_match_ip_address_prefix_list,
+       no_match_ip_address_prefix_list_val_cmd,
+       "no match ip address prefix-list WORD",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+
+DEFUN (match_ip_next_hop_prefix_list, 
+       match_ip_next_hop_prefix_list_cmd,
+       "match ip next-hop prefix-list WORD",
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]);
+}
+
+DEFUN (no_match_ip_next_hop_prefix_list,
+       no_match_ip_next_hop_prefix_list_cmd,
+       "no match ip next-hop prefix-list",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "Match entries of prefix-lists\n")
+{
+  if (argc == 0)
+    return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL);
+
+  return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]);
+}
+
+ALIAS (no_match_ip_next_hop_prefix_list,
+       no_match_ip_next_hop_prefix_list_val_cmd,
+       "no match ip next-hop prefix-list WORD",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+
+DEFUN (match_metric, 
+       match_metric_cmd,
+       "match metric <0-4294967295>",
+       MATCH_STR
+       "Match metric of route\n"
+       "Metric value\n")
+{
+  return bgp_route_match_add (vty, vty->index, "metric", argv[0]);
+}
+
+DEFUN (no_match_metric,
+       no_match_metric_cmd,
+       "no match metric",
+       NO_STR
+       MATCH_STR
+       "Match metric of route\n")
+{
+  if (argc == 0)
+    return bgp_route_match_delete (vty, vty->index, "metric", NULL);
+
+  return bgp_route_match_delete (vty, vty->index, "metric", argv[0]);
+}
+
+ALIAS (no_match_metric,
+       no_match_metric_val_cmd,
+       "no match metric <0-4294967295>",
+       NO_STR
+       MATCH_STR
+       "Match metric of route\n"
+       "Metric value\n")
+
+DEFUN (match_community, 
+       match_community_cmd,
+       "match community (<1-99>|<100-199>|WORD)",
+       MATCH_STR
+       "Match BGP community list\n"
+       "Community-list number (standard)\n"
+       "Community-list number (expanded)\n"
+       "Community-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "community", argv[0]);
+}
+
+DEFUN (match_community_exact, 
+       match_community_exact_cmd,
+       "match community (<1-99>|<100-199>|WORD) exact-match",
+       MATCH_STR
+       "Match BGP community list\n"
+       "Community-list number (standard)\n"
+       "Community-list number (expanded)\n"
+       "Community-list name\n"
+       "Do exact matching of communities\n")
+{
+  int ret;
+  char *argstr;
+
+  argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
+		    strlen (argv[0]) + strlen ("exact-match") + 2);
+
+  sprintf (argstr, "%s exact-match", argv[0]);
+
+  ret = bgp_route_match_add (vty, vty->index, "community", argstr);
+
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
+
+  return ret;
+}
+
+DEFUN (no_match_community,
+       no_match_community_cmd,
+       "no match community",
+       NO_STR
+       MATCH_STR
+       "Match BGP community list\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "community", NULL);
+}
+
+ALIAS (no_match_community,
+       no_match_community_val_cmd,
+       "no match community (<1-99>|<100-199>|WORD)",
+       NO_STR
+       MATCH_STR
+       "Match BGP community list\n"
+       "Community-list number (standard)\n"
+       "Community-list number (expanded)\n"
+       "Community-list name\n")
+
+ALIAS (no_match_community,
+       no_match_community_exact_cmd,
+       "no match community (<1-99>|<100-199>|WORD) exact-match",
+       NO_STR
+       MATCH_STR
+       "Match BGP community list\n"
+       "Community-list number (standard)\n"
+       "Community-list number (expanded)\n"
+       "Community-list name\n"
+       "Do exact matching of communities\n")
+
+DEFUN (match_aspath,
+       match_aspath_cmd,
+       "match as-path WORD",
+       MATCH_STR
+       "Match BGP AS path list\n"
+       "AS path access-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "as-path", argv[0]);
+}
+
+DEFUN (no_match_aspath,
+       no_match_aspath_cmd,
+       "no match as-path",
+       NO_STR
+       MATCH_STR
+       "Match BGP AS path list\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "as-path", NULL);
+}
+
+ALIAS (no_match_aspath,
+       no_match_aspath_val_cmd,
+       "no match as-path WORD",
+       NO_STR
+       MATCH_STR
+       "Match BGP AS path list\n"
+       "AS path access-list name\n")
+
+DEFUN (match_origin,
+       match_origin_cmd,
+       "match origin (egp|igp|incomplete)",
+       MATCH_STR
+       "BGP origin code\n"
+       "remote EGP\n"
+       "local IGP\n"
+       "unknown heritage\n")
+{
+  if (strncmp (argv[0], "igp", 2) == 0)
+    return bgp_route_match_add (vty, vty->index, "origin", "igp");
+  if (strncmp (argv[0], "egp", 1) == 0)
+    return bgp_route_match_add (vty, vty->index, "origin", "egp");
+  if (strncmp (argv[0], "incomplete", 2) == 0)
+    return bgp_route_match_add (vty, vty->index, "origin", "incomplete");
+
+  return CMD_WARNING;
+}
+
+DEFUN (no_match_origin,
+       no_match_origin_cmd,
+       "no match origin",
+       NO_STR
+       MATCH_STR
+       "BGP origin code\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "origin", NULL);
+}
+
+ALIAS (no_match_origin,
+       no_match_origin_val_cmd,
+       "no match origin (egp|igp|incomplete)",
+       NO_STR
+       MATCH_STR
+       "BGP origin code\n"
+       "remote EGP\n"
+       "local IGP\n"
+       "unknown heritage\n")
+
+DEFUN (set_ip_nexthop,
+       set_ip_nexthop_cmd,
+       "set ip next-hop A.B.C.D",
+       SET_STR
+       IP_STR
+       "Next hop address\n"
+       "IP address of next hop\n")
+{
+  union sockunion su;
+  int ret;
+
+  ret = str2sockunion (argv[0], &su);
+  if (ret < 0)
+    {
+      vty_out (vty, "%% Malformed Next-hop address%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+ 
+  return bgp_route_set_add (vty, vty->index, "ip next-hop", argv[0]);
+}
+
+DEFUN (no_set_ip_nexthop,
+       no_set_ip_nexthop_cmd,
+       "no set ip next-hop",
+       NO_STR
+       SET_STR
+       IP_STR
+       "Next hop address\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
+
+  return bgp_route_set_delete (vty, vty->index, "ip next-hop", argv[0]);
+}
+
+ALIAS (no_set_ip_nexthop,
+       no_set_ip_nexthop_val_cmd,
+       "no set ip next-hop A.B.C.D",
+       NO_STR
+       SET_STR
+       IP_STR
+       "Next hop address\n"
+       "IP address of next hop\n")
+
+DEFUN (set_metric,
+       set_metric_cmd,
+       "set metric (<0-4294967295>|<+/-metric>)",
+       SET_STR
+       "Metric value for destination routing protocol\n"
+       "Metric value\n"
+       "Add or subtract metric\n")
+{
+  return bgp_route_set_add (vty, vty->index, "metric", argv[0]);
+}
+
+DEFUN (no_set_metric,
+       no_set_metric_cmd,
+       "no set metric",
+       NO_STR
+       SET_STR
+       "Metric value for destination routing protocol\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "metric", NULL);
+
+  return bgp_route_set_delete (vty, vty->index, "metric", argv[0]);
+}
+
+ALIAS (no_set_metric,
+       no_set_metric_val_cmd,
+       "no set metric <0-4294967295>",
+       NO_STR
+       SET_STR
+       "Metric value for destination routing protocol\n"
+       "Metric value\n")
+
+DEFUN (set_local_pref,
+       set_local_pref_cmd,
+       "set local-preference <0-4294967295>",
+       SET_STR
+       "BGP local preference path attribute\n"
+       "Preference value\n")
+{
+  return bgp_route_set_add (vty, vty->index, "local-preference", argv[0]);
+}
+
+DEFUN (no_set_local_pref,
+       no_set_local_pref_cmd,
+       "no set local-preference",
+       NO_STR
+       SET_STR
+       "BGP local preference path attribute\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "local-preference", NULL);
+
+  return bgp_route_set_delete (vty, vty->index, "local-preference", argv[0]);
+}
+
+ALIAS (no_set_local_pref,
+       no_set_local_pref_val_cmd,
+       "no set local-preference <0-4294967295>",
+       NO_STR
+       SET_STR
+       "BGP local preference path attribute\n"
+       "Preference value\n")
+
+DEFUN (set_weight,
+       set_weight_cmd,
+       "set weight <0-4294967295>",
+       SET_STR
+       "BGP weight for routing table\n"
+       "Weight value\n")
+{
+  return bgp_route_set_add (vty, vty->index, "weight", argv[0]);
+}
+
+DEFUN (no_set_weight,
+       no_set_weight_cmd,
+       "no set weight",
+       NO_STR
+       SET_STR
+       "BGP weight for routing table\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "weight", NULL);
+  
+  return bgp_route_set_delete (vty, vty->index, "weight", argv[0]);
+}
+
+ALIAS (no_set_weight,
+       no_set_weight_val_cmd,
+       "no set weight <0-4294967295>",
+       NO_STR
+       SET_STR
+       "BGP weight for routing table\n"
+       "Weight value\n")
+
+DEFUN (set_aspath_prepend,
+       set_aspath_prepend_cmd,
+       "set as-path prepend .<1-65535>",
+       SET_STR
+       "Prepend string for a BGP AS-path attribute\n"
+       "Prepend to the as-path\n"
+       "AS number\n")
+{
+  int ret;
+  char *str;
+
+  str = argv_concat (argv, argc, 0);
+  ret = bgp_route_set_add (vty, vty->index, "as-path prepend", str);
+  XFREE (MTYPE_TMP, str);
+
+  return ret;
+}
+
+DEFUN (no_set_aspath_prepend,
+       no_set_aspath_prepend_cmd,
+       "no set as-path prepend",
+       NO_STR
+       SET_STR
+       "Prepend string for a BGP AS-path attribute\n"
+       "Prepend to the as-path\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "as-path prepend", NULL);
+}
+
+ALIAS (no_set_aspath_prepend,
+       no_set_aspath_prepend_val_cmd,
+       "no set as-path prepend .<1-65535>",
+       NO_STR
+       SET_STR
+       "Prepend string for a BGP AS-path attribute\n"
+       "Prepend to the as-path\n"
+       "AS number\n")
+
+DEFUN (set_community,
+       set_community_cmd,
+       "set community .AA:NN",
+       SET_STR
+       "BGP community attribute\n"
+       "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
+{
+  int i;
+  int first = 0;
+  int additive = 0;
+  struct buffer *b;
+  struct community *com = NULL;
+  char *str;
+  char *argstr;
+  int ret;
+
+  b = buffer_new (1024);
+
+  for (i = 0; i < argc; i++)
+    {
+      if (strncmp (argv[i], "additive", strlen (argv[i])) == 0)
+ 	{
+ 	  additive = 1;
+ 	  continue;
+ 	}
+
+      if (first)
+	buffer_putc (b, ' ');
+      else
+	first = 1;
+
+      if (strncmp (argv[i], "internet", strlen (argv[i])) == 0)
+ 	{
+	  buffer_putstr (b, "internet");
+ 	  continue;
+ 	}
+      if (strncmp (argv[i], "local-AS", strlen (argv[i])) == 0)
+ 	{
+	  buffer_putstr (b, "local-AS");
+ 	  continue;
+ 	}
+      if (strncmp (argv[i], "no-a", strlen ("no-a")) == 0
+	  && strncmp (argv[i], "no-advertise", strlen (argv[i])) == 0)
+ 	{
+	  buffer_putstr (b, "no-advertise");
+ 	  continue;
+ 	}
+      if (strncmp (argv[i], "no-e", strlen ("no-e"))== 0
+	  && strncmp (argv[i], "no-export", strlen (argv[i])) == 0)
+ 	{
+	  buffer_putstr (b, "no-export");
+ 	  continue;
+ 	}
+      buffer_putstr (b, argv[i]);
+    }
+  buffer_putc (b, '\0');
+
+  /* Fetch result string then compile it to communities attribute.  */
+  str = buffer_getstr (b);
+  buffer_free (b);
+
+  if (str)
+    {
+      com = community_str2com (str);
+      free (str);
+    }
+
+  /* Can't compile user input into communities attribute.  */
+  if (! com)
+    {
+      vty_out (vty, "%% Malformed communities attribute%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Set communites attribute string.  */
+  str = community_str (com);
+
+  if (additive)
+    {
+      argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
+      strcpy (argstr, str);
+      strcpy (argstr + strlen (str), " additive");
+      ret =  bgp_route_set_add (vty, vty->index, "community", argstr);
+      XFREE (MTYPE_TMP, argstr);
+    }
+  else
+    ret =  bgp_route_set_add (vty, vty->index, "community", str);
+
+  community_free (com);
+
+  return ret;
+}
+
+DEFUN (set_community_none,
+       set_community_none_cmd,
+       "set community none",
+       SET_STR
+       "BGP community attribute\n"
+       "No community attribute\n")
+{
+  return bgp_route_set_add (vty, vty->index, "community", "none");
+}
+
+DEFUN (no_set_community,
+       no_set_community_cmd,
+       "no set community",
+       NO_STR
+       SET_STR
+       "BGP community attribute\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "community", NULL);
+}
+
+ALIAS (no_set_community,
+       no_set_community_val_cmd,
+       "no set community .AA:NN",
+       NO_STR
+       SET_STR
+       "BGP community attribute\n"
+       "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
+
+ALIAS (no_set_community,
+       no_set_community_none_cmd,
+       "no set community none",
+       NO_STR
+       SET_STR
+       "BGP community attribute\n"
+       "No community attribute\n")
+
+DEFUN (set_community_delete,
+       set_community_delete_cmd,
+       "set comm-list (<1-99>|<100-199>|WORD) delete",
+       SET_STR
+       "set BGP community list (for deletion)\n"
+       "Community-list number (standard)\n"
+       "Communitly-list number (expanded)\n"
+       "Community-list name\n"
+       "Delete matching communities\n")
+{
+  char *str;
+
+  str = XCALLOC (MTYPE_TMP, strlen (argv[0]) + strlen (" delete") + 1);
+  strcpy (str, argv[0]);
+  strcpy (str + strlen (argv[0]), " delete");
+
+  bgp_route_set_add (vty, vty->index, "comm-list", str);
+
+  XFREE (MTYPE_TMP, str);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_set_community_delete,
+       no_set_community_delete_cmd,
+       "no set comm-list",
+       NO_STR
+       SET_STR
+       "set BGP community list (for deletion)\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "comm-list", NULL);
+}
+
+ALIAS (no_set_community_delete,
+       no_set_community_delete_val_cmd,
+       "no set comm-list (<1-99>|<100-199>|WORD) delete",
+       NO_STR
+       SET_STR
+       "set BGP community list (for deletion)\n"
+       "Community-list number (standard)\n"
+       "Communitly-list number (expanded)\n"
+       "Community-list name\n"
+       "Delete matching communities\n")
+
+DEFUN (set_ecommunity_rt,
+       set_ecommunity_rt_cmd,
+       "set extcommunity rt .ASN:nn_or_IP-address:nn",
+       SET_STR
+       "BGP extended community attribute\n"
+       "Route Target extened communityt\n"
+       "VPN extended community\n")
+{
+  int ret;
+  char *str;
+
+  str = argv_concat (argv, argc, 0);
+  ret = bgp_route_set_add (vty, vty->index, "extcommunity rt", str);
+  XFREE (MTYPE_TMP, str);
+
+  return ret;
+}
+
+DEFUN (no_set_ecommunity_rt,
+       no_set_ecommunity_rt_cmd,
+       "no set extcommunity rt",
+       NO_STR
+       SET_STR
+       "BGP extended community attribute\n"
+       "Route Target extened communityt\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "extcommunity rt", NULL);
+}
+
+ALIAS (no_set_ecommunity_rt,
+       no_set_ecommunity_rt_val_cmd,
+       "no set extcommunity rt .ASN:nn_or_IP-address:nn",
+       NO_STR
+       SET_STR
+       "BGP extended community attribute\n"
+       "Route Target extened communityt\n"
+       "VPN extended community\n")
+
+DEFUN (set_ecommunity_soo,
+       set_ecommunity_soo_cmd,
+       "set extcommunity soo .ASN:nn_or_IP-address:nn",
+       SET_STR
+       "BGP extended community attribute\n"
+       "Site-of-Origin extended community\n"
+       "VPN extended community\n")
+{
+  int ret;
+  char *str;
+
+  str = argv_concat (argv, argc, 0);
+  ret = bgp_route_set_add (vty, vty->index, "extcommunity soo", str);
+  XFREE (MTYPE_TMP, str);
+  return ret;
+}
+
+DEFUN (no_set_ecommunity_soo,
+       no_set_ecommunity_soo_cmd,
+       "no set extcommunity soo",
+       NO_STR
+       SET_STR
+       "BGP extended community attribute\n"
+       "Site-of-Origin extended community\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "extcommunity soo", NULL);
+}
+
+ALIAS (no_set_ecommunity_soo,
+       no_set_ecommunity_soo_val_cmd,
+       "no set extcommunity soo .ASN:nn_or_IP-address:nn",
+       NO_STR
+       SET_STR
+       "BGP extended community attribute\n"
+       "Site-of-Origin extended community\n"
+       "VPN extended community\n")
+
+DEFUN (set_origin,
+       set_origin_cmd,
+       "set origin (egp|igp|incomplete)",
+       SET_STR
+       "BGP origin code\n"
+       "remote EGP\n"
+       "local IGP\n"
+       "unknown heritage\n")
+{
+  if (strncmp (argv[0], "igp", 2) == 0)
+    return bgp_route_set_add (vty, vty->index, "origin", "igp");
+  if (strncmp (argv[0], "egp", 1) == 0)
+    return bgp_route_set_add (vty, vty->index, "origin", "egp");
+  if (strncmp (argv[0], "incomplete", 2) == 0)
+    return bgp_route_set_add (vty, vty->index, "origin", "incomplete");
+
+  return CMD_WARNING;
+}
+
+DEFUN (no_set_origin,
+       no_set_origin_cmd,
+       "no set origin",
+       NO_STR
+       SET_STR
+       "BGP origin code\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "origin", NULL);
+}
+
+ALIAS (no_set_origin,
+       no_set_origin_val_cmd,
+       "no set origin (egp|igp|incomplete)",
+       NO_STR
+       SET_STR
+       "BGP origin code\n"
+       "remote EGP\n"
+       "local IGP\n"
+       "unknown heritage\n")
+
+DEFUN (set_atomic_aggregate,
+       set_atomic_aggregate_cmd,
+       "set atomic-aggregate",
+       SET_STR
+       "BGP atomic aggregate attribute\n" )
+{
+  return bgp_route_set_add (vty, vty->index, "atomic-aggregate", NULL);
+}
+
+DEFUN (no_set_atomic_aggregate,
+       no_set_atomic_aggregate_cmd,
+       "no set atomic-aggregate",
+       NO_STR
+       SET_STR
+       "BGP atomic aggregate attribute\n" )
+{
+  return bgp_route_set_delete (vty, vty->index, "atomic-aggregate", NULL);
+}
+
+DEFUN (set_aggregator_as,
+       set_aggregator_as_cmd,
+       "set aggregator as <1-65535> A.B.C.D",
+       SET_STR
+       "BGP aggregator attribute\n"
+       "AS number of aggregator\n"
+       "AS number\n"
+       "IP address of aggregator\n")
+{
+  int ret;
+  as_t as;
+  struct in_addr address;
+  char *endptr = NULL;
+  char *argstr;
+
+  as = strtoul (argv[0], &endptr, 10);
+  if (as == 0 || as == ULONG_MAX || *endptr != '\0')
+    {
+      vty_out (vty, "AS path value malformed%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = inet_aton (argv[1], &address);
+  if (ret == 0)
+    {
+      vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
+		    strlen (argv[0]) + strlen (argv[1]) + 2);
+
+  sprintf (argstr, "%s %s", argv[0], argv[1]);
+
+  ret = bgp_route_set_add (vty, vty->index, "aggregator as", argstr);
+
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
+
+  return ret;
+}
+
+DEFUN (no_set_aggregator_as,
+       no_set_aggregator_as_cmd,
+       "no set aggregator as",
+       NO_STR
+       SET_STR
+       "BGP aggregator attribute\n"
+       "AS number of aggregator\n")
+{
+  int ret;
+  as_t as;
+  struct in_addr address;
+  char *endptr = NULL;
+  char *argstr;
+
+  if (argv == 0)
+    return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
+  
+  as = strtoul (argv[0], &endptr, 10);
+  if (as == 0 || as == ULONG_MAX || *endptr != '\0')
+    {
+      vty_out (vty, "AS path value malformed%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = inet_aton (argv[1], &address);
+  if (ret == 0)
+    {
+      vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
+		    strlen (argv[0]) + strlen (argv[1]) + 2);
+
+  sprintf (argstr, "%s %s", argv[0], argv[1]);
+
+  ret = bgp_route_set_delete (vty, vty->index, "aggregator as", argstr);
+
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
+
+  return ret;
+}
+
+ALIAS (no_set_aggregator_as,
+       no_set_aggregator_as_val_cmd,
+       "no set aggregator as <1-65535> A.B.C.D",
+       NO_STR
+       SET_STR
+       "BGP aggregator attribute\n"
+       "AS number of aggregator\n"
+       "AS number\n"
+       "IP address of aggregator\n")
+
+
+#ifdef HAVE_IPV6
+DEFUN (match_ipv6_address, 
+       match_ipv6_address_cmd,
+       "match ipv6 address WORD",
+       MATCH_STR
+       IPV6_STR
+       "Match IPv6 address of route\n"
+       "IPv6 access-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0]);
+}
+
+DEFUN (no_match_ipv6_address, 
+       no_match_ipv6_address_cmd,
+       "no match ipv6 address WORD",
+       NO_STR
+       MATCH_STR
+       IPV6_STR
+       "Match IPv6 address of route\n"
+       "IPv6 access-list name\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0]);
+}
+
+DEFUN (match_ipv6_next_hop, 
+       match_ipv6_next_hop_cmd,
+       "match ipv6 next-hop X:X::X:X",
+       MATCH_STR
+       IPV6_STR
+       "Match IPv6 next-hop address of route\n"
+       "IPv6 address of next hop\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0]);
+}
+
+DEFUN (no_match_ipv6_next_hop,
+       no_match_ipv6_next_hop_cmd,
+       "no match ipv6 next-hop X:X::X:X",
+       NO_STR
+       MATCH_STR
+       IPV6_STR
+       "Match IPv6 next-hop address of route\n"
+       "IPv6 address of next hop\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0]);
+}
+
+DEFUN (match_ipv6_address_prefix_list, 
+       match_ipv6_address_prefix_list_cmd,
+       "match ipv6 address prefix-list WORD",
+       MATCH_STR
+       IPV6_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list", argv[0]);
+}
+
+DEFUN (no_match_ipv6_address_prefix_list,
+       no_match_ipv6_address_prefix_list_cmd,
+       "no match ipv6 address prefix-list WORD",
+       NO_STR
+       MATCH_STR
+       IPV6_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]);
+}
+
+DEFUN (set_ipv6_nexthop_global,
+       set_ipv6_nexthop_global_cmd,
+       "set ipv6 next-hop global X:X::X:X",
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 global address\n"
+       "IPv6 address of next hop\n")
+{
+  return bgp_route_set_add (vty, vty->index, "ipv6 next-hop global", argv[0]);
+}
+
+DEFUN (no_set_ipv6_nexthop_global,
+       no_set_ipv6_nexthop_global_cmd,
+       "no set ipv6 next-hop global",
+       NO_STR
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 global address\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", NULL);
+
+  return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", argv[0]);
+}
+
+ALIAS (no_set_ipv6_nexthop_global,
+       no_set_ipv6_nexthop_global_val_cmd,
+       "no set ipv6 next-hop global X:X::X:X",
+       NO_STR
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 global address\n"
+       "IPv6 address of next hop\n")
+
+DEFUN (set_ipv6_nexthop_local,
+       set_ipv6_nexthop_local_cmd,
+       "set ipv6 next-hop local X:X::X:X",
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 local address\n"
+       "IPv6 address of next hop\n")
+{
+  return bgp_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[0]);
+}
+
+DEFUN (no_set_ipv6_nexthop_local,
+       no_set_ipv6_nexthop_local_cmd,
+       "no set ipv6 next-hop local",
+       NO_STR
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 local address\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL);
+  
+  return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[0]);
+}
+
+ALIAS (no_set_ipv6_nexthop_local,
+       no_set_ipv6_nexthop_local_val_cmd,
+       "no set ipv6 next-hop local X:X::X:X",
+       NO_STR
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 local address\n"
+       "IPv6 address of next hop\n")
+#endif /* HAVE_IPV6 */
+
+DEFUN (set_vpnv4_nexthop,
+       set_vpnv4_nexthop_cmd,
+       "set vpnv4 next-hop A.B.C.D",
+       SET_STR
+       "VPNv4 information\n"
+       "VPNv4 next-hop address\n"
+       "IP address of next hop\n")
+{
+  return bgp_route_set_add (vty, vty->index, "vpnv4 next-hop", argv[0]);
+}
+
+DEFUN (no_set_vpnv4_nexthop,
+       no_set_vpnv4_nexthop_cmd,
+       "no set vpnv4 next-hop",
+       NO_STR
+       SET_STR
+       "VPNv4 information\n"
+       "VPNv4 next-hop address\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", NULL);
+
+  return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", argv[0]);
+}
+
+ALIAS (no_set_vpnv4_nexthop,
+       no_set_vpnv4_nexthop_val_cmd,
+       "no set vpnv4 next-hop A.B.C.D",
+       NO_STR
+       SET_STR
+       "VPNv4 information\n"
+       "VPNv4 next-hop address\n"
+       "IP address of next hop\n")
+
+DEFUN (set_originator_id,
+       set_originator_id_cmd,
+       "set originator-id A.B.C.D",
+       SET_STR
+       "BGP originator ID attribute\n"
+       "IP address of originator\n")
+{
+  return bgp_route_set_add (vty, vty->index, "originator-id", argv[0]);
+}
+
+DEFUN (no_set_originator_id,
+       no_set_originator_id_cmd,
+       "no set originator-id",
+       NO_STR
+       SET_STR
+       "BGP originator ID attribute\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "originator-id", NULL);
+  
+  return bgp_route_set_delete (vty, vty->index, "originator-id", argv[0]);
+}
+
+ALIAS (no_set_originator_id,
+       no_set_originator_id_val_cmd,
+       "no set originator-id A.B.C.D",
+       NO_STR
+       SET_STR
+       "BGP originator ID attribute\n"
+       "IP address of originator\n")
+
+
+/* Initialization of route map. */
+void
+bgp_route_map_init ()
+{
+  route_map_init ();
+  route_map_init_vty ();
+  route_map_add_hook (bgp_route_map_update);
+  route_map_delete_hook (bgp_route_map_update);
+
+  route_map_install_match (&route_match_ip_address_cmd);
+  route_map_install_match (&route_match_ip_next_hop_cmd);
+  route_map_install_match (&route_match_ip_address_prefix_list_cmd);
+  route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
+  route_map_install_match (&route_match_aspath_cmd);
+  route_map_install_match (&route_match_community_cmd);
+  route_map_install_match (&route_match_metric_cmd);
+  route_map_install_match (&route_match_origin_cmd);
+
+  route_map_install_set (&route_set_ip_nexthop_cmd);
+  route_map_install_set (&route_set_local_pref_cmd);
+  route_map_install_set (&route_set_weight_cmd);
+  route_map_install_set (&route_set_metric_cmd);
+  route_map_install_set (&route_set_aspath_prepend_cmd);
+  route_map_install_set (&route_set_origin_cmd);
+  route_map_install_set (&route_set_atomic_aggregate_cmd);
+  route_map_install_set (&route_set_aggregator_as_cmd);
+  route_map_install_set (&route_set_community_cmd);
+  route_map_install_set (&route_set_community_delete_cmd);
+  route_map_install_set (&route_set_vpnv4_nexthop_cmd);
+  route_map_install_set (&route_set_originator_id_cmd);
+  route_map_install_set (&route_set_ecommunity_rt_cmd);
+  route_map_install_set (&route_set_ecommunity_soo_cmd);
+
+  install_element (RMAP_NODE, &match_ip_address_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
+  install_element (RMAP_NODE, &match_ip_next_hop_cmd);
+  install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
+  install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
+
+  install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
+  install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
+
+  install_element (RMAP_NODE, &match_aspath_cmd);
+  install_element (RMAP_NODE, &no_match_aspath_cmd);
+  install_element (RMAP_NODE, &no_match_aspath_val_cmd);
+  install_element (RMAP_NODE, &match_metric_cmd);
+  install_element (RMAP_NODE, &no_match_metric_cmd);
+  install_element (RMAP_NODE, &no_match_metric_val_cmd);
+  install_element (RMAP_NODE, &match_community_cmd);
+  install_element (RMAP_NODE, &match_community_exact_cmd);
+  install_element (RMAP_NODE, &no_match_community_cmd);
+  install_element (RMAP_NODE, &no_match_community_val_cmd);
+  install_element (RMAP_NODE, &no_match_community_exact_cmd);
+  install_element (RMAP_NODE, &match_origin_cmd);
+  install_element (RMAP_NODE, &no_match_origin_cmd);
+  install_element (RMAP_NODE, &no_match_origin_val_cmd);
+
+  install_element (RMAP_NODE, &set_ip_nexthop_cmd);
+  install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
+  install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
+  install_element (RMAP_NODE, &set_local_pref_cmd);
+  install_element (RMAP_NODE, &no_set_local_pref_cmd);
+  install_element (RMAP_NODE, &no_set_local_pref_val_cmd);
+  install_element (RMAP_NODE, &set_weight_cmd);
+  install_element (RMAP_NODE, &no_set_weight_cmd);
+  install_element (RMAP_NODE, &no_set_weight_val_cmd);
+  install_element (RMAP_NODE, &set_metric_cmd);
+  install_element (RMAP_NODE, &no_set_metric_cmd);
+  install_element (RMAP_NODE, &no_set_metric_val_cmd);
+  install_element (RMAP_NODE, &set_aspath_prepend_cmd);
+  install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
+  install_element (RMAP_NODE, &no_set_aspath_prepend_val_cmd);
+  install_element (RMAP_NODE, &set_origin_cmd);
+  install_element (RMAP_NODE, &no_set_origin_cmd);
+  install_element (RMAP_NODE, &no_set_origin_val_cmd);
+  install_element (RMAP_NODE, &set_atomic_aggregate_cmd);
+  install_element (RMAP_NODE, &no_set_atomic_aggregate_cmd);
+  install_element (RMAP_NODE, &set_aggregator_as_cmd);
+  install_element (RMAP_NODE, &no_set_aggregator_as_cmd);
+  install_element (RMAP_NODE, &no_set_aggregator_as_val_cmd);
+  install_element (RMAP_NODE, &set_community_cmd);
+  install_element (RMAP_NODE, &set_community_none_cmd);
+  install_element (RMAP_NODE, &no_set_community_cmd);
+  install_element (RMAP_NODE, &no_set_community_val_cmd);
+  install_element (RMAP_NODE, &no_set_community_none_cmd);
+  install_element (RMAP_NODE, &set_community_delete_cmd);
+  install_element (RMAP_NODE, &no_set_community_delete_cmd);
+  install_element (RMAP_NODE, &no_set_community_delete_val_cmd);
+  install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
+  install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
+  install_element (RMAP_NODE, &no_set_ecommunity_rt_val_cmd);
+  install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
+  install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
+  install_element (RMAP_NODE, &no_set_ecommunity_soo_val_cmd);
+  install_element (RMAP_NODE, &set_vpnv4_nexthop_cmd);
+  install_element (RMAP_NODE, &no_set_vpnv4_nexthop_cmd);
+  install_element (RMAP_NODE, &no_set_vpnv4_nexthop_val_cmd);
+  install_element (RMAP_NODE, &set_originator_id_cmd);
+  install_element (RMAP_NODE, &no_set_originator_id_cmd);
+  install_element (RMAP_NODE, &no_set_originator_id_val_cmd);
+
+#ifdef HAVE_IPV6
+  route_map_install_match (&route_match_ipv6_address_cmd);
+  route_map_install_match (&route_match_ipv6_next_hop_cmd);
+  route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
+  route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
+  route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
+
+  install_element (RMAP_NODE, &match_ipv6_address_cmd);
+  install_element (RMAP_NODE, &no_match_ipv6_address_cmd);
+  install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
+  install_element (RMAP_NODE, &no_match_ipv6_next_hop_cmd);
+  install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
+  install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd);
+  install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
+  install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_val_cmd);
+  install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
+  install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
+  install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
+#endif /* HAVE_IPV6 */
+}