File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_routemap.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:38 2013 UTC (10 years, 11 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

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

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