/* * IS-IS Rout(e)ing protocol - isis_routemap.c * * Copyright (C) 2001,2002 Sampo Saaristo * Tampere University of Technology * Institute of Communications Engineering * * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licenseas published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful,but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "command.h" #include "filter.h" #include "hash.h" #include "if.h" #include "linklist.h" #include "log.h" #include "memory.h" #include "prefix.h" #include "plist.h" #include "routemap.h" #include "table.h" #include "thread.h" #include "vty.h" #include "isis_constants.h" #include "isis_common.h" #include "isis_flags.h" #include "dict.h" #include "isisd.h" #include "isis_misc.h" #include "isis_adjacency.h" #include "isis_circuit.h" #include "isis_tlv.h" #include "isis_pdu.h" #include "isis_lsp.h" #include "isis_spf.h" #include "isis_route.h" #include "isis_zebra.h" #include "isis_routemap.h" static route_map_result_t route_match_ip_address(void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct access_list *alist; if (type != RMAP_ISIS) return RMAP_NOMATCH; alist = access_list_lookup(AFI_IP, (char*)rule); if (access_list_apply(alist, prefix) != FILTER_DENY) return RMAP_MATCH; return RMAP_NOMATCH; } static void * route_match_ip_address_compile(const char *arg) { return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } static void route_match_ip_address_free(void *rule) { XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } static struct route_map_rule_cmd route_match_ip_address_cmd = { "ip address", route_match_ip_address, route_match_ip_address_compile, route_match_ip_address_free }; /* ------------------------------------------------------------*/ static route_map_result_t route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; if (type != RMAP_ISIS) return RMAP_NOMATCH; plist = prefix_list_lookup(AFI_IP, (char*)rule); if (prefix_list_apply(plist, prefix) != PREFIX_DENY) return RMAP_MATCH; return RMAP_NOMATCH; } static void * route_match_ip_address_prefix_list_compile(const char *arg) { return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); } static void route_match_ip_address_prefix_list_free (void *rule) { XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); } struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { "ip address prefix-list", route_match_ip_address_prefix_list, route_match_ip_address_prefix_list_compile, route_match_ip_address_prefix_list_free }; /* ------------------------------------------------------------*/ #ifdef HAVE_IPV6 static route_map_result_t route_match_ipv6_address(void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct access_list *alist; if (type != RMAP_ISIS) return RMAP_NOMATCH; alist = access_list_lookup(AFI_IP6, (char*)rule); if (access_list_apply(alist, prefix) != FILTER_DENY) return RMAP_MATCH; return RMAP_NOMATCH; } static void * route_match_ipv6_address_compile(const char *arg) { return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } static void route_match_ipv6_address_free(void *rule) { XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } static struct route_map_rule_cmd route_match_ipv6_address_cmd = { "ipv6 address", route_match_ipv6_address, route_match_ipv6_address_compile, route_match_ipv6_address_free }; /* ------------------------------------------------------------*/ static route_map_result_t route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; if (type != RMAP_ISIS) return RMAP_NOMATCH; plist = prefix_list_lookup(AFI_IP6, (char*)rule); if (prefix_list_apply(plist, prefix) != PREFIX_DENY) return RMAP_MATCH; return RMAP_NOMATCH; } static void * route_match_ipv6_address_prefix_list_compile(const char *arg) { return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); } static void route_match_ipv6_address_prefix_list_free (void *rule) { XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); } struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { "ipv6 address prefix-list", route_match_ipv6_address_prefix_list, route_match_ipv6_address_prefix_list_compile, route_match_ipv6_address_prefix_list_free }; #endif /* HAVE_IPV6 */ /* ------------------------------------------------------------*/ static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, route_map_object_t type, void *object) { uint32_t *metric; struct isis_ext_info *info; if (type == RMAP_ISIS) { metric = rule; info = object; info->metric = *metric; } return RMAP_OKAY; } static void * route_set_metric_compile(const char *arg) { unsigned long metric; char *endp; uint32_t *ret; metric = strtoul(arg, &endp, 10); if (arg[0] == '\0' || *endp != '\0' || metric > MAX_WIDE_PATH_METRIC) return NULL; ret = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(ret)); *ret = metric; return ret; } static void route_set_metric_free(void *rule) { XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } static struct route_map_rule_cmd route_set_metric_cmd = { "metric", route_set_metric, route_set_metric_compile, route_set_metric_free }; /* ------------------------------------------------------------*/ static int isis_route_match_add(struct vty *vty, struct route_map_index *index, const char *command, const char *arg) { int ret; ret = route_map_add_match (index, command, arg); if (ret) { switch (ret) { case RMAP_RULE_MISSING: vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } return CMD_SUCCESS; } static int isis_route_match_delete(struct vty *vty, struct route_map_index *index, const char *command, const char *arg) { int ret; ret = route_map_delete_match (index, command, arg); if (ret) { switch (ret) { case RMAP_RULE_MISSING: vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } return CMD_SUCCESS; } static int isis_route_set_add(struct vty *vty, struct route_map_index *index, const char *command, const char *arg) { int ret; ret = route_map_add_set(index, command, arg); if (ret) { switch (ret) { case RMAP_RULE_MISSING: vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } return CMD_SUCCESS; } static int isis_route_set_delete (struct vty *vty, struct route_map_index *index, const char *command, const char *arg) { int ret; ret = route_map_delete_set (index, command, arg); if (ret) { switch (ret) { case RMAP_RULE_MISSING: vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } return CMD_SUCCESS; } /* ------------------------------------------------------------*/ DEFUN(match_ip_address, match_ip_address_cmd, "match ip address (<1-199>|<1300-2699>|WORD)", MATCH_STR IP_STR "Match address of route\n" "IP access-list number\n" "IP access-list number (expanded range)\n" "IP Access-list name\n") { return isis_route_match_add(vty, vty->index, "ip address", argv[0]); } DEFUN(no_match_ip_address, no_match_ip_address_val_cmd, "no match ip address (<1-199>|<1300-2699>|WORD)", NO_STR MATCH_STR IP_STR "Match address of route\n" "IP access-list number\n" "IP access-list number (expanded range)\n" "IP Access-list name\n") { if (argc == 0) return isis_route_match_delete(vty, vty->index, "ip address", NULL); return isis_route_match_delete(vty, vty->index, "ip address", argv[0]); } ALIAS(no_match_ip_address, no_match_ip_address_cmd, "no match ip address", NO_STR MATCH_STR IP_STR "Match address of route\n" ); /* ------------------------------------------------------------*/ DEFUN(match_ip_address_prefix_list, match_ip_address_prefix_list_cmd, "match ip address prefix-list WORD", MATCH_STR IP_STR "Match address of route\n" "Match entries of prefix-lists\n" "IP prefix-list name\n") { return isis_route_match_add(vty, vty->index, "ip address prefix-list", argv[0]); } DEFUN(no_match_ip_address_prefix_list, no_match_ip_address_prefix_list_cmd, "no match ip address prefix-list", NO_STR MATCH_STR IP_STR "Match address of route\n" "Match entries of prefix-lists\n") { if (argc == 0) return isis_route_match_delete (vty, vty->index, "ip address prefix-list", NULL); return isis_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]); } ALIAS(no_match_ip_address_prefix_list, no_match_ip_address_prefix_list_val_cmd, "no match ip address prefix-list WORD", NO_STR MATCH_STR IP_STR "Match address of route\n" "Match entries of prefix-lists\n" "IP prefix-list name\n" ); /* ------------------------------------------------------------*/ #ifdef HAVE_IPV6 DEFUN(match_ipv6_address, match_ipv6_address_cmd, "match ipv6 address WORD", MATCH_STR IPV6_STR "Match IPv6 address of route\n" "IPv6 access-list name\n") { return isis_route_match_add(vty, vty->index, "ipv6 address", argv[0]); } DEFUN(no_match_ipv6_address, no_match_ipv6_address_val_cmd, "no match ipv6 address WORD", NO_STR MATCH_STR IPV6_STR "Match IPv6 address of route\n" "IPv6 access-list name\n") { if (argc == 0) return isis_route_match_delete(vty, vty->index, "ipv6 address", NULL); return isis_route_match_delete(vty, vty->index, "ipv6 address", argv[0]); } ALIAS(no_match_ipv6_address, no_match_ipv6_address_cmd, "no match ipv6 address", NO_STR MATCH_STR IPV6_STR "Match IPv6 address of route\n" ); /* ------------------------------------------------------------*/ DEFUN(match_ipv6_address_prefix_list, match_ipv6_address_prefix_list_cmd, "match ipv6 address prefix-list WORD", MATCH_STR IPV6_STR "Match address of route\n" "Match entries of prefix-lists\n" "IP prefix-list name\n") { return isis_route_match_add(vty, vty->index, "ipv6 address prefix-list", argv[0]); } DEFUN(no_match_ipv6_address_prefix_list, no_match_ipv6_address_prefix_list_cmd, "no match ipv6 address prefix-list", NO_STR MATCH_STR IPV6_STR "Match address of route\n" "Match entries of prefix-lists\n") { if (argc == 0) return isis_route_match_delete (vty, vty->index, "ipv6 address prefix-list", NULL); return isis_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]); } ALIAS(no_match_ipv6_address_prefix_list, no_match_ipv6_address_prefix_list_val_cmd, "no match ipv6 address prefix-list WORD", NO_STR MATCH_STR IPV6_STR "Match address of route\n" "Match entries of prefix-lists\n" "IP prefix-list name\n" ); #endif /* HAVE_IPV6 */ /* ------------------------------------------------------------*/ /* set metric already exists e.g. in the ospf routemap. vtysh doesn't cope well with different * commands at the same node, therefore add set metric with the same 32-bit range as ospf and * verify that the input is a valid isis metric */ DEFUN(set_metric, set_metric_cmd, "set metric <0-4294967295>", SET_STR "Metric vale for destination routing protocol\n" "Metric value\n") { return isis_route_set_add(vty, vty->index, "metric", argv[0]); } DEFUN(no_set_metric, no_set_metric_val_cmd, "no set metric <0-4294967295>", NO_STR SET_STR "Metric value for destination routing protocol\n" "Metric value\n") { if (argc == 0) return isis_route_set_delete(vty, vty->index, "metric", NULL); return isis_route_set_delete(vty, vty->index, "metric", argv[0]); } ALIAS(no_set_metric, no_set_metric_cmd, "no set metric", NO_STR SET_STR "Metric vale for destination routing protocol\n" ); void isis_route_map_init(void) { route_map_init(); route_map_init_vty(); route_map_install_match(&route_match_ip_address_cmd); install_element(RMAP_NODE, &match_ip_address_cmd); install_element(RMAP_NODE, &no_match_ip_address_val_cmd); install_element(RMAP_NODE, &no_match_ip_address_cmd); route_map_install_match(&route_match_ip_address_prefix_list_cmd); install_element(RMAP_NODE, &match_ip_address_prefix_list_cmd); install_element(RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd); install_element(RMAP_NODE, &no_match_ip_address_prefix_list_cmd); #ifdef HAVE_IPV6 route_map_install_match(&route_match_ipv6_address_cmd); install_element(RMAP_NODE, &match_ipv6_address_cmd); install_element(RMAP_NODE, &no_match_ipv6_address_val_cmd); install_element(RMAP_NODE, &no_match_ipv6_address_cmd); route_map_install_match(&route_match_ipv6_address_prefix_list_cmd); install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd); install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_val_cmd); install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd); #endif route_map_install_set(&route_set_metric_cmd); install_element(RMAP_NODE, &set_metric_cmd); install_element(RMAP_NODE, &no_set_metric_val_cmd); install_element(RMAP_NODE, &no_set_metric_cmd); }