Annotation of embedaddon/quagga/bgpd/bgp_routemap.c, revision 1.1

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

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