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