]> 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 aaf01ff772742fc12f3d513baf0cb43eaca1758f..c7bcfe25f92b22701298a4b63a1d40a7c14ccf27 100644 (file)
@@ -52,6 +52,7 @@ 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"
 
@@ -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)
@@ -847,6 +850,78 @@ 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,
@@ -1544,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. */
@@ -1916,7 +2209,6 @@ static struct route_map_rule_cmd route_set_tag_cmd =
 };
 
 
-#ifdef HAVE_IPV6
 /* `match ipv6 address IP_ACCESS_LIST' */
 
 static route_map_result_t
@@ -2341,9 +2633,7 @@ 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,
@@ -2385,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);
 }
@@ -2394,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' */
@@ -2459,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);
@@ -2489,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;
@@ -2892,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);
 }
 
@@ -2903,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);
 }
 
@@ -2920,9 +3262,9 @@ 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);
 }
 
@@ -2936,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);
 }
 
@@ -2951,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);
 }
 
@@ -2969,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);
 }
 
@@ -2987,9 +3329,9 @@ 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);
 }
 
@@ -3004,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);
 }
 
@@ -3021,9 +3363,9 @@ 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);
 }
 
@@ -3036,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);
 }
 
@@ -3051,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);
 }
@@ -3061,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"
@@ -3087,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;
 }
@@ -3111,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,
@@ -3127,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);
 }
 
@@ -3142,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);
 }
 
@@ -3155,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);
 }
 
@@ -3168,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);
 }
 
@@ -3184,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;
@@ -3207,7 +3567,7 @@ 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);
 }
 
@@ -3219,7 +3579,8 @@ DEFUN (set_ip_nexthop_peer,
        "Next hop address\n"
        "Use peer address (for BGP only)\n")
 {
-  return generic_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,
@@ -3230,7 +3591,8 @@ DEFUN (set_ip_nexthop_unchanged,
        "Next hop address\n"
        "Don't modify existing Next hop address\n")
 {
-  return generic_set_add (vty, vty->index, "ip next-hop", "unchanged");
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                          "ip next-hop", "unchanged");
 }
 
 
@@ -3242,7 +3604,8 @@ DEFUN (set_local_pref,
        "Preference value\n")
 {
   int idx_number = 2;
-  return generic_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);
 }
 
 
@@ -3256,8 +3619,10 @@ DEFUN (no_set_local_pref,
 {
   int idx_localpref = 3;
   if (argc <= idx_localpref)
-    return generic_set_delete (vty, vty->index, "local-preference", NULL);
-  return generic_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);
 }
 
 
@@ -3269,7 +3634,8 @@ DEFUN (set_weight,
        "Weight value\n")
 {
   int idx_number = 2;
-  return generic_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);
 }
 
 
@@ -3283,8 +3649,10 @@ DEFUN (no_set_weight,
 {
   int idx_weight = 3;
   if (argc <= idx_weight)
-    return generic_set_delete (vty, vty->index, "weight", NULL);
-  return generic_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);
 }
 
 
@@ -3301,7 +3669,8 @@ DEFUN (set_aspath_prepend_asn,
   char *str;
 
   str = argv_concat (argv, argc, idx_asn);
-  ret = generic_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;
@@ -3309,7 +3678,7 @@ DEFUN (set_aspath_prepend_asn,
 
 DEFUN (set_aspath_prepend_lastas,
        set_aspath_prepend_lastas_cmd,
-       "set as-path prepend last-as (1-10)",
+       "set as-path prepend last-as (1-9)",
        SET_STR
        "Transform BGP AS_PATH attribute\n"
        "Prepend to the as-path\n"
@@ -3333,7 +3702,8 @@ DEFUN (no_set_aspath_prepend,
   char *str;
 
   str = argv_concat (argv, argc, idx_asn);
-  ret = generic_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;
 }
@@ -3352,7 +3722,8 @@ DEFUN (set_aspath_exclude,
   char *str;
 
   str = argv_concat (argv, argc, idx_asn);
-  ret = generic_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;
 }
@@ -3371,7 +3742,8 @@ DEFUN (no_set_aspath_exclude,
   char *str;
 
   str = argv_concat (argv, argc, idx_asn);
-  ret = generic_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;
 }
@@ -3460,11 +3832,13 @@ DEFUN (set_community,
       argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
       strcpy (argstr, str);
       strcpy (argstr + strlen (str), " additive");
-      ret =  generic_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 =  generic_set_add (vty, vty->index, "community", str);
+    ret =  generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
+                            "community", str);
 
   community_free (com);
 
@@ -3478,7 +3852,8 @@ DEFUN (set_community_none,
        "BGP community attribute\n"
        "No community attribute\n")
 {
-  return generic_set_add (vty, vty->index, "community", "none");
+  return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "community",
+                          "none");
 }
 
 DEFUN (no_set_community,
@@ -3489,7 +3864,8 @@ DEFUN (no_set_community,
        "BGP community attribute\n"
        COMMUNITY_VAL_STR)
 {
-  return generic_set_delete (vty, vty->index, "community", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "community", NULL);
 }
 
 
@@ -3511,7 +3887,7 @@ DEFUN (set_community_delete,
   strcpy (str, argv[idx_comm_list]->arg);
   strcpy (str + strlen (argv[idx_comm_list]->arg), " delete");
 
-  generic_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;
@@ -3528,9 +3904,99 @@ DEFUN (no_set_community_delete,
        "Community-list name\n"
        "Delete matching communities\n")
 {
-  return generic_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,
@@ -3545,7 +4011,8 @@ DEFUN (set_ecommunity_rt,
   char *str;
 
   str = argv_concat (argv, argc, idx_asn_nn);
-  ret = generic_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;
@@ -3560,7 +4027,8 @@ DEFUN (no_set_ecommunity_rt,
        "Route Target extended community\n"
        "VPN extended community\n")
 {
-  return generic_set_delete (vty, vty->index, "extcommunity rt", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "extcommunity rt", NULL);
 }
 
 
@@ -3577,7 +4045,8 @@ DEFUN (set_ecommunity_soo,
   char *str;
 
   str = argv_concat (argv, argc, idx_asn_nn);
-  ret = generic_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;
 }
@@ -3592,7 +4061,8 @@ DEFUN (no_set_ecommunity_soo,
        "Site-of-Origin extended community\n"
        "VPN extended community\n")
 {
-  return generic_set_delete (vty, vty->index, "extcommunity soo", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
+                             "extcommunity soo", NULL);
 }
 
 
@@ -3607,11 +4077,14 @@ DEFUN (set_origin,
 {
   int idx_origin = 2;
   if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0)
-    return generic_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 generic_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 generic_set_add (vty, vty->index, "origin", "incomplete");
+    return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin",
+                            "incomplete");
 
   return CMD_WARNING;
 }
@@ -3627,7 +4100,8 @@ DEFUN (no_set_origin,
        "local IGP\n"
        "unknown heritage\n")
 {
-  return generic_set_delete (vty, vty->index, "origin", NULL);
+  return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "origin",
+                             NULL);
 }
 
 
@@ -3637,7 +4111,8 @@ DEFUN (set_atomic_aggregate,
        SET_STR
        "BGP atomic aggregate attribute\n" )
 {
-  return generic_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,
@@ -3647,7 +4122,8 @@ DEFUN (no_set_atomic_aggregate,
        SET_STR
        "BGP atomic aggregate attribute\n" )
 {
-  return generic_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,
@@ -3677,7 +4153,8 @@ DEFUN (set_aggregator_as,
 
   sprintf (argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
 
-  ret = generic_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);
 
@@ -3702,7 +4179,8 @@ DEFUN (no_set_aggregator_as,
   char *argstr;
 
   if (argc <= idx_asn)
-    return generic_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)
@@ -3716,14 +4194,14 @@ DEFUN (no_set_aggregator_as,
 
   sprintf (argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
 
-  ret = generic_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;
 }
 
-#ifdef HAVE_IPV6
 DEFUN (match_ipv6_next_hop,
        match_ipv6_next_hop_cmd,
        "match ipv6 next-hop X:X::X:X",
@@ -3733,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);
 }
 
@@ -3747,7 +4225,7 @@ 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);
 }
 
@@ -3760,7 +4238,8 @@ DEFUN (set_ipv6_nexthop_peer,
        "Next hop address\n"
        "Use peer address (for BGP only)\n")
 {
-  return generic_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,
@@ -3772,7 +4251,8 @@ DEFUN (no_set_ipv6_nexthop_peer,
        "IPv6 next-hop address\n"
        "Use peer address (for BGP only)\n")
 {
-  return generic_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,
@@ -3783,7 +4263,8 @@ DEFUN (set_ipv6_nexthop_prefer_global,
        "IPv6 next-hop address\n"
        "Prefer global over link-local if both exist\n")
 {
-  return generic_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,
@@ -3795,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 generic_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,
@@ -3826,7 +4308,8 @@ DEFUN (set_ipv6_nexthop_global,
       return CMD_WARNING;
     }
 
-  return generic_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);
 }
 
 
@@ -3842,39 +4325,130 @@ DEFUN (no_set_ipv6_nexthop_global,
 {
   int idx_ipv6 = 5;
   if (argc <= idx_ipv6)
-    return generic_set_delete (vty, vty->index, "ipv6 next-hop global", NULL);
-  return generic_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);
 }
-#endif /* HAVE_IPV6 */
 
-DEFUN (set_vpnv4_nexthop,
-       set_vpnv4_nexthop_cmd,
-       "set vpnv4 next-hop A.B.C.D",
+#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
        "VPNv4 information\n"
-       "VPNv4 next-hop address\n"
-       "IP address of next hop\n")
+       "VPNv6 information\n"
+       "VPN next-hop address\n"
+       "IP address of next hop\n"
+       "IPv6 address of next hop\n")
 {
-  int idx_ipv4 = 3;
-  return generic_set_add (vty, vty->index, "vpnv4 next-hop", argv[idx_ipv4]->arg);
-}
+  int idx_ip = 3;
+  afi_t afi;
+  int idx = 0;
 
+  if (argv_find_and_parse_vpnvx (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_vpn_nexthop,
+       no_set_vpn_nexthop_cmd,
+       "no set 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")
+       "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 generic_set_delete (vty, vty->index, "vpnv4 next-hop", NULL);
-  return generic_set_delete (vty, vty->index, "vpnv4 next-hop", argv[idx_ipv4]->arg);
+  int idx_ip = 4;
+  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_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_ipx_vpn_nexthop,
+       set_ipx_vpn_nexthop_cmd,
+       "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
+       SET_STR
+       "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_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_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
+       "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_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,
@@ -3884,7 +4458,8 @@ DEFUN (set_originator_id,
        "IP address of originator\n")
 {
   int idx_ipv4 = 2;
-  return generic_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);
 }
 
 
@@ -3896,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 generic_set_delete (vty, vty->index, "originator-id", NULL);
-  return generic_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);
 }
 
 
@@ -3962,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);
@@ -3981,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);
@@ -4000,8 +4580,9 @@ bgp_route_map_init (void)
   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);
@@ -4031,16 +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);
 
-#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);
@@ -4057,7 +4647,6 @@ bgp_route_map_init (void)
   install_element (RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
   install_element (RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
   install_element (RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
-#endif /* HAVE_IPV6 */
 }
 
 void