File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_routemap.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:11 2012 UTC (12 years, 4 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_20_1, v0_99_20, HEAD
quagga

    1: /* Route map function of bgpd.
    2:    Copyright (C) 1998, 1999 Kunihiro Ishiguro
    3: 
    4: This file is part of GNU Zebra.
    5: 
    6: GNU Zebra is free software; you can redistribute it and/or modify it
    7: under the terms of the GNU General Public License as published by the
    8: Free Software Foundation; either version 2, or (at your option) any
    9: later version.
   10: 
   11: GNU Zebra is distributed in the hope that it will be useful, but
   12: WITHOUT ANY WARRANTY; without even the implied warranty of
   13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14: General Public License for more details.
   15: 
   16: You should have received a copy of the GNU General Public License
   17: along with GNU Zebra; see the file COPYING.  If not, write to the Free
   18: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   19: 02111-1307, USA.  */
   20: 
   21: #include <zebra.h>
   22: 
   23: #include "prefix.h"
   24: #include "filter.h"
   25: #include "routemap.h"
   26: #include "command.h"
   27: #include "linklist.h"
   28: #include "plist.h"
   29: #include "memory.h"
   30: #include "log.h"
   31: #ifdef HAVE_LIBPCREPOSIX
   32: # include <pcreposix.h>
   33: #else
   34: # ifdef HAVE_GNU_REGEX
   35: #  include <regex.h>
   36: # else
   37: #  include "regex-gnu.h"
   38: # endif /* HAVE_GNU_REGEX */
   39: #endif /* HAVE_LIBPCREPOSIX */
   40: #include "buffer.h"
   41: #include "sockunion.h"
   42: 
   43: #include "bgpd/bgpd.h"
   44: #include "bgpd/bgp_table.h"
   45: #include "bgpd/bgp_attr.h"
   46: #include "bgpd/bgp_aspath.h"
   47: #include "bgpd/bgp_route.h"
   48: #include "bgpd/bgp_regex.h"
   49: #include "bgpd/bgp_community.h"
   50: #include "bgpd/bgp_clist.h"
   51: #include "bgpd/bgp_filter.h"
   52: #include "bgpd/bgp_mplsvpn.h"
   53: #include "bgpd/bgp_ecommunity.h"
   54: #include "bgpd/bgp_vty.h"
   55: 
   56: /* Memo of route-map commands.
   57: 
   58: o Cisco route-map
   59: 
   60:  match as-path          :  Done
   61:        community        :  Done
   62:        interface        :  Not yet
   63:        ip address       :  Done
   64:        ip next-hop      :  Done
   65:        ip route-source  :  Done
   66:        ip prefix-list   :  Done
   67:        ipv6 address     :  Done
   68:        ipv6 next-hop    :  Done
   69:        ipv6 route-source:  (This will not be implemented by bgpd)
   70:        ipv6 prefix-list :  Done
   71:        length           :  (This will not be implemented by bgpd)
   72:        metric           :  Done
   73:        route-type       :  (This will not be implemented by bgpd)
   74:        tag              :  (This will not be implemented by bgpd)
   75: 
   76:  set  as-path prepend   :  Done
   77:       as-path tag       :  Not yet
   78:       automatic-tag     :  (This will not be implemented by bgpd)
   79:       community         :  Done
   80:       comm-list         :  Not yet
   81:       dampning          :  Not yet
   82:       default           :  (This will not be implemented by bgpd)
   83:       interface         :  (This will not be implemented by bgpd)
   84:       ip default        :  (This will not be implemented by bgpd)
   85:       ip next-hop       :  Done
   86:       ip precedence     :  (This will not be implemented by bgpd)
   87:       ip tos            :  (This will not be implemented by bgpd)
   88:       level             :  (This will not be implemented by bgpd)
   89:       local-preference  :  Done
   90:       metric            :  Done
   91:       metric-type       :  Not yet
   92:       origin            :  Done
   93:       tag               :  (This will not be implemented by bgpd)
   94:       weight            :  Done
   95: 
   96: o Local extention
   97: 
   98:   set ipv6 next-hop global: Done
   99:   set ipv6 next-hop local : Done
  100:   set as-path exclude     : Done
  101: 
  102: */ 
  103: 
  104:  /* 'match peer (A.B.C.D|X:X::X:X)' */
  105: 
  106: /* Compares the peer specified in the 'match peer' clause with the peer
  107:     received in bgp_info->peer. If it is the same, or if the peer structure
  108:     received is a peer_group containing it, returns RMAP_MATCH. */
  109: static route_map_result_t
  110: route_match_peer (void *rule, struct prefix *prefix, route_map_object_t type,
  111:       void *object)
  112: {
  113:   union sockunion *su;
  114:   union sockunion *su2;
  115:   struct peer_group *group;
  116:   struct peer *peer;
  117:   struct listnode *node, *nnode;
  118: 
  119:   if (type == RMAP_BGP)
  120:     {
  121:       su = rule;
  122:       peer = ((struct bgp_info *) object)->peer;
  123: 
  124:       if ( ! CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT) &&
  125:            ! CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_EXPORT) )
  126:         return RMAP_NOMATCH;
  127: 
  128:       /* If su='0.0.0.0' (command 'match peer local'), and it's a NETWORK,
  129:           REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH */
  130:       su2 = sockunion_str2su ("0.0.0.0");
  131:       if ( sockunion_same (su, su2) )
  132:         {
  133:           int ret;
  134:           if ( CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_NETWORK) ||
  135:                CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE) ||
  136:                CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_DEFAULT))
  137:             ret = RMAP_MATCH;
  138:           else
  139:             ret = RMAP_NOMATCH;
  140:           
  141:           sockunion_free (su2);
  142:           return ret;
  143:         }
  144:       sockunion_free (su2);
  145:       
  146:       if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
  147:         {
  148:           if (sockunion_same (su, &peer->su))
  149:             return RMAP_MATCH;
  150: 
  151:           return RMAP_NOMATCH;
  152:         }
  153:       else
  154:         {
  155:           group = peer->group;
  156:           for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
  157:             {
  158:               if (sockunion_same (su, &peer->su))
  159:                 return RMAP_MATCH;
  160:             }
  161:           return RMAP_NOMATCH;
  162:         }
  163:     }
  164:   return RMAP_NOMATCH;
  165: }
  166: 
  167: static void *
  168: route_match_peer_compile (const char *arg)
  169: {
  170:   union sockunion *su;
  171:   int ret;
  172: 
  173:   su = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union sockunion));
  174: 
  175:   ret = str2sockunion ( (arg)? arg : "0.0.0.0", su);
  176:   if (ret < 0) {
  177:     XFREE (MTYPE_ROUTE_MAP_COMPILED, su);
  178:     return NULL;
  179:   }
  180: 
  181:   return su;
  182: }
  183: 
  184: /* Free route map's compiled `ip address' value. */
  185: static void
  186: route_match_peer_free (void *rule)
  187: {
  188:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  189: }
  190: 
  191: /* Route map commands for ip address matching. */
  192: struct route_map_rule_cmd route_match_peer_cmd =
  193: {
  194:   "peer",
  195:   route_match_peer,
  196:   route_match_peer_compile,
  197:   route_match_peer_free
  198: };
  199: 
  200: /* `match ip address IP_ACCESS_LIST' */
  201: 
  202: /* Match function should return 1 if match is success else return
  203:    zero. */
  204: static route_map_result_t
  205: route_match_ip_address (void *rule, struct prefix *prefix, 
  206: 			route_map_object_t type, void *object)
  207: {
  208:   struct access_list *alist;
  209:   /* struct prefix_ipv4 match; */
  210: 
  211:   if (type == RMAP_BGP)
  212:     {
  213:       alist = access_list_lookup (AFI_IP, (char *) rule);
  214:       if (alist == NULL)
  215: 	return RMAP_NOMATCH;
  216:     
  217:       return (access_list_apply (alist, prefix) == FILTER_DENY ?
  218: 	      RMAP_NOMATCH : RMAP_MATCH);
  219:     }
  220:   return RMAP_NOMATCH;
  221: }
  222: 
  223: /* Route map `ip address' match statement.  `arg' should be
  224:    access-list name. */
  225: static void *
  226: route_match_ip_address_compile (const char *arg)
  227: {
  228:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  229: }
  230: 
  231: /* Free route map's compiled `ip address' value. */
  232: static void
  233: route_match_ip_address_free (void *rule)
  234: {
  235:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  236: }
  237: 
  238: /* Route map commands for ip address matching. */
  239: struct route_map_rule_cmd route_match_ip_address_cmd =
  240: {
  241:   "ip address",
  242:   route_match_ip_address,
  243:   route_match_ip_address_compile,
  244:   route_match_ip_address_free
  245: };
  246: 
  247: /* `match ip next-hop IP_ADDRESS' */
  248: 
  249: /* Match function return 1 if match is success else return zero. */
  250: static route_map_result_t
  251: route_match_ip_next_hop (void *rule, struct prefix *prefix, 
  252: 			 route_map_object_t type, void *object)
  253: {
  254:   struct access_list *alist;
  255:   struct bgp_info *bgp_info;
  256:   struct prefix_ipv4 p;
  257: 
  258:   if (type == RMAP_BGP)
  259:     {
  260:       bgp_info = object;
  261:       p.family = AF_INET;
  262:       p.prefix = bgp_info->attr->nexthop;
  263:       p.prefixlen = IPV4_MAX_BITLEN;
  264: 
  265:       alist = access_list_lookup (AFI_IP, (char *) rule);
  266:       if (alist == NULL)
  267: 	return RMAP_NOMATCH;
  268: 
  269:       return (access_list_apply (alist, &p) == FILTER_DENY ?
  270:               RMAP_NOMATCH : RMAP_MATCH);
  271:     }
  272:   return RMAP_NOMATCH;
  273: }
  274: 
  275: /* Route map `ip next-hop' match statement. `arg' is
  276:    access-list name. */
  277: static void *
  278: route_match_ip_next_hop_compile (const char *arg)
  279: {
  280:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  281: }
  282: 
  283: /* Free route map's compiled `ip address' value. */
  284: static void
  285: route_match_ip_next_hop_free (void *rule)
  286: {
  287:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  288: }
  289: 
  290: /* Route map commands for ip next-hop matching. */
  291: struct route_map_rule_cmd route_match_ip_next_hop_cmd =
  292: {
  293:   "ip next-hop",
  294:   route_match_ip_next_hop,
  295:   route_match_ip_next_hop_compile,
  296:   route_match_ip_next_hop_free
  297: };
  298: 
  299: /* `match ip route-source ACCESS-LIST' */
  300: 
  301: /* Match function return 1 if match is success else return zero. */
  302: static route_map_result_t
  303: route_match_ip_route_source (void *rule, struct prefix *prefix, 
  304: 			     route_map_object_t type, void *object)
  305: {
  306:   struct access_list *alist;
  307:   struct bgp_info *bgp_info;
  308:   struct peer *peer;
  309:   struct prefix_ipv4 p;
  310: 
  311:   if (type == RMAP_BGP)
  312:     {
  313:       bgp_info = object;
  314:       peer = bgp_info->peer;
  315: 
  316:       if (! peer || sockunion_family (&peer->su) != AF_INET)
  317: 	return RMAP_NOMATCH;
  318: 
  319:       p.family = AF_INET;
  320:       p.prefix = peer->su.sin.sin_addr;
  321:       p.prefixlen = IPV4_MAX_BITLEN;
  322: 
  323:       alist = access_list_lookup (AFI_IP, (char *) rule);
  324:       if (alist == NULL)
  325: 	return RMAP_NOMATCH;
  326: 
  327:       return (access_list_apply (alist, &p) == FILTER_DENY ?
  328:               RMAP_NOMATCH : RMAP_MATCH);
  329:     }
  330:   return RMAP_NOMATCH;
  331: }
  332: 
  333: /* Route map `ip route-source' match statement. `arg' is
  334:    access-list name. */
  335: static void *
  336: route_match_ip_route_source_compile (const char *arg)
  337: {
  338:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  339: }
  340: 
  341: /* Free route map's compiled `ip address' value. */
  342: static void
  343: route_match_ip_route_source_free (void *rule)
  344: {
  345:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  346: }
  347: 
  348: /* Route map commands for ip route-source matching. */
  349: struct route_map_rule_cmd route_match_ip_route_source_cmd =
  350: {
  351:   "ip route-source",
  352:   route_match_ip_route_source,
  353:   route_match_ip_route_source_compile,
  354:   route_match_ip_route_source_free
  355: };
  356: 
  357: /* `match ip address prefix-list PREFIX_LIST' */
  358: 
  359: static route_map_result_t
  360: route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, 
  361: 				    route_map_object_t type, void *object)
  362: {
  363:   struct prefix_list *plist;
  364: 
  365:   if (type == RMAP_BGP)
  366:     {
  367:       plist = prefix_list_lookup (AFI_IP, (char *) rule);
  368:       if (plist == NULL)
  369: 	return RMAP_NOMATCH;
  370:     
  371:       return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
  372: 	      RMAP_NOMATCH : RMAP_MATCH);
  373:     }
  374:   return RMAP_NOMATCH;
  375: }
  376: 
  377: static void *
  378: route_match_ip_address_prefix_list_compile (const char *arg)
  379: {
  380:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  381: }
  382: 
  383: static void
  384: route_match_ip_address_prefix_list_free (void *rule)
  385: {
  386:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  387: }
  388: 
  389: struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
  390: {
  391:   "ip address prefix-list",
  392:   route_match_ip_address_prefix_list,
  393:   route_match_ip_address_prefix_list_compile,
  394:   route_match_ip_address_prefix_list_free
  395: };
  396: 
  397: /* `match ip next-hop prefix-list PREFIX_LIST' */
  398: 
  399: static route_map_result_t
  400: route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
  401:                                     route_map_object_t type, void *object)
  402: {
  403:   struct prefix_list *plist;
  404:   struct bgp_info *bgp_info;
  405:   struct prefix_ipv4 p;
  406: 
  407:   if (type == RMAP_BGP)
  408:     {
  409:       bgp_info = object;
  410:       p.family = AF_INET;
  411:       p.prefix = bgp_info->attr->nexthop;
  412:       p.prefixlen = IPV4_MAX_BITLEN;
  413: 
  414:       plist = prefix_list_lookup (AFI_IP, (char *) rule);
  415:       if (plist == NULL)
  416:         return RMAP_NOMATCH;
  417: 
  418:       return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
  419:               RMAP_NOMATCH : RMAP_MATCH);
  420:     }
  421:   return RMAP_NOMATCH;
  422: }
  423: 
  424: static void *
  425: route_match_ip_next_hop_prefix_list_compile (const char *arg)
  426: {
  427:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  428: }
  429: 
  430: static void
  431: route_match_ip_next_hop_prefix_list_free (void *rule)
  432: {
  433:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  434: }
  435: 
  436: struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
  437: {
  438:   "ip next-hop prefix-list",
  439:   route_match_ip_next_hop_prefix_list,
  440:   route_match_ip_next_hop_prefix_list_compile,
  441:   route_match_ip_next_hop_prefix_list_free
  442: };
  443: 
  444: /* `match ip route-source prefix-list PREFIX_LIST' */
  445: 
  446: static route_map_result_t
  447: route_match_ip_route_source_prefix_list (void *rule, struct prefix *prefix,
  448: 					 route_map_object_t type, void *object)
  449: {
  450:   struct prefix_list *plist;
  451:   struct bgp_info *bgp_info;
  452:   struct peer *peer;
  453:   struct prefix_ipv4 p;
  454: 
  455:   if (type == RMAP_BGP)
  456:     {
  457:       bgp_info = object;
  458:       peer = bgp_info->peer;
  459: 
  460:       if (! peer || sockunion_family (&peer->su) != AF_INET)
  461: 	return RMAP_NOMATCH;
  462: 
  463:       p.family = AF_INET;
  464:       p.prefix = peer->su.sin.sin_addr;
  465:       p.prefixlen = IPV4_MAX_BITLEN;
  466: 
  467:       plist = prefix_list_lookup (AFI_IP, (char *) rule);
  468:       if (plist == NULL)
  469:         return RMAP_NOMATCH;
  470: 
  471:       return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
  472:               RMAP_NOMATCH : RMAP_MATCH);
  473:     }
  474:   return RMAP_NOMATCH;
  475: }
  476: 
  477: static void *
  478: route_match_ip_route_source_prefix_list_compile (const char *arg)
  479: {
  480:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  481: }
  482: 
  483: static void
  484: route_match_ip_route_source_prefix_list_free (void *rule)
  485: {
  486:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  487: }
  488: 
  489: struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd =
  490: {
  491:   "ip route-source prefix-list",
  492:   route_match_ip_route_source_prefix_list,
  493:   route_match_ip_route_source_prefix_list_compile,
  494:   route_match_ip_route_source_prefix_list_free
  495: };
  496: 
  497: /* `match metric METRIC' */
  498: 
  499: /* Match function return 1 if match is success else return zero. */
  500: static route_map_result_t
  501: route_match_metric (void *rule, struct prefix *prefix, 
  502: 		    route_map_object_t type, void *object)
  503: {
  504:   u_int32_t *med;
  505:   struct bgp_info *bgp_info;
  506: 
  507:   if (type == RMAP_BGP)
  508:     {
  509:       med = rule;
  510:       bgp_info = object;
  511:     
  512:       if (bgp_info->attr->med == *med)
  513: 	return RMAP_MATCH;
  514:       else
  515: 	return RMAP_NOMATCH;
  516:     }
  517:   return RMAP_NOMATCH;
  518: }
  519: 
  520: /* Route map `match metric' match statement. `arg' is MED value */
  521: static void *
  522: route_match_metric_compile (const char *arg)
  523: {
  524:   u_int32_t *med;
  525:   char *endptr = NULL;
  526:   unsigned long tmpval;
  527: 
  528:   tmpval = strtoul (arg, &endptr, 10);
  529:   if (*endptr != '\0' || tmpval == ULONG_MAX || tmpval > UINT32_MAX)
  530:     return NULL;
  531:     
  532:   med = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
  533:   
  534:   if (!med)
  535:     return med;
  536:   
  537:   *med = tmpval;
  538:   return med;
  539: }
  540: 
  541: /* Free route map's compiled `match metric' value. */
  542: static void
  543: route_match_metric_free (void *rule)
  544: {
  545:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  546: }
  547: 
  548: /* Route map commands for metric matching. */
  549: struct route_map_rule_cmd route_match_metric_cmd =
  550: {
  551:   "metric",
  552:   route_match_metric,
  553:   route_match_metric_compile,
  554:   route_match_metric_free
  555: };
  556: 
  557: /* `match as-path ASPATH' */
  558: 
  559: /* Match function for as-path match.  I assume given object is */
  560: static route_map_result_t
  561: route_match_aspath (void *rule, struct prefix *prefix, 
  562: 		    route_map_object_t type, void *object)
  563: {
  564:   
  565:   struct as_list *as_list;
  566:   struct bgp_info *bgp_info;
  567: 
  568:   if (type == RMAP_BGP)
  569:     {
  570:       as_list = as_list_lookup ((char *) rule);
  571:       if (as_list == NULL)
  572: 	return RMAP_NOMATCH;
  573:     
  574:       bgp_info = object;
  575:     
  576:       /* Perform match. */
  577:       return ((as_list_apply (as_list, bgp_info->attr->aspath) == AS_FILTER_DENY) ? RMAP_NOMATCH : RMAP_MATCH);
  578:     }
  579:   return RMAP_NOMATCH;
  580: }
  581: 
  582: /* Compile function for as-path match. */
  583: static void *
  584: route_match_aspath_compile (const char *arg)
  585: {
  586:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  587: }
  588: 
  589: /* Compile function for as-path match. */
  590: static void
  591: route_match_aspath_free (void *rule)
  592: {
  593:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  594: }
  595: 
  596: /* Route map commands for aspath matching. */
  597: struct route_map_rule_cmd route_match_aspath_cmd = 
  598: {
  599:   "as-path",
  600:   route_match_aspath,
  601:   route_match_aspath_compile,
  602:   route_match_aspath_free
  603: };
  604: 
  605: /* `match community COMMUNIY' */
  606: struct rmap_community
  607: {
  608:   char *name;
  609:   int exact;
  610: };
  611: 
  612: /* Match function for community match. */
  613: static route_map_result_t
  614: route_match_community (void *rule, struct prefix *prefix, 
  615: 		       route_map_object_t type, void *object)
  616: {
  617:   struct community_list *list;
  618:   struct bgp_info *bgp_info;
  619:   struct rmap_community *rcom;
  620: 
  621:   if (type == RMAP_BGP) 
  622:     {
  623:       bgp_info = object;
  624:       rcom = rule;
  625: 
  626:       list = community_list_lookup (bgp_clist, rcom->name, COMMUNITY_LIST_MASTER);
  627:       if (! list)
  628: 	return RMAP_NOMATCH;
  629: 
  630:       if (rcom->exact)
  631: 	{
  632: 	  if (community_list_exact_match (bgp_info->attr->community, list))
  633: 	    return RMAP_MATCH;
  634: 	}
  635:       else
  636: 	{
  637: 	  if (community_list_match (bgp_info->attr->community, list))
  638: 	    return RMAP_MATCH;
  639: 	}
  640:     }
  641:   return RMAP_NOMATCH;
  642: }
  643: 
  644: /* Compile function for community match. */
  645: static void *
  646: route_match_community_compile (const char *arg)
  647: {
  648:   struct rmap_community *rcom;
  649:   int len;
  650:   char *p;
  651: 
  652:   rcom = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_community));
  653: 
  654:   p = strchr (arg, ' ');
  655:   if (p)
  656:     {
  657:       len = p - arg;
  658:       rcom->name = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
  659:       memcpy (rcom->name, arg, len);
  660:       rcom->exact = 1;
  661:     }
  662:   else
  663:     {
  664:       rcom->name = XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  665:       rcom->exact = 0;
  666:     }
  667:   return rcom;
  668: }
  669: 
  670: /* Compile function for community match. */
  671: static void
  672: route_match_community_free (void *rule)
  673: {
  674:   struct rmap_community *rcom = rule;
  675: 
  676:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name); 
  677:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom);
  678: }
  679: 
  680: /* Route map commands for community matching. */
  681: struct route_map_rule_cmd route_match_community_cmd = 
  682: {
  683:   "community",
  684:   route_match_community,
  685:   route_match_community_compile,
  686:   route_match_community_free
  687: };
  688: 
  689: /* Match function for extcommunity match. */
  690: static route_map_result_t
  691: route_match_ecommunity (void *rule, struct prefix *prefix, 
  692: 			route_map_object_t type, void *object)
  693: {
  694:   struct community_list *list;
  695:   struct bgp_info *bgp_info;
  696: 
  697:   if (type == RMAP_BGP) 
  698:     {
  699:       bgp_info = object;
  700:       
  701:       if (!bgp_info->attr->extra)
  702:         return RMAP_NOMATCH;
  703:       
  704:       list = community_list_lookup (bgp_clist, (char *) rule,
  705: 				    EXTCOMMUNITY_LIST_MASTER);
  706:       if (! list)
  707: 	return RMAP_NOMATCH;
  708: 
  709:       if (ecommunity_list_match (bgp_info->attr->extra->ecommunity, list))
  710: 	return RMAP_MATCH;
  711:     }
  712:   return RMAP_NOMATCH;
  713: }
  714: 
  715: /* Compile function for extcommunity match. */
  716: static void *
  717: route_match_ecommunity_compile (const char *arg)
  718: {
  719:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
  720: }
  721: 
  722: /* Compile function for extcommunity match. */
  723: static void
  724: route_match_ecommunity_free (void *rule)
  725: {
  726:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  727: }
  728: 
  729: /* Route map commands for community matching. */
  730: struct route_map_rule_cmd route_match_ecommunity_cmd = 
  731: {
  732:   "extcommunity",
  733:   route_match_ecommunity,
  734:   route_match_ecommunity_compile,
  735:   route_match_ecommunity_free
  736: };
  737: 
  738: /* `match nlri` and `set nlri` are replaced by `address-family ipv4`
  739:    and `address-family vpnv4'.  */
  740: 
  741: /* `match origin' */
  742: static route_map_result_t
  743: route_match_origin (void *rule, struct prefix *prefix, 
  744: 		    route_map_object_t type, void *object)
  745: {
  746:   u_char *origin;
  747:   struct bgp_info *bgp_info;
  748: 
  749:   if (type == RMAP_BGP)
  750:     {
  751:       origin = rule;
  752:       bgp_info = object;
  753:     
  754:       if (bgp_info->attr->origin == *origin)
  755: 	return RMAP_MATCH;
  756:     }
  757: 
  758:   return RMAP_NOMATCH;
  759: }
  760: 
  761: static void *
  762: route_match_origin_compile (const char *arg)
  763: {
  764:   u_char *origin;
  765: 
  766:   origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char));
  767: 
  768:   if (strcmp (arg, "igp") == 0)
  769:     *origin = 0;
  770:   else if (strcmp (arg, "egp") == 0)
  771:     *origin = 1;
  772:   else
  773:     *origin = 2;
  774: 
  775:   return origin;
  776: }
  777: 
  778: /* Free route map's compiled `ip address' value. */
  779: static void
  780: route_match_origin_free (void *rule)
  781: {
  782:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  783: }
  784: 
  785: /* Route map commands for origin matching. */
  786: struct route_map_rule_cmd route_match_origin_cmd =
  787: {
  788:   "origin",
  789:   route_match_origin,
  790:   route_match_origin_compile,
  791:   route_match_origin_free
  792: };
  793: /* `set ip next-hop IP_ADDRESS' */
  794: 
  795: /* Set nexthop to object.  ojbect must be pointer to struct attr. */
  796: struct rmap_ip_nexthop_set
  797: {
  798:   struct in_addr *address;
  799:   int peer_address;
  800: };
  801: 
  802: static route_map_result_t
  803: route_set_ip_nexthop (void *rule, struct prefix *prefix,
  804: 		      route_map_object_t type, void *object)
  805: {
  806:   struct rmap_ip_nexthop_set *rins = rule;
  807:   struct in_addr peer_address;
  808:   struct bgp_info *bgp_info;
  809:   struct peer *peer;
  810: 
  811:   if (type == RMAP_BGP)
  812:     {
  813:       bgp_info = object;
  814:       peer = bgp_info->peer;
  815: 
  816:       if (rins->peer_address)
  817: 	{
  818:          if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
  819:            CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
  820: 	      && peer->su_remote 
  821: 	      && sockunion_family (peer->su_remote) == AF_INET)
  822: 	    {
  823:               inet_aton (sockunion_su2str (peer->su_remote), &peer_address);
  824:               bgp_info->attr->nexthop = peer_address;
  825: 	      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
  826: 	    }
  827: 	  else if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT)
  828: 		   && peer->su_local
  829: 		   && sockunion_family (peer->su_local) == AF_INET)
  830: 	    {
  831:               inet_aton (sockunion_su2str (peer->su_local), &peer_address);
  832:               bgp_info->attr->nexthop = peer_address;
  833: 	      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
  834: 	    }
  835: 	}
  836:       else
  837: 	{
  838: 	  /* Set next hop value. */ 
  839: 	  bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
  840: 	  bgp_info->attr->nexthop = *rins->address;
  841: 	}
  842:     }
  843: 
  844:   return RMAP_OKAY;
  845: }
  846: 
  847: /* Route map `ip nexthop' compile function.  Given string is converted
  848:    to struct in_addr structure. */
  849: static void *
  850: route_set_ip_nexthop_compile (const char *arg)
  851: {
  852:   struct rmap_ip_nexthop_set *rins;
  853:   struct in_addr *address = NULL;
  854:   int peer_address = 0;
  855:   int ret;
  856: 
  857:   if (strcmp (arg, "peer-address") == 0)
  858:     peer_address = 1;
  859:   else
  860:     {
  861:       address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
  862:       ret = inet_aton (arg, address);
  863: 
  864:       if (ret == 0)
  865: 	{
  866: 	  XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
  867: 	  return NULL;
  868: 	}
  869:     }
  870: 
  871:   rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_ip_nexthop_set));
  872: 
  873:   rins->address = address;
  874:   rins->peer_address = peer_address;
  875: 
  876:   return rins;
  877: }
  878: 
  879: /* Free route map's compiled `ip nexthop' value. */
  880: static void
  881: route_set_ip_nexthop_free (void *rule)
  882: {
  883:   struct rmap_ip_nexthop_set *rins = rule;
  884: 
  885:   if (rins->address)
  886:     XFREE (MTYPE_ROUTE_MAP_COMPILED, rins->address);
  887:     
  888:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rins);
  889: }
  890: 
  891: /* Route map commands for ip nexthop set. */
  892: struct route_map_rule_cmd route_set_ip_nexthop_cmd =
  893: {
  894:   "ip next-hop",
  895:   route_set_ip_nexthop,
  896:   route_set_ip_nexthop_compile,
  897:   route_set_ip_nexthop_free
  898: };
  899: 
  900: /* `set local-preference LOCAL_PREF' */
  901: 
  902: /* Set local preference. */
  903: static route_map_result_t
  904: route_set_local_pref (void *rule, struct prefix *prefix,
  905: 		      route_map_object_t type, void *object)
  906: {
  907:   u_int32_t *local_pref;
  908:   struct bgp_info *bgp_info;
  909: 
  910:   if (type == RMAP_BGP)
  911:     {
  912:       /* Fetch routemap's rule information. */
  913:       local_pref = rule;
  914:       bgp_info = object;
  915:     
  916:       /* Set local preference value. */ 
  917:       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
  918:       bgp_info->attr->local_pref = *local_pref;
  919:     }
  920: 
  921:   return RMAP_OKAY;
  922: }
  923: 
  924: /* set local preference compilation. */
  925: static void *
  926: route_set_local_pref_compile (const char *arg)
  927: {
  928:   unsigned long tmp;
  929:   u_int32_t *local_pref;
  930:   char *endptr = NULL;
  931: 
  932:   /* Local preference value shoud be integer. */
  933:   if (! all_digit (arg))
  934:     return NULL;
  935:   
  936:   tmp = strtoul (arg, &endptr, 10);
  937:   if (*endptr != '\0' || tmp == ULONG_MAX || tmp > UINT32_MAX)
  938:     return NULL;
  939:    
  940:   local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); 
  941:   
  942:   if (!local_pref)
  943:     return local_pref;
  944:   
  945:   *local_pref = tmp;
  946:   
  947:   return local_pref;
  948: }
  949: 
  950: /* Free route map's local preference value. */
  951: static void
  952: route_set_local_pref_free (void *rule)
  953: {
  954:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
  955: }
  956: 
  957: /* Set local preference rule structure. */
  958: struct route_map_rule_cmd route_set_local_pref_cmd = 
  959: {
  960:   "local-preference",
  961:   route_set_local_pref,
  962:   route_set_local_pref_compile,
  963:   route_set_local_pref_free,
  964: };
  965: 
  966: /* `set weight WEIGHT' */
  967: 
  968: /* Set weight. */
  969: static route_map_result_t
  970: route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
  971: 		  void *object)
  972: {
  973:   u_int32_t *weight;
  974:   struct bgp_info *bgp_info;
  975: 
  976:   if (type == RMAP_BGP)
  977:     {
  978:       /* Fetch routemap's rule information. */
  979:       weight = rule;
  980:       bgp_info = object;
  981:     
  982:       /* Set weight value. */ 
  983:       if (*weight)
  984:         (bgp_attr_extra_get (bgp_info->attr))->weight = *weight;
  985:       else if (bgp_info->attr->extra)
  986:         bgp_info->attr->extra->weight = 0;
  987:     }
  988: 
  989:   return RMAP_OKAY;
  990: }
  991: 
  992: /* set local preference compilation. */
  993: static void *
  994: route_set_weight_compile (const char *arg)
  995: {
  996:   unsigned long tmp;
  997:   u_int32_t *weight;
  998:   char *endptr = NULL;
  999: 
 1000:   /* Local preference value shoud be integer. */
 1001:   if (! all_digit (arg))
 1002:     return NULL;
 1003: 
 1004: 
 1005:   tmp = strtoul (arg, &endptr, 10);
 1006:   if (*endptr != '\0' || tmp == ULONG_MAX || tmp > UINT32_MAX)
 1007:     return NULL;
 1008:   
 1009:   weight = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
 1010:   
 1011:   if (weight == NULL)
 1012:     return weight;
 1013:   
 1014:   *weight = tmp;  
 1015:   
 1016:   return weight;
 1017: }
 1018: 
 1019: /* Free route map's local preference value. */
 1020: static void
 1021: route_set_weight_free (void *rule)
 1022: {
 1023:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 1024: }
 1025: 
 1026: /* Set local preference rule structure. */
 1027: struct route_map_rule_cmd route_set_weight_cmd = 
 1028: {
 1029:   "weight",
 1030:   route_set_weight,
 1031:   route_set_weight_compile,
 1032:   route_set_weight_free,
 1033: };
 1034: 
 1035: /* `set metric METRIC' */
 1036: 
 1037: /* Set metric to attribute. */
 1038: static route_map_result_t
 1039: route_set_metric (void *rule, struct prefix *prefix, 
 1040: 		  route_map_object_t type, void *object)
 1041: {
 1042:   char *metric;
 1043:   u_int32_t metric_val;
 1044:   struct bgp_info *bgp_info;
 1045: 
 1046:   if (type == RMAP_BGP)
 1047:     {
 1048:       /* Fetch routemap's rule information. */
 1049:       metric = rule;
 1050:       bgp_info = object;
 1051: 
 1052:       if (! (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)))
 1053: 	bgp_info->attr->med = 0;
 1054:       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
 1055: 
 1056:       if (all_digit (metric))
 1057: 	{
 1058: 	  metric_val = strtoul (metric, (char **)NULL, 10);
 1059: 	  bgp_info->attr->med = metric_val;
 1060: 	}
 1061:       else
 1062: 	{
 1063: 	  metric_val = strtoul (metric+1, (char **)NULL, 10);
 1064: 
 1065: 	  if (strncmp (metric, "+", 1) == 0)
 1066: 	    {
 1067: 	      if (bgp_info->attr->med/2 + metric_val/2 > BGP_MED_MAX/2)
 1068: 	        bgp_info->attr->med = BGP_MED_MAX - 1;
 1069: 	      else
 1070: 	        bgp_info->attr->med += metric_val;
 1071: 	    }
 1072: 	  else if (strncmp (metric, "-", 1) == 0)
 1073: 	    {
 1074: 	      if (bgp_info->attr->med <= metric_val)
 1075: 	        bgp_info->attr->med = 0;
 1076: 	      else
 1077: 	        bgp_info->attr->med -= metric_val;
 1078: 	    }
 1079: 	}
 1080:     }
 1081:   return RMAP_OKAY;
 1082: }
 1083: 
 1084: /* set metric compilation. */
 1085: static void *
 1086: route_set_metric_compile (const char *arg)
 1087: {
 1088:   u_int32_t metric;
 1089:   unsigned long larg;
 1090:   char *endptr = NULL;
 1091: 
 1092:   if (all_digit (arg))
 1093:     {
 1094:       /* set metric value check*/
 1095:       larg = strtoul (arg, &endptr, 10);
 1096:       if (*endptr != '\0' || larg == ULONG_MAX || larg > UINT32_MAX)
 1097:         return NULL;
 1098:       metric = larg;
 1099:     }
 1100:   else
 1101:     {
 1102:       /* set metric +/-value check */
 1103:       if ((strncmp (arg, "+", 1) != 0
 1104: 	   && strncmp (arg, "-", 1) != 0)
 1105: 	   || (! all_digit (arg+1)))
 1106: 	return NULL;
 1107: 
 1108:       larg = strtoul (arg+1, &endptr, 10);
 1109:       if (*endptr != '\0' || larg == ULONG_MAX || larg > UINT32_MAX)
 1110: 	return NULL;
 1111:       metric = larg;
 1112:     }
 1113: 
 1114:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
 1115: }
 1116: 
 1117: /* Free route map's compiled `set metric' value. */
 1118: static void
 1119: route_set_metric_free (void *rule)
 1120: {
 1121:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 1122: }
 1123: 
 1124: /* Set metric rule structure. */
 1125: struct route_map_rule_cmd route_set_metric_cmd = 
 1126: {
 1127:   "metric",
 1128:   route_set_metric,
 1129:   route_set_metric_compile,
 1130:   route_set_metric_free,
 1131: };
 1132: 
 1133: /* `set as-path prepend ASPATH' */
 1134: 
 1135: /* For AS path prepend mechanism. */
 1136: static route_map_result_t
 1137: route_set_aspath_prepend (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
 1138: {
 1139:   struct aspath *aspath;
 1140:   struct aspath *new;
 1141:   struct bgp_info *binfo;
 1142: 
 1143:   if (type == RMAP_BGP)
 1144:     {
 1145:       aspath = rule;
 1146:       binfo = object;
 1147:     
 1148:       if (binfo->attr->aspath->refcnt)
 1149: 	new = aspath_dup (binfo->attr->aspath);
 1150:       else
 1151: 	new = binfo->attr->aspath;
 1152: 
 1153:       aspath_prepend (aspath, new);
 1154:       binfo->attr->aspath = new;
 1155:     }
 1156: 
 1157:   return RMAP_OKAY;
 1158: }
 1159: 
 1160: /* Compile function for as-path prepend. */
 1161: static void *
 1162: route_set_aspath_prepend_compile (const char *arg)
 1163: {
 1164:   struct aspath *aspath;
 1165: 
 1166:   aspath = aspath_str2aspath (arg);
 1167:   if (! aspath)
 1168:     return NULL;
 1169:   return aspath;
 1170: }
 1171: 
 1172: /* Compile function for as-path prepend. */
 1173: static void
 1174: route_set_aspath_prepend_free (void *rule)
 1175: {
 1176:   struct aspath *aspath = rule;
 1177:   aspath_free (aspath);
 1178: }
 1179: 
 1180: /* Set metric rule structure. */
 1181: struct route_map_rule_cmd route_set_aspath_prepend_cmd = 
 1182: {
 1183:   "as-path prepend",
 1184:   route_set_aspath_prepend,
 1185:   route_set_aspath_prepend_compile,
 1186:   route_set_aspath_prepend_free,
 1187: };
 1188: 
 1189: /* `set as-path exclude ASn' */
 1190: 
 1191: /* For ASN exclude mechanism.
 1192:  * Iterate over ASns requested and filter them from the given AS_PATH one by one.
 1193:  * Make a deep copy of existing AS_PATH, but for the first ASn only.
 1194:  */
 1195: static route_map_result_t
 1196: route_set_aspath_exclude (void *rule, struct prefix *dummy, route_map_object_t type, void *object)
 1197: {
 1198:   struct aspath * new_path, * exclude_path;
 1199:   struct bgp_info *binfo;
 1200: 
 1201:   if (type == RMAP_BGP)
 1202:   {
 1203:     exclude_path = rule;
 1204:     binfo = object;
 1205:     if (binfo->attr->aspath->refcnt)
 1206:       new_path = aspath_dup (binfo->attr->aspath);
 1207:     else
 1208:       new_path = binfo->attr->aspath;
 1209:     binfo->attr->aspath = aspath_filter_exclude (new_path, exclude_path);
 1210:   }
 1211:   return RMAP_OKAY;
 1212: }
 1213: 
 1214: /* FIXME: consider using route_set_aspath_prepend_compile() and
 1215:  * route_set_aspath_prepend_free(), which two below function are
 1216:  * exact clones of.
 1217:  */
 1218: 
 1219: /* Compile function for as-path exclude. */
 1220: static void *
 1221: route_set_aspath_exclude_compile (const char *arg)
 1222: {
 1223:   struct aspath *aspath;
 1224: 
 1225:   aspath = aspath_str2aspath (arg);
 1226:   if (! aspath)
 1227:     return NULL;
 1228:   return aspath;
 1229: }
 1230: 
 1231: static void
 1232: route_set_aspath_exclude_free (void *rule)
 1233: {
 1234:   struct aspath *aspath = rule;
 1235:   aspath_free (aspath);
 1236: }
 1237: 
 1238: /* Set ASn exlude rule structure. */
 1239: struct route_map_rule_cmd route_set_aspath_exclude_cmd = 
 1240: {
 1241:   "as-path exclude",
 1242:   route_set_aspath_exclude,
 1243:   route_set_aspath_exclude_compile,
 1244:   route_set_aspath_exclude_free,
 1245: };
 1246: 
 1247: /* `set community COMMUNITY' */
 1248: struct rmap_com_set
 1249: {
 1250:   struct community *com;
 1251:   int additive;
 1252:   int none;
 1253: };
 1254: 
 1255: /* For community set mechanism. */
 1256: static route_map_result_t
 1257: route_set_community (void *rule, struct prefix *prefix,
 1258: 		     route_map_object_t type, void *object)
 1259: {
 1260:   struct rmap_com_set *rcs;
 1261:   struct bgp_info *binfo;
 1262:   struct attr *attr;
 1263:   struct community *new = NULL;
 1264:   struct community *old;
 1265:   struct community *merge;
 1266:   
 1267:   if (type == RMAP_BGP)
 1268:     {
 1269:       rcs = rule;
 1270:       binfo = object;
 1271:       attr = binfo->attr;
 1272:       old = attr->community;
 1273: 
 1274:       /* "none" case.  */
 1275:       if (rcs->none)
 1276: 	{
 1277: 	  attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
 1278: 	  attr->community = NULL;
 1279: 	  return RMAP_OKAY;
 1280: 	}
 1281: 
 1282:       /* "additive" case.  */
 1283:       if (rcs->additive && old)
 1284: 	{
 1285: 	  merge = community_merge (community_dup (old), rcs->com);
 1286: 	  
 1287: 	  /* HACK: if the old community is not intern'd, 
 1288:            * we should free it here, or all reference to it may be lost.
 1289:            * Really need to cleanup attribute caching sometime.
 1290:            */
 1291: 	  if (old->refcnt == 0)
 1292: 	    community_free (old);
 1293: 	  new = community_uniq_sort (merge);
 1294: 	  community_free (merge);
 1295: 	}
 1296:       else
 1297: 	new = community_dup (rcs->com);
 1298:       
 1299:       /* will be interned by caller if required */
 1300:       attr->community = new;
 1301: 
 1302:       attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
 1303:     }
 1304: 
 1305:   return RMAP_OKAY;
 1306: }
 1307: 
 1308: /* Compile function for set community. */
 1309: static void *
 1310: route_set_community_compile (const char *arg)
 1311: {
 1312:   struct rmap_com_set *rcs;
 1313:   struct community *com = NULL;
 1314:   char *sp;
 1315:   int additive = 0;
 1316:   int none = 0;
 1317:   
 1318:   if (strcmp (arg, "none") == 0)
 1319:     none = 1;
 1320:   else
 1321:     {
 1322:       sp = strstr (arg, "additive");
 1323: 
 1324:       if (sp && sp > arg)
 1325:   	{
 1326: 	  /* "additive" keyworkd is included.  */
 1327: 	  additive = 1;
 1328: 	  *(sp - 1) = '\0';
 1329: 	}
 1330: 
 1331:       com = community_str2com (arg);
 1332: 
 1333:       if (additive)
 1334: 	*(sp - 1) = ' ';
 1335: 
 1336:       if (! com)
 1337: 	return NULL;
 1338:     }
 1339:   
 1340:   rcs = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set));
 1341:   rcs->com = com;
 1342:   rcs->additive = additive;
 1343:   rcs->none = none;
 1344:   
 1345:   return rcs;
 1346: }
 1347: 
 1348: /* Free function for set community. */
 1349: static void
 1350: route_set_community_free (void *rule)
 1351: {
 1352:   struct rmap_com_set *rcs = rule;
 1353: 
 1354:   if (rcs->com)
 1355:     community_free (rcs->com);
 1356:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs);
 1357: }
 1358: 
 1359: /* Set community rule structure. */
 1360: struct route_map_rule_cmd route_set_community_cmd = 
 1361: {
 1362:   "community",
 1363:   route_set_community,
 1364:   route_set_community_compile,
 1365:   route_set_community_free,
 1366: };
 1367: 
 1368: /* `set comm-list (<1-99>|<100-500>|WORD) delete' */
 1369: 
 1370: /* For community set mechanism. */
 1371: static route_map_result_t
 1372: route_set_community_delete (void *rule, struct prefix *prefix,
 1373: 			    route_map_object_t type, void *object)
 1374: {
 1375:   struct community_list *list;
 1376:   struct community *merge;
 1377:   struct community *new;
 1378:   struct community *old;
 1379:   struct bgp_info *binfo;
 1380: 
 1381:   if (type == RMAP_BGP)
 1382:     {
 1383:       if (! rule)
 1384: 	return RMAP_OKAY;
 1385: 
 1386:       binfo = object;
 1387:       list = community_list_lookup (bgp_clist, rule, COMMUNITY_LIST_MASTER);
 1388:       old = binfo->attr->community;
 1389: 
 1390:       if (list && old)
 1391: 	{
 1392: 	  merge = community_list_match_delete (community_dup (old), list);
 1393: 	  new = community_uniq_sort (merge);
 1394: 	  community_free (merge);
 1395: 
 1396: 	  /* HACK: if the old community is not intern'd,
 1397: 	   * we should free it here, or all reference to it may be lost.
 1398: 	   * Really need to cleanup attribute caching sometime.
 1399: 	   */
 1400: 	  if (old->refcnt == 0)
 1401: 	    community_free (old);
 1402: 
 1403: 	  if (new->size == 0)
 1404: 	    {
 1405: 	      binfo->attr->community = NULL;
 1406: 	      binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
 1407: 	      community_free (new);
 1408: 	    }
 1409: 	  else
 1410: 	    {
 1411: 	      binfo->attr->community = new;
 1412: 	      binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
 1413: 	    }
 1414: 	}
 1415:     }
 1416: 
 1417:   return RMAP_OKAY;
 1418: }
 1419: 
 1420: /* Compile function for set community. */
 1421: static void *
 1422: route_set_community_delete_compile (const char *arg)
 1423: {
 1424:   char *p;
 1425:   char *str;
 1426:   int len;
 1427: 
 1428:   p = strchr (arg, ' ');
 1429:   if (p)
 1430:     {
 1431:       len = p - arg;
 1432:       str = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
 1433:       memcpy (str, arg, len);
 1434:     }
 1435:   else
 1436:     str = NULL;
 1437: 
 1438:   return str;
 1439: }
 1440: 
 1441: /* Free function for set community. */
 1442: static void
 1443: route_set_community_delete_free (void *rule)
 1444: {
 1445:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 1446: }
 1447: 
 1448: /* Set community rule structure. */
 1449: struct route_map_rule_cmd route_set_community_delete_cmd =
 1450: {
 1451:   "comm-list",
 1452:   route_set_community_delete,
 1453:   route_set_community_delete_compile,
 1454:   route_set_community_delete_free,
 1455: };
 1456: 
 1457: /* `set extcommunity rt COMMUNITY' */
 1458: 
 1459: /* For community set mechanism. */
 1460: static route_map_result_t
 1461: route_set_ecommunity_rt (void *rule, struct prefix *prefix, 
 1462: 			 route_map_object_t type, void *object)
 1463: {
 1464:   struct ecommunity *ecom;
 1465:   struct ecommunity *new_ecom;
 1466:   struct ecommunity *old_ecom;
 1467:   struct bgp_info *bgp_info;
 1468: 
 1469:   if (type == RMAP_BGP)
 1470:     {
 1471:       ecom = rule;
 1472:       bgp_info = object;
 1473:     
 1474:       if (! ecom)
 1475: 	return RMAP_OKAY;
 1476:     
 1477:       /* We assume additive for Extended Community. */
 1478:       old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;
 1479: 
 1480:       if (old_ecom)
 1481: 	new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
 1482:       else
 1483: 	new_ecom = ecommunity_dup (ecom);
 1484: 
 1485:       bgp_info->attr->extra->ecommunity = ecommunity_intern (new_ecom);
 1486: 
 1487:       if (old_ecom)
 1488: 	ecommunity_unintern (&old_ecom);
 1489: 
 1490:       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
 1491:     }
 1492:   return RMAP_OKAY;
 1493: }
 1494: 
 1495: /* Compile function for set community. */
 1496: static void *
 1497: route_set_ecommunity_rt_compile (const char *arg)
 1498: {
 1499:   struct ecommunity *ecom;
 1500: 
 1501:   ecom = ecommunity_str2com (arg, ECOMMUNITY_ROUTE_TARGET, 0);
 1502:   if (! ecom)
 1503:     return NULL;
 1504:   return ecommunity_intern (ecom);
 1505: }
 1506: 
 1507: /* Free function for set community. */
 1508: static void
 1509: route_set_ecommunity_rt_free (void *rule)
 1510: {
 1511:   struct ecommunity *ecom = rule;
 1512:   ecommunity_unintern (&ecom);
 1513: }
 1514: 
 1515: /* Set community rule structure. */
 1516: struct route_map_rule_cmd route_set_ecommunity_rt_cmd = 
 1517: {
 1518:   "extcommunity rt",
 1519:   route_set_ecommunity_rt,
 1520:   route_set_ecommunity_rt_compile,
 1521:   route_set_ecommunity_rt_free,
 1522: };
 1523: 
 1524: /* `set extcommunity soo COMMUNITY' */
 1525: 
 1526: /* For community set mechanism. */
 1527: static route_map_result_t
 1528: route_set_ecommunity_soo (void *rule, struct prefix *prefix, 
 1529: 			 route_map_object_t type, void *object)
 1530: {
 1531:   struct ecommunity *ecom, *old_ecom, *new_ecom;
 1532:   struct bgp_info *bgp_info;
 1533: 
 1534:   if (type == RMAP_BGP)
 1535:     {
 1536:       ecom = rule;
 1537:       bgp_info = object;
 1538:     
 1539:       if (! ecom)
 1540: 	return RMAP_OKAY;
 1541:     
 1542:       old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;
 1543:       
 1544:       if (old_ecom)
 1545: 	new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
 1546:       else
 1547: 	new_ecom = ecommunity_dup (ecom);
 1548: 
 1549:       bgp_info->attr->extra->ecommunity = ecommunity_intern (new_ecom);
 1550: 
 1551:       if (old_ecom)
 1552: 	ecommunity_unintern (&old_ecom);
 1553: 
 1554:       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
 1555:     }
 1556:   return RMAP_OKAY;
 1557: }
 1558: 
 1559: /* Compile function for set community. */
 1560: static void *
 1561: route_set_ecommunity_soo_compile (const char *arg)
 1562: {
 1563:   struct ecommunity *ecom;
 1564: 
 1565:   ecom = ecommunity_str2com (arg, ECOMMUNITY_SITE_ORIGIN, 0);
 1566:   if (! ecom)
 1567:     return NULL;
 1568:   
 1569:   return ecommunity_intern (ecom);
 1570: }
 1571: 
 1572: /* Free function for set community. */
 1573: static void
 1574: route_set_ecommunity_soo_free (void *rule)
 1575: {
 1576:   struct ecommunity *ecom = rule;
 1577:   ecommunity_unintern (&ecom);
 1578: }
 1579: 
 1580: /* Set community rule structure. */
 1581: struct route_map_rule_cmd route_set_ecommunity_soo_cmd = 
 1582: {
 1583:   "extcommunity soo",
 1584:   route_set_ecommunity_soo,
 1585:   route_set_ecommunity_soo_compile,
 1586:   route_set_ecommunity_soo_free,
 1587: };
 1588: 
 1589: /* `set origin ORIGIN' */
 1590: 
 1591: /* For origin set. */
 1592: static route_map_result_t
 1593: route_set_origin (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
 1594: {
 1595:   u_char *origin;
 1596:   struct bgp_info *bgp_info;
 1597: 
 1598:   if (type == RMAP_BGP)
 1599:     {
 1600:       origin = rule;
 1601:       bgp_info = object;
 1602:     
 1603:       bgp_info->attr->origin = *origin;
 1604:     }
 1605: 
 1606:   return RMAP_OKAY;
 1607: }
 1608: 
 1609: /* Compile function for origin set. */
 1610: static void *
 1611: route_set_origin_compile (const char *arg)
 1612: {
 1613:   u_char *origin;
 1614: 
 1615:   origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char));
 1616: 
 1617:   if (strcmp (arg, "igp") == 0)
 1618:     *origin = 0;
 1619:   else if (strcmp (arg, "egp") == 0)
 1620:     *origin = 1;
 1621:   else
 1622:     *origin = 2;
 1623: 
 1624:   return origin;
 1625: }
 1626: 
 1627: /* Compile function for origin set. */
 1628: static void
 1629: route_set_origin_free (void *rule)
 1630: {
 1631:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 1632: }
 1633: 
 1634: /* Set metric rule structure. */
 1635: struct route_map_rule_cmd route_set_origin_cmd = 
 1636: {
 1637:   "origin",
 1638:   route_set_origin,
 1639:   route_set_origin_compile,
 1640:   route_set_origin_free,
 1641: };
 1642: 
 1643: /* `set atomic-aggregate' */
 1644: 
 1645: /* For atomic aggregate set. */
 1646: static route_map_result_t
 1647: route_set_atomic_aggregate (void *rule, struct prefix *prefix,
 1648: 			    route_map_object_t type, void *object)
 1649: {
 1650:   struct bgp_info *bgp_info;
 1651: 
 1652:   if (type == RMAP_BGP)
 1653:     {
 1654:       bgp_info = object;
 1655:       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
 1656:     }
 1657: 
 1658:   return RMAP_OKAY;
 1659: }
 1660: 
 1661: /* Compile function for atomic aggregate. */
 1662: static void *
 1663: route_set_atomic_aggregate_compile (const char *arg)
 1664: {
 1665:   return (void *)1;
 1666: }
 1667: 
 1668: /* Compile function for atomic aggregate. */
 1669: static void
 1670: route_set_atomic_aggregate_free (void *rule)
 1671: {
 1672:   return;
 1673: }
 1674: 
 1675: /* Set atomic aggregate rule structure. */
 1676: struct route_map_rule_cmd route_set_atomic_aggregate_cmd = 
 1677: {
 1678:   "atomic-aggregate",
 1679:   route_set_atomic_aggregate,
 1680:   route_set_atomic_aggregate_compile,
 1681:   route_set_atomic_aggregate_free,
 1682: };
 1683: 
 1684: /* `set aggregator as AS A.B.C.D' */
 1685: struct aggregator
 1686: {
 1687:   as_t as;
 1688:   struct in_addr address;
 1689: };
 1690: 
 1691: static route_map_result_t
 1692: route_set_aggregator_as (void *rule, struct prefix *prefix, 
 1693: 			 route_map_object_t type, void *object)
 1694: {
 1695:   struct bgp_info *bgp_info;
 1696:   struct aggregator *aggregator;
 1697:   struct attr_extra *ae;
 1698: 
 1699:   if (type == RMAP_BGP)
 1700:     {
 1701:       bgp_info = object;
 1702:       aggregator = rule;
 1703:       ae = bgp_attr_extra_get (bgp_info->attr);
 1704:       
 1705:       ae->aggregator_as = aggregator->as;
 1706:       ae->aggregator_addr = aggregator->address;
 1707:       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
 1708:     }
 1709: 
 1710:   return RMAP_OKAY;
 1711: }
 1712: 
 1713: static void *
 1714: route_set_aggregator_as_compile (const char *arg)
 1715: {
 1716:   struct aggregator *aggregator;
 1717:   char as[10];
 1718:   char address[20];
 1719: 
 1720:   aggregator = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct aggregator));
 1721:   sscanf (arg, "%s %s", as, address);
 1722: 
 1723:   aggregator->as = strtoul (as, NULL, 10);
 1724:   inet_aton (address, &aggregator->address);
 1725: 
 1726:   return aggregator;
 1727: }
 1728: 
 1729: static void
 1730: route_set_aggregator_as_free (void *rule)
 1731: {
 1732:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 1733: }
 1734: 
 1735: struct route_map_rule_cmd route_set_aggregator_as_cmd = 
 1736: {
 1737:   "aggregator as",
 1738:   route_set_aggregator_as,
 1739:   route_set_aggregator_as_compile,
 1740:   route_set_aggregator_as_free,
 1741: };
 1742: 
 1743: #ifdef HAVE_IPV6
 1744: /* `match ipv6 address IP_ACCESS_LIST' */
 1745: 
 1746: static route_map_result_t
 1747: route_match_ipv6_address (void *rule, struct prefix *prefix, 
 1748: 			  route_map_object_t type, void *object)
 1749: {
 1750:   struct access_list *alist;
 1751: 
 1752:   if (type == RMAP_BGP)
 1753:     {
 1754:       alist = access_list_lookup (AFI_IP6, (char *) rule);
 1755:       if (alist == NULL)
 1756: 	return RMAP_NOMATCH;
 1757:     
 1758:       return (access_list_apply (alist, prefix) == FILTER_DENY ?
 1759: 	      RMAP_NOMATCH : RMAP_MATCH);
 1760:     }
 1761:   return RMAP_NOMATCH;
 1762: }
 1763: 
 1764: static void *
 1765: route_match_ipv6_address_compile (const char *arg)
 1766: {
 1767:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
 1768: }
 1769: 
 1770: static void
 1771: route_match_ipv6_address_free (void *rule)
 1772: {
 1773:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 1774: }
 1775: 
 1776: /* Route map commands for ip address matching. */
 1777: struct route_map_rule_cmd route_match_ipv6_address_cmd =
 1778: {
 1779:   "ipv6 address",
 1780:   route_match_ipv6_address,
 1781:   route_match_ipv6_address_compile,
 1782:   route_match_ipv6_address_free
 1783: };
 1784: 
 1785: /* `match ipv6 next-hop IP_ADDRESS' */
 1786: 
 1787: static route_map_result_t
 1788: route_match_ipv6_next_hop (void *rule, struct prefix *prefix, 
 1789: 			   route_map_object_t type, void *object)
 1790: {
 1791:   struct in6_addr *addr;
 1792:   struct bgp_info *bgp_info;
 1793: 
 1794:   if (type == RMAP_BGP)
 1795:     {
 1796:       addr = rule;
 1797:       bgp_info = object;
 1798:       
 1799:       if (!bgp_info->attr->extra)
 1800:         return RMAP_NOMATCH;
 1801:       
 1802:       if (IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_global, rule))
 1803: 	return RMAP_MATCH;
 1804: 
 1805:       if (bgp_info->attr->extra->mp_nexthop_len == 32 &&
 1806: 	  IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_local, rule))
 1807: 	return RMAP_MATCH;
 1808: 
 1809:       return RMAP_NOMATCH;
 1810:     }
 1811: 
 1812:   return RMAP_NOMATCH;
 1813: }
 1814: 
 1815: static void *
 1816: route_match_ipv6_next_hop_compile (const char *arg)
 1817: {
 1818:   struct in6_addr *address;
 1819:   int ret;
 1820: 
 1821:   address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
 1822: 
 1823:   ret = inet_pton (AF_INET6, arg, address);
 1824:   if (!ret)
 1825:     {
 1826:       XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
 1827:       return NULL;
 1828:     }
 1829: 
 1830:   return address;
 1831: }
 1832: 
 1833: static void
 1834: route_match_ipv6_next_hop_free (void *rule)
 1835: {
 1836:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 1837: }
 1838: 
 1839: struct route_map_rule_cmd route_match_ipv6_next_hop_cmd =
 1840: {
 1841:   "ipv6 next-hop",
 1842:   route_match_ipv6_next_hop,
 1843:   route_match_ipv6_next_hop_compile,
 1844:   route_match_ipv6_next_hop_free
 1845: };
 1846: 
 1847: /* `match ipv6 address prefix-list PREFIX_LIST' */
 1848: 
 1849: static route_map_result_t
 1850: route_match_ipv6_address_prefix_list (void *rule, struct prefix *prefix, 
 1851: 			      route_map_object_t type, void *object)
 1852: {
 1853:   struct prefix_list *plist;
 1854: 
 1855:   if (type == RMAP_BGP)
 1856:     {
 1857:       plist = prefix_list_lookup (AFI_IP6, (char *) rule);
 1858:       if (plist == NULL)
 1859: 	return RMAP_NOMATCH;
 1860:     
 1861:       return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
 1862: 	      RMAP_NOMATCH : RMAP_MATCH);
 1863:     }
 1864:   return RMAP_NOMATCH;
 1865: }
 1866: 
 1867: static void *
 1868: route_match_ipv6_address_prefix_list_compile (const char *arg)
 1869: {
 1870:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
 1871: }
 1872: 
 1873: static void
 1874: route_match_ipv6_address_prefix_list_free (void *rule)
 1875: {
 1876:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 1877: }
 1878: 
 1879: struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd =
 1880: {
 1881:   "ipv6 address prefix-list",
 1882:   route_match_ipv6_address_prefix_list,
 1883:   route_match_ipv6_address_prefix_list_compile,
 1884:   route_match_ipv6_address_prefix_list_free
 1885: };
 1886: 
 1887: /* `set ipv6 nexthop global IP_ADDRESS' */
 1888: 
 1889: /* Set nexthop to object.  ojbect must be pointer to struct attr. */
 1890: static route_map_result_t
 1891: route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix, 
 1892: 			       route_map_object_t type, void *object)
 1893: {
 1894:   struct in6_addr *address;
 1895:   struct bgp_info *bgp_info;
 1896: 
 1897:   if (type == RMAP_BGP)
 1898:     {
 1899:       /* Fetch routemap's rule information. */
 1900:       address = rule;
 1901:       bgp_info = object;
 1902:     
 1903:       /* Set next hop value. */ 
 1904:       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = *address;
 1905:     
 1906:       /* Set nexthop length. */
 1907:       if (bgp_info->attr->extra->mp_nexthop_len == 0)
 1908: 	bgp_info->attr->extra->mp_nexthop_len = 16;
 1909:     }
 1910: 
 1911:   return RMAP_OKAY;
 1912: }
 1913: 
 1914: /* Route map `ip next-hop' compile function.  Given string is converted
 1915:    to struct in_addr structure. */
 1916: static void *
 1917: route_set_ipv6_nexthop_global_compile (const char *arg)
 1918: {
 1919:   int ret;
 1920:   struct in6_addr *address;
 1921: 
 1922:   address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
 1923: 
 1924:   ret = inet_pton (AF_INET6, arg, address);
 1925: 
 1926:   if (ret == 0)
 1927:     {
 1928:       XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
 1929:       return NULL;
 1930:     }
 1931: 
 1932:   return address;
 1933: }
 1934: 
 1935: /* Free route map's compiled `ip next-hop' value. */
 1936: static void
 1937: route_set_ipv6_nexthop_global_free (void *rule)
 1938: {
 1939:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 1940: }
 1941: 
 1942: /* Route map commands for ip nexthop set. */
 1943: struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd =
 1944: {
 1945:   "ipv6 next-hop global",
 1946:   route_set_ipv6_nexthop_global,
 1947:   route_set_ipv6_nexthop_global_compile,
 1948:   route_set_ipv6_nexthop_global_free
 1949: };
 1950: 
 1951: /* `set ipv6 nexthop local IP_ADDRESS' */
 1952: 
 1953: /* Set nexthop to object.  ojbect must be pointer to struct attr. */
 1954: static route_map_result_t
 1955: route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix, 
 1956: 			      route_map_object_t type, void *object)
 1957: {
 1958:   struct in6_addr *address;
 1959:   struct bgp_info *bgp_info;
 1960: 
 1961:   if (type == RMAP_BGP)
 1962:     {
 1963:       /* Fetch routemap's rule information. */
 1964:       address = rule;
 1965:       bgp_info = object;
 1966:     
 1967:       /* Set next hop value. */ 
 1968:       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = *address;
 1969:     
 1970:       /* Set nexthop length. */
 1971:       if (bgp_info->attr->extra->mp_nexthop_len != 32)
 1972: 	bgp_info->attr->extra->mp_nexthop_len = 32;
 1973:     }
 1974: 
 1975:   return RMAP_OKAY;
 1976: }
 1977: 
 1978: /* Route map `ip nexthop' compile function.  Given string is converted
 1979:    to struct in_addr structure. */
 1980: static void *
 1981: route_set_ipv6_nexthop_local_compile (const char *arg)
 1982: {
 1983:   int ret;
 1984:   struct in6_addr *address;
 1985: 
 1986:   address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
 1987: 
 1988:   ret = inet_pton (AF_INET6, arg, address);
 1989: 
 1990:   if (ret == 0)
 1991:     {
 1992:       XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
 1993:       return NULL;
 1994:     }
 1995: 
 1996:   return address;
 1997: }
 1998: 
 1999: /* Free route map's compiled `ip nexthop' value. */
 2000: static void
 2001: route_set_ipv6_nexthop_local_free (void *rule)
 2002: {
 2003:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 2004: }
 2005: 
 2006: /* Route map commands for ip nexthop set. */
 2007: struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd =
 2008: {
 2009:   "ipv6 next-hop local",
 2010:   route_set_ipv6_nexthop_local,
 2011:   route_set_ipv6_nexthop_local_compile,
 2012:   route_set_ipv6_nexthop_local_free
 2013: };
 2014: #endif /* HAVE_IPV6 */
 2015: 
 2016: /* `set vpnv4 nexthop A.B.C.D' */
 2017: 
 2018: static route_map_result_t
 2019: route_set_vpnv4_nexthop (void *rule, struct prefix *prefix, 
 2020: 			 route_map_object_t type, void *object)
 2021: {
 2022:   struct in_addr *address;
 2023:   struct bgp_info *bgp_info;
 2024: 
 2025:   if (type == RMAP_BGP)
 2026:     {
 2027:       /* Fetch routemap's rule information. */
 2028:       address = rule;
 2029:       bgp_info = object;
 2030:     
 2031:       /* Set next hop value. */ 
 2032:       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global_in = *address;
 2033:     }
 2034: 
 2035:   return RMAP_OKAY;
 2036: }
 2037: 
 2038: static void *
 2039: route_set_vpnv4_nexthop_compile (const char *arg)
 2040: {
 2041:   int ret;
 2042:   struct in_addr *address;
 2043: 
 2044:   address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
 2045: 
 2046:   ret = inet_aton (arg, address);
 2047: 
 2048:   if (ret == 0)
 2049:     {
 2050:       XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
 2051:       return NULL;
 2052:     }
 2053: 
 2054:   return address;
 2055: }
 2056: 
 2057: static void
 2058: route_set_vpnv4_nexthop_free (void *rule)
 2059: {
 2060:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 2061: }
 2062: 
 2063: /* Route map commands for ip nexthop set. */
 2064: struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd =
 2065: {
 2066:   "vpnv4 next-hop",
 2067:   route_set_vpnv4_nexthop,
 2068:   route_set_vpnv4_nexthop_compile,
 2069:   route_set_vpnv4_nexthop_free
 2070: };
 2071: 
 2072: /* `set originator-id' */
 2073: 
 2074: /* For origin set. */
 2075: static route_map_result_t
 2076: route_set_originator_id (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
 2077: {
 2078:   struct in_addr *address;
 2079:   struct bgp_info *bgp_info;
 2080: 
 2081:   if (type == RMAP_BGP) 
 2082:     {
 2083:       address = rule;
 2084:       bgp_info = object;
 2085:     
 2086:       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
 2087:       (bgp_attr_extra_get (bgp_info->attr))->originator_id = *address;
 2088:     }
 2089: 
 2090:   return RMAP_OKAY;
 2091: }
 2092: 
 2093: /* Compile function for originator-id set. */
 2094: static void *
 2095: route_set_originator_id_compile (const char *arg)
 2096: {
 2097:   int ret;
 2098:   struct in_addr *address;
 2099: 
 2100:   address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
 2101: 
 2102:   ret = inet_aton (arg, address);
 2103: 
 2104:   if (ret == 0)
 2105:     {
 2106:       XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
 2107:       return NULL;
 2108:     }
 2109: 
 2110:   return address;
 2111: }
 2112: 
 2113: /* Compile function for originator_id set. */
 2114: static void
 2115: route_set_originator_id_free (void *rule)
 2116: {
 2117:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 2118: }
 2119: 
 2120: /* Set metric rule structure. */
 2121: struct route_map_rule_cmd route_set_originator_id_cmd = 
 2122: {
 2123:   "originator-id",
 2124:   route_set_originator_id,
 2125:   route_set_originator_id_compile,
 2126:   route_set_originator_id_free,
 2127: };
 2128: 
 2129: /* Add bgp route map rule. */
 2130: static int
 2131: bgp_route_match_add (struct vty *vty, struct route_map_index *index,
 2132: 		     const char *command, const char *arg)
 2133: {
 2134:   int ret;
 2135: 
 2136:   ret = route_map_add_match (index, command, arg);
 2137:   if (ret)
 2138:     {
 2139:       switch (ret)
 2140: 	{
 2141: 	case RMAP_RULE_MISSING:
 2142: 	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
 2143: 	  return CMD_WARNING;
 2144: 	case RMAP_COMPILE_ERROR:
 2145: 	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
 2146: 	  return CMD_WARNING;
 2147: 	}
 2148:     }
 2149:   return CMD_SUCCESS;
 2150: }
 2151: 
 2152: /* Delete bgp route map rule. */
 2153: static int
 2154: bgp_route_match_delete (struct vty *vty, struct route_map_index *index,
 2155: 			const char *command, const char *arg)
 2156: {
 2157:   int ret;
 2158: 
 2159:   ret = route_map_delete_match (index, command, arg);
 2160:   if (ret)
 2161:     {
 2162:       switch (ret)
 2163: 	{
 2164: 	case RMAP_RULE_MISSING:
 2165: 	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
 2166: 	  return CMD_WARNING;
 2167: 	case RMAP_COMPILE_ERROR:
 2168: 	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
 2169: 	  return CMD_WARNING;
 2170: 	}
 2171:     }
 2172:   return CMD_SUCCESS;
 2173: }
 2174: 
 2175: /* Add bgp route map rule. */
 2176: static int
 2177: bgp_route_set_add (struct vty *vty, struct route_map_index *index,
 2178: 		   const char *command, const char *arg)
 2179: {
 2180:   int ret;
 2181: 
 2182:   ret = route_map_add_set (index, command, arg);
 2183:   if (ret)
 2184:     {
 2185:       switch (ret)
 2186: 	{
 2187: 	case RMAP_RULE_MISSING:
 2188: 	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
 2189: 	  return CMD_WARNING;
 2190: 	case RMAP_COMPILE_ERROR:
 2191: 	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
 2192: 	  return CMD_WARNING;
 2193: 	}
 2194:     }
 2195:   return CMD_SUCCESS;
 2196: }
 2197: 
 2198: /* Delete bgp route map rule. */
 2199: static int
 2200: bgp_route_set_delete (struct vty *vty, struct route_map_index *index,
 2201: 		      const char *command, const char *arg)
 2202: {
 2203:   int ret;
 2204: 
 2205:   ret = route_map_delete_set (index, command, arg);
 2206:   if (ret)
 2207:     {
 2208:       switch (ret)
 2209: 	{
 2210: 	case RMAP_RULE_MISSING:
 2211: 	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
 2212: 	  return CMD_WARNING;
 2213: 	case RMAP_COMPILE_ERROR:
 2214: 	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
 2215: 	  return CMD_WARNING;
 2216: 	}
 2217:     }
 2218:   return CMD_SUCCESS;
 2219: }
 2220: 
 2221: /* Hook function for updating route_map assignment. */
 2222: static void
 2223: bgp_route_map_update (const char *unused)
 2224: {
 2225:   int i;
 2226:   afi_t afi;
 2227:   safi_t safi;
 2228:   int direct;
 2229:   struct listnode *node, *nnode;
 2230:   struct listnode *mnode, *mnnode;
 2231:   struct bgp *bgp;
 2232:   struct peer *peer;
 2233:   struct peer_group *group;
 2234:   struct bgp_filter *filter;
 2235:   struct bgp_node *bn;
 2236:   struct bgp_static *bgp_static;
 2237: 
 2238:   /* For neighbor route-map updates. */
 2239:   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
 2240:     {
 2241:       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
 2242: 	{
 2243: 	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
 2244: 	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
 2245: 	      {
 2246: 		filter = &peer->filter[afi][safi];
 2247: 	  
 2248:                for (direct = RMAP_IN; direct < RMAP_MAX; direct++)
 2249: 		  {
 2250: 		    if (filter->map[direct].name)
 2251: 		      filter->map[direct].map = 
 2252: 			route_map_lookup_by_name (filter->map[direct].name);
 2253: 		    else
 2254: 		      filter->map[direct].map = NULL;
 2255: 		  }
 2256: 
 2257: 		if (filter->usmap.name)
 2258: 		  filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
 2259: 		else
 2260: 		  filter->usmap.map = NULL;
 2261: 	      }
 2262: 	}
 2263:       for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
 2264: 	{
 2265: 	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
 2266: 	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
 2267: 	      {
 2268: 		filter = &group->conf->filter[afi][safi];
 2269: 	  
 2270:                for (direct = RMAP_IN; direct < RMAP_MAX; direct++)
 2271: 		  {
 2272: 		    if (filter->map[direct].name)
 2273: 		      filter->map[direct].map = 
 2274: 			route_map_lookup_by_name (filter->map[direct].name);
 2275: 		    else
 2276: 		      filter->map[direct].map = NULL;
 2277: 		  }
 2278: 
 2279: 		if (filter->usmap.name)
 2280: 		  filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
 2281: 		else
 2282: 		  filter->usmap.map = NULL;
 2283: 	      }
 2284: 	}
 2285:     }
 2286: 
 2287:   /* For default-originate route-map updates. */
 2288:   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
 2289:     {
 2290:       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
 2291: 	{
 2292: 	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
 2293: 	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
 2294: 	      {
 2295: 		if (peer->default_rmap[afi][safi].name)
 2296: 		  peer->default_rmap[afi][safi].map =
 2297: 		    route_map_lookup_by_name (peer->default_rmap[afi][safi].name);
 2298: 		else
 2299: 		  peer->default_rmap[afi][safi].map = NULL;
 2300: 	      }
 2301: 	}
 2302:     }
 2303: 
 2304:   /* For network route-map updates. */
 2305:   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
 2306:     {
 2307:       for (afi = AFI_IP; afi < AFI_MAX; afi++)
 2308: 	for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
 2309: 	  for (bn = bgp_table_top (bgp->route[afi][safi]); bn;
 2310: 	       bn = bgp_route_next (bn))
 2311: 	    if ((bgp_static = bn->info) != NULL)
 2312: 	      {
 2313: 		if (bgp_static->rmap.name)
 2314: 		  bgp_static->rmap.map =
 2315: 			 route_map_lookup_by_name (bgp_static->rmap.name);
 2316: 		else
 2317: 		  bgp_static->rmap.map = NULL;
 2318: 	      }
 2319:     }
 2320: 
 2321:   /* For redistribute route-map updates. */
 2322:   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
 2323:     {
 2324:       for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
 2325: 	{
 2326: 	  if (bgp->rmap[ZEBRA_FAMILY_IPV4][i].name)
 2327: 	    bgp->rmap[ZEBRA_FAMILY_IPV4][i].map = 
 2328: 	      route_map_lookup_by_name (bgp->rmap[ZEBRA_FAMILY_IPV4][i].name);
 2329: #ifdef HAVE_IPV6
 2330: 	  if (bgp->rmap[ZEBRA_FAMILY_IPV6][i].name)
 2331: 	    bgp->rmap[ZEBRA_FAMILY_IPV6][i].map =
 2332: 	      route_map_lookup_by_name (bgp->rmap[ZEBRA_FAMILY_IPV6][i].name);
 2333: #endif /* HAVE_IPV6 */
 2334: 	}
 2335:     }
 2336: }
 2337: 
 2338: DEFUN (match_peer,
 2339:        match_peer_cmd,
 2340:        "match peer (A.B.C.D|X:X::X:X)",
 2341:        MATCH_STR
 2342:        "Match peer address\n"
 2343:        "IPv6 address of peer\n"
 2344:        "IP address of peer\n")
 2345: {
 2346:   return bgp_route_match_add (vty, vty->index, "peer", argv[0]);
 2347: }
 2348: 
 2349: DEFUN (match_peer_local,
 2350:         match_peer_local_cmd,
 2351:         "match peer local",
 2352:         MATCH_STR
 2353:         "Match peer address\n"
 2354:         "Static or Redistributed routes\n")
 2355: {
 2356:   return bgp_route_match_add (vty, vty->index, "peer", NULL);
 2357: }
 2358: 
 2359: DEFUN (no_match_peer,
 2360:        no_match_peer_cmd,
 2361:        "no match peer",
 2362:        NO_STR
 2363:        MATCH_STR
 2364:        "Match peer address\n")
 2365: {
 2366:  if (argc == 0)
 2367:    return bgp_route_match_delete (vty, vty->index, "peer", NULL);
 2368: 
 2369:   return bgp_route_match_delete (vty, vty->index, "peer", argv[0]);
 2370: }
 2371: 
 2372: ALIAS (no_match_peer,
 2373:        no_match_peer_val_cmd,
 2374:        "no match peer (A.B.C.D|X:X::X:X)",
 2375:        NO_STR
 2376:        MATCH_STR
 2377:        "Match peer address\n"
 2378:        "IPv6 address of peer\n"
 2379:        "IP address of peer\n")
 2380: 
 2381: ALIAS (no_match_peer,
 2382:        no_match_peer_local_cmd,
 2383:        "no match peer local",
 2384:        NO_STR
 2385:        MATCH_STR
 2386:        "Match peer address\n"
 2387:        "Static or Redistributed routes\n")
 2388: 
 2389: DEFUN (match_ip_address, 
 2390:        match_ip_address_cmd,
 2391:        "match ip address (<1-199>|<1300-2699>|WORD)",
 2392:        MATCH_STR
 2393:        IP_STR
 2394:        "Match address of route\n"
 2395:        "IP access-list number\n"
 2396:        "IP access-list number (expanded range)\n"
 2397:        "IP Access-list name\n")
 2398: {
 2399:   return bgp_route_match_add (vty, vty->index, "ip address", argv[0]);
 2400: }
 2401: 
 2402: DEFUN (no_match_ip_address, 
 2403:        no_match_ip_address_cmd,
 2404:        "no match ip address",
 2405:        NO_STR
 2406:        MATCH_STR
 2407:        IP_STR
 2408:        "Match address of route\n")
 2409: {
 2410:   if (argc == 0)
 2411:     return bgp_route_match_delete (vty, vty->index, "ip address", NULL);
 2412: 
 2413:   return bgp_route_match_delete (vty, vty->index, "ip address", argv[0]);
 2414: }
 2415: 
 2416: ALIAS (no_match_ip_address, 
 2417:        no_match_ip_address_val_cmd,
 2418:        "no match ip address (<1-199>|<1300-2699>|WORD)",
 2419:        NO_STR
 2420:        MATCH_STR
 2421:        IP_STR
 2422:        "Match address of route\n"
 2423:        "IP access-list number\n"
 2424:        "IP access-list number (expanded range)\n"
 2425:        "IP Access-list name\n")
 2426: 
 2427: DEFUN (match_ip_next_hop, 
 2428:        match_ip_next_hop_cmd,
 2429:        "match ip next-hop (<1-199>|<1300-2699>|WORD)",
 2430:        MATCH_STR
 2431:        IP_STR
 2432:        "Match next-hop address of route\n"
 2433:        "IP access-list number\n"
 2434:        "IP access-list number (expanded range)\n"
 2435:        "IP Access-list name\n")
 2436: {
 2437:   return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
 2438: }
 2439: 
 2440: DEFUN (no_match_ip_next_hop,
 2441:        no_match_ip_next_hop_cmd,
 2442:        "no match ip next-hop",
 2443:        NO_STR
 2444:        MATCH_STR
 2445:        IP_STR
 2446:        "Match next-hop address of route\n")
 2447: {
 2448:   if (argc == 0)
 2449:     return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL);
 2450: 
 2451:   return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
 2452: }
 2453: 
 2454: ALIAS (no_match_ip_next_hop,
 2455:        no_match_ip_next_hop_val_cmd,
 2456:        "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
 2457:        NO_STR
 2458:        MATCH_STR
 2459:        IP_STR
 2460:        "Match next-hop address of route\n"
 2461:        "IP access-list number\n"
 2462:        "IP access-list number (expanded range)\n"
 2463:        "IP Access-list name\n")
 2464: 
 2465: DEFUN (match_ip_route_source, 
 2466:        match_ip_route_source_cmd,
 2467:        "match ip route-source (<1-199>|<1300-2699>|WORD)",
 2468:        MATCH_STR
 2469:        IP_STR
 2470:        "Match advertising source address of route\n"
 2471:        "IP access-list number\n"
 2472:        "IP access-list number (expanded range)\n"
 2473:        "IP standard access-list name\n")
 2474: {
 2475:   return bgp_route_match_add (vty, vty->index, "ip route-source", argv[0]);
 2476: }
 2477: 
 2478: DEFUN (no_match_ip_route_source,
 2479:        no_match_ip_route_source_cmd,
 2480:        "no match ip route-source",
 2481:        NO_STR
 2482:        MATCH_STR
 2483:        IP_STR
 2484:        "Match advertising source address of route\n")
 2485: {
 2486:   if (argc == 0)
 2487:     return bgp_route_match_delete (vty, vty->index, "ip route-source", NULL);
 2488: 
 2489:   return bgp_route_match_delete (vty, vty->index, "ip route-source", argv[0]);
 2490: }
 2491: 
 2492: ALIAS (no_match_ip_route_source,
 2493:        no_match_ip_route_source_val_cmd,
 2494:        "no match ip route-source (<1-199>|<1300-2699>|WORD)",
 2495:        NO_STR
 2496:        MATCH_STR
 2497:        IP_STR
 2498:        "Match advertising source address of route\n"
 2499:        "IP access-list number\n"
 2500:        "IP access-list number (expanded range)\n"
 2501:        "IP standard access-list name\n")
 2502: 
 2503: DEFUN (match_ip_address_prefix_list, 
 2504:        match_ip_address_prefix_list_cmd,
 2505:        "match ip address prefix-list WORD",
 2506:        MATCH_STR
 2507:        IP_STR
 2508:        "Match address of route\n"
 2509:        "Match entries of prefix-lists\n"
 2510:        "IP prefix-list name\n")
 2511: {
 2512:   return bgp_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]);
 2513: }
 2514: 
 2515: DEFUN (no_match_ip_address_prefix_list,
 2516:        no_match_ip_address_prefix_list_cmd,
 2517:        "no match ip address prefix-list",
 2518:        NO_STR
 2519:        MATCH_STR
 2520:        IP_STR
 2521:        "Match address of route\n"
 2522:        "Match entries of prefix-lists\n")
 2523: {
 2524:   if (argc == 0)
 2525:     return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
 2526: 
 2527:   return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
 2528: }
 2529: 
 2530: ALIAS (no_match_ip_address_prefix_list,
 2531:        no_match_ip_address_prefix_list_val_cmd,
 2532:        "no match ip address prefix-list WORD",
 2533:        NO_STR
 2534:        MATCH_STR
 2535:        IP_STR
 2536:        "Match address of route\n"
 2537:        "Match entries of prefix-lists\n"
 2538:        "IP prefix-list name\n")
 2539: 
 2540: DEFUN (match_ip_next_hop_prefix_list, 
 2541:        match_ip_next_hop_prefix_list_cmd,
 2542:        "match ip next-hop prefix-list WORD",
 2543:        MATCH_STR
 2544:        IP_STR
 2545:        "Match next-hop address of route\n"
 2546:        "Match entries of prefix-lists\n"
 2547:        "IP prefix-list name\n")
 2548: {
 2549:   return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]);
 2550: }
 2551: 
 2552: DEFUN (no_match_ip_next_hop_prefix_list,
 2553:        no_match_ip_next_hop_prefix_list_cmd,
 2554:        "no match ip next-hop prefix-list",
 2555:        NO_STR
 2556:        MATCH_STR
 2557:        IP_STR
 2558:        "Match next-hop address of route\n"
 2559:        "Match entries of prefix-lists\n")
 2560: {
 2561:   if (argc == 0)
 2562:     return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL);
 2563: 
 2564:   return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]);
 2565: }
 2566: 
 2567: ALIAS (no_match_ip_next_hop_prefix_list,
 2568:        no_match_ip_next_hop_prefix_list_val_cmd,
 2569:        "no match ip next-hop prefix-list WORD",
 2570:        NO_STR
 2571:        MATCH_STR
 2572:        IP_STR
 2573:        "Match next-hop address of route\n"
 2574:        "Match entries of prefix-lists\n"
 2575:        "IP prefix-list name\n")
 2576: 
 2577: DEFUN (match_ip_route_source_prefix_list, 
 2578:        match_ip_route_source_prefix_list_cmd,
 2579:        "match ip route-source prefix-list WORD",
 2580:        MATCH_STR
 2581:        IP_STR
 2582:        "Match advertising source address of route\n"
 2583:        "Match entries of prefix-lists\n"
 2584:        "IP prefix-list name\n")
 2585: {
 2586:   return bgp_route_match_add (vty, vty->index, "ip route-source prefix-list", argv[0]);
 2587: }
 2588: 
 2589: DEFUN (no_match_ip_route_source_prefix_list,
 2590:        no_match_ip_route_source_prefix_list_cmd,
 2591:        "no match ip route-source prefix-list",
 2592:        NO_STR
 2593:        MATCH_STR
 2594:        IP_STR
 2595:        "Match advertising source address of route\n"
 2596:        "Match entries of prefix-lists\n")
 2597: {
 2598:   if (argc == 0)
 2599:     return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", NULL);
 2600: 
 2601:   return bgp_route_match_delete (vty, vty->index, "ip route-source prefix-list", argv[0]);
 2602: }
 2603: 
 2604: ALIAS (no_match_ip_route_source_prefix_list,
 2605:        no_match_ip_route_source_prefix_list_val_cmd,
 2606:        "no match ip route-source prefix-list WORD",
 2607:        NO_STR
 2608:        MATCH_STR
 2609:        IP_STR
 2610:        "Match advertising source address of route\n"
 2611:        "Match entries of prefix-lists\n"
 2612:        "IP prefix-list name\n")
 2613: 
 2614: DEFUN (match_metric, 
 2615:        match_metric_cmd,
 2616:        "match metric <0-4294967295>",
 2617:        MATCH_STR
 2618:        "Match metric of route\n"
 2619:        "Metric value\n")
 2620: {
 2621:   return bgp_route_match_add (vty, vty->index, "metric", argv[0]);
 2622: }
 2623: 
 2624: DEFUN (no_match_metric,
 2625:        no_match_metric_cmd,
 2626:        "no match metric",
 2627:        NO_STR
 2628:        MATCH_STR
 2629:        "Match metric of route\n")
 2630: {
 2631:   if (argc == 0)
 2632:     return bgp_route_match_delete (vty, vty->index, "metric", NULL);
 2633: 
 2634:   return bgp_route_match_delete (vty, vty->index, "metric", argv[0]);
 2635: }
 2636: 
 2637: ALIAS (no_match_metric,
 2638:        no_match_metric_val_cmd,
 2639:        "no match metric <0-4294967295>",
 2640:        NO_STR
 2641:        MATCH_STR
 2642:        "Match metric of route\n"
 2643:        "Metric value\n")
 2644: 
 2645: DEFUN (match_community, 
 2646:        match_community_cmd,
 2647:        "match community (<1-99>|<100-500>|WORD)",
 2648:        MATCH_STR
 2649:        "Match BGP community list\n"
 2650:        "Community-list number (standard)\n"
 2651:        "Community-list number (expanded)\n"
 2652:        "Community-list name\n")
 2653: {
 2654:   return bgp_route_match_add (vty, vty->index, "community", argv[0]);
 2655: }
 2656: 
 2657: DEFUN (match_community_exact, 
 2658:        match_community_exact_cmd,
 2659:        "match community (<1-99>|<100-500>|WORD) exact-match",
 2660:        MATCH_STR
 2661:        "Match BGP community list\n"
 2662:        "Community-list number (standard)\n"
 2663:        "Community-list number (expanded)\n"
 2664:        "Community-list name\n"
 2665:        "Do exact matching of communities\n")
 2666: {
 2667:   int ret;
 2668:   char *argstr;
 2669: 
 2670:   argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
 2671: 		    strlen (argv[0]) + strlen ("exact-match") + 2);
 2672: 
 2673:   sprintf (argstr, "%s exact-match", argv[0]);
 2674: 
 2675:   ret = bgp_route_match_add (vty, vty->index, "community", argstr);
 2676: 
 2677:   XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
 2678: 
 2679:   return ret;
 2680: }
 2681: 
 2682: DEFUN (no_match_community,
 2683:        no_match_community_cmd,
 2684:        "no match community",
 2685:        NO_STR
 2686:        MATCH_STR
 2687:        "Match BGP community list\n")
 2688: {
 2689:   return bgp_route_match_delete (vty, vty->index, "community", NULL);
 2690: }
 2691: 
 2692: ALIAS (no_match_community,
 2693:        no_match_community_val_cmd,
 2694:        "no match community (<1-99>|<100-500>|WORD)",
 2695:        NO_STR
 2696:        MATCH_STR
 2697:        "Match BGP community list\n"
 2698:        "Community-list number (standard)\n"
 2699:        "Community-list number (expanded)\n"
 2700:        "Community-list name\n")
 2701: 
 2702: ALIAS (no_match_community,
 2703:        no_match_community_exact_cmd,
 2704:        "no match community (<1-99>|<100-500>|WORD) exact-match",
 2705:        NO_STR
 2706:        MATCH_STR
 2707:        "Match BGP community list\n"
 2708:        "Community-list number (standard)\n"
 2709:        "Community-list number (expanded)\n"
 2710:        "Community-list name\n"
 2711:        "Do exact matching of communities\n")
 2712: 
 2713: DEFUN (match_ecommunity, 
 2714:        match_ecommunity_cmd,
 2715:        "match extcommunity (<1-99>|<100-500>|WORD)",
 2716:        MATCH_STR
 2717:        "Match BGP/VPN extended community list\n"
 2718:        "Extended community-list number (standard)\n"
 2719:        "Extended community-list number (expanded)\n"
 2720:        "Extended community-list name\n")
 2721: {
 2722:   return bgp_route_match_add (vty, vty->index, "extcommunity", argv[0]);
 2723: }
 2724: 
 2725: DEFUN (no_match_ecommunity,
 2726:        no_match_ecommunity_cmd,
 2727:        "no match extcommunity",
 2728:        NO_STR
 2729:        MATCH_STR
 2730:        "Match BGP/VPN extended community list\n")
 2731: {
 2732:   return bgp_route_match_delete (vty, vty->index, "extcommunity", NULL);
 2733: }
 2734: 
 2735: ALIAS (no_match_ecommunity,
 2736:        no_match_ecommunity_val_cmd,
 2737:        "no match extcommunity (<1-99>|<100-500>|WORD)",
 2738:        NO_STR
 2739:        MATCH_STR
 2740:        "Match BGP/VPN extended community list\n"
 2741:        "Extended community-list number (standard)\n"
 2742:        "Extended community-list number (expanded)\n"
 2743:        "Extended community-list name\n")
 2744: 
 2745: DEFUN (match_aspath,
 2746:        match_aspath_cmd,
 2747:        "match as-path WORD",
 2748:        MATCH_STR
 2749:        "Match BGP AS path list\n"
 2750:        "AS path access-list name\n")
 2751: {
 2752:   return bgp_route_match_add (vty, vty->index, "as-path", argv[0]);
 2753: }
 2754: 
 2755: DEFUN (no_match_aspath,
 2756:        no_match_aspath_cmd,
 2757:        "no match as-path",
 2758:        NO_STR
 2759:        MATCH_STR
 2760:        "Match BGP AS path list\n")
 2761: {
 2762:   return bgp_route_match_delete (vty, vty->index, "as-path", NULL);
 2763: }
 2764: 
 2765: ALIAS (no_match_aspath,
 2766:        no_match_aspath_val_cmd,
 2767:        "no match as-path WORD",
 2768:        NO_STR
 2769:        MATCH_STR
 2770:        "Match BGP AS path list\n"
 2771:        "AS path access-list name\n")
 2772: 
 2773: DEFUN (match_origin,
 2774:        match_origin_cmd,
 2775:        "match origin (egp|igp|incomplete)",
 2776:        MATCH_STR
 2777:        "BGP origin code\n"
 2778:        "remote EGP\n"
 2779:        "local IGP\n"
 2780:        "unknown heritage\n")
 2781: {
 2782:   if (strncmp (argv[0], "igp", 2) == 0)
 2783:     return bgp_route_match_add (vty, vty->index, "origin", "igp");
 2784:   if (strncmp (argv[0], "egp", 1) == 0)
 2785:     return bgp_route_match_add (vty, vty->index, "origin", "egp");
 2786:   if (strncmp (argv[0], "incomplete", 2) == 0)
 2787:     return bgp_route_match_add (vty, vty->index, "origin", "incomplete");
 2788: 
 2789:   return CMD_WARNING;
 2790: }
 2791: 
 2792: DEFUN (no_match_origin,
 2793:        no_match_origin_cmd,
 2794:        "no match origin",
 2795:        NO_STR
 2796:        MATCH_STR
 2797:        "BGP origin code\n")
 2798: {
 2799:   return bgp_route_match_delete (vty, vty->index, "origin", NULL);
 2800: }
 2801: 
 2802: ALIAS (no_match_origin,
 2803:        no_match_origin_val_cmd,
 2804:        "no match origin (egp|igp|incomplete)",
 2805:        NO_STR
 2806:        MATCH_STR
 2807:        "BGP origin code\n"
 2808:        "remote EGP\n"
 2809:        "local IGP\n"
 2810:        "unknown heritage\n")
 2811: 
 2812: DEFUN (set_ip_nexthop,
 2813:        set_ip_nexthop_cmd,
 2814:        "set ip next-hop A.B.C.D",
 2815:        SET_STR
 2816:        IP_STR
 2817:        "Next hop address\n"
 2818:        "IP address of next hop\n")
 2819: {
 2820:   union sockunion su;
 2821:   int ret;
 2822: 
 2823:   ret = str2sockunion (argv[0], &su);
 2824:   if (ret < 0)
 2825:     {
 2826:       vty_out (vty, "%% Malformed Next-hop address%s", VTY_NEWLINE);
 2827:       return CMD_WARNING;
 2828:     }
 2829:  
 2830:   return bgp_route_set_add (vty, vty->index, "ip next-hop", argv[0]);
 2831: }
 2832: 
 2833: DEFUN (set_ip_nexthop_peer,
 2834:        set_ip_nexthop_peer_cmd,
 2835:        "set ip next-hop peer-address",
 2836:        SET_STR
 2837:        IP_STR
 2838:        "Next hop address\n"
 2839:        "Use peer address (for BGP only)\n")
 2840: {
 2841:   return bgp_route_set_add (vty, vty->index, "ip next-hop", "peer-address");
 2842: }
 2843: 
 2844: DEFUN_DEPRECATED (no_set_ip_nexthop_peer,
 2845:        no_set_ip_nexthop_peer_cmd,
 2846:        "no set ip next-hop peer-address",
 2847:        NO_STR
 2848:        SET_STR
 2849:        IP_STR
 2850:        "Next hop address\n"
 2851:        "Use peer address (for BGP only)\n")
 2852: {
 2853:   return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
 2854: }
 2855: 
 2856: 
 2857: DEFUN (no_set_ip_nexthop,
 2858:        no_set_ip_nexthop_cmd,
 2859:        "no set ip next-hop",
 2860:        NO_STR
 2861:        SET_STR
 2862:        "Next hop address\n")
 2863: {
 2864:   if (argc == 0)
 2865:     return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
 2866: 
 2867:   return bgp_route_set_delete (vty, vty->index, "ip next-hop", argv[0]);
 2868: }
 2869: 
 2870: ALIAS (no_set_ip_nexthop,
 2871:        no_set_ip_nexthop_val_cmd,
 2872:        "no set ip next-hop A.B.C.D",
 2873:        NO_STR
 2874:        SET_STR
 2875:        IP_STR
 2876:        "Next hop address\n"
 2877:        "IP address of next hop\n")
 2878: 
 2879: DEFUN (set_metric,
 2880:        set_metric_cmd,
 2881:        "set metric <0-4294967295>",
 2882:        SET_STR
 2883:        "Metric value for destination routing protocol\n"
 2884:        "Metric value\n")
 2885: {
 2886:   return bgp_route_set_add (vty, vty->index, "metric", argv[0]);
 2887: }
 2888: 
 2889: ALIAS (set_metric,
 2890:        set_metric_addsub_cmd,
 2891:        "set metric <+/-metric>",
 2892:        SET_STR
 2893:        "Metric value for destination routing protocol\n"
 2894:        "Add or subtract metric\n")
 2895: 
 2896: DEFUN (no_set_metric,
 2897:        no_set_metric_cmd,
 2898:        "no set metric",
 2899:        NO_STR
 2900:        SET_STR
 2901:        "Metric value for destination routing protocol\n")
 2902: {
 2903:   if (argc == 0)
 2904:     return bgp_route_set_delete (vty, vty->index, "metric", NULL);
 2905: 
 2906:   return bgp_route_set_delete (vty, vty->index, "metric", argv[0]);
 2907: }
 2908: 
 2909: ALIAS (no_set_metric,
 2910:        no_set_metric_val_cmd,
 2911:        "no set metric <0-4294967295>",
 2912:        NO_STR
 2913:        SET_STR
 2914:        "Metric value for destination routing protocol\n"
 2915:        "Metric value\n")
 2916: 
 2917: DEFUN (set_local_pref,
 2918:        set_local_pref_cmd,
 2919:        "set local-preference <0-4294967295>",
 2920:        SET_STR
 2921:        "BGP local preference path attribute\n"
 2922:        "Preference value\n")
 2923: {
 2924:   return bgp_route_set_add (vty, vty->index, "local-preference", argv[0]);
 2925: }
 2926: 
 2927: DEFUN (no_set_local_pref,
 2928:        no_set_local_pref_cmd,
 2929:        "no set local-preference",
 2930:        NO_STR
 2931:        SET_STR
 2932:        "BGP local preference path attribute\n")
 2933: {
 2934:   if (argc == 0)
 2935:     return bgp_route_set_delete (vty, vty->index, "local-preference", NULL);
 2936: 
 2937:   return bgp_route_set_delete (vty, vty->index, "local-preference", argv[0]);
 2938: }
 2939: 
 2940: ALIAS (no_set_local_pref,
 2941:        no_set_local_pref_val_cmd,
 2942:        "no set local-preference <0-4294967295>",
 2943:        NO_STR
 2944:        SET_STR
 2945:        "BGP local preference path attribute\n"
 2946:        "Preference value\n")
 2947: 
 2948: DEFUN (set_weight,
 2949:        set_weight_cmd,
 2950:        "set weight <0-4294967295>",
 2951:        SET_STR
 2952:        "BGP weight for routing table\n"
 2953:        "Weight value\n")
 2954: {
 2955:   return bgp_route_set_add (vty, vty->index, "weight", argv[0]);
 2956: }
 2957: 
 2958: DEFUN (no_set_weight,
 2959:        no_set_weight_cmd,
 2960:        "no set weight",
 2961:        NO_STR
 2962:        SET_STR
 2963:        "BGP weight for routing table\n")
 2964: {
 2965:   if (argc == 0)
 2966:     return bgp_route_set_delete (vty, vty->index, "weight", NULL);
 2967:   
 2968:   return bgp_route_set_delete (vty, vty->index, "weight", argv[0]);
 2969: }
 2970: 
 2971: ALIAS (no_set_weight,
 2972:        no_set_weight_val_cmd,
 2973:        "no set weight <0-4294967295>",
 2974:        NO_STR
 2975:        SET_STR
 2976:        "BGP weight for routing table\n"
 2977:        "Weight value\n")
 2978: 
 2979: DEFUN (set_aspath_prepend,
 2980:        set_aspath_prepend_cmd,
 2981:        "set as-path prepend ." CMD_AS_RANGE,
 2982:        SET_STR
 2983:        "Transform BGP AS_PATH attribute\n"
 2984:        "Prepend to the as-path\n"
 2985:        "AS number\n")
 2986: {
 2987:   int ret;
 2988:   char *str;
 2989: 
 2990:   str = argv_concat (argv, argc, 0);
 2991:   ret = bgp_route_set_add (vty, vty->index, "as-path prepend", str);
 2992:   XFREE (MTYPE_TMP, str);
 2993: 
 2994:   return ret;
 2995: }
 2996: 
 2997: DEFUN (no_set_aspath_prepend,
 2998:        no_set_aspath_prepend_cmd,
 2999:        "no set as-path prepend",
 3000:        NO_STR
 3001:        SET_STR
 3002:        "Transform BGP AS_PATH attribute\n"
 3003:        "Prepend to the as-path\n")
 3004: {
 3005:   int ret;
 3006:   char *str;
 3007: 
 3008:   if (argc == 0)
 3009:     return bgp_route_set_delete (vty, vty->index, "as-path prepend", NULL);
 3010: 
 3011:   str = argv_concat (argv, argc, 0);
 3012:   ret = bgp_route_set_delete (vty, vty->index, "as-path prepend", str);
 3013:   XFREE (MTYPE_TMP, str);
 3014:   return ret;
 3015: }
 3016: 
 3017: ALIAS (no_set_aspath_prepend,
 3018:        no_set_aspath_prepend_val_cmd,
 3019:        "no set as-path prepend ." CMD_AS_RANGE,
 3020:        NO_STR
 3021:        SET_STR
 3022:        "Transform BGP AS_PATH attribute\n"
 3023:        "Prepend to the as-path\n"
 3024:        "AS number\n")
 3025: 
 3026: DEFUN (set_aspath_exclude,
 3027:        set_aspath_exclude_cmd,
 3028:        "set as-path exclude ." CMD_AS_RANGE,
 3029:        SET_STR
 3030:        "Transform BGP AS-path attribute\n"
 3031:        "Exclude from the as-path\n"
 3032:        "AS number\n")
 3033: {
 3034:   int ret;
 3035:   char *str;
 3036: 
 3037:   str = argv_concat (argv, argc, 0);
 3038:   ret = bgp_route_set_add (vty, vty->index, "as-path exclude", str);
 3039:   XFREE (MTYPE_TMP, str);
 3040:   return ret;
 3041: }
 3042: 
 3043: DEFUN (no_set_aspath_exclude,
 3044:        no_set_aspath_exclude_cmd,
 3045:        "no set as-path exclude",
 3046:        NO_STR
 3047:        SET_STR
 3048:        "Transform BGP AS_PATH attribute\n"
 3049:        "Exclude from the as-path\n")
 3050: {
 3051:   int ret;
 3052:   char *str;
 3053: 
 3054:   if (argc == 0)
 3055:     return bgp_route_set_delete (vty, vty->index, "as-path exclude", NULL);
 3056: 
 3057:   str = argv_concat (argv, argc, 0);
 3058:   ret = bgp_route_set_delete (vty, vty->index, "as-path exclude", str);
 3059:   XFREE (MTYPE_TMP, str);
 3060:   return ret;
 3061: }
 3062: 
 3063: ALIAS (no_set_aspath_exclude,
 3064:        no_set_aspath_exclude_val_cmd,
 3065:        "no set as-path exclude ." CMD_AS_RANGE,
 3066:        NO_STR
 3067:        SET_STR
 3068:        "Transform BGP AS_PATH attribute\n"
 3069:        "Exclude from the as-path\n"
 3070:        "AS number\n")
 3071: 
 3072: DEFUN (set_community,
 3073:        set_community_cmd,
 3074:        "set community .AA:NN",
 3075:        SET_STR
 3076:        "BGP community attribute\n"
 3077:        "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
 3078: {
 3079:   int i;
 3080:   int first = 0;
 3081:   int additive = 0;
 3082:   struct buffer *b;
 3083:   struct community *com = NULL;
 3084:   char *str;
 3085:   char *argstr;
 3086:   int ret;
 3087: 
 3088:   b = buffer_new (1024);
 3089: 
 3090:   for (i = 0; i < argc; i++)
 3091:     {
 3092:       if (strncmp (argv[i], "additive", strlen (argv[i])) == 0)
 3093:  	{
 3094:  	  additive = 1;
 3095:  	  continue;
 3096:  	}
 3097: 
 3098:       if (first)
 3099: 	buffer_putc (b, ' ');
 3100:       else
 3101: 	first = 1;
 3102: 
 3103:       if (strncmp (argv[i], "internet", strlen (argv[i])) == 0)
 3104:  	{
 3105: 	  buffer_putstr (b, "internet");
 3106:  	  continue;
 3107:  	}
 3108:       if (strncmp (argv[i], "local-AS", strlen (argv[i])) == 0)
 3109:  	{
 3110: 	  buffer_putstr (b, "local-AS");
 3111:  	  continue;
 3112:  	}
 3113:       if (strncmp (argv[i], "no-a", strlen ("no-a")) == 0
 3114: 	  && strncmp (argv[i], "no-advertise", strlen (argv[i])) == 0)
 3115:  	{
 3116: 	  buffer_putstr (b, "no-advertise");
 3117:  	  continue;
 3118:  	}
 3119:       if (strncmp (argv[i], "no-e", strlen ("no-e"))== 0
 3120: 	  && strncmp (argv[i], "no-export", strlen (argv[i])) == 0)
 3121:  	{
 3122: 	  buffer_putstr (b, "no-export");
 3123:  	  continue;
 3124:  	}
 3125:       buffer_putstr (b, argv[i]);
 3126:     }
 3127:   buffer_putc (b, '\0');
 3128: 
 3129:   /* Fetch result string then compile it to communities attribute.  */
 3130:   str = buffer_getstr (b);
 3131:   buffer_free (b);
 3132: 
 3133:   if (str)
 3134:     {
 3135:       com = community_str2com (str);
 3136:       XFREE (MTYPE_TMP, str);
 3137:     }
 3138: 
 3139:   /* Can't compile user input into communities attribute.  */
 3140:   if (! com)
 3141:     {
 3142:       vty_out (vty, "%% Malformed communities attribute%s", VTY_NEWLINE);
 3143:       return CMD_WARNING;
 3144:     }
 3145: 
 3146:   /* Set communites attribute string.  */
 3147:   str = community_str (com);
 3148: 
 3149:   if (additive)
 3150:     {
 3151:       argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
 3152:       strcpy (argstr, str);
 3153:       strcpy (argstr + strlen (str), " additive");
 3154:       ret =  bgp_route_set_add (vty, vty->index, "community", argstr);
 3155:       XFREE (MTYPE_TMP, argstr);
 3156:     }
 3157:   else
 3158:     ret =  bgp_route_set_add (vty, vty->index, "community", str);
 3159: 
 3160:   community_free (com);
 3161: 
 3162:   return ret;
 3163: }
 3164: 
 3165: DEFUN (set_community_none,
 3166:        set_community_none_cmd,
 3167:        "set community none",
 3168:        SET_STR
 3169:        "BGP community attribute\n"
 3170:        "No community attribute\n")
 3171: {
 3172:   return bgp_route_set_add (vty, vty->index, "community", "none");
 3173: }
 3174: 
 3175: DEFUN (no_set_community,
 3176:        no_set_community_cmd,
 3177:        "no set community",
 3178:        NO_STR
 3179:        SET_STR
 3180:        "BGP community attribute\n")
 3181: {
 3182:   return bgp_route_set_delete (vty, vty->index, "community", NULL);
 3183: }
 3184: 
 3185: ALIAS (no_set_community,
 3186:        no_set_community_val_cmd,
 3187:        "no set community .AA:NN",
 3188:        NO_STR
 3189:        SET_STR
 3190:        "BGP community attribute\n"
 3191:        "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
 3192: 
 3193: ALIAS (no_set_community,
 3194:        no_set_community_none_cmd,
 3195:        "no set community none",
 3196:        NO_STR
 3197:        SET_STR
 3198:        "BGP community attribute\n"
 3199:        "No community attribute\n")
 3200: 
 3201: DEFUN (set_community_delete,
 3202:        set_community_delete_cmd,
 3203:        "set comm-list (<1-99>|<100-500>|WORD) delete",
 3204:        SET_STR
 3205:        "set BGP community list (for deletion)\n"
 3206:        "Community-list number (standard)\n"
 3207:        "Communitly-list number (expanded)\n"
 3208:        "Community-list name\n"
 3209:        "Delete matching communities\n")
 3210: {
 3211:   char *str;
 3212: 
 3213:   str = XCALLOC (MTYPE_TMP, strlen (argv[0]) + strlen (" delete") + 1);
 3214:   strcpy (str, argv[0]);
 3215:   strcpy (str + strlen (argv[0]), " delete");
 3216: 
 3217:   bgp_route_set_add (vty, vty->index, "comm-list", str);
 3218: 
 3219:   XFREE (MTYPE_TMP, str);
 3220:   return CMD_SUCCESS;
 3221: }
 3222: 
 3223: DEFUN (no_set_community_delete,
 3224:        no_set_community_delete_cmd,
 3225:        "no set comm-list",
 3226:        NO_STR
 3227:        SET_STR
 3228:        "set BGP community list (for deletion)\n")
 3229: {
 3230:   return bgp_route_set_delete (vty, vty->index, "comm-list", NULL);
 3231: }
 3232: 
 3233: ALIAS (no_set_community_delete,
 3234:        no_set_community_delete_val_cmd,
 3235:        "no set comm-list (<1-99>|<100-500>|WORD) delete",
 3236:        NO_STR
 3237:        SET_STR
 3238:        "set BGP community list (for deletion)\n"
 3239:        "Community-list number (standard)\n"
 3240:        "Communitly-list number (expanded)\n"
 3241:        "Community-list name\n"
 3242:        "Delete matching communities\n")
 3243: 
 3244: DEFUN (set_ecommunity_rt,
 3245:        set_ecommunity_rt_cmd,
 3246:        "set extcommunity rt .ASN:nn_or_IP-address:nn",
 3247:        SET_STR
 3248:        "BGP extended community attribute\n"
 3249:        "Route Target extended community\n"
 3250:        "VPN extended community\n")
 3251: {
 3252:   int ret;
 3253:   char *str;
 3254: 
 3255:   str = argv_concat (argv, argc, 0);
 3256:   ret = bgp_route_set_add (vty, vty->index, "extcommunity rt", str);
 3257:   XFREE (MTYPE_TMP, str);
 3258: 
 3259:   return ret;
 3260: }
 3261: 
 3262: DEFUN (no_set_ecommunity_rt,
 3263:        no_set_ecommunity_rt_cmd,
 3264:        "no set extcommunity rt",
 3265:        NO_STR
 3266:        SET_STR
 3267:        "BGP extended community attribute\n"
 3268:        "Route Target extended community\n")
 3269: {
 3270:   return bgp_route_set_delete (vty, vty->index, "extcommunity rt", NULL);
 3271: }
 3272: 
 3273: ALIAS (no_set_ecommunity_rt,
 3274:        no_set_ecommunity_rt_val_cmd,
 3275:        "no set extcommunity rt .ASN:nn_or_IP-address:nn",
 3276:        NO_STR
 3277:        SET_STR
 3278:        "BGP extended community attribute\n"
 3279:        "Route Target extended community\n"
 3280:        "VPN extended community\n")
 3281: 
 3282: DEFUN (set_ecommunity_soo,
 3283:        set_ecommunity_soo_cmd,
 3284:        "set extcommunity soo .ASN:nn_or_IP-address:nn",
 3285:        SET_STR
 3286:        "BGP extended community attribute\n"
 3287:        "Site-of-Origin extended community\n"
 3288:        "VPN extended community\n")
 3289: {
 3290:   int ret;
 3291:   char *str;
 3292: 
 3293:   str = argv_concat (argv, argc, 0);
 3294:   ret = bgp_route_set_add (vty, vty->index, "extcommunity soo", str);
 3295:   XFREE (MTYPE_TMP, str);
 3296:   return ret;
 3297: }
 3298: 
 3299: DEFUN (no_set_ecommunity_soo,
 3300:        no_set_ecommunity_soo_cmd,
 3301:        "no set extcommunity soo",
 3302:        NO_STR
 3303:        SET_STR
 3304:        "BGP extended community attribute\n"
 3305:        "Site-of-Origin extended community\n")
 3306: {
 3307:   return bgp_route_set_delete (vty, vty->index, "extcommunity soo", NULL);
 3308: }
 3309: 
 3310: ALIAS (no_set_ecommunity_soo,
 3311:        no_set_ecommunity_soo_val_cmd,
 3312:        "no set extcommunity soo .ASN:nn_or_IP-address:nn",
 3313:        NO_STR
 3314:        SET_STR
 3315:        "BGP extended community attribute\n"
 3316:        "Site-of-Origin extended community\n"
 3317:        "VPN extended community\n")
 3318: 
 3319: DEFUN (set_origin,
 3320:        set_origin_cmd,
 3321:        "set origin (egp|igp|incomplete)",
 3322:        SET_STR
 3323:        "BGP origin code\n"
 3324:        "remote EGP\n"
 3325:        "local IGP\n"
 3326:        "unknown heritage\n")
 3327: {
 3328:   if (strncmp (argv[0], "igp", 2) == 0)
 3329:     return bgp_route_set_add (vty, vty->index, "origin", "igp");
 3330:   if (strncmp (argv[0], "egp", 1) == 0)
 3331:     return bgp_route_set_add (vty, vty->index, "origin", "egp");
 3332:   if (strncmp (argv[0], "incomplete", 2) == 0)
 3333:     return bgp_route_set_add (vty, vty->index, "origin", "incomplete");
 3334: 
 3335:   return CMD_WARNING;
 3336: }
 3337: 
 3338: DEFUN (no_set_origin,
 3339:        no_set_origin_cmd,
 3340:        "no set origin",
 3341:        NO_STR
 3342:        SET_STR
 3343:        "BGP origin code\n")
 3344: {
 3345:   return bgp_route_set_delete (vty, vty->index, "origin", NULL);
 3346: }
 3347: 
 3348: ALIAS (no_set_origin,
 3349:        no_set_origin_val_cmd,
 3350:        "no set origin (egp|igp|incomplete)",
 3351:        NO_STR
 3352:        SET_STR
 3353:        "BGP origin code\n"
 3354:        "remote EGP\n"
 3355:        "local IGP\n"
 3356:        "unknown heritage\n")
 3357: 
 3358: DEFUN (set_atomic_aggregate,
 3359:        set_atomic_aggregate_cmd,
 3360:        "set atomic-aggregate",
 3361:        SET_STR
 3362:        "BGP atomic aggregate attribute\n" )
 3363: {
 3364:   return bgp_route_set_add (vty, vty->index, "atomic-aggregate", NULL);
 3365: }
 3366: 
 3367: DEFUN (no_set_atomic_aggregate,
 3368:        no_set_atomic_aggregate_cmd,
 3369:        "no set atomic-aggregate",
 3370:        NO_STR
 3371:        SET_STR
 3372:        "BGP atomic aggregate attribute\n" )
 3373: {
 3374:   return bgp_route_set_delete (vty, vty->index, "atomic-aggregate", NULL);
 3375: }
 3376: 
 3377: DEFUN (set_aggregator_as,
 3378:        set_aggregator_as_cmd,
 3379:        "set aggregator as " CMD_AS_RANGE " A.B.C.D",
 3380:        SET_STR
 3381:        "BGP aggregator attribute\n"
 3382:        "AS number of aggregator\n"
 3383:        "AS number\n"
 3384:        "IP address of aggregator\n")
 3385: {
 3386:   int ret;
 3387:   as_t as;
 3388:   struct in_addr address;
 3389:   char *argstr;
 3390: 
 3391:   VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
 3392:   
 3393:   ret = inet_aton (argv[1], &address);
 3394:   if (ret == 0)
 3395:     {
 3396:       vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
 3397:       return CMD_WARNING;
 3398:     }
 3399: 
 3400:   argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
 3401: 		    strlen (argv[0]) + strlen (argv[1]) + 2);
 3402: 
 3403:   sprintf (argstr, "%s %s", argv[0], argv[1]);
 3404: 
 3405:   ret = bgp_route_set_add (vty, vty->index, "aggregator as", argstr);
 3406: 
 3407:   XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
 3408: 
 3409:   return ret;
 3410: }
 3411: 
 3412: DEFUN (no_set_aggregator_as,
 3413:        no_set_aggregator_as_cmd,
 3414:        "no set aggregator as",
 3415:        NO_STR
 3416:        SET_STR
 3417:        "BGP aggregator attribute\n"
 3418:        "AS number of aggregator\n")
 3419: {
 3420:   int ret;
 3421:   as_t as;
 3422:   struct in_addr address;
 3423:   char *argstr;
 3424: 
 3425:   if (argv == 0)
 3426:     return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
 3427:   
 3428:   VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
 3429: 
 3430:   ret = inet_aton (argv[1], &address);
 3431:   if (ret == 0)
 3432:     {
 3433:       vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
 3434:       return CMD_WARNING;
 3435:     }
 3436: 
 3437:   argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
 3438: 		    strlen (argv[0]) + strlen (argv[1]) + 2);
 3439: 
 3440:   sprintf (argstr, "%s %s", argv[0], argv[1]);
 3441: 
 3442:   ret = bgp_route_set_delete (vty, vty->index, "aggregator as", argstr);
 3443: 
 3444:   XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
 3445: 
 3446:   return ret;
 3447: }
 3448: 
 3449: ALIAS (no_set_aggregator_as,
 3450:        no_set_aggregator_as_val_cmd,
 3451:        "no set aggregator as " CMD_AS_RANGE " A.B.C.D",
 3452:        NO_STR
 3453:        SET_STR
 3454:        "BGP aggregator attribute\n"
 3455:        "AS number of aggregator\n"
 3456:        "AS number\n"
 3457:        "IP address of aggregator\n")
 3458: 
 3459: 
 3460: #ifdef HAVE_IPV6
 3461: DEFUN (match_ipv6_address, 
 3462:        match_ipv6_address_cmd,
 3463:        "match ipv6 address WORD",
 3464:        MATCH_STR
 3465:        IPV6_STR
 3466:        "Match IPv6 address of route\n"
 3467:        "IPv6 access-list name\n")
 3468: {
 3469:   return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0]);
 3470: }
 3471: 
 3472: DEFUN (no_match_ipv6_address, 
 3473:        no_match_ipv6_address_cmd,
 3474:        "no match ipv6 address WORD",
 3475:        NO_STR
 3476:        MATCH_STR
 3477:        IPV6_STR
 3478:        "Match IPv6 address of route\n"
 3479:        "IPv6 access-list name\n")
 3480: {
 3481:   return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0]);
 3482: }
 3483: 
 3484: DEFUN (match_ipv6_next_hop, 
 3485:        match_ipv6_next_hop_cmd,
 3486:        "match ipv6 next-hop X:X::X:X",
 3487:        MATCH_STR
 3488:        IPV6_STR
 3489:        "Match IPv6 next-hop address of route\n"
 3490:        "IPv6 address of next hop\n")
 3491: {
 3492:   return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0]);
 3493: }
 3494: 
 3495: DEFUN (no_match_ipv6_next_hop,
 3496:        no_match_ipv6_next_hop_cmd,
 3497:        "no match ipv6 next-hop X:X::X:X",
 3498:        NO_STR
 3499:        MATCH_STR
 3500:        IPV6_STR
 3501:        "Match IPv6 next-hop address of route\n"
 3502:        "IPv6 address of next hop\n")
 3503: {
 3504:   return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0]);
 3505: }
 3506: 
 3507: DEFUN (match_ipv6_address_prefix_list, 
 3508:        match_ipv6_address_prefix_list_cmd,
 3509:        "match ipv6 address prefix-list WORD",
 3510:        MATCH_STR
 3511:        IPV6_STR
 3512:        "Match address of route\n"
 3513:        "Match entries of prefix-lists\n"
 3514:        "IP prefix-list name\n")
 3515: {
 3516:   return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list", argv[0]);
 3517: }
 3518: 
 3519: DEFUN (no_match_ipv6_address_prefix_list,
 3520:        no_match_ipv6_address_prefix_list_cmd,
 3521:        "no match ipv6 address prefix-list WORD",
 3522:        NO_STR
 3523:        MATCH_STR
 3524:        IPV6_STR
 3525:        "Match address of route\n"
 3526:        "Match entries of prefix-lists\n"
 3527:        "IP prefix-list name\n")
 3528: {
 3529:   return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]);
 3530: }
 3531: 
 3532: DEFUN (set_ipv6_nexthop_global,
 3533:        set_ipv6_nexthop_global_cmd,
 3534:        "set ipv6 next-hop global X:X::X:X",
 3535:        SET_STR
 3536:        IPV6_STR
 3537:        "IPv6 next-hop address\n"
 3538:        "IPv6 global address\n"
 3539:        "IPv6 address of next hop\n")
 3540: {
 3541:   return bgp_route_set_add (vty, vty->index, "ipv6 next-hop global", argv[0]);
 3542: }
 3543: 
 3544: DEFUN (no_set_ipv6_nexthop_global,
 3545:        no_set_ipv6_nexthop_global_cmd,
 3546:        "no set ipv6 next-hop global",
 3547:        NO_STR
 3548:        SET_STR
 3549:        IPV6_STR
 3550:        "IPv6 next-hop address\n"
 3551:        "IPv6 global address\n")
 3552: {
 3553:   if (argc == 0)
 3554:     return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", NULL);
 3555: 
 3556:   return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", argv[0]);
 3557: }
 3558: 
 3559: ALIAS (no_set_ipv6_nexthop_global,
 3560:        no_set_ipv6_nexthop_global_val_cmd,
 3561:        "no set ipv6 next-hop global X:X::X:X",
 3562:        NO_STR
 3563:        SET_STR
 3564:        IPV6_STR
 3565:        "IPv6 next-hop address\n"
 3566:        "IPv6 global address\n"
 3567:        "IPv6 address of next hop\n")
 3568: 
 3569: DEFUN (set_ipv6_nexthop_local,
 3570:        set_ipv6_nexthop_local_cmd,
 3571:        "set ipv6 next-hop local X:X::X:X",
 3572:        SET_STR
 3573:        IPV6_STR
 3574:        "IPv6 next-hop address\n"
 3575:        "IPv6 local address\n"
 3576:        "IPv6 address of next hop\n")
 3577: {
 3578:   return bgp_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[0]);
 3579: }
 3580: 
 3581: DEFUN (no_set_ipv6_nexthop_local,
 3582:        no_set_ipv6_nexthop_local_cmd,
 3583:        "no set ipv6 next-hop local",
 3584:        NO_STR
 3585:        SET_STR
 3586:        IPV6_STR
 3587:        "IPv6 next-hop address\n"
 3588:        "IPv6 local address\n")
 3589: {
 3590:   if (argc == 0)
 3591:     return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL);
 3592:   
 3593:   return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[0]);
 3594: }
 3595: 
 3596: ALIAS (no_set_ipv6_nexthop_local,
 3597:        no_set_ipv6_nexthop_local_val_cmd,
 3598:        "no set ipv6 next-hop local X:X::X:X",
 3599:        NO_STR
 3600:        SET_STR
 3601:        IPV6_STR
 3602:        "IPv6 next-hop address\n"
 3603:        "IPv6 local address\n"
 3604:        "IPv6 address of next hop\n")
 3605: #endif /* HAVE_IPV6 */
 3606: 
 3607: DEFUN (set_vpnv4_nexthop,
 3608:        set_vpnv4_nexthop_cmd,
 3609:        "set vpnv4 next-hop A.B.C.D",
 3610:        SET_STR
 3611:        "VPNv4 information\n"
 3612:        "VPNv4 next-hop address\n"
 3613:        "IP address of next hop\n")
 3614: {
 3615:   return bgp_route_set_add (vty, vty->index, "vpnv4 next-hop", argv[0]);
 3616: }
 3617: 
 3618: DEFUN (no_set_vpnv4_nexthop,
 3619:        no_set_vpnv4_nexthop_cmd,
 3620:        "no set vpnv4 next-hop",
 3621:        NO_STR
 3622:        SET_STR
 3623:        "VPNv4 information\n"
 3624:        "VPNv4 next-hop address\n")
 3625: {
 3626:   if (argc == 0)
 3627:     return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", NULL);
 3628: 
 3629:   return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", argv[0]);
 3630: }
 3631: 
 3632: ALIAS (no_set_vpnv4_nexthop,
 3633:        no_set_vpnv4_nexthop_val_cmd,
 3634:        "no set vpnv4 next-hop A.B.C.D",
 3635:        NO_STR
 3636:        SET_STR
 3637:        "VPNv4 information\n"
 3638:        "VPNv4 next-hop address\n"
 3639:        "IP address of next hop\n")
 3640: 
 3641: DEFUN (set_originator_id,
 3642:        set_originator_id_cmd,
 3643:        "set originator-id A.B.C.D",
 3644:        SET_STR
 3645:        "BGP originator ID attribute\n"
 3646:        "IP address of originator\n")
 3647: {
 3648:   return bgp_route_set_add (vty, vty->index, "originator-id", argv[0]);
 3649: }
 3650: 
 3651: DEFUN (no_set_originator_id,
 3652:        no_set_originator_id_cmd,
 3653:        "no set originator-id",
 3654:        NO_STR
 3655:        SET_STR
 3656:        "BGP originator ID attribute\n")
 3657: {
 3658:   if (argc == 0)
 3659:     return bgp_route_set_delete (vty, vty->index, "originator-id", NULL);
 3660:   
 3661:   return bgp_route_set_delete (vty, vty->index, "originator-id", argv[0]);
 3662: }
 3663: 
 3664: ALIAS (no_set_originator_id,
 3665:        no_set_originator_id_val_cmd,
 3666:        "no set originator-id A.B.C.D",
 3667:        NO_STR
 3668:        SET_STR
 3669:        "BGP originator ID attribute\n"
 3670:        "IP address of originator\n")
 3671: 
 3672: DEFUN_DEPRECATED (set_pathlimit_ttl,
 3673:        set_pathlimit_ttl_cmd,
 3674:        "set pathlimit ttl <1-255>",
 3675:        SET_STR
 3676:        "BGP AS-Pathlimit attribute\n"
 3677:        "Set AS-Path Hop-count TTL\n")
 3678: {
 3679:   return CMD_SUCCESS;
 3680: }
 3681: 
 3682: DEFUN_DEPRECATED (no_set_pathlimit_ttl,
 3683:        no_set_pathlimit_ttl_cmd,
 3684:        "no set pathlimit ttl",
 3685:        NO_STR
 3686:        SET_STR
 3687:        "BGP AS-Pathlimit attribute\n"
 3688:        "Set AS-Path Hop-count TTL\n")
 3689: {
 3690:   return CMD_SUCCESS;
 3691: }
 3692: 
 3693: ALIAS (no_set_pathlimit_ttl,
 3694:        no_set_pathlimit_ttl_val_cmd,
 3695:        "no set pathlimit ttl <1-255>",
 3696:        NO_STR
 3697:        MATCH_STR
 3698:        "BGP AS-Pathlimit attribute\n"
 3699:        "Set AS-Path Hop-count TTL\n")
 3700: 
 3701: DEFUN_DEPRECATED (match_pathlimit_as,
 3702:        match_pathlimit_as_cmd,
 3703:        "match pathlimit as <1-65535>",
 3704:        MATCH_STR
 3705:        "BGP AS-Pathlimit attribute\n"
 3706:        "Match Pathlimit AS number\n")
 3707: {
 3708:   return CMD_SUCCESS;
 3709: }
 3710: 
 3711: DEFUN_DEPRECATED (no_match_pathlimit_as,
 3712:        no_match_pathlimit_as_cmd,
 3713:        "no match pathlimit as",
 3714:        NO_STR
 3715:        MATCH_STR
 3716:        "BGP AS-Pathlimit attribute\n"
 3717:        "Match Pathlimit AS number\n")
 3718: {
 3719:   return CMD_SUCCESS;
 3720: }
 3721: 
 3722: ALIAS (no_match_pathlimit_as,
 3723:        no_match_pathlimit_as_val_cmd,
 3724:        "no match pathlimit as <1-65535>",
 3725:        NO_STR
 3726:        MATCH_STR
 3727:        "BGP AS-Pathlimit attribute\n"
 3728:        "Match Pathlimit ASN\n")
 3729: 
 3730: 
 3731: /* Initialization of route map. */
 3732: void
 3733: bgp_route_map_init (void)
 3734: {
 3735:   route_map_init ();
 3736:   route_map_init_vty ();
 3737:   route_map_add_hook (bgp_route_map_update);
 3738:   route_map_delete_hook (bgp_route_map_update);
 3739: 
 3740:   route_map_install_match (&route_match_peer_cmd);
 3741:   route_map_install_match (&route_match_ip_address_cmd);
 3742:   route_map_install_match (&route_match_ip_next_hop_cmd);
 3743:   route_map_install_match (&route_match_ip_route_source_cmd);
 3744:   route_map_install_match (&route_match_ip_address_prefix_list_cmd);
 3745:   route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
 3746:   route_map_install_match (&route_match_ip_route_source_prefix_list_cmd);
 3747:   route_map_install_match (&route_match_aspath_cmd);
 3748:   route_map_install_match (&route_match_community_cmd);
 3749:   route_map_install_match (&route_match_ecommunity_cmd);
 3750:   route_map_install_match (&route_match_metric_cmd);
 3751:   route_map_install_match (&route_match_origin_cmd);
 3752: 
 3753:   route_map_install_set (&route_set_ip_nexthop_cmd);
 3754:   route_map_install_set (&route_set_local_pref_cmd);
 3755:   route_map_install_set (&route_set_weight_cmd);
 3756:   route_map_install_set (&route_set_metric_cmd);
 3757:   route_map_install_set (&route_set_aspath_prepend_cmd);
 3758:   route_map_install_set (&route_set_aspath_exclude_cmd);
 3759:   route_map_install_set (&route_set_origin_cmd);
 3760:   route_map_install_set (&route_set_atomic_aggregate_cmd);
 3761:   route_map_install_set (&route_set_aggregator_as_cmd);
 3762:   route_map_install_set (&route_set_community_cmd);
 3763:   route_map_install_set (&route_set_community_delete_cmd);
 3764:   route_map_install_set (&route_set_vpnv4_nexthop_cmd);
 3765:   route_map_install_set (&route_set_originator_id_cmd);
 3766:   route_map_install_set (&route_set_ecommunity_rt_cmd);
 3767:   route_map_install_set (&route_set_ecommunity_soo_cmd);
 3768: 
 3769:   install_element (RMAP_NODE, &match_peer_cmd);
 3770:   install_element (RMAP_NODE, &match_peer_local_cmd);
 3771:   install_element (RMAP_NODE, &no_match_peer_cmd);
 3772:   install_element (RMAP_NODE, &no_match_peer_val_cmd);
 3773:   install_element (RMAP_NODE, &no_match_peer_local_cmd);
 3774:   install_element (RMAP_NODE, &match_ip_address_cmd);
 3775:   install_element (RMAP_NODE, &no_match_ip_address_cmd);
 3776:   install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
 3777:   install_element (RMAP_NODE, &match_ip_next_hop_cmd);
 3778:   install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
 3779:   install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
 3780:   install_element (RMAP_NODE, &match_ip_route_source_cmd);
 3781:   install_element (RMAP_NODE, &no_match_ip_route_source_cmd);
 3782:   install_element (RMAP_NODE, &no_match_ip_route_source_val_cmd);
 3783: 
 3784:   install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
 3785:   install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
 3786:   install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
 3787:   install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
 3788:   install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
 3789:   install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
 3790:   install_element (RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
 3791:   install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
 3792:   install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_val_cmd);
 3793: 
 3794:   install_element (RMAP_NODE, &match_aspath_cmd);
 3795:   install_element (RMAP_NODE, &no_match_aspath_cmd);
 3796:   install_element (RMAP_NODE, &no_match_aspath_val_cmd);
 3797:   install_element (RMAP_NODE, &match_metric_cmd);
 3798:   install_element (RMAP_NODE, &no_match_metric_cmd);
 3799:   install_element (RMAP_NODE, &no_match_metric_val_cmd);
 3800:   install_element (RMAP_NODE, &match_community_cmd);
 3801:   install_element (RMAP_NODE, &match_community_exact_cmd);
 3802:   install_element (RMAP_NODE, &no_match_community_cmd);
 3803:   install_element (RMAP_NODE, &no_match_community_val_cmd);
 3804:   install_element (RMAP_NODE, &no_match_community_exact_cmd);
 3805:   install_element (RMAP_NODE, &match_ecommunity_cmd);
 3806:   install_element (RMAP_NODE, &no_match_ecommunity_cmd);
 3807:   install_element (RMAP_NODE, &no_match_ecommunity_val_cmd);
 3808:   install_element (RMAP_NODE, &match_origin_cmd);
 3809:   install_element (RMAP_NODE, &no_match_origin_cmd);
 3810:   install_element (RMAP_NODE, &no_match_origin_val_cmd);
 3811: 
 3812:   install_element (RMAP_NODE, &set_ip_nexthop_cmd);
 3813:   install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
 3814:   install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
 3815:   install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
 3816:   install_element (RMAP_NODE, &set_local_pref_cmd);
 3817:   install_element (RMAP_NODE, &no_set_local_pref_cmd);
 3818:   install_element (RMAP_NODE, &no_set_local_pref_val_cmd);
 3819:   install_element (RMAP_NODE, &set_weight_cmd);
 3820:   install_element (RMAP_NODE, &no_set_weight_cmd);
 3821:   install_element (RMAP_NODE, &no_set_weight_val_cmd);
 3822:   install_element (RMAP_NODE, &set_metric_cmd);
 3823:   install_element (RMAP_NODE, &set_metric_addsub_cmd);
 3824:   install_element (RMAP_NODE, &no_set_metric_cmd);
 3825:   install_element (RMAP_NODE, &no_set_metric_val_cmd);
 3826:   install_element (RMAP_NODE, &set_aspath_prepend_cmd);
 3827:   install_element (RMAP_NODE, &set_aspath_exclude_cmd);
 3828:   install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
 3829:   install_element (RMAP_NODE, &no_set_aspath_prepend_val_cmd);
 3830:   install_element (RMAP_NODE, &no_set_aspath_exclude_cmd);
 3831:   install_element (RMAP_NODE, &no_set_aspath_exclude_val_cmd);
 3832:   install_element (RMAP_NODE, &set_origin_cmd);
 3833:   install_element (RMAP_NODE, &no_set_origin_cmd);
 3834:   install_element (RMAP_NODE, &no_set_origin_val_cmd);
 3835:   install_element (RMAP_NODE, &set_atomic_aggregate_cmd);
 3836:   install_element (RMAP_NODE, &no_set_atomic_aggregate_cmd);
 3837:   install_element (RMAP_NODE, &set_aggregator_as_cmd);
 3838:   install_element (RMAP_NODE, &no_set_aggregator_as_cmd);
 3839:   install_element (RMAP_NODE, &no_set_aggregator_as_val_cmd);
 3840:   install_element (RMAP_NODE, &set_community_cmd);
 3841:   install_element (RMAP_NODE, &set_community_none_cmd);
 3842:   install_element (RMAP_NODE, &no_set_community_cmd);
 3843:   install_element (RMAP_NODE, &no_set_community_val_cmd);
 3844:   install_element (RMAP_NODE, &no_set_community_none_cmd);
 3845:   install_element (RMAP_NODE, &set_community_delete_cmd);
 3846:   install_element (RMAP_NODE, &no_set_community_delete_cmd);
 3847:   install_element (RMAP_NODE, &no_set_community_delete_val_cmd);
 3848:   install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
 3849:   install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
 3850:   install_element (RMAP_NODE, &no_set_ecommunity_rt_val_cmd);
 3851:   install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
 3852:   install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
 3853:   install_element (RMAP_NODE, &no_set_ecommunity_soo_val_cmd);
 3854:   install_element (RMAP_NODE, &set_vpnv4_nexthop_cmd);
 3855:   install_element (RMAP_NODE, &no_set_vpnv4_nexthop_cmd);
 3856:   install_element (RMAP_NODE, &no_set_vpnv4_nexthop_val_cmd);
 3857:   install_element (RMAP_NODE, &set_originator_id_cmd);
 3858:   install_element (RMAP_NODE, &no_set_originator_id_cmd);
 3859:   install_element (RMAP_NODE, &no_set_originator_id_val_cmd);
 3860: 
 3861: #ifdef HAVE_IPV6
 3862:   route_map_install_match (&route_match_ipv6_address_cmd);
 3863:   route_map_install_match (&route_match_ipv6_next_hop_cmd);
 3864:   route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
 3865:   route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
 3866:   route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
 3867:   
 3868:   install_element (RMAP_NODE, &match_ipv6_address_cmd);
 3869:   install_element (RMAP_NODE, &no_match_ipv6_address_cmd);
 3870:   install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
 3871:   install_element (RMAP_NODE, &no_match_ipv6_next_hop_cmd);
 3872:   install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
 3873:   install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
 3874:   install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd);
 3875:   install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
 3876:   install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_val_cmd);
 3877:   install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
 3878:   install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
 3879:   install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
 3880: #endif /* HAVE_IPV6 */
 3881: 
 3882:   /* AS-Pathlimit: functionality removed, commands kept for
 3883:    * compatibility.
 3884:    */
 3885:   install_element (RMAP_NODE, &set_pathlimit_ttl_cmd);
 3886:   install_element (RMAP_NODE, &no_set_pathlimit_ttl_cmd);
 3887:   install_element (RMAP_NODE, &no_set_pathlimit_ttl_val_cmd);
 3888:   install_element (RMAP_NODE, &match_pathlimit_as_cmd);
 3889:   install_element (RMAP_NODE, &no_match_pathlimit_as_cmd);
 3890:   install_element (RMAP_NODE, &no_match_pathlimit_as_val_cmd);
 3891: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>