]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_routemap.c
bgpd: Convert `struct bgp_info` to `struct bgp_path_info`
[mirror_frr.git] / bgpd / bgp_routemap.c
CommitLineData
718e3744 1/* Route map function of bgpd.
896014f4
DL
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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
718e3744 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"
1d7c7ace 31#include "lua.h"
25f45887 32#ifdef HAVE_LIBPCREPOSIX
d62a17ae 33#include <pcreposix.h>
718e3744 34#else
d62a17ae 35#include <regex.h>
25f45887 36#endif /* HAVE_LIBPCREPOSIX */
718e3744 37#include "buffer.h"
38#include "sockunion.h"
518f0eb1 39#include "hash.h"
3f9c7369 40#include "queue.h"
5d5ba018 41#include "frrstr.h"
718e3744 42
43#include "bgpd/bgpd.h"
44#include "bgpd/bgp_table.h"
45#include "bgpd/bgp_attr.h"
46#include "bgpd/bgp_aspath.h"
518f0eb1 47#include "bgpd/bgp_packet.h"
718e3744 48#include "bgpd/bgp_route.h"
73ac8160 49#include "bgpd/bgp_zebra.h"
718e3744 50#include "bgpd/bgp_regex.h"
51#include "bgpd/bgp_community.h"
52#include "bgpd/bgp_clist.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_mplsvpn.h"
55#include "bgpd/bgp_ecommunity.h"
57d187bc 56#include "bgpd/bgp_lcommunity.h"
320da874 57#include "bgpd/bgp_vty.h"
73ac8160 58#include "bgpd/bgp_debug.h"
d37ba549
MK
59#include "bgpd/bgp_evpn.h"
60#include "bgpd/bgp_evpn_private.h"
62982d5a 61#include "bgpd/bgp_evpn_vty.h"
ddb5b488 62#include "bgpd/bgp_mplsvpn.h"
718e3744 63
65efcfce 64#if ENABLE_BGP_VNC
d62a17ae 65#include "bgpd/rfapi/bgp_rfapi_cfg.h"
65efcfce 66#endif
518f0eb1 67
718e3744 68/* Memo of route-map commands.
69
70o Cisco route-map
71
72 match as-path : Done
73 community : Done
bc413143 74 interface : Done
718e3744 75 ip address : Done
76 ip next-hop : Done
c1643bb7 77 ip route-source : Done
718e3744 78 ip prefix-list : Done
79 ipv6 address : Done
80 ipv6 next-hop : Done
81 ipv6 route-source: (This will not be implemented by bgpd)
82 ipv6 prefix-list : Done
83 length : (This will not be implemented by bgpd)
84 metric : Done
85 route-type : (This will not be implemented by bgpd)
0d9551dc 86 tag : Done
af291c15 87 local-preference : Done
718e3744 88
89 set as-path prepend : Done
90 as-path tag : Not yet
91 automatic-tag : (This will not be implemented by bgpd)
92 community : Done
57d187bc
JS
93 large-community : Done
94 large-comm-list : Done
718e3744 95 comm-list : Not yet
96 dampning : Not yet
97 default : (This will not be implemented by bgpd)
98 interface : (This will not be implemented by bgpd)
99 ip default : (This will not be implemented by bgpd)
100 ip next-hop : Done
101 ip precedence : (This will not be implemented by bgpd)
102 ip tos : (This will not be implemented by bgpd)
103 level : (This will not be implemented by bgpd)
104 local-preference : Done
105 metric : Done
106 metric-type : Not yet
107 origin : Done
0d9551dc 108 tag : Done
718e3744 109 weight : Done
110
515e500c 111o Local extensions
718e3744 112
113 set ipv6 next-hop global: Done
161995ea 114 set ipv6 next-hop prefer-global: Done
718e3744 115 set ipv6 next-hop local : Done
841f7a57 116 set as-path exclude : Done
718e3744 117
e52702f2 118*/
6b0655a2 119
d62a17ae 120/* generic value manipulation to be shared in multiple rules */
76759f4f
TT
121
122#define RMAP_VALUE_SET 0
123#define RMAP_VALUE_ADD 1
124#define RMAP_VALUE_SUB 2
125
d62a17ae 126struct rmap_value {
d7c0a89a
QY
127 uint8_t action;
128 uint8_t variable;
129 uint32_t value;
76759f4f
TT
130};
131
d7c0a89a 132static int route_value_match(struct rmap_value *rv, uint32_t value)
d62a17ae 133{
134 if (rv->variable == 0 && value == rv->value)
135 return RMAP_MATCH;
76759f4f 136
d62a17ae 137 return RMAP_NOMATCH;
76759f4f
TT
138}
139
d7c0a89a
QY
140static uint32_t route_value_adjust(struct rmap_value *rv, uint32_t current,
141 struct peer *peer)
76759f4f 142{
d7c0a89a 143 uint32_t value;
baa376fc 144
d62a17ae 145 switch (rv->variable) {
146 case 1:
147 value = peer->rtt;
148 break;
149 default:
150 value = rv->value;
151 break;
152 }
76759f4f 153
d62a17ae 154 switch (rv->action) {
155 case RMAP_VALUE_ADD:
156 if (current > UINT32_MAX - value)
157 return UINT32_MAX;
158 return current + value;
159 case RMAP_VALUE_SUB:
160 if (current <= value)
161 return 0;
162 return current - value;
163 default:
164 return value;
165 }
76759f4f
TT
166}
167
d62a17ae 168static void *route_value_compile(const char *arg)
76759f4f 169{
d7c0a89a 170 uint8_t action = RMAP_VALUE_SET, var = 0;
d62a17ae 171 unsigned long larg = 0;
172 char *endptr = NULL;
173 struct rmap_value *rv;
76759f4f 174
d62a17ae 175 if (arg[0] == '+') {
176 action = RMAP_VALUE_ADD;
177 arg++;
178 } else if (arg[0] == '-') {
179 action = RMAP_VALUE_SUB;
180 arg++;
181 }
76759f4f 182
d62a17ae 183 if (all_digit(arg)) {
184 errno = 0;
185 larg = strtoul(arg, &endptr, 10);
186 if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
187 return NULL;
188 } else {
189 if (strcmp(arg, "rtt") == 0)
190 var = 1;
191 else
192 return NULL;
193 }
76759f4f 194
d62a17ae 195 rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
196 if (!rv)
197 return NULL;
76759f4f 198
d62a17ae 199 rv->action = action;
200 rv->variable = var;
201 rv->value = larg;
202 return rv;
76759f4f
TT
203}
204
d62a17ae 205static void route_value_free(void *rule)
76759f4f 206{
d62a17ae 207 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
76759f4f
TT
208}
209
d62a17ae 210/* generic as path object to be shared in multiple rules */
374f12f9 211
d62a17ae 212static void *route_aspath_compile(const char *arg)
374f12f9 213{
d62a17ae 214 struct aspath *aspath;
374f12f9 215
d62a17ae 216 aspath = aspath_str2aspath(arg);
217 if (!aspath)
218 return NULL;
219 return aspath;
374f12f9
TT
220}
221
d62a17ae 222static void route_aspath_free(void *rule)
374f12f9 223{
d62a17ae 224 struct aspath *aspath = rule;
225 aspath_free(aspath);
374f12f9
TT
226}
227
8c3433e4
DS
228struct bgp_match_peer_compiled {
229 char *interface;
230 union sockunion su;
231};
232
233/* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
fee0f4c6 234
235/* Compares the peer specified in the 'match peer' clause with the peer
236 received in bgp_info->peer. If it is the same, or if the peer structure
237 received is a peer_group containing it, returns RMAP_MATCH. */
123214ef
MS
238static route_map_result_t route_match_peer(void *rule,
239 const struct prefix *prefix,
d62a17ae 240 route_map_object_t type,
241 void *object)
242{
8c3433e4 243 struct bgp_match_peer_compiled *pc;
d62a17ae 244 union sockunion *su;
245 union sockunion su_def = {
246 .sin = {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY}};
247 struct peer_group *group;
248 struct peer *peer;
249 struct listnode *node, *nnode;
250
251 if (type == RMAP_BGP) {
8c3433e4
DS
252 pc = rule;
253 su = &pc->su;
4b7e6066 254 peer = ((struct bgp_path_info *)object)->peer;
d62a17ae 255
8c3433e4
DS
256 if (pc->interface) {
257 if (!peer->conf_if)
258 return RMAP_NOMATCH;
259
260 if (strcmp(peer->conf_if, pc->interface) == 0)
261 return RMAP_MATCH;
262
263 return RMAP_NOMATCH;
264 }
265
d62a17ae 266 /* If su='0.0.0.0' (command 'match peer local'), and it's a
267 NETWORK,
268 REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH
269 */
270 if (sockunion_same(su, &su_def)) {
271 int ret;
272 if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
273 || CHECK_FLAG(peer->rmap_type,
274 PEER_RMAP_TYPE_REDISTRIBUTE)
275 || CHECK_FLAG(peer->rmap_type,
276 PEER_RMAP_TYPE_DEFAULT))
277 ret = RMAP_MATCH;
278 else
279 ret = RMAP_NOMATCH;
280 return ret;
281 }
282
283 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
284 if (sockunion_same(su, &peer->su))
285 return RMAP_MATCH;
286
287 return RMAP_NOMATCH;
288 } else {
289 group = peer->group;
290 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
291 peer)) {
292 if (sockunion_same(su, &peer->su))
293 return RMAP_MATCH;
294 }
295 return RMAP_NOMATCH;
296 }
297 }
298 return RMAP_NOMATCH;
299}
300
301static void *route_match_peer_compile(const char *arg)
302{
8c3433e4 303 struct bgp_match_peer_compiled *pc;
d62a17ae 304 int ret;
305
a633d869 306 pc = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
8c3433e4 307 sizeof(struct bgp_match_peer_compiled));
d62a17ae 308
8c3433e4 309 ret = str2sockunion(strcmp(arg, "local") ? arg : "0.0.0.0", &pc->su);
d62a17ae 310 if (ret < 0) {
8c3433e4
DS
311 pc->interface = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
312 return pc;
d62a17ae 313 }
314
8c3433e4 315 return pc;
fee0f4c6 316}
317
318/* Free route map's compiled `ip address' value. */
d62a17ae 319static void route_match_peer_free(void *rule)
fee0f4c6 320{
8c3433e4
DS
321 struct bgp_match_peer_compiled *pc = rule;
322
323 if (pc->interface)
324 XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
325
d62a17ae 326 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
fee0f4c6 327}
328
329/* Route map commands for ip address matching. */
d62a17ae 330struct route_map_rule_cmd route_match_peer_cmd = {"peer", route_match_peer,
331 route_match_peer_compile,
332 route_match_peer_free};
fee0f4c6 333
1d7c7ace
DS
334#if defined(HAVE_LUA)
335static route_map_result_t route_match_command(void *rule,
336 const struct prefix *prefix,
337 route_map_object_t type,
338 void *object)
339{
340 int status = RMAP_NOMATCH;
341 u_int32_t locpref = 0;
342 u_int32_t newlocpref = 0;
343 enum lua_rm_status lrm_status;
4b7e6066 344 struct bgp_path_info *info = (struct bgp_path_info *)object;
1d7c7ace
DS
345 lua_State *L = lua_initialize("/etc/frr/lua.scr");
346
347 if (L == NULL)
348 return status;
349
350 /*
351 * Setup the prefix information to pass in
352 */
353 lua_setup_prefix_table(L, prefix);
354
355 zlog_debug("Set up prefix table");
356 /*
357 * Setup the bgp_info information
358 */
359 lua_newtable(L);
360 lua_pushinteger(L, info->attr->med);
361 lua_setfield(L, -2, "metric");
362 lua_pushinteger(L, info->attr->nh_ifindex);
363 lua_setfield(L, -2, "ifindex");
364 lua_pushstring(L, info->attr->aspath->str);
365 lua_setfield(L, -2, "aspath");
366 lua_pushinteger(L, info->attr->local_pref);
367 lua_setfield(L, -2, "localpref");
368 zlog_debug("%s %d", info->attr->aspath->str, info->attr->nh_ifindex);
369 lua_setglobal(L, "nexthop");
370
371 zlog_debug("Set up nexthop information");
372 /*
373 * Run the rule
374 */
375 lrm_status = lua_run_rm_rule(L, rule);
376 switch (lrm_status) {
377 case LUA_RM_FAILURE:
378 zlog_debug("RM_FAILURE");
379 break;
380 case LUA_RM_NOMATCH:
381 zlog_debug("RM_NOMATCH");
382 break;
383 case LUA_RM_MATCH_AND_CHANGE:
384 zlog_debug("MATCH AND CHANGE");
385 lua_getglobal(L, "nexthop");
386 info->attr->med = get_integer(L, "metric");
387 /*
388 * This needs to be abstraced with the set function
389 */
390 if (info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
391 locpref = info->attr->local_pref;
392 newlocpref = get_integer(L, "localpref");
393 if (newlocpref != locpref) {
394 info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
395 info->attr->local_pref = newlocpref;
396 }
397 status = RMAP_MATCH;
398 break;
399 case LUA_RM_MATCH:
400 zlog_debug("MATCH ONLY");
401 status = RMAP_MATCH;
402 break;
403 }
404 lua_close(L);
405 return status;
406}
407
408static void *route_match_command_compile(const char *arg)
409{
410 char *command;
411
412 command = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
413 return command;
414}
415
416static void
417route_match_command_free(void *rule)
418{
419 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
420}
421
422struct route_map_rule_cmd route_match_command_cmd = {
423 "command",
424 route_match_command,
425 route_match_command_compile,
426 route_match_command_free
427};
428#endif
429
718e3744 430/* `match ip address IP_ACCESS_LIST' */
431
432/* Match function should return 1 if match is success else return
433 zero. */
d62a17ae 434static route_map_result_t route_match_ip_address(void *rule,
123214ef 435 const struct prefix *prefix,
d62a17ae 436 route_map_object_t type,
437 void *object)
438{
439 struct access_list *alist;
d62a17ae 440
09cd98eb 441 if (type == RMAP_BGP && prefix->family == AF_INET) {
d62a17ae 442 alist = access_list_lookup(AFI_IP, (char *)rule);
443 if (alist == NULL)
444 return RMAP_NOMATCH;
445
446 return (access_list_apply(alist, prefix) == FILTER_DENY
447 ? RMAP_NOMATCH
448 : RMAP_MATCH);
449 }
718e3744 450 return RMAP_NOMATCH;
718e3744 451}
452
453/* Route map `ip address' match statement. `arg' should be
454 access-list name. */
d62a17ae 455static void *route_match_ip_address_compile(const char *arg)
718e3744 456{
d62a17ae 457 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 458}
459
460/* Free route map's compiled `ip address' value. */
d62a17ae 461static void route_match_ip_address_free(void *rule)
718e3744 462{
d62a17ae 463 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 464}
465
466/* Route map commands for ip address matching. */
d62a17ae 467struct route_map_rule_cmd route_match_ip_address_cmd = {
468 "ip address", route_match_ip_address, route_match_ip_address_compile,
469 route_match_ip_address_free};
6b0655a2 470
718e3744 471/* `match ip next-hop IP_ADDRESS' */
472
473/* Match function return 1 if match is success else return zero. */
d62a17ae 474static route_map_result_t route_match_ip_next_hop(void *rule,
123214ef 475 const struct prefix *prefix,
d62a17ae 476 route_map_object_t type,
477 void *object)
478{
479 struct access_list *alist;
4b7e6066 480 struct bgp_path_info *bgp_info;
d62a17ae 481 struct prefix_ipv4 p;
482
09cd98eb 483 if (type == RMAP_BGP && prefix->family == AF_INET) {
d62a17ae 484 bgp_info = object;
485 p.family = AF_INET;
486 p.prefix = bgp_info->attr->nexthop;
487 p.prefixlen = IPV4_MAX_BITLEN;
488
489 alist = access_list_lookup(AFI_IP, (char *)rule);
490 if (alist == NULL)
491 return RMAP_NOMATCH;
492
493 return (access_list_apply(alist, &p) == FILTER_DENY
494 ? RMAP_NOMATCH
495 : RMAP_MATCH);
496 }
718e3744 497 return RMAP_NOMATCH;
718e3744 498}
499
500/* Route map `ip next-hop' match statement. `arg' is
501 access-list name. */
d62a17ae 502static void *route_match_ip_next_hop_compile(const char *arg)
718e3744 503{
d62a17ae 504 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 505}
506
507/* Free route map's compiled `ip address' value. */
d62a17ae 508static void route_match_ip_next_hop_free(void *rule)
718e3744 509{
d62a17ae 510 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 511}
512
513/* Route map commands for ip next-hop matching. */
d62a17ae 514struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
515 "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile,
516 route_match_ip_next_hop_free};
6b0655a2 517
c1643bb7 518/* `match ip route-source ACCESS-LIST' */
519
520/* Match function return 1 if match is success else return zero. */
d62a17ae 521static route_map_result_t route_match_ip_route_source(void *rule,
123214ef 522 const struct prefix *pfx,
d62a17ae 523 route_map_object_t type,
524 void *object)
525{
526 struct access_list *alist;
4b7e6066 527 struct bgp_path_info *bgp_info;
d62a17ae 528 struct peer *peer;
529 struct prefix_ipv4 p;
530
123214ef 531 if (type == RMAP_BGP && pfx->family == AF_INET) {
d62a17ae 532 bgp_info = object;
533 peer = bgp_info->peer;
534
535 if (!peer || sockunion_family(&peer->su) != AF_INET)
536 return RMAP_NOMATCH;
537
538 p.family = AF_INET;
539 p.prefix = peer->su.sin.sin_addr;
540 p.prefixlen = IPV4_MAX_BITLEN;
541
542 alist = access_list_lookup(AFI_IP, (char *)rule);
543 if (alist == NULL)
544 return RMAP_NOMATCH;
545
546 return (access_list_apply(alist, &p) == FILTER_DENY
547 ? RMAP_NOMATCH
548 : RMAP_MATCH);
549 }
c1643bb7 550 return RMAP_NOMATCH;
c1643bb7 551}
552
553/* Route map `ip route-source' match statement. `arg' is
554 access-list name. */
d62a17ae 555static void *route_match_ip_route_source_compile(const char *arg)
c1643bb7 556{
d62a17ae 557 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
c1643bb7 558}
559
560/* Free route map's compiled `ip address' value. */
d62a17ae 561static void route_match_ip_route_source_free(void *rule)
c1643bb7 562{
d62a17ae 563 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
c1643bb7 564}
565
566/* Route map commands for ip route-source matching. */
d62a17ae 567struct route_map_rule_cmd route_match_ip_route_source_cmd = {
568 "ip route-source", route_match_ip_route_source,
569 route_match_ip_route_source_compile, route_match_ip_route_source_free};
6b0655a2 570
718e3744 571/* `match ip address prefix-list PREFIX_LIST' */
572
94f2b392 573static route_map_result_t
123214ef 574route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
d62a17ae 575 route_map_object_t type, void *object)
718e3744 576{
d62a17ae 577 struct prefix_list *plist;
718e3744 578
09cd98eb 579 if (type == RMAP_BGP && prefix->family == AF_INET) {
d62a17ae 580 plist = prefix_list_lookup(AFI_IP, (char *)rule);
581 if (plist == NULL)
582 return RMAP_NOMATCH;
e52702f2 583
d62a17ae 584 return (prefix_list_apply(plist, prefix) == PREFIX_DENY
585 ? RMAP_NOMATCH
586 : RMAP_MATCH);
587 }
588 return RMAP_NOMATCH;
718e3744 589}
590
d62a17ae 591static void *route_match_ip_address_prefix_list_compile(const char *arg)
718e3744 592{
d62a17ae 593 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 594}
595
d62a17ae 596static void route_match_ip_address_prefix_list_free(void *rule)
718e3744 597{
d62a17ae 598 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 599}
600
d62a17ae 601struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
602 "ip address prefix-list", route_match_ip_address_prefix_list,
603 route_match_ip_address_prefix_list_compile,
604 route_match_ip_address_prefix_list_free};
6b0655a2 605
718e3744 606/* `match ip next-hop prefix-list PREFIX_LIST' */
607
94f2b392 608static route_map_result_t
123214ef 609route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
d62a17ae 610 route_map_object_t type, void *object)
718e3744 611{
d62a17ae 612 struct prefix_list *plist;
4b7e6066 613 struct bgp_path_info *bgp_info;
d62a17ae 614 struct prefix_ipv4 p;
718e3744 615
09cd98eb 616 if (type == RMAP_BGP && prefix->family == AF_INET) {
d62a17ae 617 bgp_info = object;
618 p.family = AF_INET;
619 p.prefix = bgp_info->attr->nexthop;
620 p.prefixlen = IPV4_MAX_BITLEN;
718e3744 621
d62a17ae 622 plist = prefix_list_lookup(AFI_IP, (char *)rule);
623 if (plist == NULL)
624 return RMAP_NOMATCH;
718e3744 625
d62a17ae 626 return (prefix_list_apply(plist, &p) == PREFIX_DENY
627 ? RMAP_NOMATCH
628 : RMAP_MATCH);
629 }
630 return RMAP_NOMATCH;
718e3744 631}
632
d62a17ae 633static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
718e3744 634{
d62a17ae 635 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 636}
637
d62a17ae 638static void route_match_ip_next_hop_prefix_list_free(void *rule)
718e3744 639{
d62a17ae 640 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 641}
642
d62a17ae 643struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
644 "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list,
645 route_match_ip_next_hop_prefix_list_compile,
646 route_match_ip_next_hop_prefix_list_free};
6b0655a2 647
61ad901e
DA
648/* `match ip next-hop type <blackhole>' */
649
650static route_map_result_t
651route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
652 route_map_object_t type, void *object)
653{
4b7e6066 654 struct bgp_path_info *bgp_info;
61ad901e
DA
655
656 if (type == RMAP_BGP && prefix->family == AF_INET) {
4b7e6066 657 bgp_info = (struct bgp_path_info *)object;
61ad901e
DA
658 if (!bgp_info || !bgp_info->attr)
659 return RMAP_DENYMATCH;
660
661 /* If nexthop interface's index can't be resolved and nexthop is
662 set to any address then mark it as type `blackhole`.
663 This logic works for matching kernel/static routes like:
664 `ip route add blackhole 10.0.0.1`. */
665 if (bgp_info->attr->nexthop.s_addr == INADDR_ANY
666 && !bgp_info->attr->nh_ifindex)
667 return RMAP_MATCH;
668 }
669 return RMAP_NOMATCH;
670}
671
672static void *route_match_ip_next_hop_type_compile(const char *arg)
673{
674 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
675}
676
677static void route_match_ip_next_hop_type_free(void *rule)
678{
679 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
680}
681
682static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = {
683 "ip next-hop type", route_match_ip_next_hop_type,
684 route_match_ip_next_hop_type_compile,
685 route_match_ip_next_hop_type_free};
686
c1643bb7 687/* `match ip route-source prefix-list PREFIX_LIST' */
688
94f2b392 689static route_map_result_t
123214ef
MS
690route_match_ip_route_source_prefix_list(void *rule,
691 const struct prefix *prefix,
d62a17ae 692 route_map_object_t type, void *object)
c1643bb7 693{
d62a17ae 694 struct prefix_list *plist;
4b7e6066 695 struct bgp_path_info *bgp_info;
d62a17ae 696 struct peer *peer;
697 struct prefix_ipv4 p;
c1643bb7 698
09cd98eb 699 if (type == RMAP_BGP && prefix->family == AF_INET) {
d62a17ae 700 bgp_info = object;
701 peer = bgp_info->peer;
c1643bb7 702
d62a17ae 703 if (!peer || sockunion_family(&peer->su) != AF_INET)
704 return RMAP_NOMATCH;
c1643bb7 705
d62a17ae 706 p.family = AF_INET;
707 p.prefix = peer->su.sin.sin_addr;
708 p.prefixlen = IPV4_MAX_BITLEN;
c1643bb7 709
d62a17ae 710 plist = prefix_list_lookup(AFI_IP, (char *)rule);
711 if (plist == NULL)
712 return RMAP_NOMATCH;
c1643bb7 713
d62a17ae 714 return (prefix_list_apply(plist, &p) == PREFIX_DENY
715 ? RMAP_NOMATCH
716 : RMAP_MATCH);
717 }
718 return RMAP_NOMATCH;
c1643bb7 719}
720
d62a17ae 721static void *route_match_ip_route_source_prefix_list_compile(const char *arg)
c1643bb7 722{
d62a17ae 723 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
c1643bb7 724}
725
d62a17ae 726static void route_match_ip_route_source_prefix_list_free(void *rule)
c1643bb7 727{
d62a17ae 728 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
c1643bb7 729}
730
d62a17ae 731struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = {
732 "ip route-source prefix-list", route_match_ip_route_source_prefix_list,
733 route_match_ip_route_source_prefix_list_compile,
734 route_match_ip_route_source_prefix_list_free};
6b0655a2 735
6fb219da
MK
736/* `match evpn default-route' */
737
738/* Match function should return 1 if match is success else 0 */
739static route_map_result_t route_match_evpn_default_route(void *rule,
123214ef 740 const struct prefix *p,
6fb219da
MK
741 route_map_object_t
742 type, void *object)
743{
744 if (type == RMAP_BGP && is_evpn_prefix_default(p))
745 return RMAP_MATCH;
746
747 return RMAP_NOMATCH;
748}
749
750/* Route map commands for default-route matching. */
751struct route_map_rule_cmd route_match_evpn_default_route_cmd = {
752 "evpn default-route", route_match_evpn_default_route, NULL, NULL};
753
d37ba549
MK
754/* `match mac address MAC_ACCESS_LIST' */
755
756/* Match function should return 1 if match is success else return
757 zero. */
758static route_map_result_t route_match_mac_address(void *rule,
123214ef 759 const struct prefix *prefix,
d37ba549
MK
760 route_map_object_t type,
761 void *object)
762{
763 struct access_list *alist;
0f6476cc 764 struct prefix p;
d37ba549
MK
765
766 if (type == RMAP_BGP) {
767 alist = access_list_lookup(AFI_L2VPN, (char *)rule);
768 if (alist == NULL)
769 return RMAP_NOMATCH;
770
771 if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE)
772 return RMAP_NOMATCH;
773
0f6476cc
DS
774 p.family = AF_ETHERNET;
775 p.prefixlen = ETH_ALEN * 8;
3714a385 776 p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
0f6476cc 777
a4d82a8a 778 return (access_list_apply(alist, &p) == FILTER_DENY
d37ba549
MK
779 ? RMAP_NOMATCH
780 : RMAP_MATCH);
781 }
782
783 return RMAP_NOMATCH;
784}
785
786/* Route map `mac address' match statement. `arg' should be
787 access-list name. */
788static void *route_match_mac_address_compile(const char *arg)
789{
790 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
791}
792
793/* Free route map's compiled `ip address' value. */
794static void route_match_mac_address_free(void *rule)
795{
796 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
797}
798
799/* Route map commands for mac address matching. */
800struct route_map_rule_cmd route_match_mac_address_cmd = {
801 "mac address", route_match_mac_address, route_match_mac_address_compile,
802 route_match_mac_address_free};
803
16f7ce2b
MK
804/* `match vni' */
805
806/* Match function should return 1 if match is success else return
807 zero. */
123214ef
MS
808static route_map_result_t route_match_vni(void *rule,
809 const struct prefix *prefix,
16f7ce2b
MK
810 route_map_object_t type, void *object)
811{
812 vni_t vni = 0;
4b7e6066 813 struct bgp_path_info *bgp_info = NULL;
16f7ce2b
MK
814
815 if (type == RMAP_BGP) {
816 vni = *((vni_t *)rule);
4b7e6066 817 bgp_info = (struct bgp_path_info *)object;
16f7ce2b 818
80ced710
CS
819 if (bgp_info->extra == NULL)
820 return RMAP_NOMATCH;
821
b57ba6d2 822 if (vni == label2vni(&bgp_info->extra->label[0]))
16f7ce2b
MK
823 return RMAP_MATCH;
824 }
825
826 return RMAP_NOMATCH;
827}
828
829/* Route map `vni' match statement. */
830static void *route_match_vni_compile(const char *arg)
831{
832 vni_t *vni = NULL;
833 char *end = NULL;
834
835 vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
836 if (!vni)
837 return NULL;
838
839 *vni = strtoul(arg, &end, 10);
0af35d90
RW
840 if (*end != '\0') {
841 XFREE(MTYPE_ROUTE_MAP_COMPILED, vni);
16f7ce2b 842 return NULL;
0af35d90 843 }
16f7ce2b
MK
844
845 return vni;
846}
847
848/* Free route map's compiled `vni' value. */
849static void route_match_vni_free(void *rule)
850{
851 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
852}
853
854/* Route map commands for vni matching. */
855struct route_map_rule_cmd route_match_evpn_vni_cmd = {
646050e5
MK
856 "evpn vni", route_match_vni, route_match_vni_compile,
857 route_match_vni_free};
16f7ce2b 858
33c2ff62
MK
859/* `match evpn route-type' */
860
861/* Match function should return 1 if match is success else return
862 zero. */
863static route_map_result_t route_match_evpn_route_type(void *rule,
123214ef 864 const struct prefix *pfx,
33c2ff62
MK
865 route_map_object_t type,
866 void *object)
867{
d7c0a89a 868 uint8_t route_type = 0;
33c2ff62
MK
869
870 if (type == RMAP_BGP) {
d7c0a89a 871 route_type = *((uint8_t *)rule);
33c2ff62 872
123214ef 873 if (route_type == pfx->u.prefix_evpn.route_type)
33c2ff62
MK
874 return RMAP_MATCH;
875 }
876
877 return RMAP_NOMATCH;
878}
879
880/* Route map `route-type' match statement. */
881static void *route_match_evpn_route_type_compile(const char *arg)
882{
d7c0a89a 883 uint8_t *route_type = NULL;
33c2ff62 884
d7c0a89a 885 route_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
33c2ff62
MK
886
887 if (strncmp(arg, "ma", 2) == 0)
888 *route_type = BGP_EVPN_MAC_IP_ROUTE;
889 else if (strncmp(arg, "mu", 2) == 0)
890 *route_type = BGP_EVPN_IMET_ROUTE;
891 else
892 *route_type = BGP_EVPN_IP_PREFIX_ROUTE;
893
894 return route_type;
895}
896
897/* Free route map's compiled `route-type' value. */
898static void route_match_evpn_route_type_free(void *rule)
899{
900 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
901}
902
903/* Route map commands for evpn route-type matching. */
904struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
905 "evpn route-type", route_match_evpn_route_type,
996c9314 906 route_match_evpn_route_type_compile, route_match_evpn_route_type_free};
33c2ff62 907
af291c15
DS
908/* `match local-preference LOCAL-PREF' */
909
910/* Match function return 1 if match is success else return zero. */
d62a17ae 911static route_map_result_t route_match_local_pref(void *rule,
123214ef 912 const struct prefix *prefix,
d62a17ae 913 route_map_object_t type,
914 void *object)
915{
d7c0a89a 916 uint32_t *local_pref;
4b7e6066 917 struct bgp_path_info *bgp_info;
d62a17ae 918
919 if (type == RMAP_BGP) {
920 local_pref = rule;
921 bgp_info = object;
922
923 if (bgp_info->attr->local_pref == *local_pref)
924 return RMAP_MATCH;
925 else
926 return RMAP_NOMATCH;
927 }
af291c15 928 return RMAP_NOMATCH;
af291c15
DS
929}
930
931/* Route map `match local-preference' match statement.
932 `arg' is local-pref value */
d62a17ae 933static void *route_match_local_pref_compile(const char *arg)
af291c15 934{
d7c0a89a 935 uint32_t *local_pref;
d62a17ae 936 char *endptr = NULL;
937 unsigned long tmpval;
af291c15 938
d62a17ae 939 /* Locpref value shoud be integer. */
940 if (!all_digit(arg))
941 return NULL;
af291c15 942
d62a17ae 943 errno = 0;
944 tmpval = strtoul(arg, &endptr, 10);
945 if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
946 return NULL;
af291c15 947
d7c0a89a 948 local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
af291c15 949
d62a17ae 950 if (!local_pref)
951 return local_pref;
af291c15 952
d62a17ae 953 *local_pref = tmpval;
954 return local_pref;
af291c15
DS
955}
956
957/* Free route map's compiled `match local-preference' value. */
d62a17ae 958static void route_match_local_pref_free(void *rule)
af291c15 959{
d62a17ae 960 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
af291c15
DS
961}
962
963/* Route map commands for metric matching. */
d62a17ae 964struct route_map_rule_cmd route_match_local_pref_cmd = {
965 "local-preference", route_match_local_pref,
966 route_match_local_pref_compile, route_match_local_pref_free};
af291c15 967
718e3744 968/* `match metric METRIC' */
969
970/* Match function return 1 if match is success else return zero. */
123214ef
MS
971static route_map_result_t route_match_metric(void *rule,
972 const struct prefix *prefix,
d62a17ae 973 route_map_object_t type,
974 void *object)
718e3744 975{
d62a17ae 976 struct rmap_value *rv;
4b7e6066 977 struct bgp_path_info *bgp_info;
718e3744 978
d62a17ae 979 if (type == RMAP_BGP) {
980 rv = rule;
981 bgp_info = object;
982 return route_value_match(rv, bgp_info->attr->med);
983 }
984 return RMAP_NOMATCH;
718e3744 985}
986
718e3744 987/* Route map commands for metric matching. */
d62a17ae 988struct route_map_rule_cmd route_match_metric_cmd = {
9d303b37 989 "metric", route_match_metric, route_value_compile, route_value_free,
718e3744 990};
6b0655a2 991
718e3744 992/* `match as-path ASPATH' */
993
994/* Match function for as-path match. I assume given object is */
123214ef
MS
995static route_map_result_t route_match_aspath(void *rule,
996 const struct prefix *prefix,
d62a17ae 997 route_map_object_t type,
998 void *object)
718e3744 999{
e52702f2 1000
d62a17ae 1001 struct as_list *as_list;
4b7e6066 1002 struct bgp_path_info *bgp_info;
718e3744 1003
d62a17ae 1004 if (type == RMAP_BGP) {
1005 as_list = as_list_lookup((char *)rule);
1006 if (as_list == NULL)
1007 return RMAP_NOMATCH;
518f0eb1 1008
d62a17ae 1009 bgp_info = object;
518f0eb1 1010
d62a17ae 1011 /* Perform match. */
1012 return ((as_list_apply(as_list, bgp_info->attr->aspath)
1013 == AS_FILTER_DENY)
1014 ? RMAP_NOMATCH
1015 : RMAP_MATCH);
1016 }
1017 return RMAP_NOMATCH;
718e3744 1018}
1019
1020/* Compile function for as-path match. */
d62a17ae 1021static void *route_match_aspath_compile(const char *arg)
718e3744 1022{
d62a17ae 1023 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 1024}
1025
1026/* Compile function for as-path match. */
d62a17ae 1027static void route_match_aspath_free(void *rule)
718e3744 1028{
d62a17ae 1029 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 1030}
1031
1032/* Route map commands for aspath matching. */
d62a17ae 1033struct route_map_rule_cmd route_match_aspath_cmd = {
1034 "as-path", route_match_aspath, route_match_aspath_compile,
1035 route_match_aspath_free};
6b0655a2 1036
718e3744 1037/* `match community COMMUNIY' */
d62a17ae 1038struct rmap_community {
1039 char *name;
1040 int exact;
718e3744 1041};
1042
1043/* Match function for community match. */
d62a17ae 1044static route_map_result_t route_match_community(void *rule,
123214ef 1045 const struct prefix *prefix,
d62a17ae 1046 route_map_object_t type,
1047 void *object)
1048{
1049 struct community_list *list;
4b7e6066 1050 struct bgp_path_info *bgp_info;
d62a17ae 1051 struct rmap_community *rcom;
1052
1053 if (type == RMAP_BGP) {
1054 bgp_info = object;
1055 rcom = rule;
1056
1057 list = community_list_lookup(bgp_clist, rcom->name,
1058 COMMUNITY_LIST_MASTER);
1059 if (!list)
1060 return RMAP_NOMATCH;
1061
1062 if (rcom->exact) {
1063 if (community_list_exact_match(
1064 bgp_info->attr->community, list))
1065 return RMAP_MATCH;
1066 } else {
1067 if (community_list_match(bgp_info->attr->community,
1068 list))
1069 return RMAP_MATCH;
1070 }
718e3744 1071 }
d62a17ae 1072 return RMAP_NOMATCH;
718e3744 1073}
1074
1075/* Compile function for community match. */
d62a17ae 1076static void *route_match_community_compile(const char *arg)
1077{
1078 struct rmap_community *rcom;
1079 int len;
1080 char *p;
1081
1082 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1083
1084 p = strchr(arg, ' ');
1085 if (p) {
1086 len = p - arg;
1087 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1088 memcpy(rcom->name, arg, len);
1089 rcom->exact = 1;
1090 } else {
1091 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1092 rcom->exact = 0;
1093 }
1094 return rcom;
718e3744 1095}
1096
1097/* Compile function for community match. */
d62a17ae 1098static void route_match_community_free(void *rule)
718e3744 1099{
d62a17ae 1100 struct rmap_community *rcom = rule;
718e3744 1101
d62a17ae 1102 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1103 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
718e3744 1104}
1105
1106/* Route map commands for community matching. */
d62a17ae 1107struct route_map_rule_cmd route_match_community_cmd = {
1108 "community", route_match_community, route_match_community_compile,
1109 route_match_community_free};
6b0655a2 1110
57d187bc 1111/* Match function for lcommunity match. */
d62a17ae 1112static route_map_result_t route_match_lcommunity(void *rule,
123214ef 1113 const struct prefix *prefix,
d62a17ae 1114 route_map_object_t type,
1115 void *object)
1116{
1117 struct community_list *list;
4b7e6066 1118 struct bgp_path_info *bgp_info;
d62a17ae 1119 struct rmap_community *rcom;
1120
1121 if (type == RMAP_BGP) {
1122 bgp_info = object;
1123 rcom = rule;
1124
1125 list = community_list_lookup(bgp_clist, rcom->name,
1126 LARGE_COMMUNITY_LIST_MASTER);
1127 if (!list)
1128 return RMAP_NOMATCH;
1129
1130 if (lcommunity_list_match(bgp_info->attr->lcommunity, list))
1131 return RMAP_MATCH;
1132 }
1133 return RMAP_NOMATCH;
57d187bc
JS
1134}
1135
1136/* Compile function for community match. */
d62a17ae 1137static void *route_match_lcommunity_compile(const char *arg)
1138{
1139 struct rmap_community *rcom;
1140 int len;
1141 char *p;
1142
1143 rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1144
1145 p = strchr(arg, ' ');
1146 if (p) {
1147 len = p - arg;
1148 rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1149 memcpy(rcom->name, arg, len);
1150 } else {
1151 rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1152 rcom->exact = 0;
1153 }
1154 return rcom;
57d187bc
JS
1155}
1156
1157/* Compile function for community match. */
d62a17ae 1158static void route_match_lcommunity_free(void *rule)
57d187bc 1159{
d62a17ae 1160 struct rmap_community *rcom = rule;
57d187bc 1161
d62a17ae 1162 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1163 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
57d187bc
JS
1164}
1165
1166/* Route map commands for community matching. */
d62a17ae 1167struct route_map_rule_cmd route_match_lcommunity_cmd = {
1168 "large-community", route_match_lcommunity,
1169 route_match_lcommunity_compile, route_match_lcommunity_free};
57d187bc
JS
1170
1171
73ffb25b 1172/* Match function for extcommunity match. */
d62a17ae 1173static route_map_result_t route_match_ecommunity(void *rule,
123214ef 1174 const struct prefix *prefix,
d62a17ae 1175 route_map_object_t type,
1176 void *object)
73ffb25b 1177{
d62a17ae 1178 struct community_list *list;
4b7e6066 1179 struct bgp_path_info *bgp_info;
73ffb25b 1180
d62a17ae 1181 if (type == RMAP_BGP) {
1182 bgp_info = object;
e52702f2 1183
d62a17ae 1184 list = community_list_lookup(bgp_clist, (char *)rule,
1185 EXTCOMMUNITY_LIST_MASTER);
1186 if (!list)
1187 return RMAP_NOMATCH;
73ffb25b 1188
d62a17ae 1189 if (ecommunity_list_match(bgp_info->attr->ecommunity, list))
1190 return RMAP_MATCH;
1191 }
1192 return RMAP_NOMATCH;
73ffb25b 1193}
1194
1195/* Compile function for extcommunity match. */
d62a17ae 1196static void *route_match_ecommunity_compile(const char *arg)
73ffb25b 1197{
d62a17ae 1198 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
73ffb25b 1199}
1200
1201/* Compile function for extcommunity match. */
d62a17ae 1202static void route_match_ecommunity_free(void *rule)
73ffb25b 1203{
d62a17ae 1204 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
73ffb25b 1205}
1206
1207/* Route map commands for community matching. */
d62a17ae 1208struct route_map_rule_cmd route_match_ecommunity_cmd = {
1209 "extcommunity", route_match_ecommunity, route_match_ecommunity_compile,
1210 route_match_ecommunity_free};
6b0655a2 1211
718e3744 1212/* `match nlri` and `set nlri` are replaced by `address-family ipv4`
1213 and `address-family vpnv4'. */
6b0655a2 1214
718e3744 1215/* `match origin' */
123214ef
MS
1216static route_map_result_t route_match_origin(void *rule,
1217 const struct prefix *prefix,
d62a17ae 1218 route_map_object_t type,
1219 void *object)
718e3744 1220{
d7c0a89a 1221 uint8_t *origin;
4b7e6066 1222 struct bgp_path_info *bgp_info;
718e3744 1223
d62a17ae 1224 if (type == RMAP_BGP) {
1225 origin = rule;
1226 bgp_info = object;
e52702f2 1227
d62a17ae 1228 if (bgp_info->attr->origin == *origin)
1229 return RMAP_MATCH;
1230 }
718e3744 1231
d62a17ae 1232 return RMAP_NOMATCH;
718e3744 1233}
1234
d62a17ae 1235static void *route_match_origin_compile(const char *arg)
718e3744 1236{
d7c0a89a 1237 uint8_t *origin;
718e3744 1238
d7c0a89a 1239 origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
718e3744 1240
d62a17ae 1241 if (strcmp(arg, "igp") == 0)
1242 *origin = 0;
1243 else if (strcmp(arg, "egp") == 0)
1244 *origin = 1;
1245 else
1246 *origin = 2;
718e3744 1247
d62a17ae 1248 return origin;
718e3744 1249}
1250
1251/* Free route map's compiled `ip address' value. */
d62a17ae 1252static void route_match_origin_free(void *rule)
718e3744 1253{
d62a17ae 1254 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 1255}
1256
1257/* Route map commands for origin matching. */
d62a17ae 1258struct route_map_rule_cmd route_match_origin_cmd = {
1259 "origin", route_match_origin, route_match_origin_compile,
1260 route_match_origin_free};
1add115a
VT
1261
1262/* match probability { */
1263
d62a17ae 1264static route_map_result_t route_match_probability(void *rule,
123214ef 1265 const struct prefix *prefix,
d62a17ae 1266 route_map_object_t type,
1267 void *object)
1268{
1269 long r = random();
1270
1271 switch (*(long *)rule) {
1272 case 0:
1273 break;
1274 case RAND_MAX:
1275 return RMAP_MATCH;
1276 default:
1277 if (r < *(long *)rule) {
1278 return RMAP_MATCH;
1279 }
1280 }
1add115a 1281
d62a17ae 1282 return RMAP_NOMATCH;
1add115a
VT
1283}
1284
d62a17ae 1285static void *route_match_probability_compile(const char *arg)
1add115a 1286{
d62a17ae 1287 long *lobule;
1288 unsigned perc;
1add115a 1289
d62a17ae 1290 perc = atoi(arg);
1291 lobule = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(long));
1add115a 1292
d62a17ae 1293 switch (perc) {
1294 case 0:
1295 *lobule = 0;
1296 break;
1297 case 100:
1298 *lobule = RAND_MAX;
1299 break;
1300 default:
1301 *lobule = RAND_MAX / 100 * perc;
1302 }
1add115a 1303
d62a17ae 1304 return lobule;
1add115a
VT
1305}
1306
d62a17ae 1307static void route_match_probability_free(void *rule)
1add115a 1308{
d62a17ae 1309 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1add115a
VT
1310}
1311
d62a17ae 1312struct route_map_rule_cmd route_match_probability_cmd = {
1313 "probability", route_match_probability, route_match_probability_compile,
1314 route_match_probability_free};
1add115a 1315
bc413143
DS
1316/* `match interface IFNAME' */
1317/* Match function should return 1 if match is success else return
1318 zero. */
d62a17ae 1319static route_map_result_t route_match_interface(void *rule,
123214ef 1320 const struct prefix *prefix,
d62a17ae 1321 route_map_object_t type,
1322 void *object)
bc413143 1323{
d62a17ae 1324 struct interface *ifp;
4b7e6066 1325 struct bgp_path_info *info;
bc413143 1326
d62a17ae 1327 if (type == RMAP_BGP) {
1328 info = object;
bc413143 1329
d62a17ae 1330 if (!info || !info->attr)
1331 return RMAP_NOMATCH;
bc413143 1332
d62a17ae 1333 ifp = if_lookup_by_name_all_vrf((char *)rule);
bc413143 1334
d62a17ae 1335 if (ifp == NULL || ifp->ifindex != info->attr->nh_ifindex)
1336 return RMAP_NOMATCH;
bc413143 1337
d62a17ae 1338 return RMAP_MATCH;
1339 }
1340 return RMAP_NOMATCH;
bc413143
DS
1341}
1342
1343/* Route map `interface' match statement. `arg' should be
1344 interface name. */
d62a17ae 1345static void *route_match_interface_compile(const char *arg)
bc413143 1346{
d62a17ae 1347 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
bc413143
DS
1348}
1349
1350/* Free route map's compiled `interface' value. */
d62a17ae 1351static void route_match_interface_free(void *rule)
bc413143 1352{
d62a17ae 1353 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
bc413143
DS
1354}
1355
1356/* Route map commands for ip address matching. */
d62a17ae 1357struct route_map_rule_cmd route_match_interface_cmd = {
1358 "interface", route_match_interface, route_match_interface_compile,
1359 route_match_interface_free};
bc413143 1360
1add115a
VT
1361/* } */
1362
718e3744 1363/* `set ip next-hop IP_ADDRESS' */
1364
0d9551dc 1365/* Match function return 1 if match is success else return zero. */
123214ef
MS
1366static route_map_result_t route_match_tag(void *rule,
1367 const struct prefix *prefix,
d62a17ae 1368 route_map_object_t type, void *object)
0d9551dc 1369{
d62a17ae 1370 route_tag_t *tag;
4b7e6066 1371 struct bgp_path_info *bgp_info;
0d9551dc 1372
d62a17ae 1373 if (type == RMAP_BGP) {
1374 tag = rule;
1375 bgp_info = object;
0d9551dc 1376
d62a17ae 1377 return ((bgp_info->attr->tag == *tag) ? RMAP_MATCH
1378 : RMAP_NOMATCH);
1379 }
0d9551dc 1380
d62a17ae 1381 return RMAP_NOMATCH;
0d9551dc
DS
1382}
1383
1384
0d9551dc 1385/* Route map commands for tag matching. */
d62a17ae 1386static struct route_map_rule_cmd route_match_tag_cmd = {
9d303b37 1387 "tag", route_match_tag, route_map_rule_tag_compile,
d62a17ae 1388 route_map_rule_tag_free,
0d9551dc
DS
1389};
1390
1391
718e3744 1392/* Set nexthop to object. ojbect must be pointer to struct attr. */
d62a17ae 1393struct rmap_ip_nexthop_set {
1394 struct in_addr *address;
1395 int peer_address;
1396 int unchanged;
ac41b2a2 1397};
1398
d62a17ae 1399static route_map_result_t route_set_ip_nexthop(void *rule,
123214ef 1400 const struct prefix *prefix,
d62a17ae 1401 route_map_object_t type,
1402 void *object)
1403{
1404 struct rmap_ip_nexthop_set *rins = rule;
4b7e6066 1405 struct bgp_path_info *bgp_info;
d62a17ae 1406 struct peer *peer;
1407
1408 if (type == RMAP_BGP) {
1409 bgp_info = object;
1410 peer = bgp_info->peer;
1411
1412 if (rins->unchanged) {
1413 SET_FLAG(bgp_info->attr->rmap_change_flags,
1414 BATTR_RMAP_NEXTHOP_UNCHANGED);
1415 } else if (rins->peer_address) {
1416 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
1417 || CHECK_FLAG(peer->rmap_type,
1418 PEER_RMAP_TYPE_IMPORT))
1419 && peer->su_remote
1420 && sockunion_family(peer->su_remote) == AF_INET) {
1421 bgp_info->attr->nexthop.s_addr =
1422 sockunion2ip(peer->su_remote);
1423 bgp_info->attr->flag |=
1424 ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1425 } else if (CHECK_FLAG(peer->rmap_type,
1426 PEER_RMAP_TYPE_OUT)) {
1427 /* The next hop value will be set as part of
1428 * packet rewrite.
1429 * Set the flags here to indicate that rewrite
1430 * needs to be done.
1431 * Also, clear the value.
1432 */
1433 SET_FLAG(bgp_info->attr->rmap_change_flags,
1434 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
1435 bgp_info->attr->nexthop.s_addr = 0;
1436 }
1437 } else {
1438 /* Set next hop value. */
1439 bgp_info->attr->flag |=
1440 ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1441 bgp_info->attr->nexthop = *rins->address;
1442 SET_FLAG(bgp_info->attr->rmap_change_flags,
1443 BATTR_RMAP_IPV4_NHOP_CHANGED);
d54600fa
PG
1444 /* case for MP-BGP : MPLS VPN */
1445 bgp_info->attr->mp_nexthop_global_in = *rins->address;
1446 bgp_info->attr->mp_nexthop_len = sizeof(*rins->address);
d62a17ae 1447 }
ac41b2a2 1448 }
718e3744 1449
d62a17ae 1450 return RMAP_OKAY;
718e3744 1451}
1452
1453/* Route map `ip nexthop' compile function. Given string is converted
1454 to struct in_addr structure. */
d62a17ae 1455static void *route_set_ip_nexthop_compile(const char *arg)
1456{
1457 struct rmap_ip_nexthop_set *rins;
1458 struct in_addr *address = NULL;
1459 int peer_address = 0;
1460 int unchanged = 0;
1461 int ret;
1462
1463 if (strcmp(arg, "peer-address") == 0)
1464 peer_address = 1;
1465 else if (strcmp(arg, "unchanged") == 0)
1466 unchanged = 1;
1467 else {
1468 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
1469 sizeof(struct in_addr));
1470 ret = inet_aton(arg, address);
1471
1472 if (ret == 0) {
1473 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
1474 return NULL;
1475 }
ac41b2a2 1476 }
718e3744 1477
d62a17ae 1478 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
1479 sizeof(struct rmap_ip_nexthop_set));
ac41b2a2 1480
d62a17ae 1481 rins->address = address;
1482 rins->peer_address = peer_address;
1483 rins->unchanged = unchanged;
ac41b2a2 1484
d62a17ae 1485 return rins;
718e3744 1486}
1487
1488/* Free route map's compiled `ip nexthop' value. */
d62a17ae 1489static void route_set_ip_nexthop_free(void *rule)
718e3744 1490{
d62a17ae 1491 struct rmap_ip_nexthop_set *rins = rule;
ac41b2a2 1492
d62a17ae 1493 if (rins->address)
1494 XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
e52702f2 1495
d62a17ae 1496 XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
718e3744 1497}
1498
1499/* Route map commands for ip nexthop set. */
d62a17ae 1500struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
1501 "ip next-hop", route_set_ip_nexthop, route_set_ip_nexthop_compile,
1502 route_set_ip_nexthop_free};
6b0655a2 1503
718e3744 1504/* `set local-preference LOCAL_PREF' */
1505
1506/* Set local preference. */
d62a17ae 1507static route_map_result_t route_set_local_pref(void *rule,
123214ef 1508 const struct prefix *prefix,
d62a17ae 1509 route_map_object_t type,
1510 void *object)
1511{
1512 struct rmap_value *rv;
4b7e6066 1513 struct bgp_path_info *bgp_info;
d7c0a89a 1514 uint32_t locpref = 0;
d62a17ae 1515
1516 if (type == RMAP_BGP) {
1517 /* Fetch routemap's rule information. */
1518 rv = rule;
1519 bgp_info = object;
1520
1521 /* Set local preference value. */
1522 if (bgp_info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
1523 locpref = bgp_info->attr->local_pref;
1524
1525 bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1526 bgp_info->attr->local_pref =
1527 route_value_adjust(rv, locpref, bgp_info->peer);
1528 }
718e3744 1529
d62a17ae 1530 return RMAP_OKAY;
718e3744 1531}
1532
718e3744 1533/* Set local preference rule structure. */
d62a17ae 1534struct route_map_rule_cmd route_set_local_pref_cmd = {
9d303b37 1535 "local-preference", route_set_local_pref, route_value_compile,
d62a17ae 1536 route_value_free,
718e3744 1537};
6b0655a2 1538
718e3744 1539/* `set weight WEIGHT' */
1540
1541/* Set weight. */
123214ef
MS
1542static route_map_result_t route_set_weight(void *rule,
1543 const struct prefix *prefix,
d62a17ae 1544 route_map_object_t type,
1545 void *object)
718e3744 1546{
d62a17ae 1547 struct rmap_value *rv;
4b7e6066 1548 struct bgp_path_info *bgp_info;
718e3744 1549
d62a17ae 1550 if (type == RMAP_BGP) {
1551 /* Fetch routemap's rule information. */
1552 rv = rule;
1553 bgp_info = object;
e52702f2 1554
d62a17ae 1555 /* Set weight value. */
1556 bgp_info->attr->weight =
1557 route_value_adjust(rv, 0, bgp_info->peer);
1558 }
718e3744 1559
d62a17ae 1560 return RMAP_OKAY;
718e3744 1561}
1562
718e3744 1563/* Set local preference rule structure. */
d62a17ae 1564struct route_map_rule_cmd route_set_weight_cmd = {
9d303b37 1565 "weight", route_set_weight, route_value_compile, route_value_free,
718e3744 1566};
6b0655a2 1567
718e3744 1568/* `set metric METRIC' */
1569
1570/* Set metric to attribute. */
123214ef
MS
1571static route_map_result_t route_set_metric(void *rule,
1572 const struct prefix *prefix,
d62a17ae 1573 route_map_object_t type,
1574 void *object)
1575{
1576 struct rmap_value *rv;
4b7e6066 1577 struct bgp_path_info *bgp_info;
d7c0a89a 1578 uint32_t med = 0;
d62a17ae 1579
1580 if (type == RMAP_BGP) {
1581 /* Fetch routemap's rule information. */
1582 rv = rule;
1583 bgp_info = object;
1584
1585 if (bgp_info->attr->flag
1586 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
1587 med = bgp_info->attr->med;
1588
1589 bgp_info->attr->med =
1590 route_value_adjust(rv, med, bgp_info->peer);
1591 bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
1592 }
1593 return RMAP_OKAY;
718e3744 1594}
1595
718e3744 1596/* Set metric rule structure. */
d62a17ae 1597struct route_map_rule_cmd route_set_metric_cmd = {
9d303b37 1598 "metric", route_set_metric, route_value_compile, route_value_free,
718e3744 1599};
6b0655a2 1600
718e3744 1601/* `set as-path prepend ASPATH' */
1602
1603/* For AS path prepend mechanism. */
d62a17ae 1604static route_map_result_t route_set_aspath_prepend(void *rule,
123214ef 1605 const struct prefix *prefix,
d62a17ae 1606 route_map_object_t type,
1607 void *object)
1608{
1609 struct aspath *aspath;
1610 struct aspath *new;
4b7e6066 1611 struct bgp_path_info *binfo;
d62a17ae 1612
1613 if (type == RMAP_BGP) {
1614 binfo = object;
1615
1616 if (binfo->attr->aspath->refcnt)
1617 new = aspath_dup(binfo->attr->aspath);
1618 else
1619 new = binfo->attr->aspath;
1620
1621 if ((uintptr_t)rule > 10) {
1622 aspath = rule;
1623 aspath_prepend(aspath, new);
1624 } else {
1625 as_t as = aspath_leftmost(new);
1626 if (!as)
1627 as = binfo->peer->as;
1628 new = aspath_add_seq_n(new, as, (uintptr_t)rule);
1629 }
bc3dd427 1630
d62a17ae 1631 binfo->attr->aspath = new;
1632 }
718e3744 1633
d62a17ae 1634 return RMAP_OKAY;
718e3744 1635}
1636
d62a17ae 1637static void *route_set_aspath_prepend_compile(const char *arg)
bc3dd427 1638{
d62a17ae 1639 unsigned int num;
bc3dd427 1640
d62a17ae 1641 if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10)
1642 return (void *)(uintptr_t)num;
bc3dd427 1643
d62a17ae 1644 return route_aspath_compile(arg);
bc3dd427
DW
1645}
1646
d62a17ae 1647static void route_set_aspath_prepend_free(void *rule)
bc3dd427 1648{
d62a17ae 1649 if ((uintptr_t)rule > 10)
1650 route_aspath_free(rule);
bc3dd427
DW
1651}
1652
1653
515e500c 1654/* Set as-path prepend rule structure. */
d62a17ae 1655struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
9d303b37
DL
1656 "as-path prepend", route_set_aspath_prepend,
1657 route_set_aspath_prepend_compile, route_set_aspath_prepend_free,
718e3744 1658};
6b0655a2 1659
841f7a57
DO
1660/* `set as-path exclude ASn' */
1661
1662/* For ASN exclude mechanism.
d62a17ae 1663 * Iterate over ASns requested and filter them from the given AS_PATH one by
1664 * one.
841f7a57
DO
1665 * Make a deep copy of existing AS_PATH, but for the first ASn only.
1666 */
d62a17ae 1667static route_map_result_t route_set_aspath_exclude(void *rule,
123214ef 1668 const struct prefix *dummy,
d62a17ae 1669 route_map_object_t type,
1670 void *object)
1671{
1672 struct aspath *new_path, *exclude_path;
4b7e6066 1673 struct bgp_path_info *binfo;
d62a17ae 1674
1675 if (type == RMAP_BGP) {
1676 exclude_path = rule;
1677 binfo = object;
1678 if (binfo->attr->aspath->refcnt)
1679 new_path = aspath_dup(binfo->attr->aspath);
1680 else
1681 new_path = binfo->attr->aspath;
1682 binfo->attr->aspath =
1683 aspath_filter_exclude(new_path, exclude_path);
1684 }
1685 return RMAP_OKAY;
841f7a57
DO
1686}
1687
841f7a57 1688/* Set ASn exlude rule structure. */
d62a17ae 1689struct route_map_rule_cmd route_set_aspath_exclude_cmd = {
9d303b37 1690 "as-path exclude", route_set_aspath_exclude, route_aspath_compile,
d62a17ae 1691 route_aspath_free,
841f7a57 1692};
6b0655a2 1693
718e3744 1694/* `set community COMMUNITY' */
d62a17ae 1695struct rmap_com_set {
1696 struct community *com;
1697 int additive;
1698 int none;
718e3744 1699};
1700
1701/* For community set mechanism. */
123214ef
MS
1702static route_map_result_t route_set_community(void *rule,
1703 const struct prefix *prefix,
d62a17ae 1704 route_map_object_t type,
1705 void *object)
1706{
1707 struct rmap_com_set *rcs;
4b7e6066 1708 struct bgp_path_info *binfo;
d62a17ae 1709 struct attr *attr;
1710 struct community *new = NULL;
1711 struct community *old;
1712 struct community *merge;
1713
1714 if (type == RMAP_BGP) {
1715 rcs = rule;
1716 binfo = object;
1717 attr = binfo->attr;
1718 old = attr->community;
1719
1720 /* "none" case. */
1721 if (rcs->none) {
1722 attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
1723 attr->community = NULL;
1724 /* See the longer comment down below. */
1725 if (old && old->refcnt == 0)
1726 community_free(old);
1727 return RMAP_OKAY;
1728 }
718e3744 1729
d62a17ae 1730 /* "additive" case. */
1731 if (rcs->additive && old) {
1732 merge = community_merge(community_dup(old), rcs->com);
1733
d62a17ae 1734 new = community_uniq_sort(merge);
1735 community_free(merge);
1736 } else
1737 new = community_dup(rcs->com);
1738
f24804f4
NK
1739 /* HACK: if the old community is not intern'd,
1740 * we should free it here, or all reference to it may be
1741 * lost.
1742 * Really need to cleanup attribute caching sometime.
1743 */
1744 if (old && old->refcnt == 0)
1745 community_free(old);
1746
d62a17ae 1747 /* will be interned by caller if required */
1748 attr->community = new;
1749
1750 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
718e3744 1751 }
718e3744 1752
d62a17ae 1753 return RMAP_OKAY;
718e3744 1754}
1755
1756/* Compile function for set community. */
d62a17ae 1757static void *route_set_community_compile(const char *arg)
1758{
1759 struct rmap_com_set *rcs;
1760 struct community *com = NULL;
1761 char *sp;
1762 int additive = 0;
1763 int none = 0;
1764
1765 if (strcmp(arg, "none") == 0)
1766 none = 1;
1767 else {
1768 sp = strstr(arg, "additive");
1769
1770 if (sp && sp > arg) {
770817b4 1771 /* "additive" keyword is included. */
d62a17ae 1772 additive = 1;
1773 *(sp - 1) = '\0';
1774 }
718e3744 1775
d62a17ae 1776 com = community_str2com(arg);
718e3744 1777
d62a17ae 1778 if (additive)
1779 *(sp - 1) = ' ';
718e3744 1780
d62a17ae 1781 if (!com)
1782 return NULL;
1783 }
e52702f2 1784
d62a17ae 1785 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
1786 rcs->com = com;
1787 rcs->additive = additive;
1788 rcs->none = none;
e52702f2 1789
d62a17ae 1790 return rcs;
718e3744 1791}
1792
1793/* Free function for set community. */
d62a17ae 1794static void route_set_community_free(void *rule)
718e3744 1795{
d62a17ae 1796 struct rmap_com_set *rcs = rule;
718e3744 1797
d62a17ae 1798 if (rcs->com)
1799 community_free(rcs->com);
1800 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
718e3744 1801}
1802
1803/* Set community rule structure. */
d62a17ae 1804struct route_map_rule_cmd route_set_community_cmd = {
9d303b37 1805 "community", route_set_community, route_set_community_compile,
d62a17ae 1806 route_set_community_free,
718e3744 1807};
6b0655a2 1808
57d187bc 1809/* `set community COMMUNITY' */
d62a17ae 1810struct rmap_lcom_set {
1811 struct lcommunity *lcom;
1812 int additive;
1813 int none;
57d187bc
JS
1814};
1815
1816
1817/* For lcommunity set mechanism. */
d62a17ae 1818static route_map_result_t route_set_lcommunity(void *rule,
123214ef 1819 const struct prefix *prefix,
d62a17ae 1820 route_map_object_t type,
1821 void *object)
1822{
1823 struct rmap_lcom_set *rcs;
4b7e6066 1824 struct bgp_path_info *binfo;
d62a17ae 1825 struct attr *attr;
1826 struct lcommunity *new = NULL;
1827 struct lcommunity *old;
1828 struct lcommunity *merge;
1829
1830 if (type == RMAP_BGP) {
1831 rcs = rule;
1832 binfo = object;
1833 attr = binfo->attr;
1834 old = attr->lcommunity;
1835
1836 /* "none" case. */
1837 if (rcs->none) {
1838 attr->flag &=
1839 ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
1840 attr->lcommunity = NULL;
1841
1842 /* See the longer comment down below. */
1843 if (old && old->refcnt == 0)
1844 lcommunity_free(&old);
1845 return RMAP_OKAY;
1846 }
57d187bc 1847
d62a17ae 1848 if (rcs->additive && old) {
1849 merge = lcommunity_merge(lcommunity_dup(old),
1850 rcs->lcom);
1851
d62a17ae 1852 new = lcommunity_uniq_sort(merge);
1853 lcommunity_free(&merge);
1854 } else
1855 new = lcommunity_dup(rcs->lcom);
1856
4265a53e
NK
1857 /* HACK: if the old large-community is not intern'd,
1858 * we should free it here, or all reference to it may be
1859 * lost.
1860 * Really need to cleanup attribute caching sometime.
1861 */
1862 if (old && old->refcnt == 0)
1863 lcommunity_free(&old);
1864
d62a17ae 1865 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
1866 attr->lcommunity = new;
1867
1868 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
1869 }
57d187bc 1870
d62a17ae 1871 return RMAP_OKAY;
1872}
57d187bc 1873
d62a17ae 1874/* Compile function for set community. */
1875static void *route_set_lcommunity_compile(const char *arg)
1876{
1877 struct rmap_lcom_set *rcs;
1878 struct lcommunity *lcom = NULL;
1879 char *sp;
1880 int additive = 0;
1881 int none = 0;
1882
1883 if (strcmp(arg, "none") == 0)
1884 none = 1;
1885 else {
1886 sp = strstr(arg, "additive");
1887
1888 if (sp && sp > arg) {
1889 /* "additive" keyworkd is included. */
1890 additive = 1;
1891 *(sp - 1) = '\0';
1892 }
57d187bc 1893
d62a17ae 1894 lcom = lcommunity_str2com(arg);
57d187bc 1895
d62a17ae 1896 if (additive)
1897 *(sp - 1) = ' ';
57d187bc 1898
d62a17ae 1899 if (!lcom)
1900 return NULL;
1901 }
57d187bc 1902
d62a17ae 1903 rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
1904 rcs->lcom = lcom;
1905 rcs->additive = additive;
1906 rcs->none = none;
57d187bc 1907
d62a17ae 1908 return rcs;
57d187bc
JS
1909}
1910
1911/* Free function for set lcommunity. */
d62a17ae 1912static void route_set_lcommunity_free(void *rule)
57d187bc 1913{
d62a17ae 1914 struct rmap_lcom_set *rcs = rule;
57d187bc 1915
d62a17ae 1916 if (rcs->lcom) {
1917 lcommunity_free(&rcs->lcom);
1918 }
1919 XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
57d187bc
JS
1920}
1921
1922/* Set community rule structure. */
d62a17ae 1923struct route_map_rule_cmd route_set_lcommunity_cmd = {
9d303b37 1924 "large-community", route_set_lcommunity, route_set_lcommunity_compile,
d62a17ae 1925 route_set_lcommunity_free,
57d187bc
JS
1926};
1927
1928/* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
1929
1930/* For large community set mechanism. */
d62a17ae 1931static route_map_result_t route_set_lcommunity_delete(void *rule,
123214ef 1932 const struct prefix *pfx,
d62a17ae 1933 route_map_object_t type,
1934 void *object)
1935{
1936 struct community_list *list;
1937 struct lcommunity *merge;
1938 struct lcommunity *new;
1939 struct lcommunity *old;
4b7e6066 1940 struct bgp_path_info *binfo;
d62a17ae 1941
1942 if (type == RMAP_BGP) {
1943 if (!rule)
1944 return RMAP_OKAY;
1945
1946 binfo = object;
1947 list = community_list_lookup(bgp_clist, rule,
1948 LARGE_COMMUNITY_LIST_MASTER);
1949 old = binfo->attr->lcommunity;
1950
1951 if (list && old) {
1952 merge = lcommunity_list_match_delete(
1953 lcommunity_dup(old), list);
1954 new = lcommunity_uniq_sort(merge);
1955 lcommunity_free(&merge);
1956
1957 /* HACK: if the old community is not intern'd,
1958 * we should free it here, or all reference to it may be
1959 * lost.
1960 * Really need to cleanup attribute caching sometime.
1961 */
1962 if (old->refcnt == 0)
1963 lcommunity_free(&old);
1964
1965 if (new->size == 0) {
1966 binfo->attr->lcommunity = NULL;
1967 binfo->attr->flag &= ~ATTR_FLAG_BIT(
1968 BGP_ATTR_LARGE_COMMUNITIES);
1969 lcommunity_free(&new);
1970 } else {
1971 binfo->attr->lcommunity = new;
1972 binfo->attr->flag |= ATTR_FLAG_BIT(
1973 BGP_ATTR_LARGE_COMMUNITIES);
1974 }
1975 }
1976 }
1977
1978 return RMAP_OKAY;
57d187bc
JS
1979}
1980
1981/* Compile function for set lcommunity. */
d62a17ae 1982static void *route_set_lcommunity_delete_compile(const char *arg)
57d187bc 1983{
d62a17ae 1984 char *p;
1985 char *str;
1986 int len;
57d187bc 1987
d62a17ae 1988 p = strchr(arg, ' ');
1989 if (p) {
1990 len = p - arg;
1991 str = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1992 memcpy(str, arg, len);
1993 } else
1994 str = NULL;
57d187bc 1995
d62a17ae 1996 return str;
57d187bc
JS
1997}
1998
1999/* Free function for set lcommunity. */
d62a17ae 2000static void route_set_lcommunity_delete_free(void *rule)
57d187bc 2001{
d62a17ae 2002 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
57d187bc
JS
2003}
2004
2005/* Set lcommunity rule structure. */
d62a17ae 2006struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
9d303b37
DL
2007 "large-comm-list", route_set_lcommunity_delete,
2008 route_set_lcommunity_delete_compile, route_set_lcommunity_delete_free,
57d187bc
JS
2009};
2010
2011
fee6e4e4 2012/* `set comm-list (<1-99>|<100-500>|WORD) delete' */
718e3744 2013
2014/* For community set mechanism. */
123214ef
MS
2015static route_map_result_t route_set_community_delete(
2016 void *rule,
2017 const struct prefix *prefix,
2018 route_map_object_t type,
2019 void *object)
d62a17ae 2020{
2021 struct community_list *list;
2022 struct community *merge;
2023 struct community *new;
2024 struct community *old;
4b7e6066 2025 struct bgp_path_info *binfo;
d62a17ae 2026
2027 if (type == RMAP_BGP) {
2028 if (!rule)
2029 return RMAP_OKAY;
2030
2031 binfo = object;
2032 list = community_list_lookup(bgp_clist, rule,
2033 COMMUNITY_LIST_MASTER);
2034 old = binfo->attr->community;
2035
2036 if (list && old) {
2037 merge = community_list_match_delete(community_dup(old),
2038 list);
2039 new = community_uniq_sort(merge);
2040 community_free(merge);
2041
2042 /* HACK: if the old community is not intern'd,
2043 * we should free it here, or all reference to it may be
2044 * lost.
2045 * Really need to cleanup attribute caching sometime.
2046 */
2047 if (old->refcnt == 0)
2048 community_free(old);
2049
2050 if (new->size == 0) {
2051 binfo->attr->community = NULL;
2052 binfo->attr->flag &=
2053 ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
2054 community_free(new);
2055 } else {
2056 binfo->attr->community = new;
2057 binfo->attr->flag |=
2058 ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
2059 }
2060 }
718e3744 2061 }
718e3744 2062
d62a17ae 2063 return RMAP_OKAY;
718e3744 2064}
2065
2066/* Compile function for set community. */
d62a17ae 2067static void *route_set_community_delete_compile(const char *arg)
718e3744 2068{
d62a17ae 2069 char *p;
2070 char *str;
2071 int len;
718e3744 2072
d62a17ae 2073 p = strchr(arg, ' ');
2074 if (p) {
2075 len = p - arg;
2076 str = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
2077 memcpy(str, arg, len);
2078 } else
2079 str = NULL;
718e3744 2080
d62a17ae 2081 return str;
718e3744 2082}
2083
2084/* Free function for set community. */
d62a17ae 2085static void route_set_community_delete_free(void *rule)
718e3744 2086{
d62a17ae 2087 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2088}
2089
2090/* Set community rule structure. */
d62a17ae 2091struct route_map_rule_cmd route_set_community_delete_cmd = {
9d303b37
DL
2092 "comm-list", route_set_community_delete,
2093 route_set_community_delete_compile, route_set_community_delete_free,
718e3744 2094};
6b0655a2 2095
718e3744 2096/* `set extcommunity rt COMMUNITY' */
2097
73d78ea0 2098/* For community set mechanism. Used by _rt and _soo. */
d62a17ae 2099static route_map_result_t route_set_ecommunity(void *rule,
123214ef 2100 const struct prefix *prefix,
d62a17ae 2101 route_map_object_t type,
2102 void *object)
2103{
2104 struct ecommunity *ecom;
2105 struct ecommunity *new_ecom;
2106 struct ecommunity *old_ecom;
4b7e6066 2107 struct bgp_path_info *bgp_info;
d62a17ae 2108
2109 if (type == RMAP_BGP) {
2110 ecom = rule;
2111 bgp_info = object;
2112
2113 if (!ecom)
2114 return RMAP_OKAY;
2115
2116 /* We assume additive for Extended Community. */
2117 old_ecom = bgp_info->attr->ecommunity;
2118
2119 if (old_ecom) {
2120 new_ecom = ecommunity_merge(ecommunity_dup(old_ecom),
2121 ecom);
2122
2123 /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
2124 * bgp_update_receive()
2125 * ->refcnt = 0 => set by a previous route-map
2126 * statement */
2127 if (!old_ecom->refcnt)
2128 ecommunity_free(&old_ecom);
2129 } else
2130 new_ecom = ecommunity_dup(ecom);
2131
2132 /* will be intern()'d or attr_flush()'d by bgp_update_main() */
2133 bgp_info->attr->ecommunity = new_ecom;
2134
2135 bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
27bf90a1 2136 }
d62a17ae 2137 return RMAP_OKAY;
718e3744 2138}
2139
2140/* Compile function for set community. */
d62a17ae 2141static void *route_set_ecommunity_rt_compile(const char *arg)
718e3744 2142{
d62a17ae 2143 struct ecommunity *ecom;
718e3744 2144
d62a17ae 2145 ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0);
2146 if (!ecom)
2147 return NULL;
2148 return ecommunity_intern(ecom);
718e3744 2149}
2150
73d78ea0 2151/* Free function for set community. Used by _rt and _soo */
d62a17ae 2152static void route_set_ecommunity_free(void *rule)
718e3744 2153{
d62a17ae 2154 struct ecommunity *ecom = rule;
2155 ecommunity_unintern(&ecom);
718e3744 2156}
2157
2158/* Set community rule structure. */
d62a17ae 2159struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
9d303b37
DL
2160 "extcommunity rt", route_set_ecommunity,
2161 route_set_ecommunity_rt_compile, route_set_ecommunity_free,
718e3744 2162};
2163
2164/* `set extcommunity soo COMMUNITY' */
2165
718e3744 2166/* Compile function for set community. */
d62a17ae 2167static void *route_set_ecommunity_soo_compile(const char *arg)
718e3744 2168{
d62a17ae 2169 struct ecommunity *ecom;
718e3744 2170
d62a17ae 2171 ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0);
2172 if (!ecom)
2173 return NULL;
e52702f2 2174
d62a17ae 2175 return ecommunity_intern(ecom);
718e3744 2176}
2177
718e3744 2178/* Set community rule structure. */
d62a17ae 2179struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
9d303b37
DL
2180 "extcommunity soo", route_set_ecommunity,
2181 route_set_ecommunity_soo_compile, route_set_ecommunity_free,
718e3744 2182};
6b0655a2 2183
718e3744 2184/* `set origin ORIGIN' */
2185
2186/* For origin set. */
123214ef
MS
2187static route_map_result_t route_set_origin(void *rule,
2188 const struct prefix *prefix,
d62a17ae 2189 route_map_object_t type,
2190 void *object)
718e3744 2191{
d7c0a89a 2192 uint8_t *origin;
4b7e6066 2193 struct bgp_path_info *bgp_info;
718e3744 2194
d62a17ae 2195 if (type == RMAP_BGP) {
2196 origin = rule;
2197 bgp_info = object;
e52702f2 2198
d62a17ae 2199 bgp_info->attr->origin = *origin;
2200 }
718e3744 2201
d62a17ae 2202 return RMAP_OKAY;
718e3744 2203}
2204
2205/* Compile function for origin set. */
d62a17ae 2206static void *route_set_origin_compile(const char *arg)
718e3744 2207{
d7c0a89a 2208 uint8_t *origin;
718e3744 2209
d7c0a89a 2210 origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
718e3744 2211
d62a17ae 2212 if (strcmp(arg, "igp") == 0)
2213 *origin = 0;
2214 else if (strcmp(arg, "egp") == 0)
2215 *origin = 1;
2216 else
2217 *origin = 2;
718e3744 2218
d62a17ae 2219 return origin;
718e3744 2220}
2221
2222/* Compile function for origin set. */
d62a17ae 2223static void route_set_origin_free(void *rule)
718e3744 2224{
d62a17ae 2225 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2226}
2227
515e500c 2228/* Set origin rule structure. */
d62a17ae 2229struct route_map_rule_cmd route_set_origin_cmd = {
9d303b37 2230 "origin", route_set_origin, route_set_origin_compile,
d62a17ae 2231 route_set_origin_free,
718e3744 2232};
6b0655a2 2233
718e3744 2234/* `set atomic-aggregate' */
2235
2236/* For atomic aggregate set. */
d62a17ae 2237static route_map_result_t route_set_atomic_aggregate(void *rule,
123214ef 2238 const struct prefix *pfx,
d62a17ae 2239 route_map_object_t type,
2240 void *object)
718e3744 2241{
4b7e6066 2242 struct bgp_path_info *bgp_info;
718e3744 2243
d62a17ae 2244 if (type == RMAP_BGP) {
2245 bgp_info = object;
2246 bgp_info->attr->flag |=
2247 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
2248 }
718e3744 2249
d62a17ae 2250 return RMAP_OKAY;
718e3744 2251}
2252
2253/* Compile function for atomic aggregate. */
d62a17ae 2254static void *route_set_atomic_aggregate_compile(const char *arg)
718e3744 2255{
d62a17ae 2256 return (void *)1;
718e3744 2257}
2258
2259/* Compile function for atomic aggregate. */
d62a17ae 2260static void route_set_atomic_aggregate_free(void *rule)
718e3744 2261{
d62a17ae 2262 return;
718e3744 2263}
2264
2265/* Set atomic aggregate rule structure. */
d62a17ae 2266struct route_map_rule_cmd route_set_atomic_aggregate_cmd = {
9d303b37
DL
2267 "atomic-aggregate", route_set_atomic_aggregate,
2268 route_set_atomic_aggregate_compile, route_set_atomic_aggregate_free,
718e3744 2269};
6b0655a2 2270
718e3744 2271/* `set aggregator as AS A.B.C.D' */
d62a17ae 2272struct aggregator {
2273 as_t as;
2274 struct in_addr address;
718e3744 2275};
2276
d62a17ae 2277static route_map_result_t route_set_aggregator_as(void *rule,
123214ef 2278 const struct prefix *prefix,
d62a17ae 2279 route_map_object_t type,
2280 void *object)
718e3744 2281{
4b7e6066 2282 struct bgp_path_info *bgp_info;
d62a17ae 2283 struct aggregator *aggregator;
718e3744 2284
d62a17ae 2285 if (type == RMAP_BGP) {
2286 bgp_info = object;
2287 aggregator = rule;
e52702f2 2288
d62a17ae 2289 bgp_info->attr->aggregator_as = aggregator->as;
2290 bgp_info->attr->aggregator_addr = aggregator->address;
2291 bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
2292 }
718e3744 2293
d62a17ae 2294 return RMAP_OKAY;
718e3744 2295}
2296
d62a17ae 2297static void *route_set_aggregator_as_compile(const char *arg)
718e3744 2298{
d62a17ae 2299 struct aggregator *aggregator;
2300 char as[10];
2301 char address[20];
2302 int ret;
718e3744 2303
d62a17ae 2304 aggregator =
2305 XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct aggregator));
116e176d
DS
2306 if (sscanf(arg, "%s %s", as, address) != 2) {
2307 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
2308 return NULL;
2309 }
718e3744 2310
d62a17ae 2311 aggregator->as = strtoul(as, NULL, 10);
2312 ret = inet_aton(address, &aggregator->address);
2313 if (ret == 0) {
2314 XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
2315 return NULL;
2316 }
2317 return aggregator;
718e3744 2318}
2319
d62a17ae 2320static void route_set_aggregator_as_free(void *rule)
718e3744 2321{
d62a17ae 2322 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2323}
2324
d62a17ae 2325struct route_map_rule_cmd route_set_aggregator_as_cmd = {
9d303b37
DL
2326 "aggregator as", route_set_aggregator_as,
2327 route_set_aggregator_as_compile, route_set_aggregator_as_free,
718e3744 2328};
6b0655a2 2329
4b7e6066 2330/* Set tag to object. object must be pointer to struct bgp_path_info */
123214ef
MS
2331static route_map_result_t route_set_tag(void *rule,
2332 const struct prefix *prefix,
d62a17ae 2333 route_map_object_t type, void *object)
0d9551dc 2334{
d62a17ae 2335 route_tag_t *tag;
4b7e6066 2336 struct bgp_path_info *bgp_info;
0d9551dc 2337
d62a17ae 2338 if (type == RMAP_BGP) {
2339 tag = rule;
2340 bgp_info = object;
0d9551dc 2341
d62a17ae 2342 /* Set tag value */
2343 bgp_info->attr->tag = *tag;
2344 }
0d9551dc 2345
d62a17ae 2346 return RMAP_OKAY;
0d9551dc
DS
2347}
2348
0d9551dc 2349/* Route map commands for tag set. */
d62a17ae 2350static struct route_map_rule_cmd route_set_tag_cmd = {
9d303b37 2351 "tag", route_set_tag, route_map_rule_tag_compile,
d62a17ae 2352 route_map_rule_tag_free,
0d9551dc
DS
2353};
2354
4b7e6066 2355/* Set label-index to object. object must be pointer to struct bgp_path_info */
d62a17ae 2356static route_map_result_t route_set_label_index(void *rule,
123214ef 2357 const struct prefix *prefix,
d62a17ae 2358 route_map_object_t type,
2359 void *object)
2360{
2361 struct rmap_value *rv;
4b7e6066 2362 struct bgp_path_info *bgp_info;
d7c0a89a 2363 uint32_t label_index;
d62a17ae 2364
2365 if (type == RMAP_BGP) {
2366 /* Fetch routemap's rule information. */
2367 rv = rule;
2368 bgp_info = object;
2369
2370 /* Set label-index value. */
2371 label_index = rv->value;
2372 if (label_index) {
2373 bgp_info->attr->label_index = label_index;
2374 bgp_info->attr->flag |=
2375 ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
2376 }
2377 }
d990e384 2378
d62a17ae 2379 return RMAP_OKAY;
d990e384
DS
2380}
2381
2382/* Route map commands for label-index set. */
d62a17ae 2383static struct route_map_rule_cmd route_set_label_index_cmd = {
9d303b37 2384 "label-index", route_set_label_index, route_value_compile,
d62a17ae 2385 route_value_free,
d990e384 2386};
0d9551dc 2387
718e3744 2388/* `match ipv6 address IP_ACCESS_LIST' */
2389
d62a17ae 2390static route_map_result_t route_match_ipv6_address(void *rule,
123214ef 2391 const struct prefix *prefix,
d62a17ae 2392 route_map_object_t type,
2393 void *object)
718e3744 2394{
d62a17ae 2395 struct access_list *alist;
718e3744 2396
09cd98eb 2397 if (type == RMAP_BGP && prefix->family == AF_INET6) {
d62a17ae 2398 alist = access_list_lookup(AFI_IP6, (char *)rule);
2399 if (alist == NULL)
2400 return RMAP_NOMATCH;
e52702f2 2401
d62a17ae 2402 return (access_list_apply(alist, prefix) == FILTER_DENY
2403 ? RMAP_NOMATCH
2404 : RMAP_MATCH);
2405 }
2406 return RMAP_NOMATCH;
718e3744 2407}
2408
d62a17ae 2409static void *route_match_ipv6_address_compile(const char *arg)
718e3744 2410{
d62a17ae 2411 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 2412}
2413
d62a17ae 2414static void route_match_ipv6_address_free(void *rule)
718e3744 2415{
d62a17ae 2416 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2417}
2418
2419/* Route map commands for ip address matching. */
d62a17ae 2420struct route_map_rule_cmd route_match_ipv6_address_cmd = {
2421 "ipv6 address", route_match_ipv6_address,
2422 route_match_ipv6_address_compile, route_match_ipv6_address_free};
6b0655a2 2423
718e3744 2424/* `match ipv6 next-hop IP_ADDRESS' */
2425
d62a17ae 2426static route_map_result_t route_match_ipv6_next_hop(void *rule,
123214ef 2427 const struct prefix *prefix,
d62a17ae 2428 route_map_object_t type,
2429 void *object)
718e3744 2430{
d62a17ae 2431 struct in6_addr *addr = rule;
4b7e6066 2432 struct bgp_path_info *bgp_info;
718e3744 2433
d62a17ae 2434 if (type == RMAP_BGP) {
2435 bgp_info = object;
e52702f2 2436
d62a17ae 2437 if (IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_global, addr))
2438 return RMAP_MATCH;
718e3744 2439
d62a17ae 2440 if (bgp_info->attr->mp_nexthop_len
2441 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
2442 && IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_local, rule))
2443 return RMAP_MATCH;
718e3744 2444
d62a17ae 2445 return RMAP_NOMATCH;
2446 }
718e3744 2447
d62a17ae 2448 return RMAP_NOMATCH;
718e3744 2449}
2450
d62a17ae 2451static void *route_match_ipv6_next_hop_compile(const char *arg)
718e3744 2452{
d62a17ae 2453 struct in6_addr *address;
2454 int ret;
718e3744 2455
d62a17ae 2456 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 2457
d62a17ae 2458 ret = inet_pton(AF_INET6, arg, address);
2459 if (!ret) {
2460 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2461 return NULL;
2462 }
718e3744 2463
d62a17ae 2464 return address;
718e3744 2465}
2466
d62a17ae 2467static void route_match_ipv6_next_hop_free(void *rule)
718e3744 2468{
d62a17ae 2469 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2470}
2471
d62a17ae 2472struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
2473 "ipv6 next-hop", route_match_ipv6_next_hop,
2474 route_match_ipv6_next_hop_compile, route_match_ipv6_next_hop_free};
6b0655a2 2475
718e3744 2476/* `match ipv6 address prefix-list PREFIX_LIST' */
2477
94f2b392 2478static route_map_result_t
123214ef 2479route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
d62a17ae 2480 route_map_object_t type, void *object)
718e3744 2481{
d62a17ae 2482 struct prefix_list *plist;
718e3744 2483
09cd98eb 2484 if (type == RMAP_BGP && prefix->family == AF_INET6) {
d62a17ae 2485 plist = prefix_list_lookup(AFI_IP6, (char *)rule);
2486 if (plist == NULL)
2487 return RMAP_NOMATCH;
e52702f2 2488
d62a17ae 2489 return (prefix_list_apply(plist, prefix) == PREFIX_DENY
2490 ? RMAP_NOMATCH
2491 : RMAP_MATCH);
2492 }
2493 return RMAP_NOMATCH;
718e3744 2494}
2495
d62a17ae 2496static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
718e3744 2497{
d62a17ae 2498 return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
718e3744 2499}
2500
d62a17ae 2501static void route_match_ipv6_address_prefix_list_free(void *rule)
718e3744 2502{
d62a17ae 2503 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2504}
2505
d62a17ae 2506struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
2507 "ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
2508 route_match_ipv6_address_prefix_list_compile,
2509 route_match_ipv6_address_prefix_list_free};
6b0655a2 2510
61ad901e
DA
2511/* `match ipv6 next-hop type <TYPE>' */
2512
2513static route_map_result_t
2514route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
2515 route_map_object_t type, void *object)
2516{
4b7e6066 2517 struct bgp_path_info *bgp_info;
61ad901e
DA
2518 struct in6_addr *addr = rule;
2519
2520 if (type == RMAP_BGP && prefix->family == AF_INET6) {
4b7e6066 2521 bgp_info = (struct bgp_path_info *)object;
61ad901e
DA
2522 if (!bgp_info || !bgp_info->attr)
2523 return RMAP_DENYMATCH;
2524
2525 if (IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_global, addr)
2526 && !bgp_info->attr->nh_ifindex)
2527 return RMAP_MATCH;
2528 }
2529 return RMAP_NOMATCH;
2530}
2531
2532static void *route_match_ipv6_next_hop_type_compile(const char *arg)
2533{
2534 struct in6_addr *address;
2535 int ret;
2536
2537 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
2538
2539 ret = inet_pton(AF_INET6, "::0", address);
2540 if (!ret) {
2541 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2542 return NULL;
2543 }
2544
2545 return address;
2546}
2547
2548static void route_match_ipv6_next_hop_type_free(void *rule)
2549{
2550 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2551}
2552
2553struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd = {
2554 "ipv6 next-hop type", route_match_ipv6_next_hop_type,
2555 route_match_ipv6_next_hop_type_compile,
2556 route_match_ipv6_next_hop_type_free};
2557
718e3744 2558/* `set ipv6 nexthop global IP_ADDRESS' */
2559
2560/* Set nexthop to object. ojbect must be pointer to struct attr. */
d62a17ae 2561static route_map_result_t route_set_ipv6_nexthop_global(void *rule,
123214ef 2562 const struct prefix *p,
d62a17ae 2563 route_map_object_t type,
2564 void *object)
718e3744 2565{
d62a17ae 2566 struct in6_addr *address;
4b7e6066 2567 struct bgp_path_info *bgp_info;
718e3744 2568
d62a17ae 2569 if (type == RMAP_BGP) {
2570 /* Fetch routemap's rule information. */
2571 address = rule;
2572 bgp_info = object;
e52702f2 2573
d62a17ae 2574 /* Set next hop value. */
2575 bgp_info->attr->mp_nexthop_global = *address;
3f9c7369 2576
d62a17ae 2577 /* Set nexthop length. */
2578 if (bgp_info->attr->mp_nexthop_len == 0)
2579 bgp_info->attr->mp_nexthop_len =
2580 BGP_ATTR_NHLEN_IPV6_GLOBAL;
3f9c7369 2581
d62a17ae 2582 SET_FLAG(bgp_info->attr->rmap_change_flags,
2583 BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
2584 }
718e3744 2585
d62a17ae 2586 return RMAP_OKAY;
718e3744 2587}
2588
2589/* Route map `ip next-hop' compile function. Given string is converted
2590 to struct in_addr structure. */
d62a17ae 2591static void *route_set_ipv6_nexthop_global_compile(const char *arg)
718e3744 2592{
d62a17ae 2593 int ret;
2594 struct in6_addr *address;
718e3744 2595
d62a17ae 2596 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 2597
d62a17ae 2598 ret = inet_pton(AF_INET6, arg, address);
718e3744 2599
d62a17ae 2600 if (ret == 0) {
2601 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2602 return NULL;
2603 }
718e3744 2604
d62a17ae 2605 return address;
718e3744 2606}
2607
2608/* Free route map's compiled `ip next-hop' value. */
d62a17ae 2609static void route_set_ipv6_nexthop_global_free(void *rule)
718e3744 2610{
d62a17ae 2611 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2612}
2613
2614/* Route map commands for ip nexthop set. */
d62a17ae 2615struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd = {
2616 "ipv6 next-hop global", route_set_ipv6_nexthop_global,
2617 route_set_ipv6_nexthop_global_compile,
2618 route_set_ipv6_nexthop_global_free};
6b0655a2 2619
161995ea
DS
2620/* Set next-hop preference value. */
2621static route_map_result_t
123214ef 2622route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
d62a17ae 2623 route_map_object_t type, void *object)
2624{
4b7e6066 2625 struct bgp_path_info *bgp_info;
d62a17ae 2626 struct peer *peer;
2627
2628 if (type == RMAP_BGP) {
2629 /* Fetch routemap's rule information. */
2630 bgp_info = object;
2631 peer = bgp_info->peer;
2632
2633 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
2634 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
2635 && peer->su_remote
2636 && sockunion_family(peer->su_remote) == AF_INET6) {
2637 /* Set next hop preference to global */
2638 bgp_info->attr->mp_nexthop_prefer_global = TRUE;
2639 SET_FLAG(bgp_info->attr->rmap_change_flags,
2640 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
2641 } else {
2642 bgp_info->attr->mp_nexthop_prefer_global = FALSE;
2643 SET_FLAG(bgp_info->attr->rmap_change_flags,
2644 BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
2645 }
161995ea 2646 }
d62a17ae 2647 return RMAP_OKAY;
161995ea
DS
2648}
2649
d62a17ae 2650static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg)
161995ea 2651{
d62a17ae 2652 int *rins = NULL;
161995ea 2653
d62a17ae 2654 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
2655 *rins = 1;
161995ea 2656
d62a17ae 2657 return rins;
161995ea
DS
2658}
2659
2660/* Free route map's compiled `ip next-hop' value. */
d62a17ae 2661static void route_set_ipv6_nexthop_prefer_global_free(void *rule)
161995ea 2662{
d62a17ae 2663 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
161995ea
DS
2664}
2665
2666/* Route map commands for ip nexthop set preferred. */
d62a17ae 2667struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd = {
2668 "ipv6 next-hop prefer-global", route_set_ipv6_nexthop_prefer_global,
2669 route_set_ipv6_nexthop_prefer_global_compile,
2670 route_set_ipv6_nexthop_prefer_global_free};
161995ea 2671
718e3744 2672/* `set ipv6 nexthop local IP_ADDRESS' */
2673
2674/* Set nexthop to object. ojbect must be pointer to struct attr. */
d62a17ae 2675static route_map_result_t route_set_ipv6_nexthop_local(void *rule,
123214ef 2676 const struct prefix *p,
d62a17ae 2677 route_map_object_t type,
2678 void *object)
2679{
2680 struct in6_addr *address;
4b7e6066 2681 struct bgp_path_info *bgp_info;
d62a17ae 2682
2683 if (type == RMAP_BGP) {
2684 /* Fetch routemap's rule information. */
2685 address = rule;
2686 bgp_info = object;
2687
2688 /* Set next hop value. */
2689 bgp_info->attr->mp_nexthop_local = *address;
2690
2691 /* Set nexthop length. */
2692 if (bgp_info->attr->mp_nexthop_len
2693 != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
2694 bgp_info->attr->mp_nexthop_len =
2695 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2696
2697 SET_FLAG(bgp_info->attr->rmap_change_flags,
2698 BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
2699 }
718e3744 2700
d62a17ae 2701 return RMAP_OKAY;
718e3744 2702}
2703
2704/* Route map `ip nexthop' compile function. Given string is converted
2705 to struct in_addr structure. */
d62a17ae 2706static void *route_set_ipv6_nexthop_local_compile(const char *arg)
718e3744 2707{
d62a17ae 2708 int ret;
2709 struct in6_addr *address;
718e3744 2710
d62a17ae 2711 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
718e3744 2712
d62a17ae 2713 ret = inet_pton(AF_INET6, arg, address);
718e3744 2714
d62a17ae 2715 if (ret == 0) {
2716 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2717 return NULL;
2718 }
718e3744 2719
d62a17ae 2720 return address;
718e3744 2721}
2722
2723/* Free route map's compiled `ip nexthop' value. */
d62a17ae 2724static void route_set_ipv6_nexthop_local_free(void *rule)
718e3744 2725{
d62a17ae 2726 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2727}
2728
2729/* Route map commands for ip nexthop set. */
d62a17ae 2730struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = {
2731 "ipv6 next-hop local", route_set_ipv6_nexthop_local,
2732 route_set_ipv6_nexthop_local_compile,
2733 route_set_ipv6_nexthop_local_free};
90916ac2
DS
2734
2735/* `set ipv6 nexthop peer-address' */
2736
2737/* Set nexthop to object. ojbect must be pointer to struct attr. */
d62a17ae 2738static route_map_result_t route_set_ipv6_nexthop_peer(void *rule,
123214ef 2739 const struct prefix *pfx,
d62a17ae 2740 route_map_object_t type,
2741 void *object)
2742{
2743 struct in6_addr peer_address;
4b7e6066 2744 struct bgp_path_info *bgp_info;
d62a17ae 2745 struct peer *peer;
2746
2747 if (type == RMAP_BGP) {
2748 /* Fetch routemap's rule information. */
2749 bgp_info = object;
2750 peer = bgp_info->peer;
2751
2752 if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
2753 || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
2754 && peer->su_remote
2755 && sockunion_family(peer->su_remote) == AF_INET6) {
2756 peer_address = peer->su_remote->sin6.sin6_addr;
2757 /* Set next hop value and length in attribute. */
2758 if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
2759 bgp_info->attr->mp_nexthop_local = peer_address;
2760 if (bgp_info->attr->mp_nexthop_len != 32)
2761 bgp_info->attr->mp_nexthop_len = 32;
2762 } else {
2763 bgp_info->attr->mp_nexthop_global =
2764 peer_address;
2765 if (bgp_info->attr->mp_nexthop_len == 0)
2766 bgp_info->attr->mp_nexthop_len = 16;
2767 }
2768
2769 } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
2770 /* The next hop value will be set as part of packet
2771 * rewrite.
2772 * Set the flags here to indicate that rewrite needs to
2773 * be done.
2774 * Also, clear the value - we clear both global and
2775 * link-local
2776 * nexthops, whether we send one or both is determined
2777 * elsewhere.
2778 */
2779 SET_FLAG(bgp_info->attr->rmap_change_flags,
2780 BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
2781 /* clear next hop value. */
2782 memset(&(bgp_info->attr->mp_nexthop_global), 0,
2783 sizeof(struct in6_addr));
2784 memset(&(bgp_info->attr->mp_nexthop_local), 0,
2785 sizeof(struct in6_addr));
2786 }
90916ac2 2787 }
90916ac2 2788
d62a17ae 2789 return RMAP_OKAY;
90916ac2
DS
2790}
2791
2792/* Route map `ip next-hop' compile function. Given string is converted
2793 to struct in_addr structure. */
d62a17ae 2794static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
90916ac2 2795{
d62a17ae 2796 int *rins = NULL;
90916ac2 2797
d62a17ae 2798 rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
2799 *rins = 1;
90916ac2 2800
d62a17ae 2801 return rins;
90916ac2
DS
2802}
2803
2804/* Free route map's compiled `ip next-hop' value. */
d62a17ae 2805static void route_set_ipv6_nexthop_peer_free(void *rule)
90916ac2 2806{
d62a17ae 2807 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
90916ac2
DS
2808}
2809
2810/* Route map commands for ip nexthop set. */
d62a17ae 2811struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
2812 "ipv6 next-hop peer-address", route_set_ipv6_nexthop_peer,
2813 route_set_ipv6_nexthop_peer_compile, route_set_ipv6_nexthop_peer_free};
90916ac2 2814
69ba6dd7 2815/* `set ipv4 vpn next-hop A.B.C.D' */
718e3744 2816
d62a17ae 2817static route_map_result_t route_set_vpnv4_nexthop(void *rule,
123214ef 2818 const struct prefix *prefix,
d62a17ae 2819 route_map_object_t type,
2820 void *object)
718e3744 2821{
d62a17ae 2822 struct in_addr *address;
4b7e6066 2823 struct bgp_path_info *bgp_info;
718e3744 2824
d62a17ae 2825 if (type == RMAP_BGP) {
2826 /* Fetch routemap's rule information. */
2827 address = rule;
2828 bgp_info = object;
e52702f2 2829
d62a17ae 2830 /* Set next hop value. */
2831 bgp_info->attr->mp_nexthop_global_in = *address;
2832 bgp_info->attr->mp_nexthop_len = 4;
2833 }
718e3744 2834
d62a17ae 2835 return RMAP_OKAY;
718e3744 2836}
2837
d62a17ae 2838static void *route_set_vpnv4_nexthop_compile(const char *arg)
718e3744 2839{
d62a17ae 2840 int ret;
2841 struct in_addr *address;
718e3744 2842
d62a17ae 2843 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 2844
d62a17ae 2845 ret = inet_aton(arg, address);
718e3744 2846
d62a17ae 2847 if (ret == 0) {
2848 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2849 return NULL;
2850 }
718e3744 2851
d62a17ae 2852 return address;
718e3744 2853}
2854
69ba6dd7 2855/* `set ipv6 vpn next-hop A.B.C.D' */
d6902373 2856
d62a17ae 2857static route_map_result_t route_set_vpnv6_nexthop(void *rule,
123214ef 2858 const struct prefix *prefix,
d62a17ae 2859 route_map_object_t type,
2860 void *object)
d6902373 2861{
d62a17ae 2862 struct in6_addr *address;
4b7e6066 2863 struct bgp_path_info *bgp_info;
d6902373 2864
d62a17ae 2865 if (type == RMAP_BGP) {
2866 /* Fetch routemap's rule information. */
2867 address = rule;
2868 bgp_info = object;
d6902373 2869
d62a17ae 2870 /* Set next hop value. */
2871 memcpy(&bgp_info->attr->mp_nexthop_global, address,
2872 sizeof(struct in6_addr));
2873 bgp_info->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
2874 }
d6902373 2875
d62a17ae 2876 return RMAP_OKAY;
d6902373
PG
2877}
2878
d62a17ae 2879static void *route_set_vpnv6_nexthop_compile(const char *arg)
d6902373 2880{
d62a17ae 2881 int ret;
2882 struct in6_addr *address;
d6902373 2883
d62a17ae 2884 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
2885 ret = inet_pton(AF_INET6, arg, address);
d6902373 2886
d62a17ae 2887 if (ret == 0) {
2888 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2889 return NULL;
2890 }
d6902373 2891
d62a17ae 2892 return address;
d6902373
PG
2893}
2894
d62a17ae 2895static void route_set_vpn_nexthop_free(void *rule)
718e3744 2896{
d62a17ae 2897 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2898}
2899
69ba6dd7 2900/* Route map commands for ipv4 next-hop set. */
d62a17ae 2901struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
2902 "ipv4 vpn next-hop", route_set_vpnv4_nexthop,
2903 route_set_vpnv4_nexthop_compile, route_set_vpn_nexthop_free};
d6902373 2904
69ba6dd7 2905/* Route map commands for ipv6 next-hop set. */
d62a17ae 2906struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
2907 "ipv6 vpn next-hop", route_set_vpnv6_nexthop,
2908 route_set_vpnv6_nexthop_compile, route_set_vpn_nexthop_free};
6b0655a2 2909
718e3744 2910/* `set originator-id' */
2911
2912/* For origin set. */
d62a17ae 2913static route_map_result_t route_set_originator_id(void *rule,
123214ef 2914 const struct prefix *prefix,
d62a17ae 2915 route_map_object_t type,
2916 void *object)
718e3744 2917{
d62a17ae 2918 struct in_addr *address;
4b7e6066 2919 struct bgp_path_info *bgp_info;
718e3744 2920
d62a17ae 2921 if (type == RMAP_BGP) {
2922 address = rule;
2923 bgp_info = object;
e52702f2 2924
d62a17ae 2925 bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
2926 bgp_info->attr->originator_id = *address;
2927 }
718e3744 2928
d62a17ae 2929 return RMAP_OKAY;
718e3744 2930}
2931
2932/* Compile function for originator-id set. */
d62a17ae 2933static void *route_set_originator_id_compile(const char *arg)
718e3744 2934{
d62a17ae 2935 int ret;
2936 struct in_addr *address;
718e3744 2937
d62a17ae 2938 address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
718e3744 2939
d62a17ae 2940 ret = inet_aton(arg, address);
718e3744 2941
d62a17ae 2942 if (ret == 0) {
2943 XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2944 return NULL;
2945 }
718e3744 2946
d62a17ae 2947 return address;
718e3744 2948}
2949
2950/* Compile function for originator_id set. */
d62a17ae 2951static void route_set_originator_id_free(void *rule)
718e3744 2952{
d62a17ae 2953 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
718e3744 2954}
2955
515e500c 2956/* Set originator-id rule structure. */
d62a17ae 2957struct route_map_rule_cmd route_set_originator_id_cmd = {
9d303b37
DL
2958 "originator-id", route_set_originator_id,
2959 route_set_originator_id_compile, route_set_originator_id_free,
718e3744 2960};
6b0655a2 2961
718e3744 2962/* Add bgp route map rule. */
d62a17ae 2963static int bgp_route_match_add(struct vty *vty, const char *command,
2964 const char *arg, route_map_event_t type)
2965{
2966 VTY_DECLVAR_CONTEXT(route_map_index, index);
9ca25fed 2967 int retval = CMD_SUCCESS;
d62a17ae 2968 int ret;
2969
2970 ret = route_map_add_match(index, command, arg);
9ca25fed
DS
2971 switch (ret) {
2972 case RMAP_RULE_MISSING:
2973 vty_out(vty, "%% BGP Can't find rule.\n");
2974 retval = CMD_WARNING_CONFIG_FAILED;
2975 break;
2976 case RMAP_COMPILE_ERROR:
2977 vty_out(vty, "%% BGP Argument is malformed.\n");
2978 retval = CMD_WARNING_CONFIG_FAILED;
2979 break;
2980 case RMAP_COMPILE_SUCCESS:
2981 if (type != RMAP_EVENT_MATCH_ADDED) {
2982 route_map_upd8_dependency(type, arg, index->map->name);
d62a17ae 2983 }
9ca25fed 2984 break;
718e3744 2985 }
518f0eb1 2986
9ca25fed 2987 return retval;
718e3744 2988}
2989
2990/* Delete bgp route map rule. */
d62a17ae 2991static int bgp_route_match_delete(struct vty *vty, const char *command,
2992 const char *arg, route_map_event_t type)
2993{
2994 VTY_DECLVAR_CONTEXT(route_map_index, index);
2995 int ret;
9ca25fed 2996 int retval = CMD_SUCCESS;
d62a17ae 2997 char *dep_name = NULL;
2998 const char *tmpstr;
2999 char *rmap_name = NULL;
3000
3001 if (type != RMAP_EVENT_MATCH_DELETED) {
3002 /* ignore the mundane, the types without any dependency */
3003 if (arg == NULL) {
3004 if ((tmpstr = route_map_get_match_arg(index, command))
3005 != NULL)
3006 dep_name =
3007 XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
3008 } else {
3009 dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
3010 }
3011 rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
ffd0c037 3012 }
d62a17ae 3013
3014 ret = route_map_delete_match(index, command, dep_name);
9ca25fed
DS
3015 switch (ret) {
3016 case RMAP_RULE_MISSING:
3017 vty_out(vty, "%% BGP Can't find rule.\n");
3018 retval = CMD_WARNING_CONFIG_FAILED;
3019 break;
3020 case RMAP_COMPILE_ERROR:
3021 vty_out(vty, "%% BGP Argument is malformed.\n");
3022 retval = CMD_WARNING_CONFIG_FAILED;
3023 break;
3024 case RMAP_COMPILE_SUCCESS:
3025 if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
3026 route_map_upd8_dependency(type, dep_name, rmap_name);
3027 break;
718e3744 3028 }
518f0eb1 3029
d62a17ae 3030 if (dep_name)
3031 XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
3032 if (rmap_name)
3033 XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
518f0eb1 3034
9ca25fed 3035 return retval;
718e3744 3036}
3037
518f0eb1 3038/*
2a3d5731 3039 * This is the workhorse routine for processing in/out routemap
518f0eb1
DS
3040 * modifications.
3041 */
d62a17ae 3042static void bgp_route_map_process_peer(const char *rmap_name,
3043 struct route_map *map, struct peer *peer,
3044 int afi, int safi, int route_update)
3045{
3046
3047 int update;
3048 struct bgp_filter *filter;
3049
3050 if (!peer || !rmap_name)
3051 return;
3052
3053 filter = &peer->filter[afi][safi];
3054 /*
3055 * in is for non-route-server clients,
3056 * out is for all peers
3057 */
3058 if (!CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) {
3059 if (filter->map[RMAP_IN].name
3060 && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
3061 filter->map[RMAP_IN].map = map;
3062
3063 if (route_update && peer->status == Established) {
3064 if (CHECK_FLAG(peer->af_flags[afi][safi],
3065 PEER_FLAG_SOFT_RECONFIG)) {
3066 if (bgp_debug_update(peer, NULL, NULL,
3067 1))
3068 zlog_debug(
3069 "Processing route_map %s update on "
3070 "peer %s (inbound, soft-reconfig)",
3071 rmap_name, peer->host);
3072
3073 bgp_soft_reconfig_in(peer, afi, safi);
3074 } else if (
3075 CHECK_FLAG(peer->cap,
3076 PEER_CAP_REFRESH_OLD_RCV)
3077 || CHECK_FLAG(
3078 peer->cap,
3079 PEER_CAP_REFRESH_NEW_RCV)) {
3080
3081 if (bgp_debug_update(peer, NULL, NULL,
3082 1))
3083 zlog_debug(
3084 "Processing route_map %s update on "
3085 "peer %s (inbound, route-refresh)",
3086 rmap_name, peer->host);
3087 bgp_route_refresh_send(peer, afi, safi,
3088 0, 0, 0);
3089 }
3090 }
518f0eb1 3091 }
718e3744 3092 }
d62a17ae 3093
3094 if (CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) {
3095 update = 0;
3096
3097 if (update && route_update && peer->status == Established) {
3098 if (CHECK_FLAG(peer->af_flags[afi][safi],
3099 PEER_FLAG_SOFT_RECONFIG)) {
3100 if (bgp_debug_update(peer, NULL, NULL, 1))
3101 zlog_debug(
3102 "Processing route_map %s update on "
3103 "peer %s (import, soft-reconfig)",
3104 rmap_name, peer->host);
3105
3106 bgp_soft_reconfig_in(peer, afi, safi);
3107 } else if (CHECK_FLAG(peer->cap,
3108 PEER_CAP_REFRESH_OLD_RCV)
3109 || CHECK_FLAG(peer->cap,
3110 PEER_CAP_REFRESH_NEW_RCV)) {
3111 if (bgp_debug_update(peer, NULL, NULL, 1))
3112 zlog_debug(
3113 "Processing route_map %s update on "
3114 "peer %s (import, route-refresh)",
3115 rmap_name, peer->host);
3116 bgp_route_refresh_send(peer, afi, safi, 0, 0,
3117 0);
3118 }
3119 /* DD: Else, what else do we do ? Reset peer ? */
3120 }
518f0eb1 3121 }
d62a17ae 3122
3123 /*
3124 * For outbound, unsuppress and default-originate map change (content or
3125 * map created), merely update the "config" here, the actual route
3126 * announcement happens at the group level.
3127 */
3128 if (filter->map[RMAP_OUT].name
3129 && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
3130 filter->map[RMAP_OUT].map = map;
3131
3132 if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
3133 filter->usmap.map = map;
3134
3135 if (peer->default_rmap[afi][safi].name
3136 && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
3137 peer->default_rmap[afi][safi].map = map;
3138}
3139
3140static void bgp_route_map_update_peer_group(const char *rmap_name,
3141 struct route_map *map,
3142 struct bgp *bgp)
3143{
3144 struct peer_group *group;
3145 struct listnode *node, *nnode;
3146 struct bgp_filter *filter;
3147 int afi, safi;
3148 int direct;
3149
3150 if (!bgp)
3151 return;
3152
3153 /* All the peers have been updated correctly already. This is
3154 * just updating the placeholder data. No real update required.
3155 */
05c7a1cc
QY
3156 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
3157 FOREACH_AFI_SAFI (afi, safi) {
3158 filter = &group->conf->filter[afi][safi];
3159
3160 for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
3161 if ((filter->map[direct].name)
3162 && (strcmp(rmap_name,
3163 filter->map[direct].name)
d62a17ae 3164 == 0))
05c7a1cc 3165 filter->map[direct].map = map;
d62a17ae 3166 }
05c7a1cc
QY
3167
3168 if (filter->usmap.name
3169 && (strcmp(rmap_name, filter->usmap.name) == 0))
3170 filter->usmap.map = map;
3171 }
3172 }
518f0eb1
DS
3173}
3174
a6e0d253
DW
3175/*
3176 * Note that if an extreme number (tens of thousands) of route-maps are in use
3177 * and if bgp has an extreme number of peers, network statements, etc then this
3178 * function can consume a lot of cycles. This is due to this function being
3179 * called for each route-map and within this function we walk the list of peers,
3180 * network statements, etc looking to see if they use this route-map.
3181 */
d62a17ae 3182static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
3183 int route_update)
3184{
3185 int i;
3186 afi_t afi;
3187 safi_t safi;
3188 struct peer *peer;
3189 struct bgp_node *bn;
3190 struct bgp_static *bgp_static;
3191 struct listnode *node, *nnode;
3192 struct route_map *map;
3193 char buf[INET6_ADDRSTRLEN];
3194
3195 map = route_map_lookup_by_name(rmap_name);
3196
3197 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
3198
3199 /* Ignore dummy peer-group structure */
3200 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
3201 continue;
3202
05c7a1cc
QY
3203 FOREACH_AFI_SAFI (afi, safi) {
3204 /* process in/out/import/export/default-orig
3205 * route-maps */
3206 bgp_route_map_process_peer(rmap_name, map, peer, afi,
3207 safi, route_update);
3208 }
d62a17ae 3209 }
3210
3211 /* for outbound/default-orig route-maps, process for groups */
3212 update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
3213 route_update, 0);
3214
3215 /* update peer-group config (template) */
3216 bgp_route_map_update_peer_group(rmap_name, map, bgp);
3217
05c7a1cc
QY
3218 FOREACH_AFI_SAFI (afi, safi) {
3219 /* For table route-map updates. */
3220 if (!bgp_fibupd_safi(safi))
3221 continue;
d62a17ae 3222
05c7a1cc
QY
3223 if (bgp->table_map[afi][safi].name
3224 && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
3225 == 0)) {
3226 bgp->table_map[afi][safi].map = map;
3227
3228 if (BGP_DEBUG(zebra, ZEBRA))
3229 zlog_debug(
3230 "Processing route_map %s update on "
3231 "table map",
3232 rmap_name);
3233 if (route_update)
3234 bgp_zebra_announce_table(bgp, afi, safi);
3235 }
d62a17ae 3236
05c7a1cc
QY
3237 /* For network route-map updates. */
3238 for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
3239 bn = bgp_route_next(bn))
3240 if ((bgp_static = bn->info) != NULL) {
3241 if (bgp_static->rmap.name
3242 && (strcmp(rmap_name, bgp_static->rmap.name)
3243 == 0)) {
3244 bgp_static->rmap.map = map;
3245
3246 if (route_update)
3247 if (!bgp_static->backdoor) {
3248 if (bgp_debug_zebra(
3249 &bn->p))
3250 zlog_debug(
3251 "Processing route_map %s update on "
3252 "static route %s",
3253 rmap_name,
3254 inet_ntop(
3255 bn->p.family,
3256 &bn->p.u.prefix,
3257 buf,
3258 INET6_ADDRSTRLEN));
3259 bgp_static_update(
3260 bgp, &bn->p,
3261 bgp_static, afi,
3262 safi);
3263 }
d62a17ae 3264 }
05c7a1cc
QY
3265 }
3266 }
d62a17ae 3267
3268 /* For redistribute route-map updates. */
3269 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3270 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
3271 struct list *red_list;
d62a17ae 3272 struct bgp_redist *red;
3273
3274 red_list = bgp->redist[afi][i];
3275 if (!red_list)
3276 continue;
3277
3278 for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
3279 if (red->rmap.name
3280 && (strcmp(rmap_name, red->rmap.name)
3281 == 0)) {
3282 red->rmap.map = map;
3283
3284 if (route_update) {
3285 if (BGP_DEBUG(zebra, ZEBRA))
3286 zlog_debug(
3287 "Processing route_map %s update on "
3288 "redistributed routes",
3289 rmap_name);
3290
3291 bgp_redistribute_resend(
3292 bgp, afi, i,
3293 red->instance);
3294 }
3295 }
3296 }
3297 }
53c84f78
MK
3298
3299 /* for type5 command route-maps */
3300 FOREACH_AFI_SAFI (afi, safi) {
996c9314
LB
3301 if (bgp->adv_cmd_rmap[afi][safi].name
3302 && strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
3303 == 0) {
53c84f78
MK
3304 if (BGP_DEBUG(zebra, ZEBRA))
3305 zlog_debug(
996c9314
LB
3306 "Processing route_map %s update on advertise type5 route command",
3307 rmap_name);
53c84f78
MK
3308 bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
3309 bgp_evpn_advertise_type5_routes(bgp, afi, safi);
3310 }
3311 }
d62a17ae 3312}
3313
46a69f10 3314static void bgp_route_map_process_update_cb(char *rmap_name)
d62a17ae 3315{
3316 struct listnode *node, *nnode;
3317 struct bgp *bgp;
3318
ddb5b488 3319 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
d62a17ae 3320 bgp_route_map_process_update(bgp, rmap_name, 1);
5fe9f963 3321
65efcfce 3322#if ENABLE_BGP_VNC
ddb5b488
PZ
3323 /* zlog_debug("%s: calling vnc_routemap_update", __func__); */
3324 vnc_routemap_update(bgp, __func__);
65efcfce 3325#endif
ddb5b488
PZ
3326 }
3327
3328 vpn_policy_routemap_event(rmap_name);
518f0eb1
DS
3329}
3330
d62a17ae 3331int bgp_route_map_update_timer(struct thread *thread)
518f0eb1 3332{
d62a17ae 3333 bm->t_rmap_update = NULL;
518f0eb1 3334
d62a17ae 3335 route_map_walk_update_list(bgp_route_map_process_update_cb);
518f0eb1 3336
d62a17ae 3337 return (0);
518f0eb1
DS
3338}
3339
d62a17ae 3340static void bgp_route_map_mark_update(const char *rmap_name)
518f0eb1 3341{
d62a17ae 3342 if (bm->t_rmap_update == NULL) {
3343 struct listnode *node, *nnode;
3344 struct bgp *bgp;
3f9c7369 3345
d62a17ae 3346 /* rmap_update_timer of 0 means don't do route updates */
3347 if (bm->rmap_update_timer) {
3348 bm->t_rmap_update = NULL;
3349 thread_add_timer(bm->master, bgp_route_map_update_timer,
3350 NULL, bm->rmap_update_timer,
3351 &bm->t_rmap_update);
5fe9f963 3352
d62a17ae 3353 /* Signal the groups that a route-map update event has
3354 * started */
3355 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3356 update_group_policy_update(bgp,
3357 BGP_POLICY_ROUTE_MAP,
3358 rmap_name, 1, 1);
3359 } else {
3360 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3361 bgp_route_map_process_update(bgp, rmap_name, 0);
3362#if ENABLE_BGP_VNC
3363 zlog_debug("%s: calling vnc_routemap_update", __func__);
3364 vnc_routemap_update(bgp, __func__);
65efcfce 3365#endif
d62a17ae 3366 }
3367 }
718e3744 3368}
6b0655a2 3369
d62a17ae 3370static void bgp_route_map_add(const char *rmap_name)
73ac8160 3371{
7096e938 3372 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3373 bgp_route_map_mark_update(rmap_name);
73ac8160 3374
d62a17ae 3375 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160 3376}
518f0eb1 3377
d62a17ae 3378static void bgp_route_map_delete(const char *rmap_name)
73ac8160 3379{
7096e938 3380 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3381 bgp_route_map_mark_update(rmap_name);
73ac8160 3382
d62a17ae 3383 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
73ac8160 3384}
518f0eb1 3385
d62a17ae 3386static void bgp_route_map_event(route_map_event_t event, const char *rmap_name)
73ac8160 3387{
7096e938 3388 if (route_map_mark_updated(rmap_name) == 0)
d62a17ae 3389 bgp_route_map_mark_update(rmap_name);
518f0eb1 3390
d62a17ae 3391 route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
73ac8160
DS
3392}
3393
d37ba549
MK
3394DEFUN (match_mac_address,
3395 match_mac_address_cmd,
3396 "match mac address WORD",
3397 MATCH_STR
3398 "mac address\n"
3399 "Match address of route\n"
3400 "MAC Access-list name\n")
3401{
3402 return bgp_route_match_add(vty, "mac address", argv[3]->arg,
3403 RMAP_EVENT_FILTER_ADDED);
3404}
3405
3406DEFUN (no_match_mac_address,
3407 no_match_mac_address_cmd,
646050e5 3408 "no match mac address WORD",
d37ba549
MK
3409 NO_STR
3410 MATCH_STR
3411 "mac\n"
646050e5
MK
3412 "Match address of route\n"
3413 "MAC acess-list name\n")
d37ba549 3414{
d37ba549
MK
3415 return bgp_route_match_delete(vty, "mac address", argv[4]->arg,
3416 RMAP_EVENT_FILTER_DELETED);
3417}
73ac8160 3418
33c2ff62
MK
3419DEFUN (match_evpn_route_type,
3420 match_evpn_route_type_cmd,
d4ef18b6 3421 "match evpn route-type <macip | multicast | prefix>",
33c2ff62
MK
3422 MATCH_STR
3423 EVPN_HELP_STR
3424 "Match route-type\n"
3425 "mac-ip route\n"
3426 "IMET route\n"
3427 "prefix route\n")
3428{
3429 return bgp_route_match_add(vty, "evpn route-type", argv[3]->arg,
3430 RMAP_EVENT_MATCH_ADDED);
3431}
3432
3433DEFUN (no_match_evpn_route_type,
3434 no_match_evpn_route_type_cmd,
d4ef18b6 3435 "no match evpn route-type <macip | multicast | prefix>",
33c2ff62
MK
3436 NO_STR
3437 MATCH_STR
3438 EVPN_HELP_STR
3439 "Match route-type\n"
3440 "mac-ip route\n"
3441 "IMET route\n"
3442 "prefix route\n")
3443{
3444 return bgp_route_match_delete(vty, "evpn route-type", argv[4]->arg,
3445 RMAP_EVENT_MATCH_DELETED);
3446}
3447
3448
16f7ce2b
MK
3449DEFUN (match_evpn_vni,
3450 match_evpn_vni_cmd,
3451 "match evpn vni (1-16777215)",
3452 MATCH_STR
62982d5a 3453 EVPN_HELP_STR
16f7ce2b
MK
3454 "Match VNI\n"
3455 "VNI ID\n")
3456{
646050e5 3457 return bgp_route_match_add(vty, "evpn vni", argv[3]->arg,
16f7ce2b
MK
3458 RMAP_EVENT_MATCH_ADDED);
3459}
3460
3461DEFUN (no_match_evpn_vni,
3462 no_match_evpn_vni_cmd,
3463 "no match evpn vni (1-16777215)",
3464 NO_STR
3465 MATCH_STR
62982d5a 3466 EVPN_HELP_STR
16f7ce2b
MK
3467 "Match VNI\n"
3468 "VNI ID\n")
3469{
646050e5 3470 return bgp_route_match_delete(vty, "evpn vni", argv[4]->arg,
16f7ce2b
MK
3471 RMAP_EVENT_MATCH_DELETED);
3472}
3473
6fb219da
MK
3474DEFUN (match_evpn_default_route,
3475 match_evpn_default_route_cmd,
3476 "match evpn default-route",
3477 MATCH_STR
3478 EVPN_HELP_STR
3479 "default EVPN type-5 route\n")
3480{
3481 return bgp_route_match_add(vty, "evpn default-route", NULL,
3482 RMAP_EVENT_MATCH_ADDED);
3483}
3484
3485DEFUN (no_match_evpn_default_route,
3486 no_match_evpn_default_route_cmd,
3487 "no match evpn default-route",
3488 NO_STR
3489 MATCH_STR
3490 EVPN_HELP_STR
3491 "default EVPN type-5 route\n")
3492{
3493 return bgp_route_match_delete(vty, "evpn default-route", NULL,
3494 RMAP_EVENT_MATCH_DELETED);
3495}
3496
fee0f4c6 3497DEFUN (match_peer,
3498 match_peer_cmd,
8c3433e4 3499 "match peer <A.B.C.D|X:X::X:X|WORD>",
fee0f4c6 3500 MATCH_STR
3501 "Match peer address\n"
6e13ed4a 3502 "IP address of peer\n"
8c3433e4
DS
3503 "IPv6 address of peer\n"
3504 "Interface name of peer\n")
fee0f4c6 3505{
d62a17ae 3506 int idx_ip = 2;
3507 return bgp_route_match_add(vty, "peer", argv[idx_ip]->arg,
3508 RMAP_EVENT_MATCH_ADDED);
fee0f4c6 3509}
3510
3511DEFUN (match_peer_local,
f412b39a 3512 match_peer_local_cmd,
fee0f4c6 3513 "match peer local",
3514 MATCH_STR
3515 "Match peer address\n"
3516 "Static or Redistributed routes\n")
3517{
d62a17ae 3518 return bgp_route_match_add(vty, "peer", "local",
3519 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 3520}
3521
3522DEFUN (no_match_peer,
3523 no_match_peer_cmd,
8c3433e4 3524 "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
fee0f4c6 3525 NO_STR
3526 MATCH_STR
4c9bd275
DW
3527 "Match peer address\n"
3528 "Static or Redistributed routes\n"
3529 "IP address of peer\n"
8c3433e4
DS
3530 "IPv6 address of peer\n"
3531 "Interface name of peer\n")
fee0f4c6 3532{
d62a17ae 3533 int idx_peer = 3;
4c9bd275 3534
d62a17ae 3535 if (argc <= idx_peer)
3536 return bgp_route_match_delete(vty, "peer", NULL,
3537 RMAP_EVENT_MATCH_DELETED);
3538 return bgp_route_match_delete(vty, "peer", argv[idx_peer]->arg,
3539 RMAP_EVENT_MATCH_DELETED);
fee0f4c6 3540}
3541
1d7c7ace
DS
3542#if defined(HAVE_LUA)
3543DEFUN (match_command,
3544 match_command_cmd,
3545 "match command WORD",
3546 MATCH_STR
3547 "Run a command to match\n"
3548 "The command to run\n")
3549{
3550 return bgp_route_match_add(vty, "command", argv[2]->arg,
3551 RMAP_EVENT_FILTER_ADDED);
3552}
3553
3554DEFUN (no_match_command,
3555 no_match_command_cmd,
3556 "no match command WORD",
3557 NO_STR
3558 MATCH_STR
3559 "Run a command to match\n"
3560 "The command to run\n")
3561{
3562 return bgp_route_match_delete(vty, "command", argv[3]->arg,
3563 RMAP_EVENT_FILTER_DELETED);
3564}
3565#endif
fee0f4c6 3566
4c9bd275 3567/* match probability */
1add115a
VT
3568DEFUN (match_probability,
3569 match_probability_cmd,
6147e2c6 3570 "match probability (0-100)",
1add115a
VT
3571 MATCH_STR
3572 "Match portion of routes defined by percentage value\n"
3573 "Percentage of routes\n")
3574{
d62a17ae 3575 int idx_number = 2;
3576 return bgp_route_match_add(vty, "probability", argv[idx_number]->arg,
3577 RMAP_EVENT_MATCH_ADDED);
1add115a
VT
3578}
3579
4c9bd275 3580
1add115a
VT
3581DEFUN (no_match_probability,
3582 no_match_probability_cmd,
4c9bd275 3583 "no match probability [(1-99)]",
1add115a
VT
3584 NO_STR
3585 MATCH_STR
4c9bd275
DW
3586 "Match portion of routes defined by percentage value\n"
3587 "Percentage of routes\n")
1add115a 3588{
d62a17ae 3589 int idx_number = 3;
3590 if (argc <= idx_number)
3591 return bgp_route_match_delete(vty, "probability", NULL,
3592 RMAP_EVENT_MATCH_DELETED);
3593 return bgp_route_match_delete(vty, "probability", argv[idx_number]->arg,
3594 RMAP_EVENT_MATCH_DELETED);
1add115a
VT
3595}
3596
1add115a 3597
f412b39a 3598DEFUN (match_ip_route_source,
c1643bb7 3599 match_ip_route_source_cmd,
6147e2c6 3600 "match ip route-source <(1-199)|(1300-2699)|WORD>",
c1643bb7 3601 MATCH_STR
3602 IP_STR
3603 "Match advertising source address of route\n"
3604 "IP access-list number\n"
3605 "IP access-list number (expanded range)\n"
3606 "IP standard access-list name\n")
3607{
d62a17ae 3608 int idx_acl = 3;
3609 return bgp_route_match_add(vty, "ip route-source", argv[idx_acl]->arg,
3610 RMAP_EVENT_FILTER_ADDED);
c1643bb7 3611}
3612
4c9bd275 3613
c1643bb7 3614DEFUN (no_match_ip_route_source,
3615 no_match_ip_route_source_cmd,
6de69f83 3616 "no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
c1643bb7 3617 NO_STR
3618 MATCH_STR
3619 IP_STR
4c9bd275
DW
3620 "Match advertising source address of route\n"
3621 "IP access-list number\n"
3622 "IP access-list number (expanded range)\n"
3623 "IP standard access-list name\n")
c1643bb7 3624{
d62a17ae 3625 int idx_number = 4;
3626 if (argc <= idx_number)
3627 return bgp_route_match_delete(vty, "ip route-source", NULL,
3628 RMAP_EVENT_FILTER_DELETED);
3629 return bgp_route_match_delete(vty, "ip route-source",
3630 argv[idx_number]->arg,
3631 RMAP_EVENT_FILTER_DELETED);
c1643bb7 3632}
3633
c1643bb7 3634
f412b39a 3635DEFUN (match_ip_route_source_prefix_list,
c1643bb7 3636 match_ip_route_source_prefix_list_cmd,
3637 "match ip route-source prefix-list WORD",
3638 MATCH_STR
3639 IP_STR
3640 "Match advertising source address of route\n"
3641 "Match entries of prefix-lists\n"
3642 "IP prefix-list name\n")
3643{
d62a17ae 3644 int idx_word = 4;
3645 return bgp_route_match_add(vty, "ip route-source prefix-list",
3646 argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
c1643bb7 3647}
3648
4c9bd275 3649
c1643bb7 3650DEFUN (no_match_ip_route_source_prefix_list,
3651 no_match_ip_route_source_prefix_list_cmd,
4c9bd275 3652 "no match ip route-source prefix-list [WORD]",
c1643bb7 3653 NO_STR
3654 MATCH_STR
3655 IP_STR
3656 "Match advertising source address of route\n"
4c9bd275
DW
3657 "Match entries of prefix-lists\n"
3658 "IP prefix-list name\n")
c1643bb7 3659{
d62a17ae 3660 int idx_word = 5;
3661 if (argc <= idx_word)
3662 return bgp_route_match_delete(vty,
3663 "ip route-source prefix-list",
3664 NULL, RMAP_EVENT_PLIST_DELETED);
3665 return bgp_route_match_delete(vty, "ip route-source prefix-list",
3666 argv[idx_word]->arg,
3667 RMAP_EVENT_PLIST_DELETED);
c1643bb7 3668}
3669
c1643bb7 3670
af291c15
DS
3671DEFUN (match_local_pref,
3672 match_local_pref_cmd,
6147e2c6 3673 "match local-preference (0-4294967295)",
af291c15
DS
3674 MATCH_STR
3675 "Match local-preference of route\n"
3676 "Metric value\n")
3677{
d62a17ae 3678 int idx_number = 2;
3679 return bgp_route_match_add(vty, "local-preference",
3680 argv[idx_number]->arg,
3681 RMAP_EVENT_MATCH_ADDED);
af291c15
DS
3682}
3683
4c9bd275 3684
af291c15
DS
3685DEFUN (no_match_local_pref,
3686 no_match_local_pref_cmd,
4c9bd275 3687 "no match local-preference [(0-4294967295)]",
af291c15
DS
3688 NO_STR
3689 MATCH_STR
4c9bd275
DW
3690 "Match local preference of route\n"
3691 "Local preference value\n")
af291c15 3692{
d62a17ae 3693 int idx_localpref = 3;
3694 if (argc <= idx_localpref)
3695 return bgp_route_match_delete(vty, "local-preference", NULL,
3696 RMAP_EVENT_MATCH_DELETED);
3697 return bgp_route_match_delete(vty, "local-preference",
3698 argv[idx_localpref]->arg,
3699 RMAP_EVENT_MATCH_DELETED);
af291c15
DS
3700}
3701
af291c15 3702
f412b39a 3703DEFUN (match_community,
718e3744 3704 match_community_cmd,
0d702986 3705 "match community <(1-99)|(100-500)|WORD> [exact-match]",
718e3744 3706 MATCH_STR
3707 "Match BGP community list\n"
3708 "Community-list number (standard)\n"
3709 "Community-list number (expanded)\n"
3710 "Community-list name\n"
3711 "Do exact matching of communities\n")
3712{
d62a17ae 3713 int idx_comm_list = 2;
3714 int ret;
3715 char *argstr;
718e3744 3716
d62a17ae 3717 if (argc == 4) {
3718 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
3719 strlen(argv[idx_comm_list]->arg)
3720 + strlen("exact-match") + 2);
718e3744 3721
d62a17ae 3722 sprintf(argstr, "%s exact-match", argv[idx_comm_list]->arg);
3723 } else
3724 argstr = argv[idx_comm_list]->arg;
718e3744 3725
d62a17ae 3726 ret = bgp_route_match_add(vty, "community", argstr,
3727 RMAP_EVENT_CLIST_ADDED);
718e3744 3728
d62a17ae 3729 if (argstr != argv[idx_comm_list]->arg)
3730 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 3731
d62a17ae 3732 return ret;
718e3744 3733}
3734
3735DEFUN (no_match_community,
3736 no_match_community_cmd,
4c9bd275 3737 "no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
718e3744 3738 NO_STR
3739 MATCH_STR
4c9bd275
DW
3740 "Match BGP community list\n"
3741 "Community-list number (standard)\n"
3742 "Community-list number (expanded)\n"
3743 "Community-list name\n"
3744 "Do exact matching of communities\n")
718e3744 3745{
d62a17ae 3746 return bgp_route_match_delete(vty, "community", NULL,
3747 RMAP_EVENT_CLIST_DELETED);
718e3744 3748}
3749
57d187bc
JS
3750DEFUN (match_lcommunity,
3751 match_lcommunity_cmd,
0d702986 3752 "match large-community <(1-99)|(100-500)|WORD>",
57d187bc
JS
3753 MATCH_STR
3754 "Match BGP large community list\n"
3755 "Large Community-list number (standard)\n"
3756 "Large Community-list number (expanded)\n"
3757 "Large Community-list name\n")
3758{
d62a17ae 3759 return bgp_route_match_add(vty, "large-community", argv[2]->arg,
3760 RMAP_EVENT_LLIST_ADDED);
57d187bc 3761}
718e3744 3762
57d187bc
JS
3763DEFUN (no_match_lcommunity,
3764 no_match_lcommunity_cmd,
52951b63 3765 "no match large-community [<(1-99)|(100-500)|WORD>]",
57d187bc
JS
3766 NO_STR
3767 MATCH_STR
3768 "Match BGP large community list\n"
3769 "Large Community-list number (standard)\n"
3770 "Large Community-list number (expanded)\n"
3771 "Large Community-list name\n")
3772{
d62a17ae 3773 return bgp_route_match_delete(vty, "large-community", NULL,
3774 RMAP_EVENT_LLIST_DELETED);
57d187bc 3775}
718e3744 3776
f412b39a 3777DEFUN (match_ecommunity,
73ffb25b 3778 match_ecommunity_cmd,
6147e2c6 3779 "match extcommunity <(1-99)|(100-500)|WORD>",
73ffb25b 3780 MATCH_STR
3781 "Match BGP/VPN extended community list\n"
3782 "Extended community-list number (standard)\n"
3783 "Extended community-list number (expanded)\n"
3784 "Extended community-list name\n")
3785{
d62a17ae 3786 int idx_comm_list = 2;
3787 return bgp_route_match_add(vty, "extcommunity",
3788 argv[idx_comm_list]->arg,
3789 RMAP_EVENT_ECLIST_ADDED);
73ffb25b 3790}
3791
4c9bd275 3792
73ffb25b 3793DEFUN (no_match_ecommunity,
3794 no_match_ecommunity_cmd,
4c9bd275 3795 "no match extcommunity [<(1-99)|(100-500)|WORD>]",
73ffb25b 3796 NO_STR
3797 MATCH_STR
4c9bd275
DW
3798 "Match BGP/VPN extended community list\n"
3799 "Extended community-list number (standard)\n"
3800 "Extended community-list number (expanded)\n"
3801 "Extended community-list name\n")
73ffb25b 3802{
d62a17ae 3803 return bgp_route_match_delete(vty, "extcommunity", NULL,
3804 RMAP_EVENT_ECLIST_DELETED);
73ffb25b 3805}
3806
73ffb25b 3807
718e3744 3808DEFUN (match_aspath,
3809 match_aspath_cmd,
3810 "match as-path WORD",
3811 MATCH_STR
3812 "Match BGP AS path list\n"
3813 "AS path access-list name\n")
3814{
d62a17ae 3815 int idx_word = 2;
3816 return bgp_route_match_add(vty, "as-path", argv[idx_word]->arg,
3817 RMAP_EVENT_ASLIST_ADDED);
718e3744 3818}
3819
4c9bd275 3820
718e3744 3821DEFUN (no_match_aspath,
3822 no_match_aspath_cmd,
4c9bd275 3823 "no match as-path [WORD]",
718e3744 3824 NO_STR
3825 MATCH_STR
4c9bd275
DW
3826 "Match BGP AS path list\n"
3827 "AS path access-list name\n")
718e3744 3828{
d62a17ae 3829 return bgp_route_match_delete(vty, "as-path", NULL,
3830 RMAP_EVENT_ASLIST_DELETED);
718e3744 3831}
3832
718e3744 3833
3834DEFUN (match_origin,
3835 match_origin_cmd,
6147e2c6 3836 "match origin <egp|igp|incomplete>",
718e3744 3837 MATCH_STR
3838 "BGP origin code\n"
3839 "remote EGP\n"
3840 "local IGP\n"
3841 "unknown heritage\n")
3842{
d62a17ae 3843 int idx_origin = 2;
3844 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
3845 return bgp_route_match_add(vty, "origin", "igp",
3846 RMAP_EVENT_MATCH_ADDED);
3847 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
3848 return bgp_route_match_add(vty, "origin", "egp",
3849 RMAP_EVENT_MATCH_ADDED);
3850 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
3851 return bgp_route_match_add(vty, "origin", "incomplete",
3852 RMAP_EVENT_MATCH_ADDED);
718e3744 3853
d62a17ae 3854 vty_out(vty, "%% Invalid match origin type\n");
3855 return CMD_WARNING_CONFIG_FAILED;
718e3744 3856}
3857
4c9bd275 3858
718e3744 3859DEFUN (no_match_origin,
3860 no_match_origin_cmd,
4c9bd275 3861 "no match origin [<egp|igp|incomplete>]",
718e3744 3862 NO_STR
3863 MATCH_STR
4c9bd275
DW
3864 "BGP origin code\n"
3865 "remote EGP\n"
3866 "local IGP\n"
3867 "unknown heritage\n")
718e3744 3868{
d62a17ae 3869 return bgp_route_match_delete(vty, "origin", NULL,
3870 RMAP_EVENT_MATCH_DELETED);
718e3744 3871}
3872
af5cd0a5 3873DEFUN (set_ip_nexthop_peer,
3874 set_ip_nexthop_peer_cmd,
89602edb
QY
3875 "[no] set ip next-hop peer-address",
3876 NO_STR
af5cd0a5 3877 SET_STR
3878 IP_STR
3879 "Next hop address\n"
3880 "Use peer address (for BGP only)\n")
3881{
89602edb 3882 int (*func)(struct vty *, struct route_map_index *, const char *,
a4d82a8a
PZ
3883 const char *) = strmatch(argv[0]->text, "no")
3884 ? generic_set_delete
3885 : generic_set_add;
89602edb
QY
3886
3887 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
3888 "peer-address");
af5cd0a5 3889}
3890
316e074d
DS
3891DEFUN (set_ip_nexthop_unchanged,
3892 set_ip_nexthop_unchanged_cmd,
cca30ba8
QY
3893 "[no] set ip next-hop unchanged",
3894 NO_STR
316e074d
DS
3895 SET_STR
3896 IP_STR
3897 "Next hop address\n"
3898 "Don't modify existing Next hop address\n")
3899{
cca30ba8 3900 int (*func)(struct vty *, struct route_map_index *, const char *,
a4d82a8a
PZ
3901 const char *) = strmatch(argv[0]->text, "no")
3902 ? generic_set_delete
3903 : generic_set_add;
cca30ba8
QY
3904
3905 return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
3906 "unchanged");
718e3744 3907}
3908
718e3744 3909
3910DEFUN (set_local_pref,
3911 set_local_pref_cmd,
6147e2c6 3912 "set local-preference (0-4294967295)",
718e3744 3913 SET_STR
3914 "BGP local preference path attribute\n"
3915 "Preference value\n")
3916{
d62a17ae 3917 int idx_number = 2;
3918 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3919 "local-preference", argv[idx_number]->arg);
718e3744 3920}
3921
4c9bd275 3922
718e3744 3923DEFUN (no_set_local_pref,
3924 no_set_local_pref_cmd,
4c9bd275 3925 "no set local-preference [(0-4294967295)]",
718e3744 3926 NO_STR
3927 SET_STR
4c9bd275
DW
3928 "BGP local preference path attribute\n"
3929 "Preference value\n")
718e3744 3930{
d62a17ae 3931 int idx_localpref = 3;
3932 if (argc <= idx_localpref)
3933 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3934 "local-preference", NULL);
3935 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3936 "local-preference", argv[idx_localpref]->arg);
718e3744 3937}
3938
718e3744 3939
3940DEFUN (set_weight,
3941 set_weight_cmd,
6147e2c6 3942 "set weight (0-4294967295)",
718e3744 3943 SET_STR
3944 "BGP weight for routing table\n"
3945 "Weight value\n")
3946{
d62a17ae 3947 int idx_number = 2;
3948 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "weight",
3949 argv[idx_number]->arg);
718e3744 3950}
3951
4c9bd275 3952
718e3744 3953DEFUN (no_set_weight,
3954 no_set_weight_cmd,
4c9bd275 3955 "no set weight [(0-4294967295)]",
718e3744 3956 NO_STR
3957 SET_STR
4c9bd275
DW
3958 "BGP weight for routing table\n"
3959 "Weight value\n")
718e3744 3960{
d62a17ae 3961 int idx_weight = 3;
3962 if (argc <= idx_weight)
3963 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3964 "weight", NULL);
3965 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3966 "weight", argv[idx_weight]->arg);
718e3744 3967}
3968
d990e384
DS
3969DEFUN (set_label_index,
3970 set_label_index_cmd,
8b81993e 3971 "set label-index (0-1048560)",
d990e384
DS
3972 SET_STR
3973 "Label index to associate with the prefix\n"
3974 "Label index value\n")
3975{
d62a17ae 3976 int idx_number = 2;
3977 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
3978 "label-index", argv[idx_number]->arg);
d990e384
DS
3979}
3980
3981DEFUN (no_set_label_index,
3982 no_set_label_index_cmd,
8b81993e 3983 "no set label-index [(0-1048560)]",
d990e384
DS
3984 NO_STR
3985 SET_STR
3986 "Label index to associate with the prefix\n"
3987 "Label index value\n")
3988{
d62a17ae 3989 int idx_label_index = 3;
3990 if (argc <= idx_label_index)
3991 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3992 "label-index", NULL);
3993 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
3994 "label-index", argv[idx_label_index]->arg);
d990e384 3995}
718e3744 3996
12dcf78e
QY
3997DEFUN (set_aspath_prepend_asn,
3998 set_aspath_prepend_asn_cmd,
3999 "set as-path prepend (1-4294967295)...",
718e3744 4000 SET_STR
841f7a57 4001 "Transform BGP AS_PATH attribute\n"
718e3744 4002 "Prepend to the as-path\n"
12dcf78e 4003 "AS number\n")
718e3744 4004{
d62a17ae 4005 int idx_asn = 3;
4006 int ret;
4007 char *str;
718e3744 4008
d62a17ae 4009 str = argv_concat(argv, argc, idx_asn);
4010 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4011 "as-path prepend", str);
4012 XFREE(MTYPE_TMP, str);
718e3744 4013
d62a17ae 4014 return ret;
718e3744 4015}
4016
12dcf78e
QY
4017DEFUN (set_aspath_prepend_lastas,
4018 set_aspath_prepend_lastas_cmd,
b6ab2929 4019 "set as-path prepend last-as (1-10)",
12dcf78e
QY
4020 SET_STR
4021 "Transform BGP AS_PATH attribute\n"
4022 "Prepend to the as-path\n"
4023 "Use the peer's AS-number\n"
b6ab2929 4024 "Number of times to insert\n")
12dcf78e 4025{
d62a17ae 4026 return set_aspath_prepend_asn(self, vty, argc, argv);
12dcf78e 4027}
bc3dd427 4028
718e3744 4029DEFUN (no_set_aspath_prepend,
4030 no_set_aspath_prepend_cmd,
a4b2b610 4031 "no set as-path prepend [(1-4294967295)]",
718e3744 4032 NO_STR
4033 SET_STR
841f7a57 4034 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
4035 "Prepend to the as-path\n"
4036 "AS number\n")
718e3744 4037{
d62a17ae 4038 int idx_asn = 4;
4039 int ret;
4040 char *str;
a7f93f3e 4041
d62a17ae 4042 str = argv_concat(argv, argc, idx_asn);
4043 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4044 "as-path prepend", str);
4045 XFREE(MTYPE_TMP, str);
4046 return ret;
718e3744 4047}
4048
718e3744 4049
841f7a57
DO
4050DEFUN (set_aspath_exclude,
4051 set_aspath_exclude_cmd,
a4b2b610 4052 "set as-path exclude (1-4294967295)...",
841f7a57
DO
4053 SET_STR
4054 "Transform BGP AS-path attribute\n"
4055 "Exclude from the as-path\n"
4056 "AS number\n")
4057{
d62a17ae 4058 int idx_asn = 3;
4059 int ret;
4060 char *str;
841f7a57 4061
d62a17ae 4062 str = argv_concat(argv, argc, idx_asn);
4063 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4064 "as-path exclude", str);
4065 XFREE(MTYPE_TMP, str);
4066 return ret;
841f7a57
DO
4067}
4068
4069DEFUN (no_set_aspath_exclude,
4070 no_set_aspath_exclude_cmd,
a4b2b610 4071 "no set as-path exclude (1-4294967295)...",
841f7a57
DO
4072 NO_STR
4073 SET_STR
4074 "Transform BGP AS_PATH attribute\n"
a4b2b610
DW
4075 "Exclude from the as-path\n"
4076 "AS number\n")
841f7a57 4077{
d62a17ae 4078 int idx_asn = 4;
4079 int ret;
4080 char *str;
841f7a57 4081
d62a17ae 4082 str = argv_concat(argv, argc, idx_asn);
4083 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4084 "as-path exclude", str);
4085 XFREE(MTYPE_TMP, str);
4086 return ret;
841f7a57
DO
4087}
4088
841f7a57 4089
718e3744 4090DEFUN (set_community,
4091 set_community_cmd,
e961923c 4092 "set community AA:NN...",
718e3744 4093 SET_STR
4094 "BGP community attribute\n"
859d388e 4095 COMMUNITY_VAL_STR)
718e3744 4096{
d62a17ae 4097 int idx_aa_nn = 2;
4098 int i;
4099 int first = 0;
4100 int additive = 0;
4101 struct buffer *b;
4102 struct community *com = NULL;
4103 char *str;
4104 char *argstr;
4105 int ret;
4106
4107 b = buffer_new(1024);
4108
4109 for (i = idx_aa_nn; i < argc; i++) {
4110 if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
4111 == 0) {
4112 additive = 1;
4113 continue;
4114 }
4115
4116 if (first)
4117 buffer_putc(b, ' ');
4118 else
4119 first = 1;
4120
4121 if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
4122 == 0) {
4123 buffer_putstr(b, "internet");
4124 continue;
4125 }
4126 if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
4127 == 0) {
4128 buffer_putstr(b, "local-AS");
4129 continue;
4130 }
4131 if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
4132 && strncmp(argv[i]->arg, "no-advertise",
4133 strlen(argv[i]->arg))
4134 == 0) {
4135 buffer_putstr(b, "no-advertise");
4136 continue;
4137 }
4138 if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
4139 && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
4140 == 0) {
4141 buffer_putstr(b, "no-export");
4142 continue;
4143 }
a4d82a8a
PZ
4144 if (strncmp(argv[i]->arg, "graceful-shutdown",
4145 strlen(argv[i]->arg))
7f323236
DW
4146 == 0) {
4147 buffer_putstr(b, "graceful-shutdown");
4148 continue;
4149 }
d62a17ae 4150 buffer_putstr(b, argv[i]->arg);
4151 }
4152 buffer_putc(b, '\0');
4153
4154 /* Fetch result string then compile it to communities attribute. */
4155 str = buffer_getstr(b);
4156 buffer_free(b);
4157
4158 if (str) {
4159 com = community_str2com(str);
4160 XFREE(MTYPE_TMP, str);
4161 }
4162
4163 /* Can't compile user input into communities attribute. */
4164 if (!com) {
4165 vty_out(vty, "%% Malformed communities attribute\n");
4166 return CMD_WARNING_CONFIG_FAILED;
4167 }
4168
4169 /* Set communites attribute string. */
a69ea8ae 4170 str = community_str(com, false);
d62a17ae 4171
4172 if (additive) {
4173 argstr = XCALLOC(MTYPE_TMP,
4174 strlen(str) + strlen(" additive") + 1);
4175 strcpy(argstr, str);
4176 strcpy(argstr + strlen(str), " additive");
4177 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4178 "community", argstr);
4179 XFREE(MTYPE_TMP, argstr);
4180 } else
4181 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4182 "community", str);
4183
4184 community_free(com);
4185
4186 return ret;
718e3744 4187}
4188
4189DEFUN (set_community_none,
4190 set_community_none_cmd,
4191 "set community none",
4192 SET_STR
4193 "BGP community attribute\n"
4194 "No community attribute\n")
4195{
d62a17ae 4196 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4197 "community", "none");
718e3744 4198}
4199
4200DEFUN (no_set_community,
4201 no_set_community_cmd,
a4b2b610 4202 "no set community AA:NN...",
718e3744 4203 NO_STR
4204 SET_STR
d7fa34c1
QY
4205 "BGP community attribute\n"
4206 COMMUNITY_VAL_STR)
718e3744 4207{
d62a17ae 4208 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4209 "community", NULL);
718e3744 4210}
4211
718e3744 4212
718e3744 4213DEFUN (set_community_delete,
4214 set_community_delete_cmd,
6147e2c6 4215 "set comm-list <(1-99)|(100-500)|WORD> delete",
718e3744 4216 SET_STR
4217 "set BGP community list (for deletion)\n"
4218 "Community-list number (standard)\n"
5e3edbf5 4219 "Community-list number (expanded)\n"
718e3744 4220 "Community-list name\n"
4221 "Delete matching communities\n")
4222{
d62a17ae 4223 int idx_comm_list = 2;
4224 char *str;
718e3744 4225
d62a17ae 4226 str = XCALLOC(MTYPE_TMP,
4227 strlen(argv[idx_comm_list]->arg) + strlen(" delete") + 1);
4228 strcpy(str, argv[idx_comm_list]->arg);
4229 strcpy(str + strlen(argv[idx_comm_list]->arg), " delete");
718e3744 4230
d62a17ae 4231 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list",
4232 str);
718e3744 4233
d62a17ae 4234 XFREE(MTYPE_TMP, str);
4235 return CMD_SUCCESS;
718e3744 4236}
4237
4238DEFUN (no_set_community_delete,
4239 no_set_community_delete_cmd,
a4b2b610 4240 "no set comm-list [<(1-99)|(100-500)|WORD> delete]",
718e3744 4241 NO_STR
4242 SET_STR
d7fa34c1
QY
4243 "set BGP community list (for deletion)\n"
4244 "Community-list number (standard)\n"
4245 "Community-list number (expanded)\n"
4246 "Community-list name\n"
4247 "Delete matching communities\n")
718e3744 4248{
d62a17ae 4249 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4250 "comm-list", NULL);
718e3744 4251}
4252
57d187bc
JS
4253DEFUN (set_lcommunity,
4254 set_lcommunity_cmd,
4255 "set large-community AA:BB:CC...",
4256 SET_STR
4257 "BGP large community attribute\n"
4258 "Large Community number in aa:bb:cc format or additive\n")
4259{
d62a17ae 4260 int ret;
4261 char *str;
57d187bc 4262
d62a17ae 4263 str = argv_concat(argv, argc, 2);
4264 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4265 "large-community", str);
4266 XFREE(MTYPE_TMP, str);
57d187bc 4267
d62a17ae 4268 return ret;
57d187bc
JS
4269}
4270
4271DEFUN (set_lcommunity_none,
4272 set_lcommunity_none_cmd,
4273 "set large-community none",
4274 SET_STR
4275 "BGP large community attribute\n"
4276 "No large community attribute\n")
4277{
d62a17ae 4278 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4279 "large-community", "none");
57d187bc
JS
4280}
4281
4282DEFUN (no_set_lcommunity,
4283 no_set_lcommunity_cmd,
52951b63 4284 "no set large-community none",
57d187bc
JS
4285 NO_STR
4286 SET_STR
4287 "BGP large community attribute\n"
52951b63 4288 "No community attribute\n")
57d187bc 4289{
d62a17ae 4290 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4291 "large-community", NULL);
57d187bc
JS
4292}
4293
52951b63
DS
4294DEFUN (no_set_lcommunity1,
4295 no_set_lcommunity1_cmd,
4296 "no set large-community AA:BB:CC...",
4297 NO_STR
4298 SET_STR
4299 "BGP large community attribute\n"
4300 "Large community in AA:BB:CC... format or additive\n")
4301{
d62a17ae 4302 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4303 "large-community", NULL);
52951b63 4304}
57d187bc
JS
4305
4306DEFUN (set_lcommunity_delete,
4307 set_lcommunity_delete_cmd,
4308 "set large-comm-list <(1-99)|(100-500)|WORD> delete",
4309 SET_STR
4310 "set BGP large community list (for deletion)\n"
4311 "Large Community-list number (standard)\n"
4312 "Large Communitly-list number (expanded)\n"
4313 "Large Community-list name\n"
4314 "Delete matching large communities\n")
4315{
d62a17ae 4316 char *str;
57d187bc 4317
d62a17ae 4318 str = XCALLOC(MTYPE_TMP, strlen(argv[2]->arg) + strlen(" delete") + 1);
4319 strcpy(str, argv[2]->arg);
4320 strcpy(str + strlen(argv[2]->arg), " delete");
57d187bc 4321
d62a17ae 4322 generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4323 "large-comm-list", str);
57d187bc 4324
d62a17ae 4325 XFREE(MTYPE_TMP, str);
4326 return CMD_SUCCESS;
57d187bc
JS
4327}
4328
4329DEFUN (no_set_lcommunity_delete,
4330 no_set_lcommunity_delete_cmd,
db4f7086 4331 "no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
57d187bc
JS
4332 NO_STR
4333 SET_STR
4334 "set BGP large community list (for deletion)\n"
4335 "Large Community-list number (standard)\n"
4336 "Large Communitly-list number (expanded)\n"
4337 "Large Community-list name\n"
4338 "Delete matching large communities\n")
4339{
d62a17ae 4340 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4341 "large-comm-list", NULL);
57d187bc 4342}
718e3744 4343
4344DEFUN (set_ecommunity_rt,
4345 set_ecommunity_rt_cmd,
d114b977 4346 "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 4347 SET_STR
4348 "BGP extended community attribute\n"
e6b6a564 4349 "Route Target extended community\n"
718e3744 4350 "VPN extended community\n")
4351{
d62a17ae 4352 int idx_asn_nn = 3;
4353 int ret;
4354 char *str;
718e3744 4355
d62a17ae 4356 str = argv_concat(argv, argc, idx_asn_nn);
4357 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4358 "extcommunity rt", str);
4359 XFREE(MTYPE_TMP, str);
718e3744 4360
d62a17ae 4361 return ret;
718e3744 4362}
4363
4364DEFUN (no_set_ecommunity_rt,
4365 no_set_ecommunity_rt_cmd,
d114b977 4366 "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 4367 NO_STR
4368 SET_STR
4369 "BGP extended community attribute\n"
3a2d747c
QY
4370 "Route Target extended community\n"
4371 "VPN extended community\n")
718e3744 4372{
d62a17ae 4373 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4374 "extcommunity rt", NULL);
718e3744 4375}
4376
718e3744 4377
4378DEFUN (set_ecommunity_soo,
4379 set_ecommunity_soo_cmd,
d114b977 4380 "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 4381 SET_STR
4382 "BGP extended community attribute\n"
4383 "Site-of-Origin extended community\n"
4384 "VPN extended community\n")
4385{
d62a17ae 4386 int idx_asn_nn = 3;
4387 int ret;
4388 char *str;
718e3744 4389
d62a17ae 4390 str = argv_concat(argv, argc, idx_asn_nn);
4391 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4392 "extcommunity soo", str);
4393 XFREE(MTYPE_TMP, str);
4394 return ret;
718e3744 4395}
4396
a4b2b610 4397
718e3744 4398DEFUN (no_set_ecommunity_soo,
4399 no_set_ecommunity_soo_cmd,
d114b977 4400 "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
718e3744 4401 NO_STR
4402 SET_STR
4403 "BGP extended community attribute\n"
3a2d747c
QY
4404 "Site-of-Origin extended community\n"
4405 "VPN extended community\n")
718e3744 4406{
d62a17ae 4407 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4408 "extcommunity soo", NULL);
718e3744 4409}
4410
718e3744 4411
4412DEFUN (set_origin,
4413 set_origin_cmd,
6147e2c6 4414 "set origin <egp|igp|incomplete>",
718e3744 4415 SET_STR
4416 "BGP origin code\n"
4417 "remote EGP\n"
4418 "local IGP\n"
4419 "unknown heritage\n")
4420{
d62a17ae 4421 int idx_origin = 2;
4422 if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
4423 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4424 "origin", "igp");
4425 if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
4426 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4427 "origin", "egp");
4428 if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
4429 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4430 "origin", "incomplete");
718e3744 4431
d62a17ae 4432 vty_out(vty, "%% Invalid set origin type\n");
4433 return CMD_WARNING_CONFIG_FAILED;
718e3744 4434}
4435
a4b2b610 4436
718e3744 4437DEFUN (no_set_origin,
4438 no_set_origin_cmd,
a4b2b610 4439 "no set origin [<egp|igp|incomplete>]",
718e3744 4440 NO_STR
4441 SET_STR
d7fa34c1
QY
4442 "BGP origin code\n"
4443 "remote EGP\n"
4444 "local IGP\n"
4445 "unknown heritage\n")
718e3744 4446{
d62a17ae 4447 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4448 "origin", NULL);
718e3744 4449}
4450
718e3744 4451
4452DEFUN (set_atomic_aggregate,
4453 set_atomic_aggregate_cmd,
4454 "set atomic-aggregate",
4455 SET_STR
4456 "BGP atomic aggregate attribute\n" )
4457{
d62a17ae 4458 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4459 "atomic-aggregate", NULL);
718e3744 4460}
4461
4462DEFUN (no_set_atomic_aggregate,
4463 no_set_atomic_aggregate_cmd,
4464 "no set atomic-aggregate",
4465 NO_STR
4466 SET_STR
4467 "BGP atomic aggregate attribute\n" )
4468{
d62a17ae 4469 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4470 "atomic-aggregate", NULL);
718e3744 4471}
4472
4473DEFUN (set_aggregator_as,
4474 set_aggregator_as_cmd,
9ccf14f7 4475 "set aggregator as (1-4294967295) A.B.C.D",
718e3744 4476 SET_STR
4477 "BGP aggregator attribute\n"
4478 "AS number of aggregator\n"
4479 "AS number\n"
4480 "IP address of aggregator\n")
4481{
d62a17ae 4482 int idx_number = 3;
4483 int idx_ipv4 = 4;
4484 int ret;
4485 struct in_addr address;
4486 char *argstr;
e52702f2 4487
d62a17ae 4488 ret = inet_aton(argv[idx_ipv4]->arg, &address);
4489 if (ret == 0) {
4490 vty_out(vty, "Aggregator IP address is invalid\n");
4491 return CMD_WARNING_CONFIG_FAILED;
4492 }
718e3744 4493
d62a17ae 4494 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4495 strlen(argv[idx_number]->arg)
4496 + strlen(argv[idx_ipv4]->arg) + 2);
718e3744 4497
d62a17ae 4498 sprintf(argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
718e3744 4499
d62a17ae 4500 ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4501 "aggregator as", argstr);
718e3744 4502
d62a17ae 4503 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 4504
d62a17ae 4505 return ret;
718e3744 4506}
4507
a4b2b610 4508
718e3744 4509DEFUN (no_set_aggregator_as,
4510 no_set_aggregator_as_cmd,
a4b2b610 4511 "no set aggregator as [(1-4294967295) A.B.C.D]",
718e3744 4512 NO_STR
4513 SET_STR
4514 "BGP aggregator attribute\n"
a4b2b610
DW
4515 "AS number of aggregator\n"
4516 "AS number\n"
4517 "IP address of aggregator\n")
718e3744 4518{
d62a17ae 4519 int idx_asn = 4;
4520 int idx_ip = 5;
4521 int ret;
4522 struct in_addr address;
4523 char *argstr;
718e3744 4524
d62a17ae 4525 if (argc <= idx_asn)
4526 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4527 "aggregator as", NULL);
e52702f2 4528
d62a17ae 4529 ret = inet_aton(argv[idx_ip]->arg, &address);
4530 if (ret == 0) {
4531 vty_out(vty, "Aggregator IP address is invalid\n");
4532 return CMD_WARNING_CONFIG_FAILED;
4533 }
718e3744 4534
d62a17ae 4535 argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
4536 strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg)
4537 + 2);
718e3744 4538
d62a17ae 4539 sprintf(argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
718e3744 4540
d62a17ae 4541 ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4542 "aggregator as", argstr);
718e3744 4543
d62a17ae 4544 XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
718e3744 4545
d62a17ae 4546 return ret;
718e3744 4547}
4548
f412b39a 4549DEFUN (match_ipv6_next_hop,
718e3744 4550 match_ipv6_next_hop_cmd,
4551 "match ipv6 next-hop X:X::X:X",
4552 MATCH_STR
4553 IPV6_STR
4554 "Match IPv6 next-hop address of route\n"
4555 "IPv6 address of next hop\n")
4556{
d62a17ae 4557 int idx_ipv6 = 3;
4558 return bgp_route_match_add(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
4559 RMAP_EVENT_MATCH_ADDED);
718e3744 4560}
4561
4562DEFUN (no_match_ipv6_next_hop,
4563 no_match_ipv6_next_hop_cmd,
4564 "no match ipv6 next-hop X:X::X:X",
4565 NO_STR
4566 MATCH_STR
4567 IPV6_STR
4568 "Match IPv6 next-hop address of route\n"
4569 "IPv6 address of next hop\n")
4570{
d62a17ae 4571 int idx_ipv6 = 4;
4572 return bgp_route_match_delete(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
4573 RMAP_EVENT_MATCH_DELETED);
718e3744 4574}
4575
718e3744 4576
90916ac2
DS
4577DEFUN (set_ipv6_nexthop_peer,
4578 set_ipv6_nexthop_peer_cmd,
4579 "set ipv6 next-hop peer-address",
4580 SET_STR
4581 IPV6_STR
4582 "Next hop address\n"
4583 "Use peer address (for BGP only)\n")
4584{
d62a17ae 4585 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4586 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
4587}
4588
4589DEFUN (no_set_ipv6_nexthop_peer,
4590 no_set_ipv6_nexthop_peer_cmd,
4591 "no set ipv6 next-hop peer-address",
4592 NO_STR
4593 SET_STR
4594 IPV6_STR
4595 "IPv6 next-hop address\n"
161995ea 4596 "Use peer address (for BGP only)\n")
90916ac2 4597{
d62a17ae 4598 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4599 "ipv6 next-hop peer-address", NULL);
90916ac2
DS
4600}
4601
161995ea
DS
4602DEFUN (set_ipv6_nexthop_prefer_global,
4603 set_ipv6_nexthop_prefer_global_cmd,
4604 "set ipv6 next-hop prefer-global",
4605 SET_STR
4606 IPV6_STR
4607 "IPv6 next-hop address\n"
4608 "Prefer global over link-local if both exist\n")
4609{
d62a17ae 4610 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4611 "ipv6 next-hop prefer-global", NULL);
4612 ;
161995ea
DS
4613}
4614
4615DEFUN (no_set_ipv6_nexthop_prefer_global,
4616 no_set_ipv6_nexthop_prefer_global_cmd,
4617 "no set ipv6 next-hop prefer-global",
4618 NO_STR
4619 SET_STR
4620 IPV6_STR
4621 "IPv6 next-hop address\n"
4622 "Prefer global over link-local if both exist\n")
4623{
d62a17ae 4624 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4625 "ipv6 next-hop prefer-global", NULL);
161995ea
DS
4626}
4627
718e3744 4628DEFUN (set_ipv6_nexthop_global,
4629 set_ipv6_nexthop_global_cmd,
4630 "set ipv6 next-hop global X:X::X:X",
4631 SET_STR
4632 IPV6_STR
4633 "IPv6 next-hop address\n"
4634 "IPv6 global address\n"
4635 "IPv6 address of next hop\n")
4636{
d62a17ae 4637 int idx_ipv6 = 4;
4638 struct in6_addr addr;
4639 int ret;
bf8b3d27 4640
d62a17ae 4641 ret = inet_pton(AF_INET6, argv[idx_ipv6]->arg, &addr);
4642 if (!ret) {
4643 vty_out(vty, "%% Malformed nexthop address\n");
4644 return CMD_WARNING_CONFIG_FAILED;
4645 }
4646 if (IN6_IS_ADDR_UNSPECIFIED(&addr) || IN6_IS_ADDR_LOOPBACK(&addr)
4647 || IN6_IS_ADDR_MULTICAST(&addr) || IN6_IS_ADDR_LINKLOCAL(&addr)) {
4648 vty_out(vty, "%% Invalid global nexthop address\n");
4649 return CMD_WARNING_CONFIG_FAILED;
4650 }
bf8b3d27 4651
d62a17ae 4652 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4653 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 4654}
4655
a4b2b610 4656
718e3744 4657DEFUN (no_set_ipv6_nexthop_global,
4658 no_set_ipv6_nexthop_global_cmd,
a4b2b610 4659 "no set ipv6 next-hop global X:X::X:X",
718e3744 4660 NO_STR
4661 SET_STR
4662 IPV6_STR
4663 "IPv6 next-hop address\n"
a4b2b610
DW
4664 "IPv6 global address\n"
4665 "IPv6 address of next hop\n")
718e3744 4666{
d62a17ae 4667 int idx_ipv6 = 5;
4668 if (argc <= idx_ipv6)
4669 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4670 "ipv6 next-hop global", NULL);
4671 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4672 "ipv6 next-hop global", argv[idx_ipv6]->arg);
718e3744 4673}
718e3744 4674
d6902373
PG
4675#ifdef KEEP_OLD_VPN_COMMANDS
4676DEFUN (set_vpn_nexthop,
4677 set_vpn_nexthop_cmd,
a13c883e 4678 "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
718e3744 4679 SET_STR
4680 "VPNv4 information\n"
d6902373
PG
4681 "VPN next-hop address\n"
4682 "IP address of next hop\n"
a13c883e
QY
4683 "VPNv6 information\n"
4684 "VPN next-hop address\n"
d6902373 4685 "IPv6 address of next hop\n")
718e3744 4686{
d62a17ae 4687 int idx_ip = 3;
4688 afi_t afi;
4689 int idx = 0;
4690
4691 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
4692 if (afi == AFI_IP)
4693 return generic_set_add(
4694 vty, VTY_GET_CONTEXT(route_map_index),
4695 "ipv4 vpn next-hop", argv[idx_ip]->arg);
4696 else
4697 return generic_set_add(
4698 vty, VTY_GET_CONTEXT(route_map_index),
4699 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4700 }
4701 return CMD_SUCCESS;
d6902373 4702}
a4b2b610 4703
d6902373
PG
4704DEFUN (no_set_vpn_nexthop,
4705 no_set_vpn_nexthop_cmd,
a13c883e 4706 "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
718e3744 4707 NO_STR
4708 SET_STR
a13c883e 4709 "VPNv4 information\n"
d6902373
PG
4710 "VPN next-hop address\n"
4711 "IP address of next hop\n"
a13c883e
QY
4712 "VPNv6 information\n"
4713 "VPN next-hop address\n"
d6902373 4714 "IPv6 address of next hop\n")
718e3744 4715{
d62a17ae 4716 int idx_ip = 4;
4717 char *arg;
4718 afi_t afi;
4719 int idx = 0;
4720
4721 if (argc <= idx_ip)
4722 arg = NULL;
4723 else
4724 arg = argv[idx_ip]->arg;
4725 if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
4726 if (afi == AFI_IP)
4727 return generic_set_delete(
4728 vty, VTY_GET_CONTEXT(route_map_index),
4729 "ipv4 vpn next-hop", arg);
4730 else
4731 return generic_set_delete(
4732 vty, VTY_GET_CONTEXT(route_map_index),
4733 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4734 }
4735 return CMD_SUCCESS;
d6902373
PG
4736}
4737#endif /* KEEP_OLD_VPN_COMMANDS */
4738
4739DEFUN (set_ipx_vpn_nexthop,
4740 set_ipx_vpn_nexthop_cmd,
0d702986 4741 "set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
d6902373
PG
4742 SET_STR
4743 "IPv4 information\n"
4744 "IPv6 information\n"
4745 "VPN information\n"
4746 "VPN next-hop address\n"
4747 "IP address of next hop\n"
4748 "IPv6 address of next hop\n")
4749{
d62a17ae 4750 int idx_ip = 4;
4751 afi_t afi;
4752 int idx = 0;
4753
4754 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
4755 if (afi == AFI_IP)
4756 return generic_set_add(
4757 vty, VTY_GET_CONTEXT(route_map_index),
4758 "ipv4 vpn next-hop", argv[idx_ip]->arg);
4759 else
4760 return generic_set_add(
4761 vty, VTY_GET_CONTEXT(route_map_index),
4762 "ipv6 vpn next-hop", argv[idx_ip]->arg);
4763 }
4764 return CMD_SUCCESS;
718e3744 4765}
4766
d6902373
PG
4767DEFUN (no_set_ipx_vpn_nexthop,
4768 no_set_ipx_vpn_nexthop_cmd,
9fa4d336 4769 "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
d6902373
PG
4770 NO_STR
4771 SET_STR
4772 "IPv4 information\n"
4773 "IPv6 information\n"
4774 "VPN information\n"
4775 "VPN next-hop address\n"
4776 "IP address of next hop\n"
4777 "IPv6 address of next hop\n")
4778{
d62a17ae 4779 int idx_ip = 5;
4780 char *arg;
4781 afi_t afi;
4782 int idx = 0;
4783
4784 if (argc <= idx_ip)
4785 arg = NULL;
4786 else
4787 arg = argv[idx_ip]->arg;
4788 if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
4789 if (afi == AFI_IP)
4790 return generic_set_delete(
4791 vty, VTY_GET_CONTEXT(route_map_index),
4792 "ipv4 vpn next-hop", arg);
4793 else
4794 return generic_set_delete(
4795 vty, VTY_GET_CONTEXT(route_map_index),
4796 "ipv6 vpn next-hop", arg);
4797 }
4798 return CMD_SUCCESS;
d6902373 4799}
718e3744 4800
4801DEFUN (set_originator_id,
4802 set_originator_id_cmd,
4803 "set originator-id A.B.C.D",
4804 SET_STR
4805 "BGP originator ID attribute\n"
4806 "IP address of originator\n")
4807{
d62a17ae 4808 int idx_ipv4 = 2;
4809 return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
4810 "originator-id", argv[idx_ipv4]->arg);
718e3744 4811}
4812
4c9bd275 4813
718e3744 4814DEFUN (no_set_originator_id,
4815 no_set_originator_id_cmd,
4c9bd275 4816 "no set originator-id [A.B.C.D]",
718e3744 4817 NO_STR
4818 SET_STR
4c9bd275
DW
4819 "BGP originator ID attribute\n"
4820 "IP address of originator\n")
718e3744 4821{
d62a17ae 4822 int idx = 0;
4823 char *arg =
4824 argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
0d702986 4825
d62a17ae 4826 return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
4827 "originator-id", arg);
718e3744 4828}
4829
718e3744 4830
718e3744 4831/* Initialization of route map. */
d62a17ae 4832void bgp_route_map_init(void)
4833{
4834 route_map_init();
4835
4836 route_map_add_hook(bgp_route_map_add);
4837 route_map_delete_hook(bgp_route_map_delete);
4838 route_map_event_hook(bgp_route_map_event);
4839
4840 route_map_match_interface_hook(generic_match_add);
4841 route_map_no_match_interface_hook(generic_match_delete);
4842
4843 route_map_match_ip_address_hook(generic_match_add);
4844 route_map_no_match_ip_address_hook(generic_match_delete);
4845
4846 route_map_match_ip_address_prefix_list_hook(generic_match_add);
4847 route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
4848
4849 route_map_match_ip_next_hop_hook(generic_match_add);
4850 route_map_no_match_ip_next_hop_hook(generic_match_delete);
4851
4852 route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
4853 route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
4854
61ad901e
DA
4855 route_map_match_ip_next_hop_type_hook(generic_match_add);
4856 route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
4857
d62a17ae 4858 route_map_match_ipv6_address_hook(generic_match_add);
4859 route_map_no_match_ipv6_address_hook(generic_match_delete);
4860
4861 route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
4862 route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
4863
61ad901e
DA
4864 route_map_match_ipv6_next_hop_type_hook(generic_match_add);
4865 route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
4866
d62a17ae 4867 route_map_match_metric_hook(generic_match_add);
4868 route_map_no_match_metric_hook(generic_match_delete);
4869
4870 route_map_match_tag_hook(generic_match_add);
4871 route_map_no_match_tag_hook(generic_match_delete);
4872
4873 route_map_set_ip_nexthop_hook(generic_set_add);
4874 route_map_no_set_ip_nexthop_hook(generic_set_delete);
4875
4876 route_map_set_ipv6_nexthop_local_hook(generic_set_add);
4877 route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
4878
4879 route_map_set_metric_hook(generic_set_add);
4880 route_map_no_set_metric_hook(generic_set_delete);
4881
4882 route_map_set_tag_hook(generic_set_add);
4883 route_map_no_set_tag_hook(generic_set_delete);
4884
4885 route_map_install_match(&route_match_peer_cmd);
4886 route_map_install_match(&route_match_local_pref_cmd);
1d7c7ace
DS
4887#if defined(HAVE_LUA)
4888 route_map_install_match(&route_match_command_cmd);
4889#endif
d62a17ae 4890 route_map_install_match(&route_match_ip_address_cmd);
4891 route_map_install_match(&route_match_ip_next_hop_cmd);
4892 route_map_install_match(&route_match_ip_route_source_cmd);
4893 route_map_install_match(&route_match_ip_address_prefix_list_cmd);
4894 route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
61ad901e 4895 route_map_install_match(&route_match_ip_next_hop_type_cmd);
d62a17ae 4896 route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
4897 route_map_install_match(&route_match_aspath_cmd);
4898 route_map_install_match(&route_match_community_cmd);
4899 route_map_install_match(&route_match_lcommunity_cmd);
4900 route_map_install_match(&route_match_ecommunity_cmd);
4901 route_map_install_match(&route_match_local_pref_cmd);
4902 route_map_install_match(&route_match_metric_cmd);
4903 route_map_install_match(&route_match_origin_cmd);
4904 route_map_install_match(&route_match_probability_cmd);
4905 route_map_install_match(&route_match_interface_cmd);
4906 route_map_install_match(&route_match_tag_cmd);
d37ba549 4907 route_map_install_match(&route_match_mac_address_cmd);
16f7ce2b 4908 route_map_install_match(&route_match_evpn_vni_cmd);
33c2ff62 4909 route_map_install_match(&route_match_evpn_route_type_cmd);
6fb219da 4910 route_map_install_match(&route_match_evpn_default_route_cmd);
d62a17ae 4911
4912 route_map_install_set(&route_set_ip_nexthop_cmd);
4913 route_map_install_set(&route_set_local_pref_cmd);
4914 route_map_install_set(&route_set_weight_cmd);
4915 route_map_install_set(&route_set_label_index_cmd);
4916 route_map_install_set(&route_set_metric_cmd);
4917 route_map_install_set(&route_set_aspath_prepend_cmd);
4918 route_map_install_set(&route_set_aspath_exclude_cmd);
4919 route_map_install_set(&route_set_origin_cmd);
4920 route_map_install_set(&route_set_atomic_aggregate_cmd);
4921 route_map_install_set(&route_set_aggregator_as_cmd);
4922 route_map_install_set(&route_set_community_cmd);
4923 route_map_install_set(&route_set_community_delete_cmd);
4924 route_map_install_set(&route_set_lcommunity_cmd);
4925 route_map_install_set(&route_set_lcommunity_delete_cmd);
4926 route_map_install_set(&route_set_vpnv4_nexthop_cmd);
4927 route_map_install_set(&route_set_vpnv6_nexthop_cmd);
4928 route_map_install_set(&route_set_originator_id_cmd);
4929 route_map_install_set(&route_set_ecommunity_rt_cmd);
4930 route_map_install_set(&route_set_ecommunity_soo_cmd);
4931 route_map_install_set(&route_set_tag_cmd);
4932 route_map_install_set(&route_set_label_index_cmd);
4933
4934 install_element(RMAP_NODE, &match_peer_cmd);
4935 install_element(RMAP_NODE, &match_peer_local_cmd);
4936 install_element(RMAP_NODE, &no_match_peer_cmd);
4937 install_element(RMAP_NODE, &match_ip_route_source_cmd);
4938 install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
4939 install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
4940 install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
d37ba549
MK
4941 install_element(RMAP_NODE, &match_mac_address_cmd);
4942 install_element(RMAP_NODE, &no_match_mac_address_cmd);
16f7ce2b
MK
4943 install_element(RMAP_NODE, &match_evpn_vni_cmd);
4944 install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
33c2ff62
MK
4945 install_element(RMAP_NODE, &match_evpn_route_type_cmd);
4946 install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
6fb219da
MK
4947 install_element(RMAP_NODE, &match_evpn_default_route_cmd);
4948 install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
d62a17ae 4949
4950 install_element(RMAP_NODE, &match_aspath_cmd);
4951 install_element(RMAP_NODE, &no_match_aspath_cmd);
4952 install_element(RMAP_NODE, &match_local_pref_cmd);
4953 install_element(RMAP_NODE, &no_match_local_pref_cmd);
4954 install_element(RMAP_NODE, &match_community_cmd);
4955 install_element(RMAP_NODE, &no_match_community_cmd);
4956 install_element(RMAP_NODE, &match_lcommunity_cmd);
4957 install_element(RMAP_NODE, &no_match_lcommunity_cmd);
4958 install_element(RMAP_NODE, &match_ecommunity_cmd);
4959 install_element(RMAP_NODE, &no_match_ecommunity_cmd);
4960 install_element(RMAP_NODE, &match_origin_cmd);
4961 install_element(RMAP_NODE, &no_match_origin_cmd);
4962 install_element(RMAP_NODE, &match_probability_cmd);
4963 install_element(RMAP_NODE, &no_match_probability_cmd);
4964
4965 install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
4966 install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
4967 install_element(RMAP_NODE, &set_local_pref_cmd);
4968 install_element(RMAP_NODE, &no_set_local_pref_cmd);
4969 install_element(RMAP_NODE, &set_weight_cmd);
4970 install_element(RMAP_NODE, &set_label_index_cmd);
4971 install_element(RMAP_NODE, &no_set_weight_cmd);
4972 install_element(RMAP_NODE, &no_set_label_index_cmd);
4973 install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
4974 install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
4975 install_element(RMAP_NODE, &set_aspath_exclude_cmd);
4976 install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
4977 install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
4978 install_element(RMAP_NODE, &set_origin_cmd);
4979 install_element(RMAP_NODE, &no_set_origin_cmd);
4980 install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
4981 install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
4982 install_element(RMAP_NODE, &set_aggregator_as_cmd);
4983 install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
4984 install_element(RMAP_NODE, &set_community_cmd);
4985 install_element(RMAP_NODE, &set_community_none_cmd);
4986 install_element(RMAP_NODE, &no_set_community_cmd);
4987 install_element(RMAP_NODE, &set_community_delete_cmd);
4988 install_element(RMAP_NODE, &no_set_community_delete_cmd);
4989 install_element(RMAP_NODE, &set_lcommunity_cmd);
4990 install_element(RMAP_NODE, &set_lcommunity_none_cmd);
4991 install_element(RMAP_NODE, &no_set_lcommunity_cmd);
4992 install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
4993 install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
4994 install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
4995 install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
4996 install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
4997 install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
4998 install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
d6902373 4999#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 5000 install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
5001 install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
d6902373 5002#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 5003 install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
5004 install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
5005 install_element(RMAP_NODE, &set_originator_id_cmd);
5006 install_element(RMAP_NODE, &no_set_originator_id_cmd);
5007
5008 route_map_install_match(&route_match_ipv6_address_cmd);
5009 route_map_install_match(&route_match_ipv6_next_hop_cmd);
5010 route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
61ad901e 5011 route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
d62a17ae 5012 route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
5013 route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
5014 route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
5015 route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
5016
5017 install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
5018 install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
5019 install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
5020 install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
5021 install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
5022 install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
5023 install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
5024 install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
1d7c7ace
DS
5025#if defined(HAVE_LUA)
5026 install_element(RMAP_NODE, &match_command_cmd);
5027 install_element(RMAP_NODE, &no_match_command_cmd);
5028#endif
d62a17ae 5029}
5030
5031void bgp_route_map_terminate(void)
5032{
5033 /* ToDo: Cleanup all the used memory */
d62a17ae 5034 route_map_finish();
518f0eb1 5035}