]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_routemap.c
bgpd: Cleanup grabbag of coverity scan issues found
[mirror_frr.git] / bgpd / bgp_routemap.c
index d823b962b83903693a653e922d6aa11876b3d4ec..c7bcfe25f92b22701298a4b63a1d40a7c14ccf27 100644 (file)
@@ -22,6 +22,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
 #include "prefix.h"
 #include "filter.h"
+#include "vty.h"
 #include "routemap.h"
 #include "command.h"
 #include "linklist.h"
@@ -31,11 +32,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #ifdef HAVE_LIBPCREPOSIX
 # include <pcreposix.h>
 #else
-# ifdef HAVE_GNU_REGEX
-#  include <regex.h>
-# else
-#  include "regex-gnu.h"
-# endif /* HAVE_GNU_REGEX */
+# include <regex.h>
 #endif /* HAVE_LIBPCREPOSIX */
 #include "buffer.h"
 #include "sockunion.h"
@@ -55,9 +52,13 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "bgpd/bgp_filter.h"
 #include "bgpd/bgp_mplsvpn.h"
 #include "bgpd/bgp_ecommunity.h"
+#include "bgpd/bgp_lcommunity.h"
 #include "bgpd/bgp_vty.h"
 #include "bgpd/bgp_debug.h"
 
+#if ENABLE_BGP_VNC
+# include "bgpd/rfapi/bgp_rfapi_cfg.h"
+#endif
 
 /* Memo of route-map commands.
 
@@ -84,6 +85,8 @@ o Cisco route-map
       as-path tag       :  Not yet
       automatic-tag     :  (This will not be implemented by bgpd)
       community         :  Done
+      large-community   :  Done
+      large-comm-list   :  Done
       comm-list         :  Not yet
       dampning          :  Not yet
       default           :  (This will not be implemented by bgpd)
@@ -107,7 +110,7 @@ o Local extensions
   set ipv6 next-hop local : Done
   set as-path exclude     : Done
 
-*/ 
+*/
 
  /* generic value manipulation to be shared in multiple rules */
 
@@ -329,7 +332,7 @@ struct route_map_rule_cmd route_match_peer_cmd =
 /* Match function should return 1 if match is success else return
    zero. */
 static route_map_result_t
-route_match_ip_address (void *rule, struct prefix *prefix, 
+route_match_ip_address (void *rule, struct prefix *prefix,
                        route_map_object_t type, void *object)
 {
   struct access_list *alist;
@@ -340,7 +343,7 @@ route_match_ip_address (void *rule, struct prefix *prefix,
       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);
     }
@@ -375,7 +378,7 @@ struct route_map_rule_cmd route_match_ip_address_cmd =
 
 /* Match function return 1 if match is success else return zero. */
 static route_map_result_t
-route_match_ip_next_hop (void *rule, struct prefix *prefix, 
+route_match_ip_next_hop (void *rule, struct prefix *prefix,
                         route_map_object_t type, void *object)
 {
   struct access_list *alist;
@@ -427,7 +430,7 @@ struct route_map_rule_cmd route_match_ip_next_hop_cmd =
 
 /* Match function return 1 if match is success else return zero. */
 static route_map_result_t
-route_match_ip_route_source (void *rule, struct prefix *prefix, 
+route_match_ip_route_source (void *rule, struct prefix *prefix,
                             route_map_object_t type, void *object)
 {
   struct access_list *alist;
@@ -484,7 +487,7 @@ struct route_map_rule_cmd route_match_ip_route_source_cmd =
 /* `match ip address prefix-list PREFIX_LIST' */
 
 static route_map_result_t
-route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, 
+route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
                                    route_map_object_t type, void *object)
 {
   struct prefix_list *plist;
@@ -494,7 +497,7 @@ route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
       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);
     }
@@ -691,7 +694,7 @@ struct route_map_rule_cmd route_match_local_pref_cmd =
 
 /* Match function return 1 if match is success else return zero. */
 static route_map_result_t
-route_match_metric (void *rule, struct prefix *prefix, 
+route_match_metric (void *rule, struct prefix *prefix,
                    route_map_object_t type, void *object)
 {
   struct rmap_value *rv;
@@ -719,10 +722,10 @@ struct route_map_rule_cmd route_match_metric_cmd =
 
 /* Match function for as-path match.  I assume given object is */
 static route_map_result_t
-route_match_aspath (void *rule, struct prefix *prefix, 
+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;
 
@@ -755,7 +758,7 @@ route_match_aspath_free (void *rule)
 }
 
 /* Route map commands for aspath matching. */
-struct route_map_rule_cmd route_match_aspath_cmd = 
+struct route_map_rule_cmd route_match_aspath_cmd =
 {
   "as-path",
   route_match_aspath,
@@ -772,14 +775,14 @@ struct rmap_community
 
 /* Match function for community match. */
 static route_map_result_t
-route_match_community (void *rule, struct prefix *prefix, 
+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) 
+  if (type == RMAP_BGP)
     {
       bgp_info = object;
       rcom = rule;
@@ -834,12 +837,12 @@ route_match_community_free (void *rule)
 {
   struct rmap_community *rcom = rule;
 
-  XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name); 
+  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 = 
+struct route_map_rule_cmd route_match_community_cmd =
 {
   "community",
   route_match_community,
@@ -847,21 +850,93 @@ struct route_map_rule_cmd route_match_community_cmd =
   route_match_community_free
 };
 
+/* Match function for lcommunity match. */
+static route_map_result_t
+route_match_lcommunity (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,
+                                    LARGE_COMMUNITY_LIST_MASTER);
+      if (! list)
+        return RMAP_NOMATCH;
+
+      if (bgp_info->attr->extra &&
+          lcommunity_list_match (bgp_info->attr->extra->lcommunity, list))
+        return RMAP_MATCH;
+
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Compile function for community match. */
+static void *
+route_match_lcommunity_compile (const 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);
+    }
+  else
+    {
+      rcom->name = XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+      rcom->exact = 0;
+    }
+  return rcom;
+}
+
+/* Compile function for community match. */
+static void
+route_match_lcommunity_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_lcommunity_cmd =
+{
+  "large-community",
+  route_match_lcommunity,
+  route_match_lcommunity_compile,
+  route_match_lcommunity_free
+};
+
+
 /* Match function for extcommunity match. */
 static route_map_result_t
-route_match_ecommunity (void *rule, struct prefix *prefix, 
+route_match_ecommunity (void *rule, struct prefix *prefix,
                        route_map_object_t type, void *object)
 {
   struct community_list *list;
   struct bgp_info *bgp_info;
 
-  if (type == RMAP_BGP) 
+  if (type == RMAP_BGP)
     {
       bgp_info = object;
-      
+
       if (!bgp_info->attr->extra)
         return RMAP_NOMATCH;
-      
+
       list = community_list_lookup (bgp_clist, (char *) rule,
                                    EXTCOMMUNITY_LIST_MASTER);
       if (! list)
@@ -888,7 +963,7 @@ route_match_ecommunity_free (void *rule)
 }
 
 /* Route map commands for community matching. */
-struct route_map_rule_cmd route_match_ecommunity_cmd = 
+struct route_map_rule_cmd route_match_ecommunity_cmd =
 {
   "extcommunity",
   route_match_ecommunity,
@@ -901,7 +976,7 @@ struct route_map_rule_cmd route_match_ecommunity_cmd =
 
 /* `match origin' */
 static route_map_result_t
-route_match_origin (void *rule, struct prefix *prefix, 
+route_match_origin (void *rule, struct prefix *prefix,
                    route_map_object_t type, void *object)
 {
   u_char *origin;
@@ -911,7 +986,7 @@ route_match_origin (void *rule, struct prefix *prefix,
     {
       origin = rule;
       bgp_info = object;
-    
+
       if (bgp_info->attr->origin == *origin)
        return RMAP_MATCH;
     }
@@ -1067,7 +1142,7 @@ static route_map_result_t
 route_match_tag (void *rule, struct prefix *prefix,
                  route_map_object_t type, void *object)
 {
-  u_short *tag;
+  route_tag_t *tag;
   struct bgp_info *bgp_info;
 
   if (type == RMAP_BGP)
@@ -1085,46 +1160,13 @@ route_match_tag (void *rule, struct prefix *prefix,
 }
 
 
-/*  Route map `match tag' match statement. `arg' is TAG value */
-static void *
-route_match_tag_compile (const char *arg)
-{
-  u_short *tag;
-  u_short tmp;
-
-  /* tag value shoud be integer. */
-  if (! all_digit (arg))
-    return NULL;
-
-  tmp = atoi(arg);
-  if (tmp < 1)
-    return NULL;
-
-  tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
-
-  if (!tag)
-    return tag;
-
-  *tag = tmp;
-
-  return tag;
-}
-
-
-/* Free route map's compiled 'match tag' value. */
-static void
-route_match_tag_free (void *rule)
-{
-  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
-}
-
 /* Route map commands for tag matching. */
-struct route_map_rule_cmd route_match_tag_cmd =
+static struct route_map_rule_cmd route_match_tag_cmd =
 {
   "tag",
   route_match_tag,
-  route_match_tag_compile,
-  route_match_tag_free,
+  route_map_rule_tag_compile,
+  route_map_rule_tag_free,
 };
 
 
@@ -1158,7 +1200,7 @@ route_set_ip_nexthop (void *rule, struct prefix *prefix,
        {
          if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
            CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
-             && peer->su_remote 
+             && peer->su_remote
              && sockunion_family (peer->su_remote) == AF_INET)
            {
              bgp_info->attr->nexthop.s_addr = sockunion2ip (peer->su_remote);
@@ -1232,7 +1274,7 @@ route_set_ip_nexthop_free (void *rule)
 
   if (rins->address)
     XFREE (MTYPE_ROUTE_MAP_COMPILED, rins->address);
-    
+
   XFREE (MTYPE_ROUTE_MAP_COMPILED, rins);
 }
 
@@ -1261,8 +1303,8 @@ route_set_local_pref (void *rule, struct prefix *prefix,
       /* Fetch routemap's rule information. */
       rv = rule;
       bgp_info = object;
-    
-      /* Set local preference value. */ 
+
+      /* Set local preference value. */
       if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
        locpref = bgp_info->attr->local_pref;
 
@@ -1274,7 +1316,7 @@ route_set_local_pref (void *rule, struct prefix *prefix,
 }
 
 /* Set local preference rule structure. */
-struct route_map_rule_cmd route_set_local_pref_cmd = 
+struct route_map_rule_cmd route_set_local_pref_cmd =
 {
   "local-preference",
   route_set_local_pref,
@@ -1298,8 +1340,8 @@ route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
       /* Fetch routemap's rule information. */
       rv = rule;
       bgp_info = object;
-    
-      /* Set weight value. */ 
+
+      /* Set weight value. */
       weight = route_value_adjust(rv, 0, bgp_info->peer);
       if (weight)
         (bgp_attr_extra_get (bgp_info->attr))->weight = weight;
@@ -1311,7 +1353,7 @@ route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
 }
 
 /* Set local preference rule structure. */
-struct route_map_rule_cmd route_set_weight_cmd = 
+struct route_map_rule_cmd route_set_weight_cmd =
 {
   "weight",
   route_set_weight,
@@ -1323,7 +1365,7 @@ struct route_map_rule_cmd route_set_weight_cmd =
 
 /* Set metric to attribute. */
 static route_map_result_t
-route_set_metric (void *rule, struct prefix *prefix, 
+route_set_metric (void *rule, struct prefix *prefix,
                  route_map_object_t type, void *object)
 {
   struct rmap_value *rv;
@@ -1346,7 +1388,7 @@ route_set_metric (void *rule, struct prefix *prefix,
 }
 
 /* Set metric rule structure. */
-struct route_map_rule_cmd route_set_metric_cmd = 
+struct route_map_rule_cmd route_set_metric_cmd =
 {
   "metric",
   route_set_metric,
@@ -1367,7 +1409,7 @@ route_set_aspath_prepend (void *rule, struct prefix *prefix, route_map_object_t
   if (type == RMAP_BGP)
     {
       binfo = object;
-    
+
       if (binfo->attr->aspath->refcnt)
        new = aspath_dup (binfo->attr->aspath);
       else
@@ -1411,7 +1453,7 @@ route_set_aspath_prepend_free (void *rule)
 
 
 /* Set as-path prepend rule structure. */
-struct route_map_rule_cmd route_set_aspath_prepend_cmd = 
+struct route_map_rule_cmd route_set_aspath_prepend_cmd =
 {
   "as-path prepend",
   route_set_aspath_prepend,
@@ -1445,7 +1487,7 @@ route_set_aspath_exclude (void *rule, struct prefix *dummy, route_map_object_t t
 }
 
 /* Set ASn exlude rule structure. */
-struct route_map_rule_cmd route_set_aspath_exclude_cmd = 
+struct route_map_rule_cmd route_set_aspath_exclude_cmd =
 {
   "as-path exclude",
   route_set_aspath_exclude,
@@ -1472,7 +1514,7 @@ route_set_community (void *rule, struct prefix *prefix,
   struct community *new = NULL;
   struct community *old;
   struct community *merge;
-  
+
   if (type == RMAP_BGP)
     {
       rcs = rule;
@@ -1495,8 +1537,8 @@ route_set_community (void *rule, struct prefix *prefix,
       if (rcs->additive && old)
        {
          merge = community_merge (community_dup (old), rcs->com);
-         
-         /* HACK: if the old community is not intern'd, 
+
+         /* HACK: if the old community is not intern'd,
            * we should free it here, or all reference to it may be lost.
            * Really need to cleanup attribute caching sometime.
            */
@@ -1507,7 +1549,7 @@ route_set_community (void *rule, struct prefix *prefix,
        }
       else
        new = community_dup (rcs->com);
-      
+
       /* will be interned by caller if required */
       attr->community = new;
 
@@ -1526,7 +1568,7 @@ route_set_community_compile (const char *arg)
   char *sp;
   int additive = 0;
   int none = 0;
-  
+
   if (strcmp (arg, "none") == 0)
     none = 1;
   else
@@ -1548,12 +1590,12 @@ route_set_community_compile (const char *arg)
       if (! com)
        return NULL;
     }
-  
+
   rcs = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set));
   rcs->com = com;
   rcs->additive = additive;
   rcs->none = none;
-  
+
   return rcs;
 }
 
@@ -1569,7 +1611,7 @@ route_set_community_free (void *rule)
 }
 
 /* Set community rule structure. */
-struct route_map_rule_cmd route_set_community_cmd = 
+struct route_map_rule_cmd route_set_community_cmd =
 {
   "community",
   route_set_community,
@@ -1577,6 +1619,224 @@ struct route_map_rule_cmd route_set_community_cmd =
   route_set_community_free,
 };
 
+/* `set community COMMUNITY' */
+struct rmap_lcom_set
+{
+  struct lcommunity *lcom;
+  int additive;
+  int none;
+};
+
+
+/* For lcommunity set mechanism. */
+static route_map_result_t
+route_set_lcommunity (void *rule, struct prefix *prefix,
+                     route_map_object_t type, void *object)
+{
+  struct rmap_lcom_set *rcs;
+  struct bgp_info *binfo;
+  struct attr *attr;
+  struct lcommunity *new = NULL;
+  struct lcommunity *old;
+  struct lcommunity *merge;
+
+  if (type == RMAP_BGP)
+    {
+      rcs = rule;
+      binfo = object;
+      attr = binfo->attr;
+      old = (attr->extra) ? attr->extra->lcommunity : NULL;
+
+      /* "none" case.  */
+      if (rcs->none)
+        {
+          attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES));
+          if (attr->extra)
+            attr->extra->lcommunity = NULL;
+
+          /* See the longer comment down below. */
+          if (old && old->refcnt == 0)
+            lcommunity_free(&old);
+          return RMAP_OKAY;
+        }
+
+      if (rcs->additive && old)
+        {
+          merge = lcommunity_merge (lcommunity_dup (old), rcs->lcom);
+
+          /* HACK: if the old large-community is not intern'd,
+           * we should free it here, or all reference to it may be lost.
+           * Really need to cleanup attribute caching sometime.
+           */
+          if (old->refcnt == 0)
+            lcommunity_free (&old);
+          new = lcommunity_uniq_sort (merge);
+          lcommunity_free (&merge);
+        }
+      else
+        new = lcommunity_dup (rcs->lcom);
+
+      /* will be intern()'d or attr_flush()'d by bgp_update_main() */
+      (bgp_attr_extra_get (attr))->lcommunity = new;
+
+      attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for set community. */
+static void *
+route_set_lcommunity_compile (const char *arg)
+{
+  struct rmap_lcom_set *rcs;
+  struct lcommunity *lcom = 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';
+        }
+
+      lcom = lcommunity_str2com (arg);
+
+      if (additive)
+        *(sp - 1) = ' ';
+
+      if (! lcom)
+        return NULL;
+    }
+
+  rcs = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set));
+  rcs->lcom = lcom;
+  rcs->additive = additive;
+  rcs->none = none;
+
+  return rcs;
+}
+
+/* Free function for set lcommunity. */
+static void
+route_set_lcommunity_free (void *rule)
+{
+  struct rmap_lcom_set *rcs = rule;
+
+  if (rcs->lcom) {
+    lcommunity_free (&rcs->lcom);
+  }
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs);
+}
+
+/* Set community rule structure. */
+struct route_map_rule_cmd route_set_lcommunity_cmd =
+{
+  "large-community",
+  route_set_lcommunity,
+  route_set_lcommunity_compile,
+  route_set_lcommunity_free,
+};
+
+/* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
+
+/* For large community set mechanism. */
+static route_map_result_t
+route_set_lcommunity_delete (void *rule, struct prefix *prefix,
+                             route_map_object_t type, void *object)
+{
+  struct community_list *list;
+  struct lcommunity *merge;
+  struct lcommunity *new;
+  struct lcommunity *old;
+  struct bgp_info *binfo;
+
+  if (type == RMAP_BGP)
+    {
+      if (! rule)
+        return RMAP_OKAY;
+
+      binfo = object;
+      list = community_list_lookup (bgp_clist, rule,
+                                    LARGE_COMMUNITY_LIST_MASTER);
+      old = ((binfo->attr->extra) ? binfo->attr->extra->lcommunity : NULL);
+
+      if (list && old)
+        {
+          merge = lcommunity_list_match_delete (lcommunity_dup (old), list);
+          new = lcommunity_uniq_sort (merge);
+          lcommunity_free (&merge);
+
+          /* HACK: if the old community is not intern'd,
+           * we should free it here, or all reference to it may be lost.
+           * Really need to cleanup attribute caching sometime.
+           */
+          if (old->refcnt == 0)
+            lcommunity_free (&old);
+
+          if (new->size == 0)
+            {
+              binfo->attr->extra->lcommunity = NULL;
+              binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
+              lcommunity_free (&new);
+            }
+          else
+            {
+              binfo->attr->extra->lcommunity = new;
+              binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
+            }
+        }
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for set lcommunity. */
+static void *
+route_set_lcommunity_delete_compile (const 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 lcommunity. */
+static void
+route_set_lcommunity_delete_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set lcommunity rule structure. */
+struct route_map_rule_cmd route_set_lcommunity_delete_cmd =
+{
+  "large-comm-list",
+  route_set_lcommunity_delete,
+  route_set_lcommunity_delete_compile,
+  route_set_lcommunity_delete_free,
+};
+
+
 /* `set comm-list (<1-99>|<100-500>|WORD) delete' */
 
 /* For community set mechanism. */
@@ -1682,10 +1942,10 @@ route_set_ecommunity (void *rule, struct prefix *prefix,
     {
       ecom = rule;
       bgp_info = object;
-    
+
       if (! ecom)
        return RMAP_OKAY;
-    
+
       /* We assume additive for Extended Community. */
       old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;
 
@@ -1730,7 +1990,7 @@ route_set_ecommunity_free (void *rule)
 }
 
 /* Set community rule structure. */
-struct route_map_rule_cmd route_set_ecommunity_rt_cmd = 
+struct route_map_rule_cmd route_set_ecommunity_rt_cmd =
 {
   "extcommunity rt",
   route_set_ecommunity,
@@ -1749,12 +2009,12 @@ route_set_ecommunity_soo_compile (const char *arg)
   ecom = ecommunity_str2com (arg, ECOMMUNITY_SITE_ORIGIN, 0);
   if (! ecom)
     return NULL;
-  
+
   return ecommunity_intern (ecom);
 }
 
 /* Set community rule structure. */
-struct route_map_rule_cmd route_set_ecommunity_soo_cmd = 
+struct route_map_rule_cmd route_set_ecommunity_soo_cmd =
 {
   "extcommunity soo",
   route_set_ecommunity,
@@ -1775,7 +2035,7 @@ route_set_origin (void *rule, struct prefix *prefix, route_map_object_t type, vo
     {
       origin = rule;
       bgp_info = object;
-    
+
       bgp_info->attr->origin = *origin;
     }
 
@@ -1808,7 +2068,7 @@ route_set_origin_free (void *rule)
 }
 
 /* Set origin rule structure. */
-struct route_map_rule_cmd route_set_origin_cmd = 
+struct route_map_rule_cmd route_set_origin_cmd =
 {
   "origin",
   route_set_origin,
@@ -1849,7 +2109,7 @@ route_set_atomic_aggregate_free (void *rule)
 }
 
 /* Set atomic aggregate rule structure. */
-struct route_map_rule_cmd route_set_atomic_aggregate_cmd = 
+struct route_map_rule_cmd route_set_atomic_aggregate_cmd =
 {
   "atomic-aggregate",
   route_set_atomic_aggregate,
@@ -1865,7 +2125,7 @@ struct aggregator
 };
 
 static route_map_result_t
-route_set_aggregator_as (void *rule, struct prefix *prefix, 
+route_set_aggregator_as (void *rule, struct prefix *prefix,
                         route_map_object_t type, void *object)
 {
   struct bgp_info *bgp_info;
@@ -1877,7 +2137,7 @@ route_set_aggregator_as (void *rule, struct prefix *prefix,
       bgp_info = object;
       aggregator = rule;
       ae = bgp_attr_extra_get (bgp_info->attr);
-      
+
       ae->aggregator_as = aggregator->as;
       ae->aggregator_addr = aggregator->address;
       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
@@ -1908,7 +2168,7 @@ route_set_aggregator_as_free (void *rule)
   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 }
 
-struct route_map_rule_cmd route_set_aggregator_as_cmd = 
+struct route_map_rule_cmd route_set_aggregator_as_cmd =
 {
   "aggregator as",
   route_set_aggregator_as,
@@ -1921,7 +2181,7 @@ static route_map_result_t
 route_set_tag (void *rule, struct prefix *prefix,
                route_map_object_t type, void *object)
 {
-  u_short *tag;
+  route_tag_t *tag;
   struct bgp_info *bgp_info;
   struct attr_extra *ae;
 
@@ -1939,65 +2199,30 @@ route_set_tag (void *rule, struct prefix *prefix,
   return RMAP_OKAY;
 }
 
-/* Route map `tag' compile function.  Given string is converted to u_short. */
-static void *
-route_set_tag_compile (const char *arg)
+/* Route map commands for tag set. */
+static struct route_map_rule_cmd route_set_tag_cmd =
 {
-  u_short *tag;
-  u_short tmp;
-
-  /* tag value shoud be integer. */
-  if (! all_digit (arg))
-    return NULL;
+  "tag",
+  route_set_tag,
+  route_map_rule_tag_compile,
+  route_map_rule_tag_free,
+};
 
-  tmp = atoi(arg);
 
-  if (tmp < 1)
-      return NULL;
+/* `match ipv6 address IP_ACCESS_LIST' */
 
-  tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
+static 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 (!tag)
-    return tag;
+  if (type == RMAP_BGP)
+    {
+      alist = access_list_lookup (AFI_IP6, (char *) rule);
+      if (alist == NULL)
+       return RMAP_NOMATCH;
 
-  *tag = tmp;
-
-  return tag;
-}
-
-/* Free route map's tag value. */
-static void
-route_set_tag_free (void *rule)
-{
-  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
-}
-
-
-/* Route map commands for tag set. */
-struct route_map_rule_cmd route_set_tag_cmd =
-{
-  "tag",
-  route_set_tag,
-  route_set_tag_compile,
-  route_set_tag_free,
-};
-
-
-#ifdef HAVE_IPV6
-/* `match ipv6 address IP_ACCESS_LIST' */
-
-static 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);
     }
@@ -2028,7 +2253,7 @@ struct route_map_rule_cmd route_match_ipv6_address_cmd =
 /* `match ipv6 next-hop IP_ADDRESS' */
 
 static route_map_result_t
-route_match_ipv6_next_hop (void *rule, struct prefix *prefix, 
+route_match_ipv6_next_hop (void *rule, struct prefix *prefix,
                           route_map_object_t type, void *object)
 {
   struct in6_addr *addr = rule;
@@ -2037,10 +2262,10 @@ route_match_ipv6_next_hop (void *rule, struct prefix *prefix,
   if (type == RMAP_BGP)
     {
       bgp_info = object;
-      
+
       if (!bgp_info->attr->extra)
         return RMAP_NOMATCH;
-      
+
       if (IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_global, addr))
        return RMAP_MATCH;
 
@@ -2089,7 +2314,7 @@ struct route_map_rule_cmd route_match_ipv6_next_hop_cmd =
 /* `match ipv6 address prefix-list PREFIX_LIST' */
 
 static route_map_result_t
-route_match_ipv6_address_prefix_list (void *rule, struct prefix *prefix, 
+route_match_ipv6_address_prefix_list (void *rule, struct prefix *prefix,
                              route_map_object_t type, void *object)
 {
   struct prefix_list *plist;
@@ -2099,7 +2324,7 @@ route_match_ipv6_address_prefix_list (void *rule, struct prefix *prefix,
       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);
     }
@@ -2130,7 +2355,7 @@ struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd =
 
 /* Set nexthop to object.  ojbect must be pointer to struct attr. */
 static route_map_result_t
-route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix, 
+route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix,
                               route_map_object_t type, void *object)
 {
   struct in6_addr *address;
@@ -2141,8 +2366,8 @@ route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix,
       /* Fetch routemap's rule information. */
       address = rule;
       bgp_info = object;
-    
-      /* Set next hop value. */ 
+
+      /* Set next hop value. */
       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = *address;
 
       /* Set nexthop length. */
@@ -2258,7 +2483,7 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd =
 
 /* Set nexthop to object.  ojbect must be pointer to struct attr. */
 static route_map_result_t
-route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix, 
+route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix,
                              route_map_object_t type, void *object)
 {
   struct in6_addr *address;
@@ -2269,10 +2494,10 @@ route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix,
       /* Fetch routemap's rule information. */
       address = rule;
       bgp_info = object;
-    
-      /* Set next hop value. */ 
+
+      /* Set next hop value. */
       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = *address;
-    
+
       /* Set nexthop length. */
       if (bgp_info->attr->extra->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
        bgp_info->attr->extra->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
@@ -2331,7 +2556,6 @@ route_set_ipv6_nexthop_peer (void *rule, struct prefix *prefix,
   struct in6_addr peer_address;
   struct bgp_info *bgp_info;
   struct peer *peer;
-  char peer_addr_buf[INET6_ADDRSTRLEN];
 
   if (type == RMAP_BGP)
     {
@@ -2344,10 +2568,7 @@ route_set_ipv6_nexthop_peer (void *rule, struct prefix *prefix,
          && peer->su_remote
          && sockunion_family (peer->su_remote) == AF_INET6)
        {
-         inet_pton (AF_INET6, sockunion2str (peer->su_remote,
-                                             peer_addr_buf,
-                                             INET6_ADDRSTRLEN),
-                    &peer_address);
+         peer_address = peer->su_remote->sin6.sin6_addr;
           /* Set next hop value and length in attribute. */
           if (IN6_IS_ADDR_LINKLOCAL(&peer_address))
             {
@@ -2412,12 +2633,10 @@ struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd =
   route_set_ipv6_nexthop_peer_free
 };
 
-#endif /* HAVE_IPV6 */
-
-/* `set vpnv4 nexthop A.B.C.D' */
+/* `set ip vpn nexthop A.B.C.D' */
 
 static route_map_result_t
-route_set_vpnv4_nexthop (void *rule, struct prefix *prefix, 
+route_set_vpnv4_nexthop (void *rule, struct prefix *prefix,
                         route_map_object_t type, void *object)
 {
   struct in_addr *address;
@@ -2428,8 +2647,8 @@ route_set_vpnv4_nexthop (void *rule, struct prefix *prefix,
       /* Fetch routemap's rule information. */
       address = rule;
       bgp_info = object;
-    
-      /* Set next hop value. */ 
+
+      /* Set next hop value. */
       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global_in = *address;
       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = 4;
     }
@@ -2456,8 +2675,49 @@ route_set_vpnv4_nexthop_compile (const char *arg)
   return address;
 }
 
+/* `set ipv6 vpn nexthop A.B.C.D' */
+
+static route_map_result_t
+route_set_vpnv6_nexthop (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. */
+      memcpy (&(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global, address, sizeof(struct in6_addr));
+      (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
+    }
+
+  return RMAP_OKAY;
+}
+
+static void *
+route_set_vpnv6_nexthop_compile (const 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;
+}
+
 static void
-route_set_vpnv4_nexthop_free (void *rule)
+route_set_vpn_nexthop_free (void *rule)
 {
   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 }
@@ -2465,10 +2725,19 @@ route_set_vpnv4_nexthop_free (void *rule)
 /* Route map commands for ip nexthop set. */
 struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd =
 {
-  "vpnv4 next-hop",
+  "ip vpn next-hop",
   route_set_vpnv4_nexthop,
   route_set_vpnv4_nexthop_compile,
-  route_set_vpnv4_nexthop_free
+  route_set_vpn_nexthop_free
+};
+
+/* Route map commands for ip nexthop set. */
+struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd =
+{
+  "ipv6 vpn next-hop",
+  route_set_vpnv6_nexthop,
+  route_set_vpnv6_nexthop_compile,
+  route_set_vpn_nexthop_free
 };
 
 /* `set originator-id' */
@@ -2480,11 +2749,11 @@ route_set_originator_id (void *rule, struct prefix *prefix, route_map_object_t t
   struct in_addr *address;
   struct bgp_info *bgp_info;
 
-  if (type == RMAP_BGP) 
+  if (type == RMAP_BGP)
     {
       address = rule;
       bgp_info = object;
-    
+
       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
       (bgp_attr_extra_get (bgp_info->attr))->originator_id = *address;
     }
@@ -2520,7 +2789,7 @@ route_set_originator_id_free (void *rule)
 }
 
 /* Set originator-id rule structure. */
-struct route_map_rule_cmd route_set_originator_id_cmd = 
+struct route_map_rule_cmd route_set_originator_id_cmd =
 {
   "originator-id",
   route_set_originator_id,
@@ -2530,10 +2799,11 @@ struct route_map_rule_cmd route_set_originator_id_cmd =
 
 /* Add bgp route map rule. */
 static int
-bgp_route_match_add (struct vty *vty, struct route_map_index *index,
+bgp_route_match_add (struct vty *vty,
                     const char *command, const char *arg,
                     route_map_event_t type)
 {
+  VTY_DECLVAR_CONTEXT(route_map_index, index);
   int ret;
 
   ret = route_map_add_match (index, command, arg);
@@ -2560,10 +2830,11 @@ bgp_route_match_add (struct vty *vty, struct route_map_index *index,
 
 /* Delete bgp route map rule. */
 static int
-bgp_route_match_delete (struct vty *vty, struct route_map_index *index,
+bgp_route_match_delete (struct vty *vty,
                        const char *command, const char *arg,
                        route_map_event_t type)
 {
+  VTY_DECLVAR_CONTEXT(route_map_index, index);
   int ret;
   char *dep_name = NULL;
   const char *tmpstr;
@@ -2614,52 +2885,6 @@ bgp_route_match_delete (struct vty *vty, struct route_map_index *index,
   return CMD_SUCCESS;
 }
 
-/* Add bgp route map rule. */
-static int
-bgp_route_set_add (struct vty *vty, struct route_map_index *index,
-                  const char *command, const char *arg)
-{
-  int ret;
-
-  ret = route_map_add_set (index, command, arg);
-  if (ret)
-    {
-      switch (ret)
-       {
-       case RMAP_RULE_MISSING:
-         vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
-         return CMD_WARNING;
-       case RMAP_COMPILE_ERROR:
-         vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
-         return CMD_WARNING;
-       }
-    }
-  return CMD_SUCCESS;
-}
-
-/* Delete bgp route map rule. */
-static int
-bgp_route_set_delete (struct vty *vty, struct route_map_index *index,
-                     const char *command, const char *arg)
-{
-  int ret;
-
-  ret = route_map_delete_set (index, command, arg);
-  if (ret)
-    {
-      switch (ret)
-       {
-       case RMAP_RULE_MISSING:
-         vty_out (vty, "%% BGP Can't find rule.%s", VTY_NEWLINE);
-         return CMD_WARNING;
-       case RMAP_COMPILE_ERROR:
-         vty_out (vty, "%% BGP Argument is malformed.%s", VTY_NEWLINE);
-         return CMD_WARNING;
-       }
-    }
-  return CMD_SUCCESS;
-}
-
 /*
  * This is the workhorse routine for processing in/out routemap
  * modifications.
@@ -2924,6 +3149,10 @@ bgp_route_map_process_update_cb (char *rmap_name)
   for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
     bgp_route_map_process_update(bgp, rmap_name, 1);
 
+#if ENABLE_BGP_VNC
+  zlog_debug("%s: calling vnc_routemap_update", __func__);
+  vnc_routemap_update(bgp, __func__);
+#endif
   return 0;
 }
 
@@ -2960,6 +3189,10 @@ bgp_route_map_mark_update (const char *rmap_name)
         {
           for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
             bgp_route_map_process_update(bgp, rmap_name, 0);
+ #if ENABLE_BGP_VNC
+          zlog_debug("%s: calling vnc_routemap_update", __func__);
+          vnc_routemap_update(bgp, __func__);
+#endif
         }
     }
 }
@@ -3001,7 +3234,7 @@ DEFUN (match_peer,
        "IPv6 address of peer\n")
 {
   int idx_ip = 2;
-  return bgp_route_match_add (vty, vty->index, "peer", argv[idx_ip]->arg,
+  return bgp_route_match_add (vty, "peer", argv[idx_ip]->arg,
                              RMAP_EVENT_MATCH_ADDED);
 }
 
@@ -3012,7 +3245,7 @@ DEFUN (match_peer_local,
         "Match peer address\n"
         "Static or Redistributed routes\n")
 {
-  return bgp_route_match_add (vty, vty->index, "peer", "local",
+  return bgp_route_match_add (vty, "peer", "local",
                              RMAP_EVENT_MATCH_DELETED);
 }
 
@@ -3029,86 +3262,13 @@ DEFUN (no_match_peer,
  int idx_peer = 3;
 
  if (argc <= idx_peer)
-   return bgp_route_match_delete (vty, vty->index, "peer", NULL,
+   return bgp_route_match_delete (vty, "peer", NULL,
                                   RMAP_EVENT_MATCH_DELETED);
- return bgp_route_match_delete (vty, vty->index, "peer", argv[idx_peer]->arg,
+ return bgp_route_match_delete (vty, "peer", argv[idx_peer]->arg,
                                RMAP_EVENT_MATCH_DELETED);
 }
 
 
-
-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")
-{
-  int idx_acl = 3;
-  return bgp_route_match_add (vty, vty->index, "ip address", argv[idx_acl]->arg,
-                             RMAP_EVENT_FILTER_ADDED);
-}
-
-
-DEFUN (no_match_ip_address,
-       no_match_ip_address_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")
-{
-  int idx_word = 4;
-  if (argc <= idx_word)
-    return bgp_route_match_delete (vty, vty->index, "ip address", NULL,
-                                   RMAP_EVENT_FILTER_DELETED);
-  return bgp_route_match_delete (vty, vty->index, "ip address", argv[idx_word]->arg,
-                                RMAP_EVENT_FILTER_DELETED);
-}
-
-
-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")
-{
-  int idx_acl = 3;
-  return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[idx_acl]->arg,
-                             RMAP_EVENT_FILTER_ADDED);
-}
-
-
-DEFUN (no_match_ip_next_hop,
-       no_match_ip_next_hop_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")
-{
-  int idx_word = 4;
-  if (argc <= idx_word)
-    return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL,
-                                   RMAP_EVENT_FILTER_DELETED);
-  return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[idx_word]->arg,
-                                RMAP_EVENT_FILTER_DELETED);
-}
-
-
 /* match probability */
 DEFUN (match_probability,
        match_probability_cmd,
@@ -3118,7 +3278,7 @@ DEFUN (match_probability,
        "Percentage of routes\n")
 {
   int idx_number = 2;
-  return bgp_route_match_add (vty, vty->index, "probability", argv[idx_number]->arg,
+  return bgp_route_match_add (vty, "probability", argv[idx_number]->arg,
                              RMAP_EVENT_MATCH_ADDED);
 }
 
@@ -3133,9 +3293,9 @@ DEFUN (no_match_probability,
 {
   int idx_number = 3;
   if (argc <= idx_number)
-    return bgp_route_match_delete (vty, vty->index, "probability", NULL,
+    return bgp_route_match_delete (vty, "probability", NULL,
                                    RMAP_EVENT_MATCH_DELETED);
-  return bgp_route_match_delete (vty, vty->index, "probability", argv[idx_number]->arg,
+  return bgp_route_match_delete (vty, "probability", argv[idx_number]->arg,
                                 RMAP_EVENT_MATCH_DELETED);
 }
 
@@ -3151,7 +3311,7 @@ DEFUN (match_ip_route_source,
        "IP standard access-list name\n")
 {
   int idx_acl = 3;
-  return bgp_route_match_add (vty, vty->index, "ip route-source", argv[idx_acl]->arg,
+  return bgp_route_match_add (vty, "ip route-source", argv[idx_acl]->arg,
                              RMAP_EVENT_FILTER_ADDED);
 }
 
@@ -3169,80 +3329,13 @@ DEFUN (no_match_ip_route_source,
 {
   int idx_number = 4;
   if (argc <= idx_number)
-    return bgp_route_match_delete (vty, vty->index, "ip route-source",
+    return bgp_route_match_delete (vty, "ip route-source",
                                    NULL, RMAP_EVENT_FILTER_DELETED);
-  return bgp_route_match_delete (vty, vty->index, "ip route-source",
+  return bgp_route_match_delete (vty, "ip route-source",
                                 argv[idx_number]->arg, RMAP_EVENT_FILTER_DELETED);
 }
 
 
-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")
-{
-  int idx_word = 4;
-  return bgp_route_match_add (vty, vty->index, "ip address prefix-list",
-                             argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
-}
-
-
-DEFUN (no_match_ip_address_prefix_list,
-       no_match_ip_address_prefix_list_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")
-{
-  int idx_word = 5;
-  if (argc <= idx_word)
-    return bgp_route_match_delete (vty, vty->index, "ip address prefix-list",
-                                   NULL, RMAP_EVENT_PLIST_DELETED);
-  return bgp_route_match_delete (vty, vty->index, "ip address prefix-list",
-                                argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED);
-}
-
-
-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")
-{
-  int idx_word = 4;
-  return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list",
-                             argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
-}
-
-DEFUN (no_match_ip_next_hop_prefix_list,
-       no_match_ip_next_hop_prefix_list_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")
-{
-  int idx_word = 5;
-  if (argc <= idx_word)
-    return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
-                                   NULL, RMAP_EVENT_PLIST_DELETED);
-  return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list",
-                                argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED);
-}
-
-
 DEFUN (match_ip_route_source_prefix_list,
        match_ip_route_source_prefix_list_cmd,
        "match ip route-source prefix-list WORD",
@@ -3253,7 +3346,7 @@ DEFUN (match_ip_route_source_prefix_list,
        "IP prefix-list name\n")
 {
   int idx_word = 4;
-  return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list",
+  return bgp_route_match_add (vty, "ip route-source prefix-list",
                              argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
 }
 
@@ -3270,44 +3363,13 @@ DEFUN (no_match_ip_route_source_prefix_list,
 {
   int idx_word = 5;
   if (argc <= idx_word)
-    return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list",
+    return bgp_route_match_delete (vty, "ip route-source prefix-list",
                                    NULL, RMAP_EVENT_PLIST_DELETED);
-  return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list",
+  return bgp_route_match_delete (vty, "ip route-source prefix-list",
                                 argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED);
 }
 
 
-DEFUN (match_metric,
-       match_metric_cmd,
-       "match metric (0-4294967295)",
-       MATCH_STR
-       "Match metric of route\n"
-       "Metric value\n")
-{
-  int idx_number = 2;
-  return bgp_route_match_add (vty, vty->index, "metric", argv[idx_number]->arg,
-                             RMAP_EVENT_MATCH_ADDED);
-}
-
-
-DEFUN (no_match_metric,
-       no_match_metric_cmd,
-       "no match metric [(0-4294967295)]",
-       NO_STR
-       MATCH_STR
-       "Match metric of route\n"
-       "Metric value\n")
-{
-  int idx_number = 3;
-  if (argc <= idx_number)
-    return bgp_route_match_delete (vty, vty->index, "metric",
-                                   NULL, RMAP_EVENT_MATCH_DELETED);
-  return bgp_route_match_delete (vty, vty->index, "metric",
-                                argv[idx_number]->arg,
-                                RMAP_EVENT_MATCH_DELETED);
-}
-
-
 DEFUN (match_local_pref,
        match_local_pref_cmd,
        "match local-preference (0-4294967295)",
@@ -3316,7 +3378,7 @@ DEFUN (match_local_pref,
        "Metric value\n")
 {
   int idx_number = 2;
-  return bgp_route_match_add (vty, vty->index, "local-preference", argv[idx_number]->arg,
+  return bgp_route_match_add (vty, "local-preference", argv[idx_number]->arg,
                              RMAP_EVENT_MATCH_ADDED);
 }
 
@@ -3331,9 +3393,9 @@ DEFUN (no_match_local_pref,
 {
   int idx_localpref = 3;
   if (argc <= idx_localpref)
-    return bgp_route_match_delete (vty, vty->index, "local-preference",
+    return bgp_route_match_delete (vty, "local-preference",
                                    NULL, RMAP_EVENT_MATCH_DELETED);
-  return bgp_route_match_delete (vty, vty->index, "local-preference",
+  return bgp_route_match_delete (vty, "local-preference",
                                 argv[idx_localpref]->arg,
                                 RMAP_EVENT_MATCH_DELETED);
 }
@@ -3341,21 +3403,7 @@ DEFUN (no_match_local_pref,
 
 DEFUN (match_community,
        match_community_cmd,
-       "match community <(1-99)|(100-500)|WORD>",
-       MATCH_STR
-       "Match BGP community list\n"
-       "Community-list number (standard)\n"
-       "Community-list number (expanded)\n"
-       "Community-list name\n")
-{
-  int idx_comm_list = 2;
-  return bgp_route_match_add (vty, vty->index, "community", argv[idx_comm_list]->arg,
-                             RMAP_EVENT_CLIST_ADDED);
-}
-
-DEFUN (match_community_exact,
-       match_community_exact_cmd,
-       "match community <(1-99)|(100-500)|WORD> exact-match",
+       "match community <(1-99)|(100-500)|WORD> [exact-match]",
        MATCH_STR
        "Match BGP community list\n"
        "Community-list number (standard)\n"
@@ -3367,15 +3415,22 @@ DEFUN (match_community_exact,
   int ret;
   char *argstr;
 
-  argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
-                   strlen (argv[idx_comm_list]->arg) + strlen ("exact-match") + 2);
+  if (argc == 4)
+    {
+      argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
+                        strlen (argv[idx_comm_list]->arg) +
+                        strlen ("exact-match") + 2);
 
-  sprintf (argstr, "%s exact-match", argv[idx_comm_list]->arg);
+      sprintf (argstr, "%s exact-match", argv[idx_comm_list]->arg);
+    }
+  else
+    argstr = argv[idx_comm_list]->arg;
 
-  ret = bgp_route_match_add (vty, vty->index, "community", argstr,
+  ret = bgp_route_match_add (vty, "community", argstr,
                             RMAP_EVENT_CLIST_ADDED);
 
-  XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
+  if (argstr != argv[idx_comm_list]->arg)
+    XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
 
   return ret;
 }
@@ -3391,11 +3446,36 @@ DEFUN (no_match_community,
        "Community-list name\n"
        "Do exact matching of communities\n")
 {
-  return bgp_route_match_delete (vty, vty->index, "community", NULL,
+  return bgp_route_match_delete (vty, "community", NULL,
                                 RMAP_EVENT_CLIST_DELETED);
 }
 
+DEFUN (match_lcommunity,
+       match_lcommunity_cmd,
+       "match large-community <(1-99)|(100-500)|WORD>",
+       MATCH_STR
+       "Match BGP large community list\n"
+       "Large Community-list number (standard)\n"
+       "Large Community-list number (expanded)\n"
+       "Large Community-list name\n")
+{
+  return bgp_route_match_add (vty, "large-community", argv[2]->arg,
+                              RMAP_EVENT_LLIST_ADDED);
+}
 
+DEFUN (no_match_lcommunity,
+       no_match_lcommunity_cmd,
+       "no match large-community [<(1-99)|(100-500)|WORD>]",
+       NO_STR
+       MATCH_STR
+       "Match BGP large community list\n"
+       "Large Community-list number (standard)\n"
+       "Large Community-list number (expanded)\n"
+       "Large Community-list name\n")
+{
+  return bgp_route_match_delete (vty, "large-community", NULL,
+                                 RMAP_EVENT_LLIST_DELETED);
+}
 
 DEFUN (match_ecommunity,
        match_ecommunity_cmd,
@@ -3407,7 +3487,7 @@ DEFUN (match_ecommunity,
        "Extended community-list name\n")
 {
   int idx_comm_list = 2;
-  return bgp_route_match_add (vty, vty->index, "extcommunity", argv[idx_comm_list]->arg,
+  return bgp_route_match_add (vty, "extcommunity", argv[idx_comm_list]->arg,
                              RMAP_EVENT_ECLIST_ADDED);
 }
 
@@ -3422,7 +3502,7 @@ DEFUN (no_match_ecommunity,
        "Extended community-list number (expanded)\n"
        "Extended community-list name\n")
 {
-  return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL,
+  return bgp_route_match_delete (vty, "extcommunity", NULL,
                                 RMAP_EVENT_ECLIST_DELETED);
 }
 
@@ -3435,7 +3515,7 @@ DEFUN (match_aspath,
        "AS path access-list name\n")
 {
   int idx_word = 2;
-  return bgp_route_match_add (vty, vty->index, "as-path", argv[idx_word]->arg,
+  return bgp_route_match_add (vty, "as-path", argv[idx_word]->arg,
                              RMAP_EVENT_ASLIST_ADDED);
 }
 
@@ -3448,7 +3528,7 @@ DEFUN (no_match_aspath,
        "Match BGP AS path list\n"
        "AS path access-list name\n")
 {
-  return bgp_route_match_delete (vty, vty->index, "as-path", NULL,
+  return bgp_route_match_delete (vty, "as-path", NULL,
                                 RMAP_EVENT_ASLIST_DELETED);
 }
 
@@ -3464,13 +3544,13 @@ DEFUN (match_origin,
 {
   int idx_origin = 2;
   if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0)
-    return bgp_route_match_add (vty, vty->index, "origin", "igp",
+    return bgp_route_match_add (vty, "origin", "igp",
                                RMAP_EVENT_MATCH_ADDED);
   if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0)
-    return bgp_route_match_add (vty, vty->index, "origin", "egp",
+    return bgp_route_match_add (vty, "origin", "egp",
                                RMAP_EVENT_MATCH_ADDED);
   if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0)
-    return bgp_route_match_add (vty, vty->index, "origin", "incomplete",
+    return bgp_route_match_add (vty, "origin", "incomplete",
                                RMAP_EVENT_MATCH_ADDED);
 
   return CMD_WARNING;
@@ -3487,92 +3567,10 @@ DEFUN (no_match_origin,
        "local IGP\n"
        "unknown heritage\n")
 {
-  return bgp_route_match_delete (vty, vty->index, "origin", NULL,
+  return bgp_route_match_delete (vty, "origin", NULL,
                                 RMAP_EVENT_MATCH_DELETED);
 }
 
-
-DEFUN (match_interface,
-       match_interface_cmd,
-       "match interface WORD",
-       MATCH_STR
-       "Match first hop interface of route\n"
-       "Interface name\n")
-{
-  int idx_word = 2;
-  return bgp_route_match_add (vty, vty->index, "interface", argv[idx_word]->arg,
-                             RMAP_EVENT_MATCH_ADDED);
-}
-
-
-DEFUN (no_match_interface,
-       no_match_interface_cmd,
-       "no match interface [WORD]",
-       NO_STR
-       MATCH_STR
-       "Match first hop interface of route\n"
-       "Interface name\n")
-{
-  return bgp_route_match_delete (vty, vty->index, "interface", argv[3]->arg,
-                                RMAP_EVENT_MATCH_DELETED);
-}
-
-
-DEFUN (match_tag,
-       match_tag_cmd,
-       "match tag (1-65535)",
-       MATCH_STR
-       "Match tag of route\n"
-       "Tag value\n")
-{
-  int idx_number = 2;
-  return bgp_route_match_add (vty, vty->index, "tag", argv[idx_number]->arg,
-                             RMAP_EVENT_MATCH_ADDED);
-}
-
-
-DEFUN (no_match_tag,
-       no_match_tag_cmd,
-       "no match tag [(1-65535)]",
-       NO_STR
-       MATCH_STR
-       "Match tag of route\n"
-       "Tag value\n")
-{
-  return bgp_route_match_delete (vty, vty->index, "tag", argv[3]->arg,
-                                RMAP_EVENT_MATCH_DELETED);
-}
-
-
-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")
-{
-  int idx_ipv4 = 3;
-  union sockunion su;
-  int ret;
-
-  ret = str2sockunion (argv[idx_ipv4]->arg, &su);
-  if (ret < 0)
-    {
-      vty_out (vty, "%% Malformed nexthop address%s", VTY_NEWLINE);
-      return CMD_WARNING;
-    }
-  if (su.sin.sin_addr.s_addr == 0 ||
-      IPV4_CLASS_DE(su.sin.sin_addr.s_addr))
-    {
-      vty_out (vty, "%% nexthop address cannot be 0.0.0.0, multicast "
-               "or reserved%s", VTY_NEWLINE);
-      return CMD_WARNING;
-    }
-  return bgp_route_set_add (vty, vty->index, "ip next-hop", argv[idx_ipv4]->arg);
-}
-
 DEFUN (set_ip_nexthop_peer,
        set_ip_nexthop_peer_cmd,
        "set ip next-hop peer-address",
@@ -3581,7 +3579,8 @@ DEFUN (set_ip_nexthop_peer,
        "Next hop address\n"
        "Use peer address (for BGP only)\n")
 {
-  return bgp_route_set_add (vty, vty->index, "ip next-hop", "peer-address");
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                          "ip next-hop", "peer-address");
 }
 
 DEFUN (set_ip_nexthop_unchanged,
@@ -3592,55 +3591,8 @@ DEFUN (set_ip_nexthop_unchanged,
        "Next hop address\n"
        "Don't modify existing Next hop address\n")
 {
-  return bgp_route_set_add (vty, vty->index, "ip next-hop", "unchanged");
-}
-
-
-DEFUN (no_set_ip_nexthop,
-       no_set_ip_nexthop_cmd,
-       "no set ip next-hop [<peer-address|A.B.C.D>]",
-       NO_STR
-       SET_STR
-       "Next hop address\n"
-       "Use peer address (for BGP only)\n"
-       "IP address of next hop\n")
-{
-  int idx_peer = 4;
-  if (argc <= idx_peer)
-    return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
-  return bgp_route_set_delete (vty, vty->index, "ip next-hop", argv[idx_peer]->arg);
-}
-
-
-DEFUN (set_metric,
-       set_metric_cmd,
-       "set metric <(0-4294967295)|rtt|+rtt|-rtt|+metric|-metric>",
-       SET_STR
-       "Metric value for destination routing protocol\n"
-       "Metric value\n"
-       "Assign round trip time\n"
-       "Add round trip time\n"
-       "Subtract round trip time\n"
-       "Add metric\n"
-       "Subtract metric\n")
-{
-  int idx_number = 2;
-  return bgp_route_set_add (vty, vty->index, "metric", argv[idx_number]->arg);
-}
-
-
-DEFUN (no_set_metric,
-       no_set_metric_cmd,
-       "no set metric [(0-4294967295)]",
-       NO_STR
-       SET_STR
-       "Metric value for destination routing protocol\n"
-       "Metric value\n")
-{
-  int idx_number = 3;
-  if (argc <= idx_number)
-    return bgp_route_set_delete (vty, vty->index, "metric", NULL);
-  return bgp_route_set_delete (vty, vty->index, "metric", argv[idx_number]->arg);
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                          "ip next-hop", "unchanged");
 }
 
 
@@ -3652,7 +3604,8 @@ DEFUN (set_local_pref,
        "Preference value\n")
 {
   int idx_number = 2;
-  return bgp_route_set_add (vty, vty->index, "local-preference", argv[idx_number]->arg);
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                          "local-preference", argv[idx_number]->arg);
 }
 
 
@@ -3666,8 +3619,10 @@ DEFUN (no_set_local_pref,
 {
   int idx_localpref = 3;
   if (argc <= idx_localpref)
-    return bgp_route_set_delete (vty, vty->index, "local-preference", NULL);
-  return bgp_route_set_delete (vty, vty->index, "local-preference", argv[idx_localpref]->arg);
+    return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                               "local-preference", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "local-preference", argv[idx_localpref]->arg);
 }
 
 
@@ -3679,7 +3634,8 @@ DEFUN (set_weight,
        "Weight value\n")
 {
   int idx_number = 2;
-  return bgp_route_set_add (vty, vty->index, "weight", argv[idx_number]->arg);
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "weight",
+                          argv[idx_number]->arg);
 }
 
 
@@ -3693,32 +3649,44 @@ DEFUN (no_set_weight,
 {
   int idx_weight = 3;
   if (argc <= idx_weight)
-    return bgp_route_set_delete (vty, vty->index, "weight", NULL);
-  return bgp_route_set_delete (vty, vty->index, "weight", argv[idx_weight]->arg);
+    return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                               "weight", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "weight",
+                             argv[idx_weight]->arg);
 }
 
 
-DEFUN (set_aspath_prepend,
-       set_aspath_prepend_cmd,
-       "set as-path prepend <(1-4294967295)...|last-as (1-10)>",
+DEFUN (set_aspath_prepend_asn,
+       set_aspath_prepend_asn_cmd,
+       "set as-path prepend (1-4294967295)...",
        SET_STR
        "Transform BGP AS_PATH attribute\n"
        "Prepend to the as-path\n"
-       "AS number\n"
-       "Use the peer's AS-number\n"
-       "Number of times to insert")
+       "AS number\n")
 {
   int idx_asn = 3;
   int ret;
   char *str;
 
   str = argv_concat (argv, argc, idx_asn);
-  ret = bgp_route_set_add (vty, vty->index, "as-path prepend", str);
+  ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                         "as-path prepend", str);
   XFREE (MTYPE_TMP, str);
 
   return ret;
 }
 
+DEFUN (set_aspath_prepend_lastas,
+       set_aspath_prepend_lastas_cmd,
+       "set as-path prepend last-as (1-9)",
+       SET_STR
+       "Transform BGP AS_PATH attribute\n"
+       "Prepend to the as-path\n"
+       "Use the peer's AS-number\n"
+       "Number of times to insert")
+{
+  return set_aspath_prepend_asn (self, vty, argc, argv);
+}
 
 DEFUN (no_set_aspath_prepend,
        no_set_aspath_prepend_cmd,
@@ -3734,7 +3702,8 @@ DEFUN (no_set_aspath_prepend,
   char *str;
 
   str = argv_concat (argv, argc, idx_asn);
-  ret = bgp_route_set_delete (vty, vty->index, "as-path prepend", str);
+  ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                            "as-path prepend", str);
   XFREE (MTYPE_TMP, str);
   return ret;
 }
@@ -3753,7 +3722,8 @@ DEFUN (set_aspath_exclude,
   char *str;
 
   str = argv_concat (argv, argc, idx_asn);
-  ret = bgp_route_set_add (vty, vty->index, "as-path exclude", str);
+  ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                         "as-path exclude", str);
   XFREE (MTYPE_TMP, str);
   return ret;
 }
@@ -3772,7 +3742,8 @@ DEFUN (no_set_aspath_exclude,
   char *str;
 
   str = argv_concat (argv, argc, idx_asn);
-  ret = bgp_route_set_delete (vty, vty->index, "as-path exclude", str);
+  ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                            "as-path exclude", str);
   XFREE (MTYPE_TMP, str);
   return ret;
 }
@@ -3861,11 +3832,13 @@ DEFUN (set_community,
       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);
+      ret =  generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                              "community", argstr);
       XFREE (MTYPE_TMP, argstr);
     }
   else
-    ret =  bgp_route_set_add (vty, vty->index, "community", str);
+    ret =  generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                            "community", str);
 
   community_free (com);
 
@@ -3879,7 +3852,8 @@ DEFUN (set_community_none,
        "BGP community attribute\n"
        "No community attribute\n")
 {
-  return bgp_route_set_add (vty, vty->index, "community", "none");
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "community",
+                          "none");
 }
 
 DEFUN (no_set_community,
@@ -3887,9 +3861,11 @@ DEFUN (no_set_community,
        "no set community AA:NN...",
        NO_STR
        SET_STR
-       "BGP community attribute\n")
+       "BGP community attribute\n"
+       COMMUNITY_VAL_STR)
 {
-  return bgp_route_set_delete (vty, vty->index, "community", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "community", NULL);
 }
 
 
@@ -3911,7 +3887,7 @@ DEFUN (set_community_delete,
   strcpy (str, argv[idx_comm_list]->arg);
   strcpy (str + strlen (argv[idx_comm_list]->arg), " delete");
 
-  bgp_route_set_add (vty, vty->index, "comm-list", str);
+  generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "comm-list", str);
 
   XFREE (MTYPE_TMP, str);
   return CMD_SUCCESS;
@@ -3922,11 +3898,105 @@ DEFUN (no_set_community_delete,
        "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
        NO_STR
        SET_STR
-       "set BGP community list (for deletion)\n")
+       "set BGP community list (for deletion)\n"
+       "Community-list number (standard)\n"
+       "Community-list number (expanded)\n"
+       "Community-list name\n"
+       "Delete matching communities\n")
 {
-  return bgp_route_set_delete (vty, vty->index, "comm-list", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "comm-list", NULL);
 }
 
+DEFUN (set_lcommunity,
+       set_lcommunity_cmd,
+       "set large-community AA:BB:CC...",
+       SET_STR
+       "BGP large community attribute\n"
+       "Large Community number in aa:bb:cc format or additive\n")
+{
+  int ret;
+  char *str;
+
+  str = argv_concat (argv, argc, 2);
+  ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "large-community", str);
+  XFREE (MTYPE_TMP, str);
+
+  return ret;
+}
+
+DEFUN (set_lcommunity_none,
+       set_lcommunity_none_cmd,
+       "set large-community none",
+       SET_STR
+       "BGP large community attribute\n"
+       "No large community attribute\n")
+{
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                          "large-community", "none");
+}
+
+DEFUN (no_set_lcommunity,
+       no_set_lcommunity_cmd,
+       "no set large-community none",
+       NO_STR
+       SET_STR
+       "BGP large community attribute\n"
+       "No community attribute\n")
+{
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "large-community", NULL);
+}
+
+DEFUN (no_set_lcommunity1,
+       no_set_lcommunity1_cmd,
+       "no set large-community AA:BB:CC...",
+       NO_STR
+       SET_STR
+       "BGP large community attribute\n"
+       "Large community in AA:BB:CC... format or additive\n")
+{
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "large-community", NULL);
+}
+
+DEFUN (set_lcommunity_delete,
+       set_lcommunity_delete_cmd,
+       "set large-comm-list <(1-99)|(100-500)|WORD> delete",
+       SET_STR
+       "set BGP large community list (for deletion)\n"
+       "Large Community-list number (standard)\n"
+       "Large Communitly-list number (expanded)\n"
+       "Large Community-list name\n"
+       "Delete matching large communities\n")
+{
+  char *str;
+
+  str = XCALLOC (MTYPE_TMP, strlen (argv[2]->arg) + strlen (" delete") + 1);
+  strcpy (str, argv[2]->arg);
+  strcpy (str + strlen (argv[2]->arg), " delete");
+
+  generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                   "large-comm-list", str);
+
+  XFREE (MTYPE_TMP, str);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_set_lcommunity_delete,
+       no_set_lcommunity_delete_cmd,
+       "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
+       NO_STR
+       SET_STR
+       "set BGP large community list (for deletion)\n"
+       "Large Community-list number (standard)\n"
+       "Large Communitly-list number (expanded)\n"
+       "Large Community-list name\n"
+       "Delete matching large communities\n")
+{
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "large-comm-list", NULL);
+}
 
 DEFUN (set_ecommunity_rt,
        set_ecommunity_rt_cmd,
@@ -3941,7 +4011,8 @@ DEFUN (set_ecommunity_rt,
   char *str;
 
   str = argv_concat (argv, argc, idx_asn_nn);
-  ret = bgp_route_set_add (vty, vty->index, "extcommunity rt", str);
+  ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                         "extcommunity rt", str);
   XFREE (MTYPE_TMP, str);
 
   return ret;
@@ -3953,9 +4024,11 @@ DEFUN (no_set_ecommunity_rt,
        NO_STR
        SET_STR
        "BGP extended community attribute\n"
-       "Route Target extended community\n")
+       "Route Target extended community\n"
+       "VPN extended community\n")
 {
-  return bgp_route_set_delete (vty, vty->index, "extcommunity rt", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "extcommunity rt", NULL);
 }
 
 
@@ -3972,7 +4045,8 @@ DEFUN (set_ecommunity_soo,
   char *str;
 
   str = argv_concat (argv, argc, idx_asn_nn);
-  ret = bgp_route_set_add (vty, vty->index, "extcommunity soo", str);
+  ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                         "extcommunity soo", str);
   XFREE (MTYPE_TMP, str);
   return ret;
 }
@@ -3984,9 +4058,11 @@ DEFUN (no_set_ecommunity_soo,
        NO_STR
        SET_STR
        "BGP extended community attribute\n"
-       "Site-of-Origin extended community\n")
+       "Site-of-Origin extended community\n"
+       "VPN extended community\n")
 {
-  return bgp_route_set_delete (vty, vty->index, "extcommunity soo", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "extcommunity soo", NULL);
 }
 
 
@@ -4001,11 +4077,14 @@ DEFUN (set_origin,
 {
   int idx_origin = 2;
   if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0)
-    return bgp_route_set_add (vty, vty->index, "origin", "igp");
+    return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
+                            "igp");
   if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0)
-    return bgp_route_set_add (vty, vty->index, "origin", "egp");
+    return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
+                            "egp");
   if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0)
-    return bgp_route_set_add (vty, vty->index, "origin", "incomplete");
+    return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
+                            "incomplete");
 
   return CMD_WARNING;
 }
@@ -4016,9 +4095,13 @@ DEFUN (no_set_origin,
        "no set origin [<egp|igp|incomplete>]",
        NO_STR
        SET_STR
-       "BGP origin code\n")
+       "BGP origin code\n"
+       "remote EGP\n"
+       "local IGP\n"
+       "unknown heritage\n")
 {
-  return bgp_route_set_delete (vty, vty->index, "origin", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "origin",
+                             NULL);
 }
 
 
@@ -4028,7 +4111,8 @@ DEFUN (set_atomic_aggregate,
        SET_STR
        "BGP atomic aggregate attribute\n" )
 {
-  return bgp_route_set_add (vty, vty->index, "atomic-aggregate", NULL);
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                          "atomic-aggregate", NULL);
 }
 
 DEFUN (no_set_atomic_aggregate,
@@ -4038,7 +4122,8 @@ DEFUN (no_set_atomic_aggregate,
        SET_STR
        "BGP atomic aggregate attribute\n" )
 {
-  return bgp_route_set_delete (vty, vty->index, "atomic-aggregate", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "atomic-aggregate", NULL);
 }
 
 DEFUN (set_aggregator_as,
@@ -4055,7 +4140,7 @@ DEFUN (set_aggregator_as,
   int ret;
   struct in_addr address;
   char *argstr;
-  
+
   ret = inet_aton (argv[idx_ipv4]->arg, &address);
   if (ret == 0)
     {
@@ -4068,7 +4153,8 @@ DEFUN (set_aggregator_as,
 
   sprintf (argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
 
-  ret = bgp_route_set_add (vty, vty->index, "aggregator as", argstr);
+  ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                         "aggregator as", argstr);
 
   XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
 
@@ -4093,8 +4179,9 @@ DEFUN (no_set_aggregator_as,
   char *argstr;
 
   if (argc <= idx_asn)
-    return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
-  
+    return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                               "aggregator as", NULL);
+
   ret = inet_aton (argv[idx_ip]->arg, &address);
   if (ret == 0)
     {
@@ -4107,70 +4194,14 @@ DEFUN (no_set_aggregator_as,
 
   sprintf (argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
 
-  ret = bgp_route_set_delete (vty, vty->index, "aggregator as", argstr);
+  ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                            "aggregator as", argstr);
 
   XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
 
   return ret;
 }
 
-
-DEFUN (set_tag,
-       set_tag_cmd,
-       "set tag (1-65535)",
-       SET_STR
-       "Tag value for routing protocol\n"
-       "Tag value\n")
-{
-  int idx_number = 2;
-  return bgp_route_set_add (vty, vty->index, "tag", argv[idx_number]->arg);
-}
-
-
-DEFUN (no_set_tag,
-       no_set_tag_cmd,
-       "no set tag [(1-65535)]",
-       NO_STR
-       SET_STR
-       "Tag value for routing protocol\n"
-       "Tag value\n")
-{
-  int idx_number = 3;
-  if (argc <= idx_number)
-    return bgp_route_set_delete (vty, vty->index, "tag", NULL);
-  return bgp_route_set_delete (vty, vty->index, "tag", argv[idx_number]->arg);
-}
-
-
-
-#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")
-{
-  int idx_word = 3;
-  return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[idx_word]->arg,
-                             RMAP_EVENT_FILTER_ADDED);
-}
-
-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")
-{
-  int idx_word = 4;
-  return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[idx_word]->arg,
-                                RMAP_EVENT_FILTER_DELETED);
-}
-
 DEFUN (match_ipv6_next_hop,
        match_ipv6_next_hop_cmd,
        "match ipv6 next-hop X:X::X:X",
@@ -4180,7 +4211,7 @@ DEFUN (match_ipv6_next_hop,
        "IPv6 address of next hop\n")
 {
   int idx_ipv6 = 3;
-  return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[idx_ipv6]->arg,
+  return bgp_route_match_add (vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
                              RMAP_EVENT_MATCH_ADDED);
 }
 
@@ -4194,38 +4225,10 @@ DEFUN (no_match_ipv6_next_hop,
        "IPv6 address of next hop\n")
 {
   int idx_ipv6 = 4;
-  return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[idx_ipv6]->arg,
+  return bgp_route_match_delete (vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
                                 RMAP_EVENT_MATCH_DELETED);
 }
 
-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")
-{
-  int idx_word = 4;
-  return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list",
-                             argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
-}
-
-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")
-{
-  int idx_word = 5;
-  return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list",
-                                argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED);
-}
 
 DEFUN (set_ipv6_nexthop_peer,
        set_ipv6_nexthop_peer_cmd,
@@ -4235,7 +4238,8 @@ DEFUN (set_ipv6_nexthop_peer,
        "Next hop address\n"
        "Use peer address (for BGP only)\n")
 {
-  return bgp_route_set_add (vty, vty->index, "ipv6 next-hop peer-address", NULL);
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                          "ipv6 next-hop peer-address", NULL);
 }
 
 DEFUN (no_set_ipv6_nexthop_peer,
@@ -4247,7 +4251,8 @@ DEFUN (no_set_ipv6_nexthop_peer,
        "IPv6 next-hop address\n"
        "Use peer address (for BGP only)\n")
 {
-  return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop peer-address", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "ipv6 next-hop peer-address", NULL);
 }
 
 DEFUN (set_ipv6_nexthop_prefer_global,
@@ -4258,7 +4263,8 @@ DEFUN (set_ipv6_nexthop_prefer_global,
        "IPv6 next-hop address\n"
        "Prefer global over link-local if both exist\n")
 {
-  return bgp_route_set_add (vty, vty->index, "ipv6 next-hop prefer-global", NULL);;
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                          "ipv6 next-hop prefer-global", NULL);;
 }
 
 DEFUN (no_set_ipv6_nexthop_prefer_global,
@@ -4270,7 +4276,8 @@ DEFUN (no_set_ipv6_nexthop_prefer_global,
        "IPv6 next-hop address\n"
        "Prefer global over link-local if both exist\n")
 {
-  return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop prefer-global", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "ipv6 next-hop prefer-global", NULL);
 }
 
 DEFUN (set_ipv6_nexthop_global,
@@ -4301,7 +4308,8 @@ DEFUN (set_ipv6_nexthop_global,
       return CMD_WARNING;
     }
 
-  return bgp_route_set_add (vty, vty->index, "ipv6 next-hop global", argv[idx_ipv6]->arg);
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                          "ipv6 next-hop global", argv[idx_ipv6]->arg);
 }
 
 
@@ -4317,86 +4325,130 @@ DEFUN (no_set_ipv6_nexthop_global,
 {
   int idx_ipv6 = 5;
   if (argc <= idx_ipv6)
-    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[idx_ipv6]->arg);
+    return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                               "ipv6 next-hop global", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "ipv6 next-hop global", argv[idx_ipv6]->arg);
 }
 
-
-DEFUN (set_ipv6_nexthop_local,
-       set_ipv6_nexthop_local_cmd,
-       "set ipv6 next-hop local X:X::X:X",
+#ifdef KEEP_OLD_VPN_COMMANDS
+DEFUN (set_vpn_nexthop,
+       set_vpn_nexthop_cmd,
+       "set <vpnv4|vpnv6> next-hop [A.B.C.D|X:X::X:X]",
        SET_STR
-       IPV6_STR
-       "IPv6 next-hop address\n"
-       "IPv6 local address\n"
+       "VPNv4 information\n"
+       "VPNv6 information\n"
+       "VPN next-hop address\n"
+       "IP address of next hop\n"
        "IPv6 address of next hop\n")
 {
-  int idx_ipv6 = 4;
-  struct in6_addr addr;
-  int ret;
+  int idx_ip = 3;
+  afi_t afi;
+  int idx = 0;
 
-  ret = inet_pton (AF_INET6, argv[idx_ipv6]->arg, &addr);
-  if (!ret)
-    {
-      vty_out (vty, "%% Malformed nexthop address%s", VTY_NEWLINE);
-      return CMD_WARNING;
-    }
-  if (!IN6_IS_ADDR_LINKLOCAL(&addr))
+  if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
     {
-      vty_out (vty, "%% Invalid link-local nexthop address%s", VTY_NEWLINE);
-      return CMD_WARNING;
+      if (afi == AFI_IP)
+        return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                              "ip vpn next-hop", argv[idx_ip]->arg);
+      else
+        return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                              "ipv6 vpn next-hop", argv[idx_ip]->arg);
     }
-
-  return bgp_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[idx_ipv6]->arg);
+  return CMD_SUCCESS;
 }
 
-
-DEFUN (no_set_ipv6_nexthop_local,
-       no_set_ipv6_nexthop_local_cmd,
-       "no set ipv6 next-hop local [X:X::X:X]",
+DEFUN (no_set_vpn_nexthop,
+       no_set_vpn_nexthop_cmd,
+       "no set vpn next-hop [A.B.C.D|X:X::X:X]",
        NO_STR
        SET_STR
-       IPV6_STR
-       "IPv6 next-hop address\n"
-       "IPv6 local address\n"
+       "VPN information\n"
+       "VPN next-hop address\n"
+       "IP address of next hop\n"
        "IPv6 address of next hop\n")
 {
-  int idx_ipv6 = 5;
-  if (argc <= idx_ipv6)
-    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[5]->arg);
-}
+  int idx_ip = 4;
+  char *arg;
+  afi_t afi;
+  int idx = 0;
 
-#endif /* HAVE_IPV6 */
+  if (argc <= idx_ip)
+    arg = NULL;
+  else
+    arg = argv[idx_ip]->arg;
+  if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
+    {
+      if (afi == AFI_IP)
+        return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                                   "ip vpn next-hop", arg);
+      else
+        return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                                   "ipv6 vpn next-hop", argv[idx_ip]->arg);
+    }
+  return CMD_SUCCESS;
+}
+#endif /* KEEP_OLD_VPN_COMMANDS */
 
-DEFUN (set_vpnv4_nexthop,
-       set_vpnv4_nexthop_cmd,
-       "set vpnv4 next-hop A.B.C.D",
+DEFUN (set_ipx_vpn_nexthop,
+       set_ipx_vpn_nexthop_cmd,
+       "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
        SET_STR
-       "VPNv4 information\n"
-       "VPNv4 next-hop address\n"
-       "IP address of next hop\n")
+       "IPv4 information\n"
+       "IPv6 information\n"
+       "VPN information\n"
+       "VPN next-hop address\n"
+       "IP address of next hop\n"
+       "IPv6 address of next hop\n")
 {
-  int idx_ipv4 = 3;
-  return bgp_route_set_add (vty, vty->index, "vpnv4 next-hop", argv[idx_ipv4]->arg);
-}
+  int idx_ip = 4;
+  afi_t afi;
+  int idx = 0;
 
+  if (argv_find_and_parse_afi (argv, argc, &idx, &afi))
+    {
+      if (afi == AFI_IP)
+        return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                              "ip vpn next-hop", argv[idx_ip]->arg);
+      else
+        return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                              "ipv6 vpn next-hop", argv[idx_ip]->arg);
+    }
+  return CMD_SUCCESS;
+}
 
-DEFUN (no_set_vpnv4_nexthop,
-       no_set_vpnv4_nexthop_cmd,
-       "no set vpnv4 next-hop [A.B.C.D]",
+DEFUN (no_set_ipx_vpn_nexthop,
+       no_set_ipx_vpn_nexthop_cmd,
+       "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
        NO_STR
        SET_STR
-       "VPNv4 information\n"
-       "VPNv4 next-hop address\n"
-       "IP address of next hop\n")
+       "IPv4 information\n"
+       "IPv6 information\n"
+       "VPN information\n"
+       "VPN next-hop address\n"
+       "IP address of next hop\n"
+       "IPv6 address of next hop\n")
 {
-  int idx_ipv4 = 4;
-  if (argc <= idx_ipv4)
-    return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", NULL);
-  return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", argv[idx_ipv4]->arg);
-}
+  int idx_ip = 5;
+  char *arg;
+  afi_t afi;
+  int idx = 0;
 
+  if (argc <= idx_ip)
+    arg = NULL;
+  else
+    arg = argv[idx_ip]->arg;
+  if (argv_find_and_parse_afi (argv, argc, &idx, &afi))
+    {
+      if (afi == AFI_IP)
+        return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                                   "ip vpn next-hop", arg);
+      else
+        return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                                   "ipv6 vpn next-hop", argv[idx_ip]->arg);
+    }
+  return CMD_SUCCESS;
+}
 
 DEFUN (set_originator_id,
        set_originator_id_cmd,
@@ -4406,7 +4458,8 @@ DEFUN (set_originator_id,
        "IP address of originator\n")
 {
   int idx_ipv4 = 2;
-  return bgp_route_set_add (vty, vty->index, "originator-id", argv[idx_ipv4]->arg);
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                          "originator-id", argv[idx_ipv4]->arg);
 }
 
 
@@ -4418,10 +4471,11 @@ DEFUN (no_set_originator_id,
        "BGP originator ID attribute\n"
        "IP address of originator\n")
 {
-  int idx_id = 3;
-  if (argc < idx_id)
-    return bgp_route_set_delete (vty, vty->index, "originator-id", NULL);
-  return bgp_route_set_delete (vty, vty->index, "originator-id", argv[idx_id]->arg);
+  int idx = 0;
+  char *arg = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
+
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "originator-id", arg);
 }
 
 
@@ -4430,11 +4484,50 @@ void
 bgp_route_map_init (void)
 {
   route_map_init ();
-  route_map_init_vty ();
+
   route_map_add_hook (bgp_route_map_add);
   route_map_delete_hook (bgp_route_map_delete);
   route_map_event_hook (bgp_route_map_event);
 
+  route_map_match_interface_hook (generic_match_add);
+  route_map_no_match_interface_hook (generic_match_delete);
+
+  route_map_match_ip_address_hook (generic_match_add);
+  route_map_no_match_ip_address_hook (generic_match_delete);
+
+  route_map_match_ip_address_prefix_list_hook (generic_match_add);
+  route_map_no_match_ip_address_prefix_list_hook (generic_match_delete);
+
+  route_map_match_ip_next_hop_hook (generic_match_add);
+  route_map_no_match_ip_next_hop_hook (generic_match_delete);
+
+  route_map_match_ip_next_hop_prefix_list_hook (generic_match_add);
+  route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete);
+
+  route_map_match_ipv6_address_hook (generic_match_add);
+  route_map_no_match_ipv6_address_hook (generic_match_delete);
+
+  route_map_match_ipv6_address_prefix_list_hook (generic_match_add);
+  route_map_no_match_ipv6_address_prefix_list_hook (generic_match_delete);
+
+  route_map_match_metric_hook (generic_match_add);
+  route_map_no_match_metric_hook (generic_match_delete);
+
+  route_map_match_tag_hook (generic_match_add);
+  route_map_no_match_tag_hook (generic_match_delete);
+
+  route_map_set_ip_nexthop_hook (generic_set_add);
+  route_map_no_set_ip_nexthop_hook (generic_set_delete);
+
+  route_map_set_ipv6_nexthop_local_hook (generic_set_add);
+  route_map_no_set_ipv6_nexthop_local_hook (generic_set_delete);
+
+  route_map_set_metric_hook (generic_set_add);
+  route_map_no_set_metric_hook (generic_set_delete);
+
+  route_map_set_tag_hook (generic_set_add);
+  route_map_no_set_tag_hook (generic_set_delete);
+
   route_map_install_match (&route_match_peer_cmd);
   route_map_install_match (&route_match_local_pref_cmd);
   route_map_install_match (&route_match_ip_address_cmd);
@@ -4445,6 +4538,7 @@ bgp_route_map_init (void)
   route_map_install_match (&route_match_ip_route_source_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_lcommunity_cmd);
   route_map_install_match (&route_match_ecommunity_cmd);
   route_map_install_match (&route_match_local_pref_cmd);
   route_map_install_match (&route_match_metric_cmd);
@@ -4464,7 +4558,10 @@ bgp_route_map_init (void)
   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_lcommunity_cmd);
+  route_map_install_set (&route_set_lcommunity_delete_cmd);
   route_map_install_set (&route_set_vpnv4_nexthop_cmd);
+  route_map_install_set (&route_set_vpnv6_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);
@@ -4473,50 +4570,34 @@ bgp_route_map_init (void)
   install_element (RMAP_NODE, &match_peer_cmd);
   install_element (RMAP_NODE, &match_peer_local_cmd);
   install_element (RMAP_NODE, &no_match_peer_cmd);
-  install_element (RMAP_NODE, &match_ip_address_cmd);
-  install_element (RMAP_NODE, &no_match_ip_address_cmd);
-  install_element (RMAP_NODE, &match_ip_next_hop_cmd);
-  install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
   install_element (RMAP_NODE, &match_ip_route_source_cmd);
   install_element (RMAP_NODE, &no_match_ip_route_source_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, &match_ip_next_hop_prefix_list_cmd);
-  install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
   install_element (RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
   install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
 
   install_element (RMAP_NODE, &match_aspath_cmd);
   install_element (RMAP_NODE, &no_match_aspath_cmd);
-  install_element (RMAP_NODE, &match_metric_cmd);
-  install_element (RMAP_NODE, &no_match_metric_cmd);
   install_element (RMAP_NODE, &match_local_pref_cmd);
   install_element (RMAP_NODE, &no_match_local_pref_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, &match_lcommunity_cmd);
+  install_element (RMAP_NODE, &no_match_lcommunity_cmd);
   install_element (RMAP_NODE, &match_ecommunity_cmd);
   install_element (RMAP_NODE, &no_match_ecommunity_cmd);
   install_element (RMAP_NODE, &match_origin_cmd);
   install_element (RMAP_NODE, &no_match_origin_cmd);
   install_element (RMAP_NODE, &match_probability_cmd);
   install_element (RMAP_NODE, &no_match_probability_cmd);
-  install_element (RMAP_NODE, &match_interface_cmd);
-  install_element (RMAP_NODE, &no_match_interface_cmd);
-  install_element (RMAP_NODE, &match_tag_cmd);
-  install_element (RMAP_NODE, &no_match_tag_cmd);
 
-  install_element (RMAP_NODE, &set_ip_nexthop_cmd);
   install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
   install_element (RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
-  install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
   install_element (RMAP_NODE, &set_local_pref_cmd);
   install_element (RMAP_NODE, &no_set_local_pref_cmd);
   install_element (RMAP_NODE, &set_weight_cmd);
   install_element (RMAP_NODE, &no_set_weight_cmd);
-  install_element (RMAP_NODE, &set_metric_cmd);
-  install_element (RMAP_NODE, &no_set_metric_cmd);
-  install_element (RMAP_NODE, &set_aspath_prepend_cmd);
+  install_element (RMAP_NODE, &set_aspath_prepend_asn_cmd);
+  install_element (RMAP_NODE, &set_aspath_prepend_lastas_cmd);
   install_element (RMAP_NODE, &set_aspath_exclude_cmd);
   install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
   install_element (RMAP_NODE, &no_set_aspath_exclude_cmd);
@@ -4531,18 +4612,25 @@ bgp_route_map_init (void)
   install_element (RMAP_NODE, &no_set_community_cmd);
   install_element (RMAP_NODE, &set_community_delete_cmd);
   install_element (RMAP_NODE, &no_set_community_delete_cmd);
+  install_element (RMAP_NODE, &set_lcommunity_cmd);
+  install_element (RMAP_NODE, &set_lcommunity_none_cmd);
+  install_element (RMAP_NODE, &no_set_lcommunity_cmd);
+  install_element (RMAP_NODE, &no_set_lcommunity1_cmd);
+  install_element (RMAP_NODE, &set_lcommunity_delete_cmd);
+  install_element (RMAP_NODE, &no_set_lcommunity_delete_cmd);
   install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
   install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
   install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
   install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
-  install_element (RMAP_NODE, &set_vpnv4_nexthop_cmd);
-  install_element (RMAP_NODE, &no_set_vpnv4_nexthop_cmd);
+#ifdef KEEP_OLD_VPN_COMMANDS
+  install_element (RMAP_NODE, &set_vpn_nexthop_cmd);
+  install_element (RMAP_NODE, &no_set_vpn_nexthop_cmd);
+#endif /* KEEP_OLD_VPN_COMMANDS */
+  install_element (RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
+  install_element (RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
   install_element (RMAP_NODE, &set_originator_id_cmd);
   install_element (RMAP_NODE, &no_set_originator_id_cmd);
-  install_element (RMAP_NODE, &set_tag_cmd);
-  install_element (RMAP_NODE, &no_set_tag_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);
@@ -4551,21 +4639,14 @@ bgp_route_map_init (void)
   route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
   route_map_install_set (&route_set_ipv6_nexthop_peer_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, &set_ipv6_nexthop_prefer_global_cmd);
   install_element (RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
-  install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
-  install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
   install_element (RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
   install_element (RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
-#endif /* HAVE_IPV6 */
 }
 
 void