]>
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 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with GNU Zebra; see the file COPYING. If not, write to the Free | |
18 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
19 | * 02111-1307, USA. | |
20 | */ | |
21 | ||
22 | #include <zebra.h> | |
23 | ||
24 | #include "memory.h" | |
25 | #include "prefix.h" | |
26 | #include "rib.h" | |
27 | #include "routemap.h" | |
28 | #include "command.h" | |
29 | #include "filter.h" | |
30 | #include "plist.h" | |
fb018d25 | 31 | #include "nexthop.h" |
5921ef9a PJ |
32 | |
33 | #include "zebra/zserv.h" | |
518f0eb1 DS |
34 | #include "zebra/debug.h" |
35 | ||
36 | static u_int32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER; | |
37 | static struct thread *zebra_t_rmap_update = NULL; | |
38 | char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1]; /* "any" == ZEBRA_ROUTE_MAX */ | |
39 | ||
40 | extern struct zebra_t zebrad; | |
5921ef9a PJ |
41 | |
42 | /* Add zebra route map rule */ | |
43 | static int | |
44 | zebra_route_match_add(struct vty *vty, struct route_map_index *index, | |
518f0eb1 DS |
45 | const char *command, const char *arg, |
46 | route_map_event_t type) | |
5921ef9a PJ |
47 | { |
48 | int ret; | |
49 | ||
50 | ret = route_map_add_match (index, command, arg); | |
51 | if (ret) | |
52 | { | |
53 | switch (ret) | |
54 | { | |
55 | case RMAP_RULE_MISSING: | |
56 | vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); | |
57 | return CMD_WARNING; | |
58 | case RMAP_COMPILE_ERROR: | |
59 | vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); | |
60 | return CMD_WARNING; | |
61 | } | |
62 | } | |
518f0eb1 DS |
63 | |
64 | if (type != RMAP_EVENT_MATCH_ADDED) | |
65 | { | |
66 | route_map_upd8_dependency (type, arg, index->map->name); | |
67 | } | |
5921ef9a PJ |
68 | return CMD_SUCCESS; |
69 | } | |
70 | ||
71 | /* Delete zebra route map rule. */ | |
72 | static int | |
73 | zebra_route_match_delete (struct vty *vty, struct route_map_index *index, | |
518f0eb1 DS |
74 | const char *command, const char *arg, |
75 | route_map_event_t type) | |
5921ef9a PJ |
76 | { |
77 | int ret; | |
518f0eb1 DS |
78 | char *dep_name = (char *)arg; |
79 | const char *tmpstr; | |
80 | char *rmap_name = NULL; | |
81 | ||
82 | if (type != RMAP_EVENT_MATCH_DELETED) | |
83 | { | |
84 | /* ignore the mundane, the types without any dependency */ | |
85 | if (arg == NULL) | |
86 | { | |
87 | if ((tmpstr = route_map_get_match_arg(index, command)) != NULL) | |
88 | dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); | |
89 | } | |
90 | rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); | |
91 | } | |
5921ef9a PJ |
92 | |
93 | ret = route_map_delete_match (index, command, arg); | |
94 | if (ret) | |
95 | { | |
96 | switch (ret) | |
97 | { | |
98 | case RMAP_RULE_MISSING: | |
99 | vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); | |
100 | return CMD_WARNING; | |
101 | case RMAP_COMPILE_ERROR: | |
102 | vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); | |
103 | return CMD_WARNING; | |
104 | } | |
105 | } | |
518f0eb1 DS |
106 | |
107 | if (type != RMAP_EVENT_MATCH_DELETED && dep_name) | |
108 | route_map_upd8_dependency(type, dep_name, rmap_name); | |
109 | ||
110 | if (arg == NULL && dep_name) | |
111 | XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); | |
112 | if (rmap_name) | |
113 | XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); | |
114 | ||
5921ef9a PJ |
115 | return CMD_SUCCESS; |
116 | } | |
117 | ||
118 | /* Add zebra route map rule. */ | |
119 | static int | |
120 | zebra_route_set_add (struct vty *vty, struct route_map_index *index, | |
121 | const char *command, const char *arg) | |
122 | { | |
123 | int ret; | |
124 | ||
125 | ret = route_map_add_set (index, command, arg); | |
126 | if (ret) | |
127 | { | |
128 | switch (ret) | |
129 | { | |
130 | case RMAP_RULE_MISSING: | |
131 | vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); | |
132 | return CMD_WARNING; | |
133 | case RMAP_COMPILE_ERROR: | |
134 | vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); | |
135 | return CMD_WARNING; | |
136 | } | |
137 | } | |
138 | return CMD_SUCCESS; | |
139 | } | |
140 | ||
141 | /* Delete zebra route map rule. */ | |
142 | static int | |
143 | zebra_route_set_delete (struct vty *vty, struct route_map_index *index, | |
144 | const char *command, const char *arg) | |
145 | { | |
146 | int ret; | |
147 | ||
148 | ret = route_map_delete_set (index, command, arg); | |
149 | if (ret) | |
150 | { | |
151 | switch (ret) | |
152 | { | |
153 | case RMAP_RULE_MISSING: | |
154 | vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); | |
155 | return CMD_WARNING; | |
156 | case RMAP_COMPILE_ERROR: | |
157 | vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); | |
158 | return CMD_WARNING; | |
159 | } | |
160 | } | |
161 | return CMD_SUCCESS; | |
162 | } | |
163 | ||
6b0655a2 | 164 | |
5921ef9a PJ |
165 | /* `match interface IFNAME' */ |
166 | /* Match function return 1 if match is success else return zero. */ | |
167 | static route_map_result_t | |
168 | route_match_interface (void *rule, struct prefix *prefix, | |
169 | route_map_object_t type, void *object) | |
170 | { | |
171 | struct nexthop *nexthop; | |
172 | char *ifname = rule; | |
173 | unsigned int ifindex; | |
174 | ||
175 | if (type == RMAP_ZEBRA) | |
176 | { | |
177 | if (strcasecmp(ifname, "any") == 0) | |
178 | return RMAP_MATCH; | |
179 | ifindex = ifname2ifindex(ifname); | |
180 | if (ifindex == 0) | |
181 | return RMAP_NOMATCH; | |
182 | nexthop = object; | |
183 | if (!nexthop) | |
184 | return RMAP_NOMATCH; | |
185 | if (nexthop->ifindex == ifindex) | |
186 | return RMAP_MATCH; | |
187 | } | |
188 | return RMAP_NOMATCH; | |
189 | } | |
190 | ||
191 | /* Route map `match interface' match statement. `arg' is IFNAME value */ | |
192 | static void * | |
193 | route_match_interface_compile (const char *arg) | |
194 | { | |
195 | return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); | |
196 | } | |
197 | ||
198 | /* Free route map's compiled `match interface' value. */ | |
199 | static void | |
200 | route_match_interface_free (void *rule) | |
201 | { | |
202 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
203 | } | |
204 | ||
205 | /* Route map commands for interface matching */ | |
206 | struct route_map_rule_cmd route_match_interface_cmd = | |
207 | { | |
208 | "interface", | |
209 | route_match_interface, | |
210 | route_match_interface_compile, | |
211 | route_match_interface_free | |
212 | }; | |
213 | ||
214 | DEFUN (match_interface, | |
215 | match_interface_cmd, | |
216 | "match interface WORD", | |
217 | MATCH_STR | |
218 | "match first hop interface of route\n" | |
219 | "Interface name\n") | |
220 | { | |
518f0eb1 DS |
221 | return zebra_route_match_add (vty, vty->index, "interface", argv[0], |
222 | RMAP_EVENT_FILTER_ADDED); | |
5921ef9a PJ |
223 | } |
224 | ||
225 | DEFUN (no_match_interface, | |
226 | no_match_interface_cmd, | |
227 | "no match interface", | |
228 | NO_STR | |
229 | MATCH_STR | |
230 | "Match first hop interface of route\n") | |
231 | { | |
232 | if (argc == 0) | |
518f0eb1 | 233 | return zebra_route_match_delete (vty, vty->index, "interface", NULL, RMAP_EVENT_MATCH_DELETED); |
5921ef9a | 234 | |
518f0eb1 | 235 | return zebra_route_match_delete (vty, vty->index, "interface", argv[0], RMAP_EVENT_MATCH_DELETED); |
5921ef9a PJ |
236 | } |
237 | ||
238 | ALIAS (no_match_interface, | |
239 | no_match_interface_val_cmd, | |
240 | "no match interface WORD", | |
241 | NO_STR | |
242 | MATCH_STR | |
243 | "Match first hop interface of route\n" | |
244 | "Interface name\n") | |
245 | ||
246 | DEFUN (match_ip_next_hop, | |
247 | match_ip_next_hop_cmd, | |
248 | "match ip next-hop (<1-199>|<1300-2699>|WORD)", | |
249 | MATCH_STR | |
250 | IP_STR | |
251 | "Match next-hop address of route\n" | |
252 | "IP access-list number\n" | |
253 | "IP access-list number (expanded range)\n" | |
254 | "IP Access-list name\n") | |
255 | { | |
518f0eb1 | 256 | return zebra_route_match_add (vty, vty->index, "ip next-hop", argv[0], RMAP_EVENT_FILTER_ADDED); |
5921ef9a PJ |
257 | } |
258 | ||
259 | DEFUN (no_match_ip_next_hop, | |
260 | no_match_ip_next_hop_cmd, | |
261 | "no match ip next-hop", | |
262 | NO_STR | |
263 | MATCH_STR | |
264 | IP_STR | |
265 | "Match next-hop address of route\n") | |
266 | { | |
267 | if (argc == 0) | |
518f0eb1 DS |
268 | return zebra_route_match_delete (vty, vty->index, "ip next-hop", NULL, |
269 | RMAP_EVENT_FILTER_DELETED); | |
5921ef9a | 270 | |
518f0eb1 DS |
271 | return zebra_route_match_delete (vty, vty->index, "ip next-hop", argv[0], |
272 | RMAP_EVENT_FILTER_DELETED); | |
5921ef9a PJ |
273 | } |
274 | ||
275 | ALIAS (no_match_ip_next_hop, | |
276 | no_match_ip_next_hop_val_cmd, | |
277 | "no match ip next-hop (<1-199>|<1300-2699>|WORD)", | |
278 | NO_STR | |
279 | MATCH_STR | |
280 | IP_STR | |
281 | "Match next-hop address of route\n" | |
282 | "IP access-list number\n" | |
283 | "IP access-list number (expanded range)\n" | |
284 | "IP Access-list name\n") | |
285 | ||
286 | DEFUN (match_ip_next_hop_prefix_list, | |
287 | match_ip_next_hop_prefix_list_cmd, | |
288 | "match ip next-hop prefix-list WORD", | |
289 | MATCH_STR | |
290 | IP_STR | |
291 | "Match next-hop address of route\n" | |
292 | "Match entries of prefix-lists\n" | |
293 | "IP prefix-list name\n") | |
294 | { | |
518f0eb1 DS |
295 | return zebra_route_match_add (vty, vty->index, "ip next-hop prefix-list", |
296 | argv[0], RMAP_EVENT_PLIST_ADDED); | |
5921ef9a PJ |
297 | } |
298 | ||
299 | DEFUN (no_match_ip_next_hop_prefix_list, | |
300 | no_match_ip_next_hop_prefix_list_cmd, | |
301 | "no match ip next-hop prefix-list", | |
302 | NO_STR | |
303 | MATCH_STR | |
304 | IP_STR | |
305 | "Match next-hop address of route\n" | |
306 | "Match entries of prefix-lists\n") | |
307 | { | |
308 | if (argc == 0) | |
518f0eb1 DS |
309 | return zebra_route_match_delete (vty, vty->index, |
310 | "ip next-hop prefix-list", NULL, | |
311 | RMAP_EVENT_PLIST_DELETED); | |
5921ef9a | 312 | |
518f0eb1 DS |
313 | return zebra_route_match_delete (vty, vty->index, |
314 | "ip next-hop prefix-list", argv[0], | |
315 | RMAP_EVENT_PLIST_DELETED); | |
5921ef9a PJ |
316 | } |
317 | ||
318 | ALIAS (no_match_ip_next_hop_prefix_list, | |
319 | no_match_ip_next_hop_prefix_list_val_cmd, | |
320 | "no match ip next-hop prefix-list WORD", | |
321 | NO_STR | |
322 | MATCH_STR | |
323 | IP_STR | |
324 | "Match next-hop address of route\n" | |
325 | "Match entries of prefix-lists\n" | |
326 | "IP prefix-list name\n") | |
327 | ||
328 | DEFUN (match_ip_address, | |
329 | match_ip_address_cmd, | |
330 | "match ip address (<1-199>|<1300-2699>|WORD)", | |
331 | MATCH_STR | |
332 | IP_STR | |
333 | "Match address of route\n" | |
334 | "IP access-list number\n" | |
335 | "IP access-list number (expanded range)\n" | |
336 | "IP Access-list name\n") | |
337 | ||
338 | { | |
518f0eb1 DS |
339 | return zebra_route_match_add (vty, vty->index, "ip address", argv[0], |
340 | RMAP_EVENT_FILTER_ADDED); | |
5921ef9a PJ |
341 | } |
342 | ||
343 | DEFUN (no_match_ip_address, | |
344 | no_match_ip_address_cmd, | |
345 | "no match ip address", | |
346 | NO_STR | |
347 | MATCH_STR | |
348 | IP_STR | |
349 | "Match address of route\n") | |
350 | { | |
351 | if (argc == 0) | |
518f0eb1 DS |
352 | return zebra_route_match_delete (vty, vty->index, "ip address", NULL, |
353 | RMAP_EVENT_FILTER_DELETED); | |
5921ef9a | 354 | |
518f0eb1 DS |
355 | return zebra_route_match_delete (vty, vty->index, "ip address", argv[0], |
356 | RMAP_EVENT_FILTER_DELETED); | |
5921ef9a PJ |
357 | } |
358 | ||
359 | ALIAS (no_match_ip_address, | |
360 | no_match_ip_address_val_cmd, | |
361 | "no match ip address (<1-199>|<1300-2699>|WORD)", | |
362 | NO_STR | |
363 | MATCH_STR | |
364 | IP_STR | |
365 | "Match address of route\n" | |
366 | "IP access-list number\n" | |
367 | "IP access-list number (expanded range)\n" | |
368 | "IP Access-list name\n") | |
369 | ||
370 | DEFUN (match_ip_address_prefix_list, | |
371 | match_ip_address_prefix_list_cmd, | |
372 | "match ip address prefix-list WORD", | |
373 | MATCH_STR | |
374 | IP_STR | |
375 | "Match address of route\n" | |
376 | "Match entries of prefix-lists\n" | |
377 | "IP prefix-list name\n") | |
378 | { | |
518f0eb1 DS |
379 | return zebra_route_match_add (vty, vty->index, "ip address prefix-list", |
380 | argv[0], RMAP_EVENT_PLIST_ADDED); | |
5921ef9a PJ |
381 | } |
382 | ||
383 | DEFUN (no_match_ip_address_prefix_list, | |
384 | no_match_ip_address_prefix_list_cmd, | |
385 | "no match ip address prefix-list", | |
386 | NO_STR | |
387 | MATCH_STR | |
388 | IP_STR | |
389 | "Match address of route\n" | |
390 | "Match entries of prefix-lists\n") | |
391 | { | |
392 | if (argc == 0) | |
518f0eb1 DS |
393 | return zebra_route_match_delete (vty, vty->index, |
394 | "ip address prefix-list", NULL, | |
395 | RMAP_EVENT_PLIST_DELETED); | |
5921ef9a | 396 | |
518f0eb1 DS |
397 | return zebra_route_match_delete (vty, vty->index, |
398 | "ip address prefix-list", argv[0], | |
399 | RMAP_EVENT_PLIST_DELETED); | |
5921ef9a PJ |
400 | } |
401 | ||
402 | ALIAS (no_match_ip_address_prefix_list, | |
403 | no_match_ip_address_prefix_list_val_cmd, | |
404 | "no match ip address prefix-list WORD", | |
405 | NO_STR | |
406 | MATCH_STR | |
407 | IP_STR | |
408 | "Match address of route\n" | |
409 | "Match entries of prefix-lists\n" | |
410 | "IP prefix-list name\n") | |
411 | ||
412 | /* set functions */ | |
413 | ||
414 | DEFUN (set_src, | |
415 | set_src_cmd, | |
416 | "set src A.B.C.D", | |
417 | SET_STR | |
418 | "src address for route\n" | |
419 | "src address\n") | |
420 | { | |
421 | struct in_addr src; | |
422 | struct interface *pif; | |
423 | ||
424 | if (inet_pton(AF_INET, argv[0], &src) <= 0) | |
425 | { | |
426 | vty_out (vty, "%% not a local address%s", VTY_NEWLINE); | |
427 | return CMD_WARNING; | |
428 | } | |
429 | ||
430 | pif = if_lookup_exact_address (src); | |
431 | if (!pif) | |
432 | { | |
433 | vty_out (vty, "%% not a local address%s", VTY_NEWLINE); | |
434 | return CMD_WARNING; | |
435 | } | |
436 | return zebra_route_set_add (vty, vty->index, "src", argv[0]); | |
437 | } | |
438 | ||
439 | DEFUN (no_set_src, | |
440 | no_set_src_cmd, | |
441 | "no set src", | |
442 | NO_STR | |
443 | SET_STR | |
444 | "Source address for route\n") | |
445 | { | |
446 | if (argc == 0) | |
447 | return zebra_route_set_delete (vty, vty->index, "src", NULL); | |
448 | ||
449 | return zebra_route_set_delete (vty, vty->index, "src", argv[0]); | |
450 | } | |
451 | ||
452 | ALIAS (no_set_src, | |
453 | no_set_src_val_cmd, | |
454 | "no set src (A.B.C.D)", | |
455 | NO_STR | |
456 | SET_STR | |
457 | "src address for route\n" | |
458 | "src address\n") | |
459 | ||
518f0eb1 DS |
460 | DEFUN (zebra_route_map_timer, |
461 | zebra_route_map_timer_cmd, | |
462 | "zebra route-map delay-timer <0-600>", | |
463 | "Time to wait before route-map updates are\n" | |
464 | "processed. 0 means disable event driven\n" | |
465 | "route-map updates. Set this to a larger\n" | |
466 | "value than protocol route-map delay timer\n" | |
467 | "to avoid unnecessary churn in routing tables\n") | |
468 | { | |
469 | u_int32_t rmap_delay_timer; | |
470 | ||
471 | VTY_GET_INTEGER_RANGE ("delay-timer", rmap_delay_timer, argv[0], 0, 600); | |
472 | zebra_route_map_set_delay_timer(rmap_delay_timer); | |
473 | ||
474 | return (CMD_SUCCESS); | |
475 | } | |
476 | ||
477 | DEFUN (no_zebra_route_map_timer, | |
478 | no_zebra_route_map_timer_cmd, | |
479 | "no zebra route-map delay-timer", | |
480 | NO_STR | |
481 | "Reset delay-timer to default value, 30 secs\n") | |
482 | { | |
483 | zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER); | |
484 | ||
485 | return (CMD_SUCCESS); | |
486 | } | |
487 | ||
488 | DEFUN (ip_protocol, | |
489 | ip_protocol_cmd, | |
490 | "ip protocol PROTO route-map ROUTE-MAP", | |
491 | NO_STR | |
492 | "Apply route map to PROTO\n" | |
493 | "Protocol name\n" | |
494 | "Route map name\n") | |
495 | { | |
496 | int i; | |
497 | ||
498 | if (strcasecmp(argv[0], "any") == 0) | |
499 | i = ZEBRA_ROUTE_MAX; | |
500 | else | |
501 | i = proto_name2num(argv[0]); | |
502 | if (i < 0) | |
503 | { | |
504 | vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "", | |
505 | VTY_NEWLINE); | |
506 | return CMD_WARNING; | |
507 | } | |
508 | if (proto_rm[AFI_IP][i]) | |
509 | { | |
510 | if (strcmp(proto_rm[AFI_IP][i], argv[1]) == 0) | |
511 | return CMD_SUCCESS; | |
512 | ||
513 | XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); | |
514 | } | |
515 | proto_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]); | |
516 | rib_update(); | |
517 | return CMD_SUCCESS; | |
518 | } | |
519 | ||
520 | DEFUN (no_ip_protocol, | |
521 | no_ip_protocol_cmd, | |
522 | "no ip protocol PROTO", | |
523 | NO_STR | |
524 | "Remove route map from PROTO\n" | |
525 | "Protocol name\n") | |
526 | { | |
527 | int i; | |
528 | ||
529 | if (strcasecmp(argv[0], "any") == 0) | |
530 | i = ZEBRA_ROUTE_MAX; | |
531 | else | |
532 | i = proto_name2num(argv[0]); | |
533 | if (i < 0) | |
534 | { | |
535 | vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "", | |
536 | VTY_NEWLINE); | |
537 | return CMD_WARNING; | |
538 | } | |
539 | if (!proto_rm[AFI_IP][i]) | |
540 | return CMD_SUCCESS; | |
541 | ||
542 | XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); | |
543 | proto_rm[AFI_IP][i] = NULL; | |
544 | rib_update(); | |
545 | return CMD_SUCCESS; | |
546 | } | |
547 | ||
548 | DEFUN (show_ip_protocol, | |
549 | show_ip_protocol_cmd, | |
550 | "show ip protocol", | |
551 | SHOW_STR | |
552 | IP_STR | |
553 | "IP protocol filtering status\n") | |
554 | { | |
555 | int i; | |
556 | ||
557 | vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE); | |
558 | vty_out(vty, "------------------------%s", VTY_NEWLINE); | |
559 | for (i=0;i<ZEBRA_ROUTE_MAX;i++) | |
560 | { | |
561 | if (proto_rm[AFI_IP][i]) | |
562 | vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i), | |
563 | proto_rm[AFI_IP][i], | |
564 | VTY_NEWLINE); | |
565 | else | |
566 | vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE); | |
567 | } | |
568 | if (proto_rm[AFI_IP][i]) | |
569 | vty_out (vty, "%-10s : %-10s%s", "any", proto_rm[AFI_IP][i], | |
570 | VTY_NEWLINE); | |
571 | else | |
572 | vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE); | |
573 | ||
574 | return CMD_SUCCESS; | |
575 | } | |
576 | ||
5921ef9a PJ |
577 | /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/ |
578 | ||
579 | /* `match ip next-hop IP_ACCESS_LIST' */ | |
580 | ||
581 | /* Match function return 1 if match is success else return zero. */ | |
582 | static route_map_result_t | |
583 | route_match_ip_next_hop (void *rule, struct prefix *prefix, | |
584 | route_map_object_t type, void *object) | |
585 | { | |
586 | struct access_list *alist; | |
587 | struct nexthop *nexthop; | |
588 | struct prefix_ipv4 p; | |
589 | ||
590 | if (type == RMAP_ZEBRA) | |
591 | { | |
592 | nexthop = object; | |
593 | switch (nexthop->type) { | |
594 | case NEXTHOP_TYPE_IFINDEX: | |
595 | case NEXTHOP_TYPE_IFNAME: | |
fa713d9e CF |
596 | /* Interface routes can't match ip next-hop */ |
597 | return RMAP_NOMATCH; | |
5921ef9a PJ |
598 | case NEXTHOP_TYPE_IPV4_IFINDEX: |
599 | case NEXTHOP_TYPE_IPV4_IFNAME: | |
5921ef9a PJ |
600 | case NEXTHOP_TYPE_IPV4: |
601 | p.family = AF_INET; | |
602 | p.prefix = nexthop->gate.ipv4; | |
603 | p.prefixlen = IPV4_MAX_BITLEN; | |
604 | break; | |
605 | default: | |
606 | return RMAP_NOMATCH; | |
607 | } | |
608 | alist = access_list_lookup (AFI_IP, (char *) rule); | |
609 | if (alist == NULL) | |
610 | return RMAP_NOMATCH; | |
611 | ||
612 | return (access_list_apply (alist, &p) == FILTER_DENY ? | |
613 | RMAP_NOMATCH : RMAP_MATCH); | |
614 | } | |
615 | return RMAP_NOMATCH; | |
616 | } | |
617 | ||
618 | /* Route map `ip next-hop' match statement. `arg' should be | |
619 | access-list name. */ | |
620 | static void * | |
621 | route_match_ip_next_hop_compile (const char *arg) | |
622 | { | |
623 | return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); | |
624 | } | |
625 | ||
626 | /* Free route map's compiled `. */ | |
627 | static void | |
628 | route_match_ip_next_hop_free (void *rule) | |
629 | { | |
630 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
631 | } | |
632 | ||
633 | /* Route map commands for ip next-hop matching. */ | |
634 | static struct route_map_rule_cmd route_match_ip_next_hop_cmd = | |
635 | { | |
636 | "ip next-hop", | |
637 | route_match_ip_next_hop, | |
638 | route_match_ip_next_hop_compile, | |
639 | route_match_ip_next_hop_free | |
640 | }; | |
6b0655a2 | 641 | |
5921ef9a PJ |
642 | /* `match ip next-hop prefix-list PREFIX_LIST' */ |
643 | ||
644 | static route_map_result_t | |
645 | route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix, | |
646 | route_map_object_t type, void *object) | |
647 | { | |
648 | struct prefix_list *plist; | |
649 | struct nexthop *nexthop; | |
650 | struct prefix_ipv4 p; | |
651 | ||
652 | if (type == RMAP_ZEBRA) | |
653 | { | |
654 | nexthop = object; | |
655 | switch (nexthop->type) { | |
656 | case NEXTHOP_TYPE_IFINDEX: | |
657 | case NEXTHOP_TYPE_IFNAME: | |
fa713d9e CF |
658 | /* Interface routes can't match ip next-hop */ |
659 | return RMAP_NOMATCH; | |
5921ef9a PJ |
660 | case NEXTHOP_TYPE_IPV4_IFINDEX: |
661 | case NEXTHOP_TYPE_IPV4_IFNAME: | |
5921ef9a PJ |
662 | case NEXTHOP_TYPE_IPV4: |
663 | p.family = AF_INET; | |
664 | p.prefix = nexthop->gate.ipv4; | |
665 | p.prefixlen = IPV4_MAX_BITLEN; | |
666 | break; | |
667 | default: | |
668 | return RMAP_NOMATCH; | |
669 | } | |
670 | plist = prefix_list_lookup (AFI_IP, (char *) rule); | |
671 | if (plist == NULL) | |
672 | return RMAP_NOMATCH; | |
673 | ||
674 | return (prefix_list_apply (plist, &p) == PREFIX_DENY ? | |
675 | RMAP_NOMATCH : RMAP_MATCH); | |
676 | } | |
677 | return RMAP_NOMATCH; | |
678 | } | |
679 | ||
680 | static void * | |
681 | route_match_ip_next_hop_prefix_list_compile (const char *arg) | |
682 | { | |
683 | return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); | |
684 | } | |
685 | ||
686 | static void | |
687 | route_match_ip_next_hop_prefix_list_free (void *rule) | |
688 | { | |
689 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
690 | } | |
691 | ||
692 | static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = | |
693 | { | |
694 | "ip next-hop prefix-list", | |
695 | route_match_ip_next_hop_prefix_list, | |
696 | route_match_ip_next_hop_prefix_list_compile, | |
697 | route_match_ip_next_hop_prefix_list_free | |
698 | }; | |
6b0655a2 | 699 | |
5921ef9a PJ |
700 | /* `match ip address IP_ACCESS_LIST' */ |
701 | ||
702 | /* Match function should return 1 if match is success else return | |
703 | zero. */ | |
704 | static route_map_result_t | |
705 | route_match_ip_address (void *rule, struct prefix *prefix, | |
706 | route_map_object_t type, void *object) | |
707 | { | |
708 | struct access_list *alist; | |
709 | ||
710 | if (type == RMAP_ZEBRA) | |
711 | { | |
712 | alist = access_list_lookup (AFI_IP, (char *) rule); | |
713 | if (alist == NULL) | |
714 | return RMAP_NOMATCH; | |
715 | ||
716 | return (access_list_apply (alist, prefix) == FILTER_DENY ? | |
717 | RMAP_NOMATCH : RMAP_MATCH); | |
718 | } | |
719 | return RMAP_NOMATCH; | |
720 | } | |
721 | ||
722 | /* Route map `ip address' match statement. `arg' should be | |
723 | access-list name. */ | |
724 | static void * | |
725 | route_match_ip_address_compile (const char *arg) | |
726 | { | |
727 | return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); | |
728 | } | |
729 | ||
730 | /* Free route map's compiled `ip address' value. */ | |
731 | static void | |
732 | route_match_ip_address_free (void *rule) | |
733 | { | |
734 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
735 | } | |
736 | ||
737 | /* Route map commands for ip address matching. */ | |
738 | static struct route_map_rule_cmd route_match_ip_address_cmd = | |
739 | { | |
740 | "ip address", | |
741 | route_match_ip_address, | |
742 | route_match_ip_address_compile, | |
743 | route_match_ip_address_free | |
744 | }; | |
6b0655a2 | 745 | |
5921ef9a PJ |
746 | /* `match ip address prefix-list PREFIX_LIST' */ |
747 | ||
748 | static route_map_result_t | |
749 | route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, | |
750 | route_map_object_t type, void *object) | |
751 | { | |
752 | struct prefix_list *plist; | |
753 | ||
754 | if (type == RMAP_ZEBRA) | |
755 | { | |
756 | plist = prefix_list_lookup (AFI_IP, (char *) rule); | |
757 | if (plist == NULL) | |
758 | return RMAP_NOMATCH; | |
759 | ||
760 | return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? | |
761 | RMAP_NOMATCH : RMAP_MATCH); | |
762 | } | |
763 | return RMAP_NOMATCH; | |
764 | } | |
765 | ||
766 | static void * | |
767 | route_match_ip_address_prefix_list_compile (const char *arg) | |
768 | { | |
769 | return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); | |
770 | } | |
771 | ||
772 | static void | |
773 | route_match_ip_address_prefix_list_free (void *rule) | |
774 | { | |
775 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
776 | } | |
777 | ||
778 | static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = | |
779 | { | |
780 | "ip address prefix-list", | |
781 | route_match_ip_address_prefix_list, | |
782 | route_match_ip_address_prefix_list_compile, | |
783 | route_match_ip_address_prefix_list_free | |
784 | }; | |
785 | ||
6b0655a2 | 786 | |
5921ef9a PJ |
787 | /* `set src A.B.C.D' */ |
788 | ||
789 | /* Set src. */ | |
790 | static route_map_result_t | |
791 | route_set_src (void *rule, struct prefix *prefix, | |
792 | route_map_object_t type, void *object) | |
793 | { | |
794 | if (type == RMAP_ZEBRA) | |
795 | { | |
796 | struct nexthop *nexthop; | |
797 | ||
798 | nexthop = object; | |
799 | nexthop->src = *(union g_addr *)rule; | |
800 | } | |
801 | return RMAP_OKAY; | |
802 | } | |
803 | ||
804 | /* set src compilation. */ | |
805 | static void * | |
806 | route_set_src_compile (const char *arg) | |
807 | { | |
5921ef9a PJ |
808 | union g_addr src, *psrc; |
809 | ||
8dd1a8da | 810 | if (inet_pton(AF_INET, arg, &src.ipv4) != 1 |
09303314 | 811 | #ifdef HAVE_IPV6 |
8dd1a8da | 812 | && inet_pton(AF_INET6, arg, &src.ipv6) != 1 |
09303314 | 813 | #endif /* HAVE_IPV6 */ |
8dd1a8da PJ |
814 | ) |
815 | return NULL; | |
5921ef9a PJ |
816 | |
817 | psrc = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union g_addr)); | |
818 | *psrc = src; | |
819 | ||
820 | return psrc; | |
821 | } | |
822 | ||
823 | /* Free route map's compiled `set src' value. */ | |
824 | static void | |
825 | route_set_src_free (void *rule) | |
826 | { | |
827 | XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); | |
828 | } | |
829 | ||
830 | /* Set src rule structure. */ | |
831 | static struct route_map_rule_cmd route_set_src_cmd = | |
832 | { | |
833 | "src", | |
834 | route_set_src, | |
835 | route_set_src_compile, | |
836 | route_set_src_free, | |
837 | }; | |
838 | ||
518f0eb1 DS |
839 | static int |
840 | zebra_route_map_update_timer (struct thread *thread) | |
841 | { | |
842 | zebra_t_rmap_update = NULL; | |
843 | ||
844 | if (IS_ZEBRA_DEBUG_EVENT) | |
845 | zlog_debug("Event driven route-map update triggered"); | |
846 | ||
847 | rib_update(); | |
848 | } | |
849 | ||
850 | void | |
851 | zebra_route_map_set_delay_timer(u_int32_t value) | |
852 | { | |
853 | zebra_rmap_update_timer = value; | |
854 | if (!value && zebra_t_rmap_update) | |
855 | { | |
856 | /* Event driven route map updates is being disabled */ | |
857 | /* But there's a pending timer. Fire it off now */ | |
858 | thread_cancel(zebra_t_rmap_update); | |
859 | zebra_route_map_update_timer(zebra_t_rmap_update); | |
860 | } | |
861 | } | |
862 | ||
863 | void | |
864 | zebra_route_map_write_delay_timer (struct vty *vty) | |
865 | { | |
866 | if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)) | |
867 | vty_out (vty, "zebra route-map delay-timer %d%s", zebra_rmap_update_timer, | |
868 | VTY_NEWLINE); | |
869 | return; | |
870 | } | |
871 | ||
872 | route_map_result_t | |
873 | zebra_route_map_check (int family, int rib_type, struct prefix *p, | |
874 | struct nexthop *nexthop) | |
875 | { | |
876 | struct route_map *rmap = NULL; | |
877 | route_map_result_t ret = RMAP_MATCH; | |
878 | ||
879 | if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) | |
880 | rmap = route_map_lookup_by_name (proto_rm[family][rib_type]); | |
881 | if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX]) | |
882 | rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]); | |
883 | if (rmap) { | |
884 | ret = route_map_apply(rmap, p, RMAP_ZEBRA, nexthop); | |
885 | } | |
886 | ||
887 | return (ret); | |
888 | } | |
889 | ||
890 | static void | |
891 | zebra_route_map_mark_update (char *rmap_name) | |
892 | { | |
893 | /* rmap_update_timer of 0 means don't do route updates */ | |
894 | if (zebra_rmap_update_timer && !zebra_t_rmap_update) | |
895 | zebra_t_rmap_update = | |
896 | thread_add_timer(zebrad.master, zebra_route_map_update_timer, NULL, | |
897 | zebra_rmap_update_timer); | |
898 | } | |
899 | ||
900 | static void | |
901 | zebra_route_map_add (const char *rmap_name) | |
902 | { | |
903 | zebra_route_map_mark_update(rmap_name); | |
904 | route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); | |
905 | } | |
906 | ||
907 | static void | |
908 | zebra_route_map_delete (const char *rmap_name) | |
909 | { | |
910 | zebra_route_map_mark_update(rmap_name); | |
911 | route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); | |
912 | } | |
913 | ||
914 | static void | |
915 | zebra_route_map_event (route_map_event_t event, const char *rmap_name) | |
916 | { | |
917 | zebra_route_map_mark_update(rmap_name); | |
918 | route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); | |
919 | } | |
920 | ||
921 | /* ip protocol configuration write function */ | |
922 | static int config_write_protocol(struct vty *vty) | |
923 | { | |
924 | int i; | |
925 | ||
926 | for (i=0;i<ZEBRA_ROUTE_MAX;i++) | |
927 | { | |
928 | if (proto_rm[AFI_IP][i]) | |
929 | vty_out (vty, "ip protocol %s route-map %s%s", zebra_route_string(i), | |
930 | proto_rm[AFI_IP][i], VTY_NEWLINE); | |
931 | } | |
932 | if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]) | |
933 | vty_out (vty, "ip protocol %s route-map %s%s", "any", | |
934 | proto_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE); | |
935 | ||
936 | if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER) | |
937 | vty_out (vty, "zebra route-map delay-timer %d%s", zebra_rmap_update_timer, | |
938 | VTY_NEWLINE); | |
939 | return 1; | |
940 | } | |
941 | /* table node for protocol filtering */ | |
942 | static struct cmd_node protocol_node = { PROTOCOL_NODE, "", 1 }; | |
943 | ||
5921ef9a PJ |
944 | void |
945 | zebra_route_map_init () | |
946 | { | |
518f0eb1 DS |
947 | install_node (&protocol_node, config_write_protocol); |
948 | install_element (CONFIG_NODE, &ip_protocol_cmd); | |
949 | install_element (CONFIG_NODE, &no_ip_protocol_cmd); | |
950 | install_element (VIEW_NODE, &show_ip_protocol_cmd); | |
951 | install_element (ENABLE_NODE, &show_ip_protocol_cmd); | |
952 | install_element (CONFIG_NODE, &zebra_route_map_timer_cmd); | |
953 | install_element (CONFIG_NODE, &no_zebra_route_map_timer_cmd); | |
954 | ||
5921ef9a PJ |
955 | route_map_init (); |
956 | route_map_init_vty (); | |
957 | ||
518f0eb1 DS |
958 | route_map_add_hook (zebra_route_map_add); |
959 | route_map_delete_hook (zebra_route_map_delete); | |
960 | route_map_event_hook (zebra_route_map_event); | |
961 | ||
5921ef9a PJ |
962 | route_map_install_match (&route_match_interface_cmd); |
963 | route_map_install_match (&route_match_ip_next_hop_cmd); | |
964 | route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd); | |
965 | route_map_install_match (&route_match_ip_address_cmd); | |
966 | route_map_install_match (&route_match_ip_address_prefix_list_cmd); | |
967 | /* */ | |
968 | route_map_install_set (&route_set_src_cmd); | |
969 | /* */ | |
970 | install_element (RMAP_NODE, &match_interface_cmd); | |
971 | install_element (RMAP_NODE, &no_match_interface_cmd); | |
972 | install_element (RMAP_NODE, &no_match_interface_val_cmd); | |
973 | install_element (RMAP_NODE, &match_ip_next_hop_cmd); | |
974 | install_element (RMAP_NODE, &no_match_ip_next_hop_cmd); | |
975 | install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd); | |
976 | install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd); | |
977 | install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd); | |
978 | install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd); | |
979 | install_element (RMAP_NODE, &match_ip_address_cmd); | |
980 | install_element (RMAP_NODE, &no_match_ip_address_cmd); | |
981 | install_element (RMAP_NODE, &no_match_ip_address_val_cmd); | |
982 | install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd); | |
983 | install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd); | |
984 | install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd); | |
985 | /* */ | |
986 | install_element (RMAP_NODE, &set_src_cmd); | |
987 | install_element (RMAP_NODE, &no_set_src_cmd); | |
988 | } |