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