1/* route-map for interface. 2 * Copyright (C) 1999 Kunihiro Ishiguro 3 * 4 * This file is part of GNU Zebra. 5 * 6 * GNU Zebra is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2, or (at your option) any 9 * later version. 10 * 11 * GNU Zebra is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GNU Zebra; see the file COPYING. If not, write to the Free 18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 * 02111-1307, USA. 20 */ 21 22#include <zebra.h> 23 24#include "hash.h" 25#include "command.h" 26#include "memory.h" 27#include "if.h" 28#include "if_rmap.h" 29 30struct hash *ifrmaphash; 31 32/* Hook functions. */ 33static void (*if_rmap_add_hook) (struct if_rmap *) = NULL; 34static void (*if_rmap_delete_hook) (struct if_rmap *) = NULL; 35 36static struct if_rmap * 37if_rmap_new (void) 38{ 39 struct if_rmap *new; 40 41 new = XCALLOC (MTYPE_IF_RMAP, sizeof (struct if_rmap)); 42 43 return new; 44} 45 46static void 47if_rmap_free (struct if_rmap *if_rmap) 48{ 49 if (if_rmap->ifname) 50 XFREE (MTYPE_IF_RMAP_NAME, if_rmap->ifname); 51 52 if (if_rmap->routemap[IF_RMAP_IN]) 53 XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); 54 if (if_rmap->routemap[IF_RMAP_OUT]) 55 XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); 56 57 XFREE (MTYPE_IF_RMAP, if_rmap); 58} 59 60struct if_rmap * 61if_rmap_lookup (const char *ifname) 62{ 63 struct if_rmap key; 64 struct if_rmap *if_rmap; 65 66 /* temporary copy */ 67 key.ifname = (char *)ifname; 68 69 if_rmap = hash_lookup (ifrmaphash, &key); 70 71 return if_rmap; 72} 73 74void 75if_rmap_hook_add (void (*func) (struct if_rmap *)) 76{ 77 if_rmap_add_hook = func; 78} 79 80void 81if_rmap_hook_delete (void (*func) (struct if_rmap *)) 82{ 83 if_rmap_delete_hook = func; 84} 85 86static void * 87if_rmap_hash_alloc (void *arg) 88{ 89 struct if_rmap *ifarg = arg; 90 struct if_rmap *if_rmap; 91 92 if_rmap = if_rmap_new (); 93 if_rmap->ifname = XSTRDUP (MTYPE_IF_RMAP_NAME, ifarg->ifname); 94 95 return if_rmap; 96} 97 98static struct if_rmap * 99if_rmap_get (const char *ifname) 100{ 101 struct if_rmap key; 102 103 /* temporary copy */ 104 key.ifname = (char *)ifname; 105 106 return (struct if_rmap *) hash_get (ifrmaphash, &key, if_rmap_hash_alloc); 107} 108 109static unsigned int 110if_rmap_hash_make (void *data) 111{ 112 const struct if_rmap *if_rmap = data; 113 114 return string_hash_make (if_rmap->ifname); 115} 116 117static int 118if_rmap_hash_cmp (const void *arg1, const void* arg2) 119{ 120 const struct if_rmap *if_rmap1 = arg1; 121 const struct if_rmap *if_rmap2 = arg2; 122 123 return strcmp (if_rmap1->ifname, if_rmap2->ifname) == 0; 124} 125 126static struct if_rmap * 127if_rmap_set (const char *ifname, enum if_rmap_type type, 128 const char *routemap_name) 129{ 130 struct if_rmap *if_rmap; 131 132 if_rmap = if_rmap_get (ifname); 133 134 if (type == IF_RMAP_IN) 135 { 136 if (if_rmap->routemap[IF_RMAP_IN]) 137 XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); 138 if_rmap->routemap[IF_RMAP_IN] 139 = XSTRDUP (MTYPE_IF_RMAP_NAME, routemap_name); 140 } 141 if (type == IF_RMAP_OUT) 142 { 143 if (if_rmap->routemap[IF_RMAP_OUT]) 144 XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); 145 if_rmap->routemap[IF_RMAP_OUT] 146 = XSTRDUP (MTYPE_IF_RMAP_NAME, routemap_name); 147 } 148 149 if (if_rmap_add_hook) 150 (*if_rmap_add_hook) (if_rmap); 151 152 return if_rmap; 153} 154 155static int 156if_rmap_unset (const char *ifname, enum if_rmap_type type, 157 const char *routemap_name) 158{ 159 struct if_rmap *if_rmap; 160 161 if_rmap = if_rmap_lookup (ifname); 162 if (!if_rmap) 163 return 0; 164 165 if (type == IF_RMAP_IN) 166 { 167 if (!if_rmap->routemap[IF_RMAP_IN]) 168 return 0; 169 if (strcmp (if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0) 170 return 0; 171 172 XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); 173 if_rmap->routemap[IF_RMAP_IN] = NULL; 174 } 175 176 if (type == IF_RMAP_OUT) 177 { 178 if (!if_rmap->routemap[IF_RMAP_OUT]) 179 return 0; 180 if (strcmp (if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0) 181 return 0; 182 183 XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); 184 if_rmap->routemap[IF_RMAP_OUT] = NULL; 185 } 186 187 if (if_rmap_delete_hook) 188 (*if_rmap_delete_hook) (if_rmap); 189 190 if (if_rmap->routemap[IF_RMAP_IN] == NULL && 191 if_rmap->routemap[IF_RMAP_OUT] == NULL) 192 { 193 hash_release (ifrmaphash, if_rmap); 194 if_rmap_free (if_rmap); 195 } 196 197 return 1; 198} 199 200DEFUN (if_rmap, 201 if_rmap_cmd, 202 "route-map RMAP_NAME (in|out) IFNAME", 203 "Route map set\n" 204 "Route map name\n" 205 "Route map set for input filtering\n" 206 "Route map set for output filtering\n" 207 "Route map interface name\n") 208{ 209 enum if_rmap_type type; 210 211 if (strncmp (argv[1], "i", 1) == 0) 212 type = IF_RMAP_IN; 213 else if (strncmp (argv[1], "o", 1) == 0) 214 type = IF_RMAP_OUT; 215 else 216 { 217 vty_out (vty, "route-map direction must be [in|out]%s", VTY_NEWLINE); 218 return CMD_WARNING; 219 } 220 221 if_rmap_set (argv[2], type, argv[0]); 222 223 return CMD_SUCCESS; 224} 225 226ALIAS (if_rmap, 227 if_ipv6_rmap_cmd, 228 "route-map RMAP_NAME (in|out) IFNAME", 229 "Route map set\n" 230 "Route map name\n" 231 "Route map set for input filtering\n" 232 "Route map set for output filtering\n" 233 "Route map interface name\n") 234 235DEFUN (no_if_rmap, 236 no_if_rmap_cmd, 237 "no route-map ROUTEMAP_NAME (in|out) IFNAME", 238 NO_STR 239 "Route map unset\n" 240 "Route map name\n" 241 "Route map for input filtering\n" 242 "Route map for output filtering\n" 243 "Route map interface name\n") 244{ 245 int ret; 246 enum if_rmap_type type; 247 248 if (strncmp (argv[1], "i", 1) == 0) 249 type = IF_RMAP_IN; 250 else if (strncmp (argv[1], "o", 1) == 0) 251 type = IF_RMAP_OUT; 252 else 253 { 254 vty_out (vty, "route-map direction must be [in|out]%s", VTY_NEWLINE); 255 return CMD_WARNING; 256 } 257 258 ret = if_rmap_unset (argv[2], type, argv[0]); 259 if (! ret) 260 { 261 vty_out (vty, "route-map doesn't exist%s", VTY_NEWLINE); 262 return CMD_WARNING; 263 } 264 return CMD_SUCCESS; 265} 266 267ALIAS (no_if_rmap, 268 no_if_ipv6_rmap_cmd, 269 "no route-map ROUTEMAP_NAME (in|out) IFNAME", 270 NO_STR 271 "Route map unset\n" 272 "Route map name\n" 273 "Route map for input filtering\n" 274 "Route map for output filtering\n" 275 "Route map interface name\n") 276 277/* Configuration write function. */ 278int 279config_write_if_rmap (struct vty *vty) 280{ 281 unsigned int i; 282 struct hash_backet *mp; 283 int write = 0; 284 285 for (i = 0; i < ifrmaphash->size; i++) 286 for (mp = ifrmaphash->index[i]; mp; mp = mp->next) 287 { 288 struct if_rmap *if_rmap; 289 290 if_rmap = mp->data; 291 292 if (if_rmap->routemap[IF_RMAP_IN]) 293 { 294 vty_out (vty, " route-map %s in %s%s", 295 if_rmap->routemap[IF_RMAP_IN], 296 if_rmap->ifname, 297 VTY_NEWLINE); 298 write++; 299 } 300 301 if (if_rmap->routemap[IF_RMAP_OUT]) 302 { 303 vty_out (vty, " route-map %s out %s%s", 304 if_rmap->routemap[IF_RMAP_OUT], 305 if_rmap->ifname, 306 VTY_NEWLINE); 307 write++; 308 } 309 } 310 return write; 311} 312 313void 314if_rmap_reset () 315{ 316 hash_clean (ifrmaphash, (void (*) (void *)) if_rmap_free); 317} 318 319void 320if_rmap_init (int node) 321{ 322 ifrmaphash = hash_create (if_rmap_hash_make, if_rmap_hash_cmp); 323 if (node == RIPNG_NODE) { 324 install_element (RIPNG_NODE, &if_ipv6_rmap_cmd); 325 install_element (RIPNG_NODE, &no_if_ipv6_rmap_cmd); 326 } else if (node == RIP_NODE) { 327 install_element (RIP_NODE, &if_rmap_cmd); 328 install_element (RIP_NODE, &no_if_rmap_cmd); 329 } 330} 331