]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_routemap.c
Make the private AS number check 4 byte compatible.
[mirror_frr.git] / zebra / zebra_routemap.c
CommitLineData
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
36static u_int32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER;
37static struct thread *zebra_t_rmap_update = NULL;
38char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1]; /* "any" == ZEBRA_ROUTE_MAX */
39
40extern struct zebra_t zebrad;
5921ef9a
PJ
41
42/* Add zebra route map rule */
43static int
44zebra_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. */
72static int
73zebra_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. */
119static int
120zebra_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. */
142static int
143zebra_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. */
167static route_map_result_t
168route_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 */
192static void *
193route_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. */
199static void
200route_match_interface_free (void *rule)
201{
202 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
203}
204
205/* Route map commands for interface matching */
206struct 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
214DEFUN (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
225DEFUN (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
238ALIAS (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
246DEFUN (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
259DEFUN (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
275ALIAS (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
286DEFUN (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
299DEFUN (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
318ALIAS (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
328DEFUN (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
343DEFUN (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
359ALIAS (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
370DEFUN (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
383DEFUN (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
402ALIAS (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
414DEFUN (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
439DEFUN (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
452ALIAS (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
460DEFUN (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
477DEFUN (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
488DEFUN (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
520DEFUN (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
548DEFUN (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. */
582static route_map_result_t
583route_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. */
620static void *
621route_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 `. */
627static void
628route_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. */
634static 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
644static route_map_result_t
645route_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
680static void *
681route_match_ip_next_hop_prefix_list_compile (const char *arg)
682{
683 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
684}
685
686static void
687route_match_ip_next_hop_prefix_list_free (void *rule)
688{
689 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
690}
691
692static 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. */
704static route_map_result_t
705route_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. */
724static void *
725route_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. */
731static void
732route_match_ip_address_free (void *rule)
733{
734 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
735}
736
737/* Route map commands for ip address matching. */
738static 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
748static route_map_result_t
749route_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
766static void *
767route_match_ip_address_prefix_list_compile (const char *arg)
768{
769 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
770}
771
772static void
773route_match_ip_address_prefix_list_free (void *rule)
774{
775 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
776}
777
778static 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. */
790static route_map_result_t
791route_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. */
805static void *
806route_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. */
824static void
825route_set_src_free (void *rule)
826{
827 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
828}
829
830/* Set src rule structure. */
831static 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
839static int
840zebra_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
850void
851zebra_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
863void
864zebra_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
872route_map_result_t
873zebra_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
890static void
891zebra_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
900static void
901zebra_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
907static void
908zebra_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
914static void
915zebra_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 */
922static 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 */
942static struct cmd_node protocol_node = { PROTOCOL_NODE, "", 1 };
943
5921ef9a
PJ
944void
945zebra_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}