File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_routemap.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

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

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