2 * Route map function of ospfd.
3 * Copyright (C) 2000 IP Infusion Inc.
5 * Written by Toshiaki Takada.
7 * This file is part of GNU Zebra.
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
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.
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
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"
43 /* Hook function for updating route_map assignment. */
45 ospf_route_map_update (const char *name
)
50 /* If OSPF instatnce does not exist, return right now. */
51 ospf
= ospf_lookup ();
55 /* Update route-map */
56 for (type
= 0; type
<= ZEBRA_ROUTE_MAX
; type
++)
58 struct list
*red_list
;
59 struct listnode
*node
;
60 struct ospf_redist
*red
;
62 red_list
= ospf
->redist
[type
];
66 for (ALL_LIST_ELEMENTS_RO(red_list
, node
, red
))
68 if (ROUTEMAP_NAME (red
)
69 && strcmp (ROUTEMAP_NAME (red
), name
) == 0)
71 /* Keep old route-map. */
72 struct route_map
*old
= ROUTEMAP (red
);
74 /* Update route-map. */
76 route_map_lookup_by_name (ROUTEMAP_NAME (red
));
78 /* No update for this distribute type. */
79 if (old
== NULL
&& ROUTEMAP (red
) == NULL
)
82 ospf_distribute_list_update (ospf
, type
, red
->instance
);
89 ospf_route_map_event (route_map_event_t event
, const char *name
)
94 /* If OSPF instatnce does not exist, return right now. */
95 ospf
= ospf_lookup ();
99 for (type
= 0; type
<= ZEBRA_ROUTE_MAX
; type
++)
101 struct list
*red_list
;
102 struct listnode
*node
;
103 struct ospf_redist
*red
;
105 red_list
= ospf
->redist
[type
];
109 for (ALL_LIST_ELEMENTS_RO(red_list
, node
, red
))
111 if (ROUTEMAP_NAME (red
) && ROUTEMAP (red
)
112 && !strcmp (ROUTEMAP_NAME (red
), name
))
114 ospf_distribute_list_update (ospf
, type
, red
->instance
);
120 /* Delete rip route map rule. */
122 ospf_route_match_delete (struct vty
*vty
,
123 const char *command
, const char *arg
)
125 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
128 ret
= route_map_delete_match (index
, command
, arg
);
133 case RMAP_RULE_MISSING
:
134 vty_out (vty
, "%% OSPF Can't find rule.%s", VTY_NEWLINE
);
136 case RMAP_COMPILE_ERROR
:
137 vty_out (vty
, "%% OSPF Argument is malformed.%s", VTY_NEWLINE
);
146 ospf_route_match_add (struct vty
*vty
,
147 const char *command
, const char *arg
)
149 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
152 ret
= route_map_add_match (index
, command
, arg
);
157 case RMAP_RULE_MISSING
:
158 vty_out (vty
, "%% OSPF Can't find rule.%s", VTY_NEWLINE
);
160 case RMAP_COMPILE_ERROR
:
161 vty_out (vty
, "%% OSPF Argument is malformed.%s", VTY_NEWLINE
);
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
)
175 struct access_list
*alist
;
176 struct external_info
*ei
= object
;
177 struct prefix_ipv4 p
;
179 if (type
== RMAP_OSPF
)
182 p
.prefix
= ei
->nexthop
;
183 p
.prefixlen
= IPV4_MAX_BITLEN
;
185 alist
= access_list_lookup (AFI_IP
, (char *) rule
);
189 return (access_list_apply (alist
, &p
) == FILTER_DENY
?
190 RMAP_NOMATCH
: RMAP_MATCH
);
195 /* Route map `ip next-hop' match statement. `arg' should be
198 route_match_ip_nexthop_compile (const char *arg
)
200 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
203 /* Free route map's compiled `ip address' value. */
205 route_match_ip_nexthop_free (void *rule
)
207 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
210 /* Route map commands for metric matching. */
211 struct route_map_rule_cmd route_match_ip_nexthop_cmd
=
214 route_match_ip_nexthop
,
215 route_match_ip_nexthop_compile
,
216 route_match_ip_nexthop_free
219 /* `match ip next-hop prefix-list PREFIX_LIST' */
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
)
225 struct prefix_list
*plist
;
226 struct external_info
*ei
= object
;
227 struct prefix_ipv4 p
;
229 if (type
== RMAP_OSPF
)
232 p
.prefix
= ei
->nexthop
;
233 p
.prefixlen
= IPV4_MAX_BITLEN
;
235 plist
= prefix_list_lookup (AFI_IP
, (char *) rule
);
239 return (prefix_list_apply (plist
, &p
) == PREFIX_DENY
?
240 RMAP_NOMATCH
: RMAP_MATCH
);
246 route_match_ip_next_hop_prefix_list_compile (const char *arg
)
248 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
252 route_match_ip_next_hop_prefix_list_free (void *rule
)
254 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
257 struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd
=
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
265 /* `match ip address IP_ACCESS_LIST' */
266 /* Match function should return 1 if match is success else return
268 static route_map_result_t
269 route_match_ip_address (void *rule
, struct prefix
*prefix
,
270 route_map_object_t type
, void *object
)
272 struct access_list
*alist
;
273 /* struct prefix_ipv4 match; */
275 if (type
== RMAP_OSPF
)
277 alist
= access_list_lookup (AFI_IP
, (char *) rule
);
281 return (access_list_apply (alist
, prefix
) == FILTER_DENY
?
282 RMAP_NOMATCH
: RMAP_MATCH
);
287 /* Route map `ip address' match statement. `arg' should be
290 route_match_ip_address_compile (const char *arg
)
292 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
295 /* Free route map's compiled `ip address' value. */
297 route_match_ip_address_free (void *rule
)
299 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
302 /* Route map commands for ip address matching. */
303 struct route_map_rule_cmd route_match_ip_address_cmd
=
306 route_match_ip_address
,
307 route_match_ip_address_compile
,
308 route_match_ip_address_free
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
)
316 struct prefix_list
*plist
;
318 if (type
== RMAP_OSPF
)
320 plist
= prefix_list_lookup (AFI_IP
, (char *) rule
);
324 return (prefix_list_apply (plist
, prefix
) == PREFIX_DENY
?
325 RMAP_NOMATCH
: RMAP_MATCH
);
331 route_match_ip_address_prefix_list_compile (const char *arg
)
333 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
337 route_match_ip_address_prefix_list_free (void *rule
)
339 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
342 struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd
=
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
350 /* `match interface IFNAME' */
351 /* Match function should return 1 if match is success else return
353 static route_map_result_t
354 route_match_interface (void *rule
, struct prefix
*prefix
,
355 route_map_object_t type
, void *object
)
357 struct interface
*ifp
;
358 struct external_info
*ei
;
360 if (type
== RMAP_OSPF
)
363 ifp
= if_lookup_by_name ((char *)rule
, VRF_DEFAULT
);
365 if (ifp
== NULL
|| ifp
->ifindex
!= ei
->ifindex
)
373 /* Route map `interface' match statement. `arg' should be
376 route_match_interface_compile (const char *arg
)
378 return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED
, arg
);
381 /* Free route map's compiled `interface' value. */
383 route_match_interface_free (void *rule
)
385 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
388 /* Route map commands for ip address matching. */
389 struct route_map_rule_cmd route_match_interface_cmd
=
392 route_match_interface
,
393 route_match_interface_compile
,
394 route_match_interface_free
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
)
403 struct external_info
*ei
;
405 if (type
== RMAP_OSPF
)
410 return ((ei
->tag
== *tag
)? RMAP_MATCH
: RMAP_NOMATCH
);
416 /* Route map commands for tag matching. */
417 static struct route_map_rule_cmd route_match_tag_cmd
=
421 route_map_rule_tag_compile
,
422 route_map_rule_tag_free
,
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
)
433 struct external_info
*ei
;
435 if (type
== RMAP_OSPF
)
437 /* Fetch routemap's rule information. */
441 /* Set metric out value. */
442 ei
->route_map_set
.metric
= *metric
;
447 /* set metric compilation. */
449 route_set_metric_compile (const char *arg
)
454 /* OSPF doesn't support the +/- in
455 set metric <+/-metric> check
456 Ignore the +/- component */
457 if (! all_digit (arg
))
459 if ((strncmp (arg
, "+", 1) == 0 || strncmp (arg
, "-", 1) == 0) &&
462 zlog_warn ("OSPF does not support 'set metric +/-'");
470 metric
= XCALLOC (MTYPE_ROUTE_MAP_COMPILED
, sizeof (u_int32_t
));
475 *metric
= (u_int32_t
)ret
;
479 XFREE (MTYPE_ROUTE_MAP_COMPILED
, metric
);
483 /* Free route map's compiled `set metric' value. */
485 route_set_metric_free (void *rule
)
487 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
490 /* Set metric rule structure. */
491 struct route_map_rule_cmd route_set_metric_cmd
=
495 route_set_metric_compile
,
496 route_set_metric_free
,
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
)
505 u_int32_t
*metric_type
;
506 struct external_info
*ei
;
508 if (type
== RMAP_OSPF
)
510 /* Fetch routemap's rule information. */
514 /* Set metric out value. */
515 ei
->route_map_set
.metric_type
= *metric_type
;
520 /* set metric-type compilation. */
522 route_set_metric_type_compile (const char *arg
)
524 u_int32_t
*metric_type
;
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
;
532 if (*metric_type
== EXTERNAL_METRIC_TYPE_1
||
533 *metric_type
== EXTERNAL_METRIC_TYPE_2
)
536 XFREE (MTYPE_ROUTE_MAP_COMPILED
, metric_type
);
540 /* Free route map's compiled `set metric-type' value. */
542 route_set_metric_type_free (void *rule
)
544 XFREE (MTYPE_ROUTE_MAP_COMPILED
, rule
);
547 /* Set metric rule structure. */
548 struct route_map_rule_cmd route_set_metric_type_cmd
=
551 route_set_metric_type
,
552 route_set_metric_type_compile
,
553 route_set_metric_type_free
,
556 static route_map_result_t
557 route_set_tag (void *rule
, struct prefix
*prefix
,
558 route_map_object_t type
, void *object
)
561 struct external_info
*ei
;
563 if (type
== RMAP_OSPF
)
575 /* Route map commands for tag set. */
576 static struct route_map_rule_cmd route_set_tag_cmd
=
580 route_map_rule_tag_compile
,
581 route_map_rule_tag_free
,
584 DEFUN (match_ip_nexthop
,
585 match_ip_nexthop_cmd
,
586 "match ip next-hop <(1-199)|(1300-2699)|WORD>",
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")
595 return ospf_route_match_add (vty
, "ip next-hop", argv
[idx_acl
]->arg
);
598 DEFUN (no_match_ip_nexthop
,
599 no_match_ip_nexthop_cmd
,
600 "no match ip next-hop [<(1-199)|(1300-2699)|WORD>]",
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")
609 char *al
= (argc
== 5) ? argv
[4]->arg
: NULL
;
610 return ospf_route_match_delete (vty
, "ip next-hop", al
);
613 DEFUN (set_metric_type
,
615 "set metric-type <type-1|type-2>",
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")
621 char *ext
= argv
[2]->text
;
622 return generic_set_add (vty
, VTY_GET_CONTEXT(route_map_index
),
626 DEFUN (no_set_metric_type
,
627 no_set_metric_type_cmd
,
628 "no set metric-type [<type-1|type-2>]",
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")
635 char *ext
= (argc
== 4) ? argv
[3]->text
: NULL
;
636 return generic_set_delete (vty
, VTY_GET_CONTEXT(route_map_index
),
642 ospf_route_map_init (void)
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
);
650 route_map_match_interface_hook (generic_match_add
);
651 route_map_no_match_interface_hook (generic_match_delete
);
653 route_map_match_ip_address_hook (generic_match_add
);
654 route_map_no_match_ip_address_hook (generic_match_delete
);
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
);
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
);
662 route_map_match_tag_hook (generic_match_add
);
663 route_map_no_match_tag_hook (generic_match_delete
);
665 route_map_set_metric_hook (generic_set_add
);
666 route_map_no_set_metric_hook (generic_set_delete
);
668 route_map_set_tag_hook (generic_set_add
);
669 route_map_no_set_tag_hook (generic_set_delete
);
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
);
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
);
682 install_element (RMAP_NODE
, &match_ip_nexthop_cmd
);
683 install_element (RMAP_NODE
, &no_match_ip_nexthop_cmd
);
685 install_element (RMAP_NODE
, &set_metric_type_cmd
);
686 install_element (RMAP_NODE
, &no_set_metric_type_cmd
);