]>
Commit | Line | Data |
---|---|---|
5921ef9a PJ |
1 | /* zebra routemap. |
2 | * Copyright (C) 2006 IBM Corporation | |
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 | * | |
896014f4 DL |
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 | |
5921ef9a PJ |
19 | */ |
20 | ||
21 | #include <zebra.h> | |
22 | ||
23 | #include "memory.h" | |
4a1ab8e4 | 24 | #include "zebra_memory.h" |
5921ef9a PJ |
25 | #include "prefix.h" |
26 | #include "rib.h" | |
82f97584 | 27 | #include "vty.h" |
5921ef9a PJ |
28 | #include "routemap.h" |
29 | #include "command.h" | |
30 | #include "filter.h" | |
31 | #include "plist.h" | |
fb018d25 | 32 | #include "nexthop.h" |
0032dd59 | 33 | #include "vrf.h" |
5921ef9a PJ |
34 | |
35 | #include "zebra/zserv.h" | |
8902474b | 36 | #include "zebra/redistribute.h" |
518f0eb1 | 37 | #include "zebra/debug.h" |
9f0ea7d4 | 38 | #include "zebra/zebra_rnh.h" |
6baf7bb8 | 39 | #include "zebra/zebra_routemap.h" |
518f0eb1 DS |
40 | |
41 | static u_int32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER; | |
42 | static struct thread *zebra_t_rmap_update = NULL; | |
d62a17ae | 43 | char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */ |
9f0ea7d4 | 44 | /* NH Tracking route map */ |
d62a17ae | 45 | char *nht_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */ |
8902474b | 46 | char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; |
518f0eb1 | 47 | |
d62a17ae | 48 | struct nh_rmap_obj { |
49 | struct nexthop *nexthop; | |
50 | vrf_id_t vrf_id; | |
51 | u_int32_t source_protocol; | |
52 | int metric; | |
53 | route_tag_t tag; | |
9f0ea7d4 DS |
54 | }; |
55 | ||
56 | static void zebra_route_map_set_delay_timer(u_int32_t value); | |
5921ef9a | 57 | |
82f97584 | 58 | |
5921ef9a | 59 | /* Add zebra route map rule */ |
d62a17ae | 60 | static int zebra_route_match_add(struct vty *vty, const char *command, |
61 | const char *arg, route_map_event_t type) | |
62 | { | |
63 | VTY_DECLVAR_CONTEXT(route_map_index, index); | |
64 | int ret; | |
9ca25fed | 65 | int retval = CMD_SUCCESS; |
d62a17ae | 66 | |
67 | ret = route_map_add_match(index, command, arg); | |
9ca25fed DS |
68 | switch (ret) { |
69 | case RMAP_RULE_MISSING: | |
70 | vty_out(vty, "%% Zebra Can't find rule.\n"); | |
71 | retval = CMD_WARNING_CONFIG_FAILED; | |
72 | break; | |
73 | case RMAP_COMPILE_ERROR: | |
74 | vty_out(vty, "%% Zebra Argument is malformed.\n"); | |
75 | retval = CMD_WARNING_CONFIG_FAILED; | |
76 | break; | |
77 | case RMAP_COMPILE_SUCCESS: | |
78 | if (type != RMAP_EVENT_MATCH_ADDED) { | |
79 | route_map_upd8_dependency(type, arg, index->map->name); | |
d62a17ae | 80 | } |
9ca25fed | 81 | break; |
5921ef9a | 82 | } |
518f0eb1 | 83 | |
9ca25fed | 84 | return retval; |
5921ef9a PJ |
85 | } |
86 | ||
87 | /* Delete zebra route map rule. */ | |
d62a17ae | 88 | static int zebra_route_match_delete(struct vty *vty, const char *command, |
89 | const char *arg, route_map_event_t type) | |
90 | { | |
91 | VTY_DECLVAR_CONTEXT(route_map_index, index); | |
92 | int ret; | |
9ca25fed | 93 | int retval = CMD_SUCCESS; |
d62a17ae | 94 | char *dep_name = NULL; |
95 | const char *tmpstr; | |
96 | char *rmap_name = NULL; | |
97 | ||
98 | if (type != RMAP_EVENT_MATCH_DELETED) { | |
99 | /* ignore the mundane, the types without any dependency */ | |
100 | if (arg == NULL) { | |
101 | if ((tmpstr = route_map_get_match_arg(index, command)) | |
102 | != NULL) | |
103 | dep_name = | |
104 | XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); | |
105 | } else { | |
106 | dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg); | |
107 | } | |
108 | rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); | |
4e3afb14 | 109 | } |
5921ef9a | 110 | |
d62a17ae | 111 | ret = route_map_delete_match(index, command, arg); |
9ca25fed DS |
112 | switch (ret) { |
113 | case RMAP_RULE_MISSING: | |
114 | vty_out(vty, "%% Zebra Can't find rule.\n"); | |
115 | retval = CMD_WARNING_CONFIG_FAILED; | |
116 | break; | |
117 | case RMAP_COMPILE_ERROR: | |
118 | vty_out(vty, "%% Zebra Argument is malformed.\n"); | |
119 | retval = CMD_WARNING_CONFIG_FAILED; | |
120 | break; | |
121 | case RMAP_COMPILE_SUCCESS: | |
122 | if (type != RMAP_EVENT_MATCH_DELETED && dep_name) | |
123 | route_map_upd8_dependency(type, dep_name, rmap_name); | |
124 | break; | |
5921ef9a | 125 | } |
518f0eb1 | 126 | |
d62a17ae | 127 | if (dep_name) |
128 | XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); | |
129 | if (rmap_name) | |
130 | XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); | |
518f0eb1 | 131 | |
9ca25fed | 132 | return retval; |
5921ef9a PJ |
133 | } |
134 | ||
ca84c8ef DS |
135 | /* 'match tag TAG' |
136 | * Match function return 1 if match is success else return 0 | |
137 | */ | |
d62a17ae | 138 | static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, |
139 | route_map_object_t type, void *object) | |
ca84c8ef | 140 | { |
d62a17ae | 141 | route_tag_t *tag; |
142 | struct nh_rmap_obj *nh_data; | |
ca84c8ef | 143 | |
d62a17ae | 144 | if (type == RMAP_ZEBRA) { |
145 | tag = rule; | |
146 | nh_data = object; | |
ca84c8ef | 147 | |
d62a17ae | 148 | if (nh_data->tag == *tag) |
149 | return RMAP_MATCH; | |
150 | } | |
151 | return RMAP_NOMATCH; | |
ca84c8ef DS |
152 | } |
153 | ||
ca84c8ef | 154 | /* Route map commands for tag matching */ |
d62a17ae | 155 | static struct route_map_rule_cmd route_match_tag_cmd = { |
9d303b37 | 156 | "tag", route_match_tag, route_map_rule_tag_compile, |
d62a17ae | 157 | route_map_rule_tag_free, |
ca84c8ef DS |
158 | }; |
159 | ||
6b0655a2 | 160 | |
5921ef9a PJ |
161 | /* `match interface IFNAME' */ |
162 | /* Match function return 1 if match is success else return zero. */ | |
d62a17ae | 163 | static route_map_result_t route_match_interface(void *rule, |
164 | struct prefix *prefix, | |
165 | route_map_object_t type, | |
166 | void *object) | |
167 | { | |
168 | struct nh_rmap_obj *nh_data; | |
169 | char *ifname = rule; | |
170 | ifindex_t ifindex; | |
171 | ||
172 | if (type == RMAP_ZEBRA) { | |
173 | if (strcasecmp(ifname, "any") == 0) | |
174 | return RMAP_MATCH; | |
175 | nh_data = object; | |
176 | if (!nh_data || !nh_data->nexthop) | |
177 | return RMAP_NOMATCH; | |
178 | ifindex = ifname2ifindex(ifname, nh_data->vrf_id); | |
179 | if (ifindex == 0) | |
180 | return RMAP_NOMATCH; | |
181 | if (nh_data->nexthop->ifindex == ifindex) | |
182 | return RMAP_MATCH; | |
183 | } | |
0032dd59 | 184 | return RMAP_NOMATCH; |
5921ef9a PJ |
185 | } |
186 | ||
187 | /* Route map `match interface' match statement. `arg' is IFNAME value */ | |
d62a17ae | 188 | static void *route_match_interface_compile(const char *arg) |
5921ef9a | 189 | { |
d62a17ae | 190 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
5921ef9a PJ |
191 | } |
192 | ||
193 | /* Free route map's compiled `match interface' value. */ | |
d62a17ae | 194 | static void route_match_interface_free(void *rule) |
5921ef9a | 195 | { |
d62a17ae | 196 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
5921ef9a PJ |
197 | } |
198 | ||
199 | /* Route map commands for interface matching */ | |
d62a17ae | 200 | struct route_map_rule_cmd route_match_interface_cmd = { |
201 | "interface", route_match_interface, route_match_interface_compile, | |
202 | route_match_interface_free}; | |
5921ef9a | 203 | |
9f0ea7d4 DS |
204 | DEFUN (match_ip_address_prefix_len, |
205 | match_ip_address_prefix_len_cmd, | |
7757e5e1 | 206 | "match ip address prefix-len (0-32)", |
9f0ea7d4 DS |
207 | MATCH_STR |
208 | IP_STR | |
209 | "Match prefix length of ip address\n" | |
210 | "Match prefix length of ip address\n" | |
211 | "Prefix length\n") | |
212 | { | |
d62a17ae | 213 | return zebra_route_match_add(vty, "ip address prefix-len", argv[4]->arg, |
214 | RMAP_EVENT_MATCH_ADDED); | |
9f0ea7d4 DS |
215 | } |
216 | ||
217 | DEFUN (no_match_ip_address_prefix_len, | |
218 | no_match_ip_address_prefix_len_cmd, | |
7757e5e1 | 219 | "no match ip address prefix-len [(0-32)]", |
9f0ea7d4 DS |
220 | NO_STR |
221 | MATCH_STR | |
222 | IP_STR | |
16cedbb0 QY |
223 | "Match prefix length of ip address\n" |
224 | "Match prefix length of ip address\n" | |
7757e5e1 | 225 | "Prefix length\n") |
9f0ea7d4 | 226 | { |
d62a17ae | 227 | char *plen = (argc == 6) ? argv[5]->arg : NULL; |
228 | return zebra_route_match_delete(vty, "ip address prefix-len", plen, | |
229 | RMAP_EVENT_MATCH_DELETED); | |
9f0ea7d4 DS |
230 | } |
231 | ||
9f0ea7d4 DS |
232 | |
233 | DEFUN (match_ip_nexthop_prefix_len, | |
234 | match_ip_nexthop_prefix_len_cmd, | |
7757e5e1 | 235 | "match ip next-hop prefix-len (0-32)", |
9f0ea7d4 DS |
236 | MATCH_STR |
237 | IP_STR | |
238 | "Match prefixlen of nexthop ip address\n" | |
239 | "Match prefixlen of given nexthop\n" | |
240 | "Prefix length\n") | |
241 | { | |
d62a17ae | 242 | return zebra_route_match_add(vty, "ip next-hop prefix-len", |
243 | argv[4]->arg, RMAP_EVENT_MATCH_ADDED); | |
9f0ea7d4 DS |
244 | } |
245 | ||
246 | DEFUN (no_match_ip_nexthop_prefix_len, | |
247 | no_match_ip_nexthop_prefix_len_cmd, | |
7757e5e1 | 248 | "no match ip next-hop prefix-len [(0-32)]", |
9f0ea7d4 DS |
249 | NO_STR |
250 | MATCH_STR | |
251 | IP_STR | |
252 | "Match prefixlen of nexthop ip address\n" | |
7757e5e1 QY |
253 | "Match prefix length of nexthop\n" |
254 | "Prefix length\n") | |
9f0ea7d4 | 255 | { |
d62a17ae | 256 | char *plen = (argc == 6) ? argv[5]->arg : NULL; |
257 | return zebra_route_match_delete(vty, "ip next-hop prefix-len", plen, | |
258 | RMAP_EVENT_MATCH_DELETED); | |
9f0ea7d4 DS |
259 | } |
260 | ||
9f0ea7d4 DS |
261 | |
262 | DEFUN (match_source_protocol, | |
263 | match_source_protocol_cmd, | |
5b9471f9 | 264 | "match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>", |
9f0ea7d4 | 265 | MATCH_STR |
16cedbb0 QY |
266 | "Match protocol via which the route was learnt\n" |
267 | "BGP protocol\n" | |
268 | "OSPF protocol\n" | |
269 | "RIP protocol\n" | |
270 | "RIPNG protocol\n" | |
271 | "ISIS protocol\n" | |
272 | "OSPF6 protocol\n" | |
5b9471f9 JB |
273 | "PIM protocol\n" |
274 | "NHRP protocol\n" | |
275 | "EIGRP protocol\n" | |
276 | "BABEL protocol\n" | |
16cedbb0 QY |
277 | "Routes from directly connected peer\n" |
278 | "Routes from system configuration\n" | |
279 | "Routes from kernel\n" | |
280 | "Statically configured routes\n") | |
9f0ea7d4 | 281 | { |
d62a17ae | 282 | char *proto = argv[2]->text; |
283 | int i; | |
9f0ea7d4 | 284 | |
d62a17ae | 285 | i = proto_name2num(proto); |
286 | if (i < 0) { | |
287 | vty_out(vty, "invalid protocol name \"%s\"\n", proto); | |
288 | return CMD_WARNING_CONFIG_FAILED; | |
289 | } | |
290 | return zebra_route_match_add(vty, "source-protocol", proto, | |
291 | RMAP_EVENT_MATCH_ADDED); | |
9f0ea7d4 DS |
292 | } |
293 | ||
294 | DEFUN (no_match_source_protocol, | |
295 | no_match_source_protocol_cmd, | |
5b9471f9 | 296 | "no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static>]", |
9f0ea7d4 DS |
297 | NO_STR |
298 | MATCH_STR | |
7757e5e1 | 299 | "No match protocol via which the route was learnt\n" |
16cedbb0 QY |
300 | "BGP protocol\n" |
301 | "OSPF protocol\n" | |
302 | "RIP protocol\n" | |
303 | "RIPNG protocol\n" | |
304 | "ISIS protocol\n" | |
305 | "OSPF6 protocol\n" | |
5b9471f9 JB |
306 | "PIM protocol\n" |
307 | "NHRP protocol\n" | |
308 | "EIGRP protocol\n" | |
309 | "BABEL protocol\n" | |
16cedbb0 QY |
310 | "Routes from directly connected peer\n" |
311 | "Routes from system configuration\n" | |
312 | "Routes from kernel\n" | |
313 | "Statically configured routes\n") | |
9f0ea7d4 | 314 | { |
d62a17ae | 315 | char *proto = (argc == 4) ? argv[3]->text : NULL; |
316 | return zebra_route_match_delete(vty, "source-protocol", proto, | |
317 | RMAP_EVENT_MATCH_DELETED); | |
9f0ea7d4 DS |
318 | } |
319 | ||
5921ef9a PJ |
320 | /* set functions */ |
321 | ||
322 | DEFUN (set_src, | |
323 | set_src_cmd, | |
6147e2c6 | 324 | "set src <A.B.C.D|X:X::X:X>", |
5921ef9a PJ |
325 | SET_STR |
326 | "src address for route\n" | |
16cedbb0 QY |
327 | "IPv4 src address\n" |
328 | "IPv6 src address\n") | |
5921ef9a | 329 | { |
d62a17ae | 330 | int idx_ip = 2; |
331 | union g_addr src; | |
332 | struct interface *pif = NULL; | |
333 | int family; | |
334 | struct prefix p; | |
335 | struct vrf *vrf; | |
336 | ||
337 | if (inet_pton(AF_INET, argv[idx_ip]->arg, &src.ipv4) != 1) { | |
338 | if (inet_pton(AF_INET6, argv[idx_ip]->arg, &src.ipv6) != 1) { | |
339 | vty_out(vty, "%% not a valid IPv4/v6 address\n"); | |
340 | return CMD_WARNING_CONFIG_FAILED; | |
341 | } | |
342 | ||
343 | p.family = family = AF_INET6; | |
344 | p.u.prefix6 = src.ipv6; | |
345 | p.prefixlen = IPV6_MAX_BITLEN; | |
346 | } else { | |
347 | p.family = family = AF_INET; | |
348 | p.u.prefix4 = src.ipv4; | |
349 | p.prefixlen = IPV4_MAX_BITLEN; | |
350 | } | |
351 | ||
352 | if (!zebra_check_addr(&p)) { | |
353 | vty_out(vty, "%% not a valid source IPv4/v6 address\n"); | |
354 | return CMD_WARNING_CONFIG_FAILED; | |
355 | } | |
5921ef9a | 356 | |
a2addae8 | 357 | RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { |
d62a17ae | 358 | if (family == AF_INET) |
359 | pif = if_lookup_exact_address((void *)&src.ipv4, | |
360 | AF_INET, vrf->vrf_id); | |
361 | else if (family == AF_INET6) | |
362 | pif = if_lookup_exact_address((void *)&src.ipv6, | |
363 | AF_INET6, vrf->vrf_id); | |
364 | ||
365 | if (pif != NULL) | |
366 | break; | |
0aabccc0 DD |
367 | } |
368 | ||
d62a17ae | 369 | if (!pif) { |
370 | vty_out(vty, "%% not a local address\n"); | |
371 | return CMD_WARNING_CONFIG_FAILED; | |
372 | } | |
373 | ||
374 | VTY_DECLVAR_CONTEXT(route_map_index, index); | |
375 | return generic_set_add(vty, index, "src", argv[idx_ip]->arg); | |
5921ef9a PJ |
376 | } |
377 | ||
378 | DEFUN (no_set_src, | |
379 | no_set_src_cmd, | |
7757e5e1 | 380 | "no set src [<A.B.C.D|X:X::X:X>]", |
5921ef9a PJ |
381 | NO_STR |
382 | SET_STR | |
3a2d747c QY |
383 | "Source address for route\n" |
384 | "IPv4 address\n" | |
385 | "IPv6 address\n") | |
5921ef9a | 386 | { |
d62a17ae | 387 | char *ip = (argc == 4) ? argv[3]->arg : NULL; |
388 | VTY_DECLVAR_CONTEXT(route_map_index, index); | |
389 | return generic_set_delete(vty, index, "src", ip); | |
5921ef9a PJ |
390 | } |
391 | ||
518f0eb1 DS |
392 | DEFUN (zebra_route_map_timer, |
393 | zebra_route_map_timer_cmd, | |
6147e2c6 | 394 | "zebra route-map delay-timer (0-600)", |
41e7fb80 | 395 | ZEBRA_STR |
16cedbb0 | 396 | "Set route-map parameters\n" |
9f0ea7d4 DS |
397 | "Time to wait before route-map updates are processed\n" |
398 | "0 means event-driven updates are disabled\n") | |
518f0eb1 | 399 | { |
d62a17ae | 400 | int idx_number = 3; |
401 | u_int32_t rmap_delay_timer; | |
518f0eb1 | 402 | |
d62a17ae | 403 | rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10); |
404 | zebra_route_map_set_delay_timer(rmap_delay_timer); | |
518f0eb1 | 405 | |
d62a17ae | 406 | return (CMD_SUCCESS); |
518f0eb1 DS |
407 | } |
408 | ||
409 | DEFUN (no_zebra_route_map_timer, | |
410 | no_zebra_route_map_timer_cmd, | |
7757e5e1 | 411 | "no zebra route-map delay-timer [(0-600)]", |
518f0eb1 | 412 | NO_STR |
41e7fb80 | 413 | ZEBRA_STR |
16cedbb0 | 414 | "Set route-map parameters\n" |
7757e5e1 QY |
415 | "Reset delay-timer to default value, 30 secs\n" |
416 | "0 means event-driven updates are disabled\n") | |
518f0eb1 | 417 | { |
d62a17ae | 418 | zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER); |
518f0eb1 | 419 | |
d62a17ae | 420 | return (CMD_SUCCESS); |
518f0eb1 DS |
421 | } |
422 | ||
813d4307 | 423 | |
518f0eb1 DS |
424 | DEFUN (ip_protocol, |
425 | ip_protocol_cmd, | |
40d1cbfb | 426 | "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP", |
9f0ea7d4 DS |
427 | IP_STR |
428 | "Filter routing info exchanged between zebra and protocol\n" | |
ab0181ee | 429 | FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA |
7757e5e1 | 430 | "Specify route-map\n" |
518f0eb1 DS |
431 | "Route map name\n") |
432 | { | |
d62a17ae | 433 | char *proto = argv[2]->text; |
434 | char *rmap = argv[4]->arg; | |
435 | int i; | |
436 | ||
437 | if (strcasecmp(proto, "any") == 0) | |
438 | i = ZEBRA_ROUTE_MAX; | |
439 | else | |
440 | i = proto_name2num(proto); | |
441 | if (i < 0) { | |
442 | vty_out(vty, "invalid protocol name \"%s\"\n", proto); | |
443 | return CMD_WARNING_CONFIG_FAILED; | |
444 | } | |
445 | if (proto_rm[AFI_IP][i]) { | |
446 | if (strcmp(proto_rm[AFI_IP][i], rmap) == 0) | |
447 | return CMD_SUCCESS; | |
518f0eb1 | 448 | |
d62a17ae | 449 | XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); |
450 | } | |
451 | proto_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); | |
b84c7253 | 452 | |
d62a17ae | 453 | if (IS_ZEBRA_DEBUG_RIB_DETAILED) |
454 | zlog_debug( | |
455 | "%u: IPv4 Routemap config for protocol %s, scheduling RIB processing", | |
456 | VRF_DEFAULT, proto); | |
b84c7253 | 457 | |
d62a17ae | 458 | rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); |
459 | return CMD_SUCCESS; | |
518f0eb1 DS |
460 | } |
461 | ||
462 | DEFUN (no_ip_protocol, | |
463 | no_ip_protocol_cmd, | |
40d1cbfb | 464 | "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]", |
518f0eb1 | 465 | NO_STR |
9f0ea7d4 DS |
466 | IP_STR |
467 | "Stop filtering routing info between zebra and protocol\n" | |
ab0181ee | 468 | FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA |
7757e5e1 QY |
469 | "Specify route map\n" |
470 | "Route map name\n") | |
518f0eb1 | 471 | { |
d62a17ae | 472 | char *proto = argv[3]->text; |
473 | char *rmap = (argc == 6) ? argv[5]->arg : NULL; | |
474 | int i; | |
518f0eb1 | 475 | |
d62a17ae | 476 | if (strcasecmp(proto, "any") == 0) |
477 | i = ZEBRA_ROUTE_MAX; | |
478 | else | |
479 | i = proto_name2num(proto); | |
7757e5e1 | 480 | |
d62a17ae | 481 | if (i < 0) { |
482 | vty_out(vty, "invalid protocol name \"%s\"\n", proto); | |
483 | return CMD_WARNING_CONFIG_FAILED; | |
484 | } | |
7757e5e1 | 485 | |
d62a17ae | 486 | if (!proto_rm[AFI_IP][i]) |
487 | return CMD_SUCCESS; | |
518f0eb1 | 488 | |
d62a17ae | 489 | if (!rmap || strcmp(rmap, proto_rm[AFI_IP][i]) == 0) { |
490 | XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); | |
491 | proto_rm[AFI_IP][i] = NULL; | |
b84c7253 | 492 | |
d62a17ae | 493 | if (IS_ZEBRA_DEBUG_RIB_DETAILED) |
494 | zlog_debug( | |
495 | "%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing", | |
496 | VRF_DEFAULT, proto); | |
497 | rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); | |
498 | } | |
499 | return CMD_SUCCESS; | |
518f0eb1 DS |
500 | } |
501 | ||
502 | DEFUN (show_ip_protocol, | |
503 | show_ip_protocol_cmd, | |
504 | "show ip protocol", | |
505 | SHOW_STR | |
506 | IP_STR | |
507 | "IP protocol filtering status\n") | |
508 | { | |
d62a17ae | 509 | int i; |
518f0eb1 | 510 | |
d62a17ae | 511 | vty_out(vty, "Protocol : route-map \n"); |
512 | vty_out(vty, "------------------------\n"); | |
513 | for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { | |
514 | if (proto_rm[AFI_IP][i]) | |
515 | vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), | |
516 | proto_rm[AFI_IP][i]); | |
517 | else | |
518 | vty_out(vty, "%-10s : none\n", zebra_route_string(i)); | |
519 | } | |
520 | if (proto_rm[AFI_IP][i]) | |
521 | vty_out(vty, "%-10s : %-10s\n", "any", proto_rm[AFI_IP][i]); | |
522 | else | |
523 | vty_out(vty, "%-10s : none\n", "any"); | |
518f0eb1 | 524 | |
d62a17ae | 525 | return CMD_SUCCESS; |
518f0eb1 DS |
526 | } |
527 | ||
0aabccc0 DD |
528 | DEFUN (ipv6_protocol, |
529 | ipv6_protocol_cmd, | |
40d1cbfb | 530 | "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP", |
0aabccc0 DD |
531 | IP6_STR |
532 | "Filter IPv6 routing info exchanged between zebra and protocol\n" | |
ab0181ee | 533 | FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA |
7757e5e1 | 534 | "Specify route map\n" |
0aabccc0 DD |
535 | "Route map name\n") |
536 | { | |
d62a17ae | 537 | char *proto = argv[2]->text; |
538 | char *rmap = argv[4]->arg; | |
539 | int i; | |
540 | ||
541 | if (strcasecmp(proto, "any") == 0) | |
542 | i = ZEBRA_ROUTE_MAX; | |
543 | else | |
544 | i = proto_name2num(proto); | |
545 | if (i < 0) { | |
546 | vty_out(vty, "invalid protocol name \"%s\"\n", proto); | |
547 | return CMD_WARNING_CONFIG_FAILED; | |
548 | } | |
549 | if (proto_rm[AFI_IP6][i]) { | |
550 | if (strcmp(proto_rm[AFI_IP6][i], rmap) == 0) | |
551 | return CMD_SUCCESS; | |
0aabccc0 | 552 | |
d62a17ae | 553 | XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); |
554 | } | |
555 | proto_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); | |
b84c7253 | 556 | |
d62a17ae | 557 | if (IS_ZEBRA_DEBUG_RIB_DETAILED) |
558 | zlog_debug( | |
559 | "%u: IPv6 Routemap config for protocol %s, scheduling RIB processing", | |
560 | VRF_DEFAULT, proto); | |
b84c7253 | 561 | |
d62a17ae | 562 | rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); |
563 | return CMD_SUCCESS; | |
0aabccc0 DD |
564 | } |
565 | ||
566 | DEFUN (no_ipv6_protocol, | |
567 | no_ipv6_protocol_cmd, | |
40d1cbfb | 568 | "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]", |
0aabccc0 DD |
569 | NO_STR |
570 | IP6_STR | |
571 | "Stop filtering IPv6 routing info between zebra and protocol\n" | |
ab0181ee | 572 | FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA |
7757e5e1 QY |
573 | "Specify route map\n" |
574 | "Route map name\n") | |
0aabccc0 | 575 | { |
d62a17ae | 576 | const char *proto = argv[3]->text; |
577 | const char *rmap = (argc == 6) ? argv[5]->arg : NULL; | |
578 | int i; | |
579 | ||
580 | if (strcasecmp(proto, "any") == 0) | |
581 | i = ZEBRA_ROUTE_MAX; | |
582 | else | |
583 | i = proto_name2num(proto); | |
584 | if (i < 0) { | |
585 | vty_out(vty, "invalid protocol name \"%s\"\n", proto); | |
586 | return CMD_WARNING_CONFIG_FAILED; | |
587 | } | |
588 | if (!proto_rm[AFI_IP6][i]) | |
589 | return CMD_SUCCESS; | |
0aabccc0 | 590 | |
d62a17ae | 591 | if (!rmap || strcmp(rmap, proto_rm[AFI_IP6][i]) == 0) { |
592 | XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); | |
593 | proto_rm[AFI_IP6][i] = NULL; | |
b84c7253 | 594 | |
d62a17ae | 595 | if (IS_ZEBRA_DEBUG_RIB_DETAILED) |
596 | zlog_debug( | |
597 | "%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing", | |
598 | VRF_DEFAULT, proto); | |
b84c7253 | 599 | |
d62a17ae | 600 | rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); |
601 | } | |
602 | return CMD_SUCCESS; | |
0aabccc0 DD |
603 | } |
604 | ||
0aabccc0 DD |
605 | DEFUN (show_ipv6_protocol, |
606 | show_ipv6_protocol_cmd, | |
607 | "show ipv6 protocol", | |
608 | SHOW_STR | |
609 | IP6_STR | |
610 | "IPv6 protocol filtering status\n") | |
611 | { | |
d62a17ae | 612 | int i; |
0aabccc0 | 613 | |
d62a17ae | 614 | vty_out(vty, "Protocol : route-map \n"); |
615 | vty_out(vty, "------------------------\n"); | |
616 | for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { | |
617 | if (proto_rm[AFI_IP6][i]) | |
618 | vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), | |
619 | proto_rm[AFI_IP6][i]); | |
620 | else | |
621 | vty_out(vty, "%-10s : none\n", zebra_route_string(i)); | |
622 | } | |
623 | if (proto_rm[AFI_IP6][i]) | |
624 | vty_out(vty, "%-10s : %-10s\n", "any", proto_rm[AFI_IP6][i]); | |
625 | else | |
626 | vty_out(vty, "%-10s : none\n", "any"); | |
0aabccc0 | 627 | |
d62a17ae | 628 | return CMD_SUCCESS; |
0aabccc0 DD |
629 | } |
630 | ||
9f0ea7d4 DS |
631 | DEFUN (ip_protocol_nht_rmap, |
632 | ip_protocol_nht_rmap_cmd, | |
40d1cbfb | 633 | "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP", |
9f0ea7d4 DS |
634 | IP_STR |
635 | "Filter Next Hop tracking route resolution\n" | |
ab0181ee | 636 | FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA |
7757e5e1 | 637 | "Specify route map\n" |
9f0ea7d4 DS |
638 | "Route map name\n") |
639 | { | |
d62a17ae | 640 | char *proto = argv[2]->text; |
641 | char *rmap = argv[4]->arg; | |
642 | int i; | |
643 | ||
644 | if (strcasecmp(proto, "any") == 0) | |
645 | i = ZEBRA_ROUTE_MAX; | |
646 | else | |
647 | i = proto_name2num(proto); | |
648 | if (i < 0) { | |
649 | vty_out(vty, "invalid protocol name \"%s\"\n", proto); | |
650 | return CMD_WARNING_CONFIG_FAILED; | |
651 | } | |
652 | if (nht_rm[AFI_IP][i]) { | |
653 | if (strcmp(nht_rm[AFI_IP][i], rmap) == 0) | |
654 | return CMD_SUCCESS; | |
9f0ea7d4 | 655 | |
d62a17ae | 656 | XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); |
657 | } | |
9f0ea7d4 | 658 | |
d62a17ae | 659 | nht_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); |
660 | zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); | |
9f0ea7d4 | 661 | |
d62a17ae | 662 | return CMD_SUCCESS; |
9f0ea7d4 DS |
663 | } |
664 | ||
665 | DEFUN (no_ip_protocol_nht_rmap, | |
666 | no_ip_protocol_nht_rmap_cmd, | |
40d1cbfb | 667 | "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]", |
9f0ea7d4 DS |
668 | NO_STR |
669 | IP_STR | |
670 | "Filter Next Hop tracking route resolution\n" | |
3b14d86e | 671 | FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA |
7757e5e1 QY |
672 | "Specify route map\n" |
673 | "Route map name\n") | |
9f0ea7d4 | 674 | { |
d62a17ae | 675 | int idx = 0; |
676 | char *proto = argv[3]->text; | |
677 | char *rmap = argv_find(argv, argc, "ROUTE-MAP", &idx) ? argv[idx]->arg | |
678 | : NULL; | |
55cb6743 | 679 | |
d62a17ae | 680 | int i = strmatch(proto, "any") ? ZEBRA_ROUTE_MAX |
681 | : proto_name2num(proto); | |
9f0ea7d4 | 682 | |
d62a17ae | 683 | if (i < 0) { |
684 | vty_out(vty, "invalid protocol name \"%s\"\n", proto); | |
685 | return CMD_WARNING_CONFIG_FAILED; | |
686 | } | |
55cb6743 | 687 | |
d62a17ae | 688 | if (!nht_rm[AFI_IP][i]) |
689 | return CMD_SUCCESS; | |
9f0ea7d4 | 690 | |
d62a17ae | 691 | if (!rmap || strcmp(rmap, nht_rm[AFI_IP][i]) == 0) { |
692 | XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); | |
693 | nht_rm[AFI_IP][i] = NULL; | |
694 | zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); | |
695 | } | |
696 | return CMD_SUCCESS; | |
9f0ea7d4 DS |
697 | } |
698 | ||
9f0ea7d4 DS |
699 | DEFUN (show_ip_protocol_nht, |
700 | show_ip_protocol_nht_cmd, | |
701 | "show ip nht route-map", | |
3a2d747c QY |
702 | SHOW_STR |
703 | IP_STR | |
704 | "IP nexthop tracking table\n" | |
9f0ea7d4 DS |
705 | "IP Next Hop tracking filtering status\n") |
706 | { | |
d62a17ae | 707 | int i; |
9f0ea7d4 | 708 | |
d62a17ae | 709 | vty_out(vty, "Protocol : route-map \n"); |
710 | vty_out(vty, "------------------------\n"); | |
711 | for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { | |
712 | if (nht_rm[AFI_IP][i]) | |
713 | vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), | |
714 | nht_rm[AFI_IP][i]); | |
715 | else | |
716 | vty_out(vty, "%-10s : none\n", zebra_route_string(i)); | |
717 | } | |
718 | if (nht_rm[AFI_IP][i]) | |
719 | vty_out(vty, "%-10s : %-10s\n", "any", nht_rm[AFI_IP][i]); | |
720 | else | |
721 | vty_out(vty, "%-10s : none\n", "any"); | |
9f0ea7d4 | 722 | |
d62a17ae | 723 | return CMD_SUCCESS; |
9f0ea7d4 DS |
724 | } |
725 | ||
726 | DEFUN (ipv6_protocol_nht_rmap, | |
727 | ipv6_protocol_nht_rmap_cmd, | |
40d1cbfb | 728 | "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP", |
9f0ea7d4 DS |
729 | IP6_STR |
730 | "Filter Next Hop tracking route resolution\n" | |
ab0181ee | 731 | FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA |
7757e5e1 | 732 | "Specify route map\n" |
9f0ea7d4 DS |
733 | "Route map name\n") |
734 | { | |
d62a17ae | 735 | char *proto = argv[2]->text; |
736 | char *rmap = argv[4]->arg; | |
737 | int i; | |
738 | ||
739 | if (strcasecmp(proto, "any") == 0) | |
740 | i = ZEBRA_ROUTE_MAX; | |
741 | else | |
742 | i = proto_name2num(proto); | |
743 | if (i < 0) { | |
744 | vty_out(vty, "invalid protocol name \"%s\"\n", proto); | |
745 | return CMD_WARNING_CONFIG_FAILED; | |
746 | } | |
747 | if (nht_rm[AFI_IP6][i]) | |
748 | XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); | |
749 | nht_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); | |
750 | zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); | |
9f0ea7d4 | 751 | |
d62a17ae | 752 | return CMD_SUCCESS; |
9f0ea7d4 DS |
753 | } |
754 | ||
755 | DEFUN (no_ipv6_protocol_nht_rmap, | |
756 | no_ipv6_protocol_nht_rmap_cmd, | |
40d1cbfb | 757 | "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]", |
9f0ea7d4 DS |
758 | NO_STR |
759 | IP6_STR | |
760 | "Filter Next Hop tracking route resolution\n" | |
3b14d86e | 761 | FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA |
7757e5e1 QY |
762 | "Specify route map\n" |
763 | "Route map name\n") | |
9f0ea7d4 | 764 | { |
d62a17ae | 765 | char *proto = argv[3]->text; |
766 | char *rmap = (argc == 6) ? argv[5]->arg : NULL; | |
767 | int i; | |
768 | ||
769 | if (strcasecmp(proto, "any") == 0) | |
770 | i = ZEBRA_ROUTE_MAX; | |
771 | else | |
772 | i = proto_name2num(proto); | |
773 | if (i < 0) { | |
774 | vty_out(vty, "invalid protocol name \"%s\"\n", proto); | |
775 | return CMD_WARNING_CONFIG_FAILED; | |
776 | } | |
9f0ea7d4 | 777 | |
d62a17ae | 778 | if (nht_rm[AFI_IP6][i] && rmap && strcmp(rmap, nht_rm[AFI_IP6][i])) { |
779 | vty_out(vty, "invalid route-map \"%s\"\n", rmap); | |
780 | return CMD_WARNING_CONFIG_FAILED; | |
781 | } | |
813d4307 | 782 | |
d62a17ae | 783 | if (nht_rm[AFI_IP6][i]) { |
784 | XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); | |
785 | nht_rm[AFI_IP6][i] = NULL; | |
786 | } | |
9f0ea7d4 | 787 | |
d62a17ae | 788 | zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); |
813d4307 | 789 | |
d62a17ae | 790 | return CMD_SUCCESS; |
9f0ea7d4 DS |
791 | } |
792 | ||
9f0ea7d4 DS |
793 | DEFUN (show_ipv6_protocol_nht, |
794 | show_ipv6_protocol_nht_cmd, | |
795 | "show ipv6 nht route-map", | |
3a2d747c QY |
796 | SHOW_STR |
797 | IP6_STR | |
798 | "Next Hop filtering status\n" | |
799 | "Route-map\n") | |
9f0ea7d4 | 800 | { |
d62a17ae | 801 | int i; |
9f0ea7d4 | 802 | |
d62a17ae | 803 | vty_out(vty, "Protocol : route-map \n"); |
804 | vty_out(vty, "------------------------\n"); | |
805 | for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { | |
806 | if (nht_rm[AFI_IP6][i]) | |
807 | vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), | |
808 | nht_rm[AFI_IP6][i]); | |
809 | else | |
810 | vty_out(vty, "%-10s : none\n", zebra_route_string(i)); | |
811 | } | |
812 | if (nht_rm[AFI_IP][i]) | |
813 | vty_out(vty, "%-10s : %-10s\n", "any", nht_rm[AFI_IP6][i]); | |
814 | else | |
815 | vty_out(vty, "%-10s : none\n", "any"); | |
9f0ea7d4 | 816 | |
d62a17ae | 817 | return CMD_SUCCESS; |
9f0ea7d4 DS |
818 | } |
819 | ||
5921ef9a PJ |
820 | /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/ |
821 | ||
822 | /* `match ip next-hop IP_ACCESS_LIST' */ | |
823 | ||
824 | /* Match function return 1 if match is success else return zero. */ | |
d62a17ae | 825 | static route_map_result_t route_match_ip_next_hop(void *rule, |
826 | struct prefix *prefix, | |
827 | route_map_object_t type, | |
828 | void *object) | |
829 | { | |
830 | struct access_list *alist; | |
831 | struct nh_rmap_obj *nh_data; | |
832 | struct prefix_ipv4 p; | |
833 | ||
834 | if (type == RMAP_ZEBRA) { | |
835 | nh_data = object; | |
836 | if (!nh_data) | |
837 | return RMAP_DENYMATCH; | |
838 | ||
839 | switch (nh_data->nexthop->type) { | |
840 | case NEXTHOP_TYPE_IFINDEX: | |
841 | /* Interface routes can't match ip next-hop */ | |
842 | return RMAP_NOMATCH; | |
843 | case NEXTHOP_TYPE_IPV4_IFINDEX: | |
844 | case NEXTHOP_TYPE_IPV4: | |
845 | p.family = AF_INET; | |
846 | p.prefix = nh_data->nexthop->gate.ipv4; | |
847 | p.prefixlen = IPV4_MAX_BITLEN; | |
848 | break; | |
849 | default: | |
850 | return RMAP_NOMATCH; | |
851 | } | |
852 | alist = access_list_lookup(AFI_IP, (char *)rule); | |
853 | if (alist == NULL) | |
854 | return RMAP_NOMATCH; | |
855 | ||
856 | return (access_list_apply(alist, &p) == FILTER_DENY | |
857 | ? RMAP_NOMATCH | |
858 | : RMAP_MATCH); | |
859 | } | |
5921ef9a | 860 | return RMAP_NOMATCH; |
5921ef9a PJ |
861 | } |
862 | ||
863 | /* Route map `ip next-hop' match statement. `arg' should be | |
864 | access-list name. */ | |
d62a17ae | 865 | static void *route_match_ip_next_hop_compile(const char *arg) |
5921ef9a | 866 | { |
d62a17ae | 867 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
5921ef9a PJ |
868 | } |
869 | ||
870 | /* Free route map's compiled `. */ | |
d62a17ae | 871 | static void route_match_ip_next_hop_free(void *rule) |
5921ef9a | 872 | { |
d62a17ae | 873 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
5921ef9a PJ |
874 | } |
875 | ||
876 | /* Route map commands for ip next-hop matching. */ | |
d62a17ae | 877 | static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { |
878 | "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile, | |
879 | route_match_ip_next_hop_free}; | |
6b0655a2 | 880 | |
5921ef9a PJ |
881 | /* `match ip next-hop prefix-list PREFIX_LIST' */ |
882 | ||
883 | static route_map_result_t | |
d62a17ae | 884 | route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, |
885 | route_map_object_t type, void *object) | |
5921ef9a | 886 | { |
d62a17ae | 887 | struct prefix_list *plist; |
888 | struct nh_rmap_obj *nh_data; | |
889 | struct prefix_ipv4 p; | |
890 | ||
891 | if (type == RMAP_ZEBRA) { | |
892 | nh_data = (struct nh_rmap_obj *)object; | |
893 | if (!nh_data) | |
894 | return RMAP_DENYMATCH; | |
895 | ||
896 | switch (nh_data->nexthop->type) { | |
897 | case NEXTHOP_TYPE_IFINDEX: | |
898 | /* Interface routes can't match ip next-hop */ | |
899 | return RMAP_NOMATCH; | |
900 | case NEXTHOP_TYPE_IPV4_IFINDEX: | |
901 | case NEXTHOP_TYPE_IPV4: | |
902 | p.family = AF_INET; | |
903 | p.prefix = nh_data->nexthop->gate.ipv4; | |
904 | p.prefixlen = IPV4_MAX_BITLEN; | |
905 | break; | |
906 | default: | |
907 | return RMAP_NOMATCH; | |
908 | } | |
909 | plist = prefix_list_lookup(AFI_IP, (char *)rule); | |
910 | if (plist == NULL) | |
911 | return RMAP_NOMATCH; | |
912 | ||
913 | return (prefix_list_apply(plist, &p) == PREFIX_DENY | |
914 | ? RMAP_NOMATCH | |
915 | : RMAP_MATCH); | |
916 | } | |
917 | return RMAP_NOMATCH; | |
5921ef9a PJ |
918 | } |
919 | ||
d62a17ae | 920 | static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) |
5921ef9a | 921 | { |
d62a17ae | 922 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
5921ef9a PJ |
923 | } |
924 | ||
d62a17ae | 925 | static void route_match_ip_next_hop_prefix_list_free(void *rule) |
5921ef9a | 926 | { |
d62a17ae | 927 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
5921ef9a PJ |
928 | } |
929 | ||
d62a17ae | 930 | static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { |
931 | "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list, | |
932 | route_match_ip_next_hop_prefix_list_compile, | |
933 | route_match_ip_next_hop_prefix_list_free}; | |
6b0655a2 | 934 | |
5921ef9a PJ |
935 | /* `match ip address IP_ACCESS_LIST' */ |
936 | ||
937 | /* Match function should return 1 if match is success else return | |
938 | zero. */ | |
d62a17ae | 939 | static route_map_result_t route_match_ip_address(void *rule, |
940 | struct prefix *prefix, | |
941 | route_map_object_t type, | |
942 | void *object) | |
5921ef9a | 943 | { |
d62a17ae | 944 | struct access_list *alist; |
945 | ||
946 | if (type == RMAP_ZEBRA) { | |
947 | alist = access_list_lookup(AFI_IP, (char *)rule); | |
948 | if (alist == NULL) | |
949 | return RMAP_NOMATCH; | |
5921ef9a | 950 | |
d62a17ae | 951 | return (access_list_apply(alist, prefix) == FILTER_DENY |
952 | ? RMAP_NOMATCH | |
953 | : RMAP_MATCH); | |
954 | } | |
5921ef9a | 955 | return RMAP_NOMATCH; |
5921ef9a PJ |
956 | } |
957 | ||
958 | /* Route map `ip address' match statement. `arg' should be | |
959 | access-list name. */ | |
d62a17ae | 960 | static void *route_match_ip_address_compile(const char *arg) |
5921ef9a | 961 | { |
d62a17ae | 962 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
5921ef9a PJ |
963 | } |
964 | ||
965 | /* Free route map's compiled `ip address' value. */ | |
d62a17ae | 966 | static void route_match_ip_address_free(void *rule) |
5921ef9a | 967 | { |
d62a17ae | 968 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
5921ef9a PJ |
969 | } |
970 | ||
971 | /* Route map commands for ip address matching. */ | |
d62a17ae | 972 | static struct route_map_rule_cmd route_match_ip_address_cmd = { |
973 | "ip address", route_match_ip_address, route_match_ip_address_compile, | |
974 | route_match_ip_address_free}; | |
6b0655a2 | 975 | |
5921ef9a PJ |
976 | /* `match ip address prefix-list PREFIX_LIST' */ |
977 | ||
978 | static route_map_result_t | |
d62a17ae | 979 | route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, |
980 | route_map_object_t type, void *object) | |
5921ef9a | 981 | { |
d62a17ae | 982 | struct prefix_list *plist; |
983 | ||
984 | if (type == RMAP_ZEBRA) { | |
985 | plist = prefix_list_lookup(AFI_IP, (char *)rule); | |
986 | if (plist == NULL) | |
987 | return RMAP_NOMATCH; | |
5921ef9a | 988 | |
d62a17ae | 989 | return (prefix_list_apply(plist, prefix) == PREFIX_DENY |
990 | ? RMAP_NOMATCH | |
991 | : RMAP_MATCH); | |
992 | } | |
5921ef9a | 993 | return RMAP_NOMATCH; |
5921ef9a PJ |
994 | } |
995 | ||
d62a17ae | 996 | static void *route_match_ip_address_prefix_list_compile(const char *arg) |
5921ef9a | 997 | { |
d62a17ae | 998 | return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); |
5921ef9a PJ |
999 | } |
1000 | ||
d62a17ae | 1001 | static void route_match_ip_address_prefix_list_free(void *rule) |
5921ef9a | 1002 | { |
d62a17ae | 1003 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
5921ef9a PJ |
1004 | } |
1005 | ||
d62a17ae | 1006 | static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { |
1007 | "ip address prefix-list", route_match_ip_address_prefix_list, | |
1008 | route_match_ip_address_prefix_list_compile, | |
1009 | route_match_ip_address_prefix_list_free}; | |
5921ef9a | 1010 | |
6b0655a2 | 1011 | |
9f0ea7d4 DS |
1012 | /* `match ip address prefix-len PREFIXLEN' */ |
1013 | ||
1014 | static route_map_result_t | |
d62a17ae | 1015 | route_match_ip_address_prefix_len(void *rule, struct prefix *prefix, |
1016 | route_map_object_t type, void *object) | |
9f0ea7d4 | 1017 | { |
d62a17ae | 1018 | u_int32_t *prefixlen = (u_int32_t *)rule; |
9f0ea7d4 | 1019 | |
d62a17ae | 1020 | if (type == RMAP_ZEBRA) { |
1021 | return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH | |
1022 | : RMAP_NOMATCH); | |
1023 | } | |
1024 | return RMAP_NOMATCH; | |
9f0ea7d4 DS |
1025 | } |
1026 | ||
d62a17ae | 1027 | static void *route_match_ip_address_prefix_len_compile(const char *arg) |
9f0ea7d4 | 1028 | { |
d62a17ae | 1029 | u_int32_t *prefix_len; |
1030 | char *endptr = NULL; | |
1031 | unsigned long tmpval; | |
9f0ea7d4 | 1032 | |
d62a17ae | 1033 | /* prefix len value shoud be integer. */ |
1034 | if (!all_digit(arg)) | |
1035 | return NULL; | |
9f0ea7d4 | 1036 | |
d62a17ae | 1037 | errno = 0; |
1038 | tmpval = strtoul(arg, &endptr, 10); | |
1039 | if (*endptr != '\0' || errno || tmpval > UINT32_MAX) | |
1040 | return NULL; | |
9f0ea7d4 | 1041 | |
d62a17ae | 1042 | prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); |
9f0ea7d4 | 1043 | |
d62a17ae | 1044 | if (!prefix_len) |
1045 | return prefix_len; | |
9f0ea7d4 | 1046 | |
d62a17ae | 1047 | *prefix_len = tmpval; |
1048 | return prefix_len; | |
9f0ea7d4 DS |
1049 | } |
1050 | ||
d62a17ae | 1051 | static void route_match_ip_address_prefix_len_free(void *rule) |
9f0ea7d4 | 1052 | { |
d62a17ae | 1053 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
9f0ea7d4 DS |
1054 | } |
1055 | ||
d62a17ae | 1056 | static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd = { |
1057 | "ip address prefix-len", route_match_ip_address_prefix_len, | |
1058 | route_match_ip_address_prefix_len_compile, | |
1059 | route_match_ip_address_prefix_len_free}; | |
9f0ea7d4 DS |
1060 | |
1061 | ||
1062 | /* `match ip nexthop prefix-len PREFIXLEN' */ | |
1063 | ||
1064 | static route_map_result_t | |
d62a17ae | 1065 | route_match_ip_nexthop_prefix_len(void *rule, struct prefix *prefix, |
1066 | route_map_object_t type, void *object) | |
1067 | { | |
1068 | u_int32_t *prefixlen = (u_int32_t *)rule; | |
1069 | struct nh_rmap_obj *nh_data; | |
1070 | struct prefix_ipv4 p; | |
1071 | ||
1072 | if (type == RMAP_ZEBRA) { | |
1073 | nh_data = (struct nh_rmap_obj *)object; | |
1074 | if (!nh_data || !nh_data->nexthop) | |
1075 | return RMAP_DENYMATCH; | |
1076 | ||
1077 | switch (nh_data->nexthop->type) { | |
1078 | case NEXTHOP_TYPE_IFINDEX: | |
1079 | /* Interface routes can't match ip next-hop */ | |
1080 | return RMAP_NOMATCH; | |
1081 | case NEXTHOP_TYPE_IPV4_IFINDEX: | |
1082 | case NEXTHOP_TYPE_IPV4: | |
1083 | p.family = AF_INET; | |
1084 | p.prefix = nh_data->nexthop->gate.ipv4; | |
1085 | p.prefixlen = IPV4_MAX_BITLEN; | |
1086 | break; | |
1087 | default: | |
1088 | return RMAP_NOMATCH; | |
1089 | } | |
1090 | return ((p.prefixlen == *prefixlen) ? RMAP_MATCH | |
1091 | : RMAP_NOMATCH); | |
1092 | } | |
1093 | return RMAP_NOMATCH; | |
1094 | } | |
1095 | ||
1096 | static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = { | |
1097 | "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len, | |
1098 | route_match_ip_address_prefix_len_compile, /* reuse */ | |
1099 | route_match_ip_address_prefix_len_free /* reuse */ | |
9f0ea7d4 DS |
1100 | }; |
1101 | ||
1102 | /* `match source-protocol PROTOCOL' */ | |
1103 | ||
d62a17ae | 1104 | static route_map_result_t route_match_source_protocol(void *rule, |
1105 | struct prefix *prefix, | |
1106 | route_map_object_t type, | |
1107 | void *object) | |
9f0ea7d4 | 1108 | { |
d62a17ae | 1109 | u_int32_t *rib_type = (u_int32_t *)rule; |
1110 | struct nh_rmap_obj *nh_data; | |
9f0ea7d4 | 1111 | |
d62a17ae | 1112 | if (type == RMAP_ZEBRA) { |
1113 | nh_data = (struct nh_rmap_obj *)object; | |
1114 | if (!nh_data) | |
1115 | return RMAP_DENYMATCH; | |
9f0ea7d4 | 1116 | |
d62a17ae | 1117 | return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH |
1118 | : RMAP_NOMATCH); | |
1119 | } | |
1120 | return RMAP_NOMATCH; | |
9f0ea7d4 DS |
1121 | } |
1122 | ||
d62a17ae | 1123 | static void *route_match_source_protocol_compile(const char *arg) |
9f0ea7d4 | 1124 | { |
d62a17ae | 1125 | u_int32_t *rib_type; |
1126 | int i; | |
9f0ea7d4 | 1127 | |
d62a17ae | 1128 | i = proto_name2num(arg); |
1129 | rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); | |
9f0ea7d4 | 1130 | |
d62a17ae | 1131 | *rib_type = i; |
9f0ea7d4 | 1132 | |
d62a17ae | 1133 | return rib_type; |
9f0ea7d4 DS |
1134 | } |
1135 | ||
d62a17ae | 1136 | static void route_match_source_protocol_free(void *rule) |
9f0ea7d4 | 1137 | { |
d62a17ae | 1138 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
9f0ea7d4 DS |
1139 | } |
1140 | ||
d62a17ae | 1141 | static struct route_map_rule_cmd route_match_source_protocol_cmd = { |
1142 | "source-protocol", route_match_source_protocol, | |
1143 | route_match_source_protocol_compile, route_match_source_protocol_free}; | |
9f0ea7d4 | 1144 | |
5921ef9a PJ |
1145 | /* `set src A.B.C.D' */ |
1146 | ||
1147 | /* Set src. */ | |
d62a17ae | 1148 | static route_map_result_t route_set_src(void *rule, struct prefix *prefix, |
1149 | route_map_object_t type, void *object) | |
5921ef9a | 1150 | { |
d62a17ae | 1151 | struct nh_rmap_obj *nh_data; |
9f0ea7d4 | 1152 | |
d62a17ae | 1153 | if (type == RMAP_ZEBRA) { |
1154 | nh_data = (struct nh_rmap_obj *)object; | |
1155 | nh_data->nexthop->rmap_src = *(union g_addr *)rule; | |
1156 | } | |
1157 | return RMAP_OKAY; | |
5921ef9a PJ |
1158 | } |
1159 | ||
1160 | /* set src compilation. */ | |
d62a17ae | 1161 | static void *route_set_src_compile(const char *arg) |
5921ef9a | 1162 | { |
d62a17ae | 1163 | union g_addr src, *psrc; |
5921ef9a | 1164 | |
d62a17ae | 1165 | if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1) |
1166 | || (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1))) { | |
1167 | psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr)); | |
1168 | *psrc = src; | |
1169 | return psrc; | |
1170 | } | |
1171 | return NULL; | |
5921ef9a PJ |
1172 | } |
1173 | ||
1174 | /* Free route map's compiled `set src' value. */ | |
d62a17ae | 1175 | static void route_set_src_free(void *rule) |
5921ef9a | 1176 | { |
d62a17ae | 1177 | XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); |
5921ef9a PJ |
1178 | } |
1179 | ||
1180 | /* Set src rule structure. */ | |
d62a17ae | 1181 | static struct route_map_rule_cmd route_set_src_cmd = { |
9d303b37 | 1182 | "src", route_set_src, route_set_src_compile, route_set_src_free, |
5921ef9a PJ |
1183 | }; |
1184 | ||
d62a17ae | 1185 | static int zebra_route_map_update_timer(struct thread *thread) |
518f0eb1 | 1186 | { |
d62a17ae | 1187 | zebra_t_rmap_update = NULL; |
518f0eb1 | 1188 | |
d62a17ae | 1189 | if (IS_ZEBRA_DEBUG_EVENT) |
1190 | zlog_debug("Event driven route-map update triggered"); | |
518f0eb1 | 1191 | |
d62a17ae | 1192 | if (IS_ZEBRA_DEBUG_RIB_DETAILED) |
1193 | zlog_debug( | |
1194 | "%u: Routemap update-timer fired, scheduling RIB processing", | |
1195 | VRF_DEFAULT); | |
b84c7253 | 1196 | |
d62a17ae | 1197 | zebra_import_table_rm_update(); |
1198 | rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); | |
1199 | zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); | |
1200 | zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); | |
9f0ea7d4 | 1201 | |
d62a17ae | 1202 | return (0); |
518f0eb1 DS |
1203 | } |
1204 | ||
d62a17ae | 1205 | static void zebra_route_map_set_delay_timer(u_int32_t value) |
518f0eb1 | 1206 | { |
d62a17ae | 1207 | zebra_rmap_update_timer = value; |
1208 | if (!value && zebra_t_rmap_update) { | |
1209 | /* Event driven route map updates is being disabled */ | |
1210 | /* But there's a pending timer. Fire it off now */ | |
1211 | thread_cancel(zebra_t_rmap_update); | |
1212 | zebra_route_map_update_timer(zebra_t_rmap_update); | |
1213 | } | |
518f0eb1 DS |
1214 | } |
1215 | ||
d62a17ae | 1216 | void zebra_route_map_write_delay_timer(struct vty *vty) |
518f0eb1 | 1217 | { |
d62a17ae | 1218 | if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)) |
1219 | vty_out(vty, "zebra route-map delay-timer %d\n", | |
1220 | zebra_rmap_update_timer); | |
1221 | return; | |
518f0eb1 DS |
1222 | } |
1223 | ||
d62a17ae | 1224 | route_map_result_t zebra_route_map_check(int family, int rib_type, |
1225 | struct prefix *p, | |
1226 | struct nexthop *nexthop, | |
1227 | vrf_id_t vrf_id, route_tag_t tag) | |
518f0eb1 | 1228 | { |
d62a17ae | 1229 | struct route_map *rmap = NULL; |
1230 | route_map_result_t ret = RMAP_MATCH; | |
1231 | struct nh_rmap_obj nh_obj; | |
9f0ea7d4 | 1232 | |
d62a17ae | 1233 | nh_obj.nexthop = nexthop; |
1234 | nh_obj.vrf_id = vrf_id; | |
1235 | nh_obj.source_protocol = rib_type; | |
1236 | nh_obj.metric = 0; | |
1237 | nh_obj.tag = tag; | |
518f0eb1 | 1238 | |
d62a17ae | 1239 | if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) |
1240 | rmap = route_map_lookup_by_name(proto_rm[family][rib_type]); | |
1241 | if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX]) | |
1242 | rmap = route_map_lookup_by_name( | |
1243 | proto_rm[family][ZEBRA_ROUTE_MAX]); | |
1244 | if (rmap) { | |
1245 | ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); | |
1246 | } | |
9f0ea7d4 | 1247 | |
d62a17ae | 1248 | return (ret); |
9f0ea7d4 DS |
1249 | } |
1250 | ||
d62a17ae | 1251 | char *zebra_get_import_table_route_map(afi_t afi, uint32_t table) |
8902474b | 1252 | { |
d62a17ae | 1253 | return zebra_import_table_routemap[afi][table]; |
8902474b DS |
1254 | } |
1255 | ||
d62a17ae | 1256 | void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name, |
1257 | uint32_t table) | |
8902474b | 1258 | { |
d62a17ae | 1259 | zebra_import_table_routemap[afi][table] = |
1260 | XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); | |
8902474b DS |
1261 | } |
1262 | ||
d62a17ae | 1263 | void zebra_del_import_table_route_map(afi_t afi, uint32_t table) |
8902474b | 1264 | { |
d62a17ae | 1265 | XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]); |
8902474b DS |
1266 | } |
1267 | ||
1268 | route_map_result_t | |
d62a17ae | 1269 | zebra_import_table_route_map_check(int family, int re_type, struct prefix *p, |
1270 | struct nexthop *nexthop, vrf_id_t vrf_id, | |
1271 | route_tag_t tag, const char *rmap_name) | |
1272 | { | |
1273 | struct route_map *rmap = NULL; | |
1274 | route_map_result_t ret = RMAP_DENYMATCH; | |
1275 | struct nh_rmap_obj nh_obj; | |
1276 | ||
1277 | nh_obj.nexthop = nexthop; | |
1278 | nh_obj.vrf_id = vrf_id; | |
1279 | nh_obj.source_protocol = re_type; | |
1280 | nh_obj.metric = 0; | |
1281 | nh_obj.tag = tag; | |
1282 | ||
1283 | if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX) | |
1284 | rmap = route_map_lookup_by_name(rmap_name); | |
1285 | if (rmap) { | |
1286 | ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); | |
1287 | } | |
8902474b | 1288 | |
d62a17ae | 1289 | return (ret); |
8902474b DS |
1290 | } |
1291 | ||
d62a17ae | 1292 | route_map_result_t zebra_nht_route_map_check(int family, int client_proto, |
1293 | struct prefix *p, | |
1294 | struct route_entry *re, | |
1295 | struct nexthop *nexthop) | |
9f0ea7d4 | 1296 | { |
d62a17ae | 1297 | struct route_map *rmap = NULL; |
1298 | route_map_result_t ret = RMAP_MATCH; | |
1299 | struct nh_rmap_obj nh_obj; | |
9f0ea7d4 | 1300 | |
d62a17ae | 1301 | nh_obj.nexthop = nexthop; |
1302 | nh_obj.vrf_id = re->vrf_id; | |
1303 | nh_obj.source_protocol = re->type; | |
1304 | nh_obj.metric = re->metric; | |
1305 | nh_obj.tag = re->tag; | |
9f0ea7d4 | 1306 | |
d62a17ae | 1307 | if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX) |
1308 | rmap = route_map_lookup_by_name(nht_rm[family][client_proto]); | |
1309 | if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX]) | |
1310 | rmap = route_map_lookup_by_name( | |
1311 | nht_rm[family][ZEBRA_ROUTE_MAX]); | |
1312 | if (rmap) { | |
1313 | ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); | |
1314 | } | |
518f0eb1 | 1315 | |
d62a17ae | 1316 | return (ret); |
518f0eb1 DS |
1317 | } |
1318 | ||
d62a17ae | 1319 | static void zebra_route_map_mark_update(const char *rmap_name) |
518f0eb1 | 1320 | { |
d62a17ae | 1321 | /* rmap_update_timer of 0 means don't do route updates */ |
1322 | if (zebra_rmap_update_timer && !zebra_t_rmap_update) { | |
1323 | zebra_t_rmap_update = NULL; | |
1324 | thread_add_timer(zebrad.master, zebra_route_map_update_timer, | |
1325 | NULL, zebra_rmap_update_timer, | |
1326 | &zebra_t_rmap_update); | |
1327 | } | |
518f0eb1 DS |
1328 | } |
1329 | ||
d62a17ae | 1330 | static void zebra_route_map_add(const char *rmap_name) |
518f0eb1 | 1331 | { |
d62a17ae | 1332 | zebra_route_map_mark_update(rmap_name); |
1333 | route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); | |
518f0eb1 DS |
1334 | } |
1335 | ||
d62a17ae | 1336 | static void zebra_route_map_delete(const char *rmap_name) |
518f0eb1 | 1337 | { |
d62a17ae | 1338 | zebra_route_map_mark_update(rmap_name); |
1339 | route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); | |
518f0eb1 DS |
1340 | } |
1341 | ||
d62a17ae | 1342 | static void zebra_route_map_event(route_map_event_t event, |
1343 | const char *rmap_name) | |
518f0eb1 | 1344 | { |
d62a17ae | 1345 | zebra_route_map_mark_update(rmap_name); |
1346 | route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); | |
518f0eb1 DS |
1347 | } |
1348 | ||
1349 | /* ip protocol configuration write function */ | |
d62a17ae | 1350 | void zebra_routemap_config_write_protocol(struct vty *vty) |
1351 | { | |
1352 | int i; | |
1353 | ||
1354 | for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { | |
1355 | if (proto_rm[AFI_IP][i]) | |
1356 | vty_out(vty, "ip protocol %s route-map %s\n", | |
1357 | zebra_route_string(i), proto_rm[AFI_IP][i]); | |
1358 | ||
1359 | if (proto_rm[AFI_IP6][i]) | |
1360 | vty_out(vty, "ipv6 protocol %s route-map %s\n", | |
1361 | zebra_route_string(i), proto_rm[AFI_IP6][i]); | |
1362 | ||
1363 | if (nht_rm[AFI_IP][i]) | |
1364 | vty_out(vty, "ip nht %s route-map %s\n", | |
1365 | zebra_route_string(i), nht_rm[AFI_IP][i]); | |
1366 | ||
1367 | if (nht_rm[AFI_IP6][i]) | |
1368 | vty_out(vty, "ipv6 nht %s route-map %s\n", | |
1369 | zebra_route_string(i), nht_rm[AFI_IP6][i]); | |
1370 | } | |
1371 | ||
1372 | if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]) | |
1373 | vty_out(vty, "ip protocol %s route-map %s\n", "any", | |
1374 | proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]); | |
1375 | ||
1376 | if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]) | |
1377 | vty_out(vty, "ipv6 protocol %s route-map %s\n", "any", | |
1378 | proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]); | |
1379 | ||
1380 | if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]) | |
1381 | vty_out(vty, "ip nht %s route-map %s\n", "any", | |
1382 | nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]); | |
1383 | ||
1384 | if (nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]) | |
1385 | vty_out(vty, "ipv6 nht %s route-map %s\n", "any", | |
1386 | nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]); | |
1387 | ||
1388 | if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER) | |
1389 | vty_out(vty, "zebra route-map delay-timer %d\n", | |
1390 | zebra_rmap_update_timer); | |
1391 | } | |
1392 | ||
1393 | void zebra_route_map_init() | |
1394 | { | |
1395 | install_element(CONFIG_NODE, &ip_protocol_cmd); | |
1396 | install_element(CONFIG_NODE, &no_ip_protocol_cmd); | |
1397 | install_element(VIEW_NODE, &show_ip_protocol_cmd); | |
1398 | install_element(CONFIG_NODE, &ipv6_protocol_cmd); | |
1399 | install_element(CONFIG_NODE, &no_ipv6_protocol_cmd); | |
1400 | install_element(VIEW_NODE, &show_ipv6_protocol_cmd); | |
1401 | install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd); | |
1402 | install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd); | |
1403 | install_element(VIEW_NODE, &show_ip_protocol_nht_cmd); | |
1404 | install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd); | |
1405 | install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd); | |
1406 | install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd); | |
1407 | install_element(CONFIG_NODE, &zebra_route_map_timer_cmd); | |
1408 | install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd); | |
1409 | ||
1410 | route_map_init(); | |
1411 | ||
1412 | route_map_add_hook(zebra_route_map_add); | |
1413 | route_map_delete_hook(zebra_route_map_delete); | |
1414 | route_map_event_hook(zebra_route_map_event); | |
1415 | ||
1416 | route_map_match_interface_hook(generic_match_add); | |
1417 | route_map_no_match_interface_hook(generic_match_delete); | |
1418 | ||
1419 | route_map_match_ip_address_hook(generic_match_add); | |
1420 | route_map_no_match_ip_address_hook(generic_match_delete); | |
1421 | ||
1422 | route_map_match_ip_address_prefix_list_hook(generic_match_add); | |
1423 | route_map_no_match_ip_address_prefix_list_hook(generic_match_delete); | |
1424 | ||
1425 | route_map_match_ip_next_hop_hook(generic_match_add); | |
1426 | route_map_no_match_ip_next_hop_hook(generic_match_delete); | |
1427 | ||
1428 | route_map_match_ip_next_hop_prefix_list_hook(generic_match_add); | |
1429 | route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete); | |
1430 | ||
1431 | route_map_match_tag_hook(generic_match_add); | |
1432 | route_map_no_match_tag_hook(generic_match_delete); | |
1433 | ||
1434 | route_map_install_match(&route_match_tag_cmd); | |
1435 | route_map_install_match(&route_match_interface_cmd); | |
1436 | route_map_install_match(&route_match_ip_next_hop_cmd); | |
1437 | route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd); | |
1438 | route_map_install_match(&route_match_ip_address_cmd); | |
1439 | route_map_install_match(&route_match_ip_address_prefix_list_cmd); | |
1440 | route_map_install_match(&route_match_ip_address_prefix_len_cmd); | |
1441 | route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd); | |
1442 | route_map_install_match(&route_match_source_protocol_cmd); | |
1443 | /* */ | |
1444 | route_map_install_set(&route_set_src_cmd); | |
1445 | /* */ | |
1446 | install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd); | |
1447 | install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd); | |
1448 | install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd); | |
1449 | install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd); | |
1450 | install_element(RMAP_NODE, &match_source_protocol_cmd); | |
1451 | install_element(RMAP_NODE, &no_match_source_protocol_cmd); | |
1452 | /* */ | |
1453 | install_element(RMAP_NODE, &set_src_cmd); | |
1454 | install_element(RMAP_NODE, &no_set_src_cmd); | |
5921ef9a | 1455 | } |