]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_routemap.c
*: make consistent & update GPLv2 file headers
[mirror_frr.git] / ospfd / ospf_routemap.c
1 /*
2 * Route map function of ospfd.
3 * Copyright (C) 2000 IP Infusion Inc.
4 *
5 * Written by Toshiaki Takada.
6 *
7 * This file is part of GNU Zebra.
8 *
9 * GNU Zebra is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
12 * later version.
13 *
14 * GNU Zebra is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; see the file COPYING; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include <zebra.h>
25
26 #include "memory.h"
27 #include "prefix.h"
28 #include "table.h"
29 #include "vty.h"
30 #include "routemap.h"
31 #include "command.h"
32 #include "log.h"
33 #include "plist.h"
34 #include "vrf.h"
35
36 #include "ospfd/ospfd.h"
37 #include "ospfd/ospf_asbr.h"
38 #include "ospfd/ospf_interface.h"
39 #include "ospfd/ospf_lsa.h"
40 #include "ospfd/ospf_route.h"
41 #include "ospfd/ospf_zebra.h"
42
43 /* Hook function for updating route_map assignment. */
44 static void
45 ospf_route_map_update (const char *name)
46 {
47 struct ospf *ospf;
48 int type;
49
50 /* If OSPF instatnce does not exist, return right now. */
51 ospf = ospf_lookup ();
52 if (ospf == NULL)
53 return;
54
55 /* Update route-map */
56 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
57 {
58 struct list *red_list;
59 struct listnode *node;
60 struct ospf_redist *red;
61
62 red_list = ospf->redist[type];
63 if (!red_list)
64 continue;
65
66 for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
67 {
68 if (ROUTEMAP_NAME (red)
69 && strcmp (ROUTEMAP_NAME (red), name) == 0)
70 {
71 /* Keep old route-map. */
72 struct route_map *old = ROUTEMAP (red);
73
74 /* Update route-map. */
75 ROUTEMAP (red) =
76 route_map_lookup_by_name (ROUTEMAP_NAME (red));
77
78 /* No update for this distribute type. */
79 if (old == NULL && ROUTEMAP (red) == NULL)
80 continue;
81
82 ospf_distribute_list_update (ospf, type, red->instance);
83 }
84 }
85 }
86 }
87
88 static void
89 ospf_route_map_event (route_map_event_t event, const char *name)
90 {
91 struct ospf *ospf;
92 int type;
93
94 /* If OSPF instatnce does not exist, return right now. */
95 ospf = ospf_lookup ();
96 if (ospf == NULL)
97 return;
98
99 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
100 {
101 struct list *red_list;
102 struct listnode *node;
103 struct ospf_redist *red;
104
105 red_list = ospf->redist[type];
106 if (!red_list)
107 continue;
108
109 for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
110 {
111 if (ROUTEMAP_NAME (red) && ROUTEMAP (red)
112 && !strcmp (ROUTEMAP_NAME (red), name))
113 {
114 ospf_distribute_list_update (ospf, type, red->instance);
115 }
116 }
117 }
118 }
119
120 /* Delete rip route map rule. */
121 static int
122 ospf_route_match_delete (struct vty *vty,
123 const char *command, const char *arg)
124 {
125 VTY_DECLVAR_CONTEXT(route_map_index, index);
126 int ret;
127
128 ret = route_map_delete_match (index, command, arg);
129 if (ret)
130 {
131 switch (ret)
132 {
133 case RMAP_RULE_MISSING:
134 vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE);
135 return CMD_WARNING;
136 case RMAP_COMPILE_ERROR:
137 vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE);
138 return CMD_WARNING;
139 }
140 }
141
142 return CMD_SUCCESS;
143 }
144
145 static int
146 ospf_route_match_add (struct vty *vty,
147 const char *command, const char *arg)
148 {
149 VTY_DECLVAR_CONTEXT(route_map_index, index);
150 int ret;
151
152 ret = route_map_add_match (index, command, arg);
153 if (ret)
154 {
155 switch (ret)
156 {
157 case RMAP_RULE_MISSING:
158 vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE);
159 return CMD_WARNING;
160 case RMAP_COMPILE_ERROR:
161 vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE);
162 return CMD_WARNING;
163 }
164 }
165
166 return CMD_SUCCESS;
167 }
168
169 /* `match ip netxthop ' */
170 /* Match function return 1 if match is success else return zero. */
171 static route_map_result_t
172 route_match_ip_nexthop (void *rule, struct prefix *prefix,
173 route_map_object_t type, void *object)
174 {
175 struct access_list *alist;
176 struct external_info *ei = object;
177 struct prefix_ipv4 p;
178
179 if (type == RMAP_OSPF)
180 {
181 p.family = AF_INET;
182 p.prefix = ei->nexthop;
183 p.prefixlen = IPV4_MAX_BITLEN;
184
185 alist = access_list_lookup (AFI_IP, (char *) rule);
186 if (alist == NULL)
187 return RMAP_NOMATCH;
188
189 return (access_list_apply (alist, &p) == FILTER_DENY ?
190 RMAP_NOMATCH : RMAP_MATCH);
191 }
192 return RMAP_NOMATCH;
193 }
194
195 /* Route map `ip next-hop' match statement. `arg' should be
196 access-list name. */
197 static void *
198 route_match_ip_nexthop_compile (const char *arg)
199 {
200 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
201 }
202
203 /* Free route map's compiled `ip address' value. */
204 static void
205 route_match_ip_nexthop_free (void *rule)
206 {
207 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
208 }
209
210 /* Route map commands for metric matching. */
211 struct route_map_rule_cmd route_match_ip_nexthop_cmd =
212 {
213 "ip next-hop",
214 route_match_ip_nexthop,
215 route_match_ip_nexthop_compile,
216 route_match_ip_nexthop_free
217 };
218
219 /* `match ip next-hop prefix-list PREFIX_LIST' */
220
221 static route_map_result_t
222 route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
223 route_map_object_t type, void *object)
224 {
225 struct prefix_list *plist;
226 struct external_info *ei = object;
227 struct prefix_ipv4 p;
228
229 if (type == RMAP_OSPF)
230 {
231 p.family = AF_INET;
232 p.prefix = ei->nexthop;
233 p.prefixlen = IPV4_MAX_BITLEN;
234
235 plist = prefix_list_lookup (AFI_IP, (char *) rule);
236 if (plist == NULL)
237 return RMAP_NOMATCH;
238
239 return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
240 RMAP_NOMATCH : RMAP_MATCH);
241 }
242 return RMAP_NOMATCH;
243 }
244
245 static void *
246 route_match_ip_next_hop_prefix_list_compile (const char *arg)
247 {
248 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
249 }
250
251 static void
252 route_match_ip_next_hop_prefix_list_free (void *rule)
253 {
254 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
255 }
256
257 struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
258 {
259 "ip next-hop prefix-list",
260 route_match_ip_next_hop_prefix_list,
261 route_match_ip_next_hop_prefix_list_compile,
262 route_match_ip_next_hop_prefix_list_free
263 };
264
265 /* `match ip address IP_ACCESS_LIST' */
266 /* Match function should return 1 if match is success else return
267 zero. */
268 static route_map_result_t
269 route_match_ip_address (void *rule, struct prefix *prefix,
270 route_map_object_t type, void *object)
271 {
272 struct access_list *alist;
273 /* struct prefix_ipv4 match; */
274
275 if (type == RMAP_OSPF)
276 {
277 alist = access_list_lookup (AFI_IP, (char *) rule);
278 if (alist == NULL)
279 return RMAP_NOMATCH;
280
281 return (access_list_apply (alist, prefix) == FILTER_DENY ?
282 RMAP_NOMATCH : RMAP_MATCH);
283 }
284 return RMAP_NOMATCH;
285 }
286
287 /* Route map `ip address' match statement. `arg' should be
288 access-list name. */
289 static void *
290 route_match_ip_address_compile (const char *arg)
291 {
292 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
293 }
294
295 /* Free route map's compiled `ip address' value. */
296 static void
297 route_match_ip_address_free (void *rule)
298 {
299 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
300 }
301
302 /* Route map commands for ip address matching. */
303 struct route_map_rule_cmd route_match_ip_address_cmd =
304 {
305 "ip address",
306 route_match_ip_address,
307 route_match_ip_address_compile,
308 route_match_ip_address_free
309 };
310
311 /* `match ip address prefix-list PREFIX_LIST' */
312 static route_map_result_t
313 route_match_ip_address_prefix_list (void *rule, struct prefix *prefix,
314 route_map_object_t type, void *object)
315 {
316 struct prefix_list *plist;
317
318 if (type == RMAP_OSPF)
319 {
320 plist = prefix_list_lookup (AFI_IP, (char *) rule);
321 if (plist == NULL)
322 return RMAP_NOMATCH;
323
324 return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
325 RMAP_NOMATCH : RMAP_MATCH);
326 }
327 return RMAP_NOMATCH;
328 }
329
330 static void *
331 route_match_ip_address_prefix_list_compile (const char *arg)
332 {
333 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
334 }
335
336 static void
337 route_match_ip_address_prefix_list_free (void *rule)
338 {
339 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
340 }
341
342 struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
343 {
344 "ip address prefix-list",
345 route_match_ip_address_prefix_list,
346 route_match_ip_address_prefix_list_compile,
347 route_match_ip_address_prefix_list_free
348 };
349
350 /* `match interface IFNAME' */
351 /* Match function should return 1 if match is success else return
352 zero. */
353 static route_map_result_t
354 route_match_interface (void *rule, struct prefix *prefix,
355 route_map_object_t type, void *object)
356 {
357 struct interface *ifp;
358 struct external_info *ei;
359
360 if (type == RMAP_OSPF)
361 {
362 ei = object;
363 ifp = if_lookup_by_name ((char *)rule, VRF_DEFAULT);
364
365 if (ifp == NULL || ifp->ifindex != ei->ifindex)
366 return RMAP_NOMATCH;
367
368 return RMAP_MATCH;
369 }
370 return RMAP_NOMATCH;
371 }
372
373 /* Route map `interface' match statement. `arg' should be
374 interface name. */
375 static void *
376 route_match_interface_compile (const char *arg)
377 {
378 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
379 }
380
381 /* Free route map's compiled `interface' value. */
382 static void
383 route_match_interface_free (void *rule)
384 {
385 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
386 }
387
388 /* Route map commands for ip address matching. */
389 struct route_map_rule_cmd route_match_interface_cmd =
390 {
391 "interface",
392 route_match_interface,
393 route_match_interface_compile,
394 route_match_interface_free
395 };
396
397 /* Match function return 1 if match is success else return zero. */
398 static route_map_result_t
399 route_match_tag (void *rule, struct prefix *prefix,
400 route_map_object_t type, void *object)
401 {
402 route_tag_t *tag;
403 struct external_info *ei;
404
405 if (type == RMAP_OSPF)
406 {
407 tag = rule;
408 ei = object;
409
410 return ((ei->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH);
411 }
412
413 return RMAP_NOMATCH;
414 }
415
416 /* Route map commands for tag matching. */
417 static struct route_map_rule_cmd route_match_tag_cmd =
418 {
419 "tag",
420 route_match_tag,
421 route_map_rule_tag_compile,
422 route_map_rule_tag_free,
423 };
424
425
426 /* `set metric METRIC' */
427 /* Set metric to attribute. */
428 static route_map_result_t
429 route_set_metric (void *rule, struct prefix *prefix,
430 route_map_object_t type, void *object)
431 {
432 u_int32_t *metric;
433 struct external_info *ei;
434
435 if (type == RMAP_OSPF)
436 {
437 /* Fetch routemap's rule information. */
438 metric = rule;
439 ei = object;
440
441 /* Set metric out value. */
442 ei->route_map_set.metric = *metric;
443 }
444 return RMAP_OKAY;
445 }
446
447 /* set metric compilation. */
448 static void *
449 route_set_metric_compile (const char *arg)
450 {
451 u_int32_t *metric;
452 int32_t ret;
453
454 /* OSPF doesn't support the +/- in
455 set metric <+/-metric> check
456 Ignore the +/- component */
457 if (! all_digit (arg))
458 {
459 if ((strncmp (arg, "+", 1) == 0 || strncmp (arg, "-", 1) == 0) &&
460 all_digit (arg+1))
461 {
462 zlog_warn ("OSPF does not support 'set metric +/-'");
463 arg++;
464 }
465 else
466 {
467 return NULL;
468 }
469 }
470 metric = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
471 ret = atoi (arg);
472
473 if (ret >= 0)
474 {
475 *metric = (u_int32_t)ret;
476 return metric;
477 }
478
479 XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
480 return NULL;
481 }
482
483 /* Free route map's compiled `set metric' value. */
484 static void
485 route_set_metric_free (void *rule)
486 {
487 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
488 }
489
490 /* Set metric rule structure. */
491 struct route_map_rule_cmd route_set_metric_cmd =
492 {
493 "metric",
494 route_set_metric,
495 route_set_metric_compile,
496 route_set_metric_free,
497 };
498
499 /* `set metric-type TYPE' */
500 /* Set metric-type to attribute. */
501 static route_map_result_t
502 route_set_metric_type (void *rule, struct prefix *prefix,
503 route_map_object_t type, void *object)
504 {
505 u_int32_t *metric_type;
506 struct external_info *ei;
507
508 if (type == RMAP_OSPF)
509 {
510 /* Fetch routemap's rule information. */
511 metric_type = rule;
512 ei = object;
513
514 /* Set metric out value. */
515 ei->route_map_set.metric_type = *metric_type;
516 }
517 return RMAP_OKAY;
518 }
519
520 /* set metric-type compilation. */
521 static void *
522 route_set_metric_type_compile (const char *arg)
523 {
524 u_int32_t *metric_type;
525
526 metric_type = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
527 if (strcmp (arg, "type-1") == 0)
528 *metric_type = EXTERNAL_METRIC_TYPE_1;
529 else if (strcmp (arg, "type-2") == 0)
530 *metric_type = EXTERNAL_METRIC_TYPE_2;
531
532 if (*metric_type == EXTERNAL_METRIC_TYPE_1 ||
533 *metric_type == EXTERNAL_METRIC_TYPE_2)
534 return metric_type;
535
536 XFREE (MTYPE_ROUTE_MAP_COMPILED, metric_type);
537 return NULL;
538 }
539
540 /* Free route map's compiled `set metric-type' value. */
541 static void
542 route_set_metric_type_free (void *rule)
543 {
544 XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
545 }
546
547 /* Set metric rule structure. */
548 struct route_map_rule_cmd route_set_metric_type_cmd =
549 {
550 "metric-type",
551 route_set_metric_type,
552 route_set_metric_type_compile,
553 route_set_metric_type_free,
554 };
555
556 static route_map_result_t
557 route_set_tag (void *rule, struct prefix *prefix,
558 route_map_object_t type, void *object)
559 {
560 route_tag_t *tag;
561 struct external_info *ei;
562
563 if (type == RMAP_OSPF)
564 {
565 tag = rule;
566 ei = object;
567
568 /* Set tag value */
569 ei->tag=*tag;
570 }
571
572 return RMAP_OKAY;
573 }
574
575 /* Route map commands for tag set. */
576 static struct route_map_rule_cmd route_set_tag_cmd =
577 {
578 "tag",
579 route_set_tag,
580 route_map_rule_tag_compile,
581 route_map_rule_tag_free,
582 };
583
584 DEFUN (match_ip_nexthop,
585 match_ip_nexthop_cmd,
586 "match ip next-hop <(1-199)|(1300-2699)|WORD>",
587 MATCH_STR
588 IP_STR
589 "Match next-hop address of route\n"
590 "IP access-list number\n"
591 "IP access-list number (expanded range)\n"
592 "IP access-list name\n")
593 {
594 int idx_acl = 3;
595 return ospf_route_match_add (vty, "ip next-hop", argv[idx_acl]->arg);
596 }
597
598 DEFUN (no_match_ip_nexthop,
599 no_match_ip_nexthop_cmd,
600 "no match ip next-hop [<(1-199)|(1300-2699)|WORD>]",
601 NO_STR
602 MATCH_STR
603 IP_STR
604 "Match next-hop address of route\n"
605 "IP access-list number\n"
606 "IP access-list number (expanded range)\n"
607 "IP access-list name\n")
608 {
609 char *al = (argc == 5) ? argv[4]->arg : NULL;
610 return ospf_route_match_delete (vty, "ip next-hop", al);
611 }
612
613 DEFUN (set_metric_type,
614 set_metric_type_cmd,
615 "set metric-type <type-1|type-2>",
616 SET_STR
617 "Type of metric for destination routing protocol\n"
618 "OSPF[6] external type 1 metric\n"
619 "OSPF[6] external type 2 metric\n")
620 {
621 char *ext = argv[2]->text;
622 return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index),
623 "metric-type", ext);
624 }
625
626 DEFUN (no_set_metric_type,
627 no_set_metric_type_cmd,
628 "no set metric-type [<type-1|type-2>]",
629 NO_STR
630 SET_STR
631 "Type of metric for destination routing protocol\n"
632 "OSPF[6] external type 1 metric\n"
633 "OSPF[6] external type 2 metric\n")
634 {
635 char *ext = (argc == 4) ? argv[3]->text : NULL;
636 return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index),
637 "metric-type", ext);
638 }
639
640 /* Route-map init */
641 void
642 ospf_route_map_init (void)
643 {
644 route_map_init ();
645
646 route_map_add_hook (ospf_route_map_update);
647 route_map_delete_hook (ospf_route_map_update);
648 route_map_event_hook (ospf_route_map_event);
649
650 route_map_match_interface_hook (generic_match_add);
651 route_map_no_match_interface_hook (generic_match_delete);
652
653 route_map_match_ip_address_hook (generic_match_add);
654 route_map_no_match_ip_address_hook (generic_match_delete);
655
656 route_map_match_ip_address_prefix_list_hook (generic_match_add);
657 route_map_no_match_ip_address_prefix_list_hook (generic_match_delete);
658
659 route_map_match_ip_next_hop_prefix_list_hook (generic_match_add);
660 route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete);
661
662 route_map_match_tag_hook (generic_match_add);
663 route_map_no_match_tag_hook (generic_match_delete);
664
665 route_map_set_metric_hook (generic_set_add);
666 route_map_no_set_metric_hook (generic_set_delete);
667
668 route_map_set_tag_hook (generic_set_add);
669 route_map_no_set_tag_hook (generic_set_delete);
670
671 route_map_install_match (&route_match_ip_nexthop_cmd);
672 route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
673 route_map_install_match (&route_match_ip_address_cmd);
674 route_map_install_match (&route_match_ip_address_prefix_list_cmd);
675 route_map_install_match (&route_match_interface_cmd);
676 route_map_install_match (&route_match_tag_cmd);
677
678 route_map_install_set (&route_set_metric_cmd);
679 route_map_install_set (&route_set_metric_type_cmd);
680 route_map_install_set (&route_set_tag_cmd);
681
682 install_element (RMAP_NODE, &match_ip_nexthop_cmd);
683 install_element (RMAP_NODE, &no_match_ip_nexthop_cmd);
684
685 install_element (RMAP_NODE, &set_metric_type_cmd);
686 install_element (RMAP_NODE, &no_set_metric_type_cmd);
687 }