| /* route-map for interface. |
| * Copyright (C) 1999 Kunihiro Ishiguro |
| * |
| * This file is part of GNU Zebra. |
| * |
| * GNU Zebra is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License as published by the |
| * Free Software Foundation; either version 2, or (at your option) any |
| * later version. |
| * |
| * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free |
| * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
| * 02111-1307, USA. |
| */ |
| |
| #include <zebra.h> |
| |
| #include "hash.h" |
| #include "command.h" |
| #include "memory.h" |
| #include "if.h" |
| #include "if_rmap.h" |
| |
| struct hash *ifrmaphash; |
| |
| /* Hook functions. */ |
| void (*if_rmap_add_hook) (struct if_rmap *) = NULL; |
| void (*if_rmap_delete_hook) (struct if_rmap *) = NULL; |
| |
| struct if_rmap * |
| if_rmap_new () |
| { |
| struct if_rmap *new; |
| |
| new = XCALLOC (MTYPE_IF_RMAP, sizeof (struct if_rmap)); |
| |
| return new; |
| } |
| |
| void |
| if_rmap_free (struct if_rmap *if_rmap) |
| { |
| if (if_rmap->ifname) |
| free (if_rmap->ifname); |
| |
| if (if_rmap->routemap[IF_RMAP_IN]) |
| free (if_rmap->routemap[IF_RMAP_IN]); |
| if (if_rmap->routemap[IF_RMAP_OUT]) |
| free (if_rmap->routemap[IF_RMAP_OUT]); |
| |
| XFREE (MTYPE_IF_RMAP, if_rmap); |
| } |
| |
| struct if_rmap * |
| if_rmap_lookup (const char *ifname) |
| { |
| struct if_rmap key; |
| struct if_rmap *if_rmap; |
| |
| /* temporary copy */ |
| key.ifname = (char *)ifname; |
| |
| if_rmap = hash_lookup (ifrmaphash, &key); |
| |
| return if_rmap; |
| } |
| |
| void |
| if_rmap_hook_add (void (*func) (struct if_rmap *)) |
| { |
| if_rmap_add_hook = func; |
| } |
| |
| void |
| if_rmap_hook_delete (void (*func) (struct if_rmap *)) |
| { |
| if_rmap_delete_hook = func; |
| } |
| |
| void * |
| if_rmap_hash_alloc (struct if_rmap *arg) |
| { |
| struct if_rmap *if_rmap; |
| |
| if_rmap = if_rmap_new (); |
| if_rmap->ifname = strdup (arg->ifname); |
| |
| return if_rmap; |
| } |
| |
| struct if_rmap * |
| if_rmap_get (const char *ifname) |
| { |
| struct if_rmap key; |
| |
| /* temporary copy */ |
| key.ifname = (char *)ifname; |
| |
| return (struct if_rmap *) hash_get (ifrmaphash, &key, if_rmap_hash_alloc); |
| } |
| |
| unsigned int |
| if_rmap_hash_make (struct if_rmap *if_rmap) |
| { |
| unsigned int i, key; |
| |
| key = 0; |
| for (i = 0; i < strlen (if_rmap->ifname); i++) |
| key += if_rmap->ifname[i]; |
| |
| return key; |
| } |
| |
| int |
| if_rmap_hash_cmp (struct if_rmap *if_rmap1, struct if_rmap *if_rmap2) |
| { |
| if (strcmp (if_rmap1->ifname, if_rmap2->ifname) == 0) |
| return 1; |
| return 0; |
| } |
| |
| struct if_rmap * |
| if_rmap_set (const char *ifname, enum if_rmap_type type, |
| const char *routemap_name) |
| { |
| struct if_rmap *if_rmap; |
| |
| if_rmap = if_rmap_get (ifname); |
| |
| if (type == IF_RMAP_IN) |
| { |
| if (if_rmap->routemap[IF_RMAP_IN]) |
| free (if_rmap->routemap[IF_RMAP_IN]); |
| if_rmap->routemap[IF_RMAP_IN] = strdup (routemap_name); |
| } |
| if (type == IF_RMAP_OUT) |
| { |
| if (if_rmap->routemap[IF_RMAP_OUT]) |
| free (if_rmap->routemap[IF_RMAP_OUT]); |
| if_rmap->routemap[IF_RMAP_OUT] = strdup (routemap_name); |
| } |
| |
| if (if_rmap_add_hook) |
| (*if_rmap_add_hook) (if_rmap); |
| |
| return if_rmap; |
| } |
| |
| int |
| if_rmap_unset (const char *ifname, enum if_rmap_type type, |
| const char *routemap_name) |
| { |
| struct if_rmap *if_rmap; |
| |
| if_rmap = if_rmap_lookup (ifname); |
| if (!if_rmap) |
| return 0; |
| |
| if (type == IF_RMAP_IN) |
| { |
| if (!if_rmap->routemap[IF_RMAP_IN]) |
| return 0; |
| if (strcmp (if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0) |
| return 0; |
| |
| free (if_rmap->routemap[IF_RMAP_IN]); |
| if_rmap->routemap[IF_RMAP_IN] = NULL; |
| } |
| |
| if (type == IF_RMAP_OUT) |
| { |
| if (!if_rmap->routemap[IF_RMAP_OUT]) |
| return 0; |
| if (strcmp (if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0) |
| return 0; |
| |
| free (if_rmap->routemap[IF_RMAP_OUT]); |
| if_rmap->routemap[IF_RMAP_OUT] = NULL; |
| } |
| |
| if (if_rmap_delete_hook) |
| (*if_rmap_delete_hook) (if_rmap); |
| |
| if (if_rmap->routemap[IF_RMAP_IN] == NULL && |
| if_rmap->routemap[IF_RMAP_OUT] == NULL) |
| { |
| hash_release (ifrmaphash, if_rmap); |
| if_rmap_free (if_rmap); |
| } |
| |
| return 1; |
| } |
| |
| DEFUN (if_rmap, |
| if_rmap_cmd, |
| "route-map RMAP_NAME (in|out) IFNAME", |
| "Route map set\n" |
| "Route map name\n" |
| "Route map set for input filtering\n" |
| "Route map set for output filtering\n" |
| "Route map interface name\n") |
| { |
| enum if_rmap_type type; |
| struct if_rmap *if_rmap; |
| |
| if (strncmp (argv[1], "i", 1) == 0) |
| type = IF_RMAP_IN; |
| else if (strncmp (argv[1], "o", 1) == 0) |
| type = IF_RMAP_OUT; |
| else |
| { |
| vty_out (vty, "route-map direction must be [in|out]%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| if_rmap = if_rmap_set (argv[2], type, argv[0]); |
| |
| return CMD_SUCCESS; |
| } |
| |
| ALIAS (if_rmap, |
| if_ipv6_rmap_cmd, |
| "route-map RMAP_NAME (in|out) IFNAME", |
| "Route map set\n" |
| "Route map name\n" |
| "Route map set for input filtering\n" |
| "Route map set for output filtering\n" |
| "Route map interface name\n") |
| |
| DEFUN (no_if_rmap, |
| no_if_rmap_cmd, |
| "no route-map ROUTEMAP_NAME (in|out) IFNAME", |
| NO_STR |
| "Route map unset\n" |
| "Route map name\n" |
| "Route map for input filtering\n" |
| "Route map for output filtering\n" |
| "Route map interface name\n") |
| { |
| int ret; |
| enum if_rmap_type type; |
| |
| if (strncmp (argv[1], "i", 1) == 0) |
| type = IF_RMAP_IN; |
| else if (strncmp (argv[1], "o", 1) == 0) |
| type = IF_RMAP_OUT; |
| else |
| { |
| vty_out (vty, "route-map direction must be [in|out]%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| |
| ret = if_rmap_unset (argv[2], type, argv[0]); |
| if (! ret) |
| { |
| vty_out (vty, "route-map doesn't exist%s", VTY_NEWLINE); |
| return CMD_WARNING; |
| } |
| return CMD_SUCCESS; |
| } |
| |
| ALIAS (no_if_rmap, |
| no_if_ipv6_rmap_cmd, |
| "no route-map ROUTEMAP_NAME (in|out) IFNAME", |
| NO_STR |
| "Route map unset\n" |
| "Route map name\n" |
| "Route map for input filtering\n" |
| "Route map for output filtering\n" |
| "Route map interface name\n") |
| |
| /* Configuration write function. */ |
| int |
| config_write_if_rmap (struct vty *vty) |
| { |
| unsigned int i; |
| struct hash_backet *mp; |
| int write = 0; |
| |
| for (i = 0; i < ifrmaphash->size; i++) |
| for (mp = ifrmaphash->index[i]; mp; mp = mp->next) |
| { |
| struct if_rmap *if_rmap; |
| |
| if_rmap = mp->data; |
| |
| if (if_rmap->routemap[IF_RMAP_IN]) |
| { |
| vty_out (vty, " route-map %s in %s%s", |
| if_rmap->routemap[IF_RMAP_IN], |
| if_rmap->ifname, |
| VTY_NEWLINE); |
| write++; |
| } |
| |
| if (if_rmap->routemap[IF_RMAP_OUT]) |
| { |
| vty_out (vty, " route-map %s out %s%s", |
| if_rmap->routemap[IF_RMAP_OUT], |
| if_rmap->ifname, |
| VTY_NEWLINE); |
| write++; |
| } |
| } |
| return write; |
| } |
| |
| void |
| if_rmap_reset () |
| { |
| hash_clean (ifrmaphash, (void (*) (void *)) if_rmap_free); |
| } |
| |
| void |
| if_rmap_init (int node) |
| { |
| ifrmaphash = hash_create (if_rmap_hash_make, if_rmap_hash_cmp); |
| if (node == RIPNG_NODE) { |
| install_element (RIPNG_NODE, &if_ipv6_rmap_cmd); |
| install_element (RIPNG_NODE, &no_if_ipv6_rmap_cmd); |
| } else if (node == RIP_NODE) { |
| install_element (RIP_NODE, &if_rmap_cmd); |
| install_element (RIP_NODE, &no_if_rmap_cmd); |
| } |
| } |