]>
Commit | Line | Data |
---|---|---|
718e3744 | 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" | |
0750d21f | 28 | #include "if_rmap.h" |
718e3744 | 29 | |
4a1ab8e4 DL |
30 | DEFINE_MTYPE_STATIC(LIB, IF_RMAP, "Interface route map") |
31 | DEFINE_MTYPE_STATIC(LIB, IF_RMAP_NAME, "I.f. route map name") | |
32 | ||
718e3744 | 33 | struct hash *ifrmaphash; |
34 | ||
35 | /* Hook functions. */ | |
8cc4198f | 36 | static void (*if_rmap_add_hook) (struct if_rmap *) = NULL; |
37 | static void (*if_rmap_delete_hook) (struct if_rmap *) = NULL; | |
6b0655a2 | 38 | |
8cc4198f | 39 | static struct if_rmap * |
40 | if_rmap_new (void) | |
718e3744 | 41 | { |
42 | struct if_rmap *new; | |
43 | ||
44 | new = XCALLOC (MTYPE_IF_RMAP, sizeof (struct if_rmap)); | |
45 | ||
46 | return new; | |
47 | } | |
48 | ||
8cc4198f | 49 | static void |
718e3744 | 50 | if_rmap_free (struct if_rmap *if_rmap) |
51 | { | |
52 | if (if_rmap->ifname) | |
0241684e | 53 | XFREE (MTYPE_IF_RMAP_NAME, if_rmap->ifname); |
718e3744 | 54 | |
55 | if (if_rmap->routemap[IF_RMAP_IN]) | |
0241684e | 56 | XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); |
718e3744 | 57 | if (if_rmap->routemap[IF_RMAP_OUT]) |
0241684e | 58 | XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); |
718e3744 | 59 | |
60 | XFREE (MTYPE_IF_RMAP, if_rmap); | |
61 | } | |
62 | ||
63 | struct if_rmap * | |
9035efaa | 64 | if_rmap_lookup (const char *ifname) |
718e3744 | 65 | { |
66 | struct if_rmap key; | |
67 | struct if_rmap *if_rmap; | |
68 | ||
9035efaa | 69 | /* temporary copy */ |
3a7c85d1 | 70 | key.ifname = (ifname) ? XSTRDUP (MTYPE_IF_RMAP_NAME, ifname) : NULL; |
718e3744 | 71 | |
72 | if_rmap = hash_lookup (ifrmaphash, &key); | |
73 | ||
3a7c85d1 DS |
74 | if (key.ifname) |
75 | XFREE(MTYPE_IF_RMAP_NAME, key.ifname); | |
76 | ||
718e3744 | 77 | return if_rmap; |
78 | } | |
79 | ||
80 | void | |
81 | if_rmap_hook_add (void (*func) (struct if_rmap *)) | |
82 | { | |
83 | if_rmap_add_hook = func; | |
84 | } | |
85 | ||
86 | void | |
87 | if_rmap_hook_delete (void (*func) (struct if_rmap *)) | |
88 | { | |
89 | if_rmap_delete_hook = func; | |
90 | } | |
91 | ||
8cc4198f | 92 | static void * |
93 | if_rmap_hash_alloc (void *arg) | |
718e3744 | 94 | { |
24873f0c | 95 | struct if_rmap *ifarg = (struct if_rmap *)arg; |
718e3744 | 96 | struct if_rmap *if_rmap; |
97 | ||
98 | if_rmap = if_rmap_new (); | |
0241684e | 99 | if_rmap->ifname = XSTRDUP (MTYPE_IF_RMAP_NAME, ifarg->ifname); |
718e3744 | 100 | |
101 | return if_rmap; | |
102 | } | |
103 | ||
8cc4198f | 104 | static struct if_rmap * |
9035efaa | 105 | if_rmap_get (const char *ifname) |
718e3744 | 106 | { |
107 | struct if_rmap key; | |
24873f0c | 108 | struct if_rmap *ret; |
718e3744 | 109 | |
9035efaa | 110 | /* temporary copy */ |
3a7c85d1 | 111 | key.ifname = (ifname) ? XSTRDUP (MTYPE_IF_RMAP_NAME, ifname) : NULL; |
718e3744 | 112 | |
24873f0c | 113 | ret = hash_get (ifrmaphash, &key, if_rmap_hash_alloc); |
3a7c85d1 | 114 | |
24873f0c DS |
115 | if (key.ifname) |
116 | XFREE(MTYPE_IF_RMAP_NAME, key.ifname); | |
117 | ||
118 | return ret; | |
718e3744 | 119 | } |
120 | ||
8cc4198f | 121 | static unsigned int |
122 | if_rmap_hash_make (void *data) | |
718e3744 | 123 | { |
6392aa83 | 124 | const struct if_rmap *if_rmap = data; |
718e3744 | 125 | |
6392aa83 | 126 | return string_hash_make (if_rmap->ifname); |
718e3744 | 127 | } |
128 | ||
8cc4198f | 129 | static int |
ffe11cfb | 130 | if_rmap_hash_cmp (const void *arg1, const void* arg2) |
718e3744 | 131 | { |
ffe11cfb SH |
132 | const struct if_rmap *if_rmap1 = arg1; |
133 | const struct if_rmap *if_rmap2 = arg2; | |
134 | ||
135 | return strcmp (if_rmap1->ifname, if_rmap2->ifname) == 0; | |
718e3744 | 136 | } |
6b0655a2 | 137 | |
8cc4198f | 138 | static struct if_rmap * |
9035efaa | 139 | if_rmap_set (const char *ifname, enum if_rmap_type type, |
140 | const char *routemap_name) | |
718e3744 | 141 | { |
142 | struct if_rmap *if_rmap; | |
143 | ||
144 | if_rmap = if_rmap_get (ifname); | |
145 | ||
146 | if (type == IF_RMAP_IN) | |
147 | { | |
148 | if (if_rmap->routemap[IF_RMAP_IN]) | |
0241684e | 149 | XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); |
150 | if_rmap->routemap[IF_RMAP_IN] | |
151 | = XSTRDUP (MTYPE_IF_RMAP_NAME, routemap_name); | |
718e3744 | 152 | } |
153 | if (type == IF_RMAP_OUT) | |
154 | { | |
155 | if (if_rmap->routemap[IF_RMAP_OUT]) | |
0241684e | 156 | XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); |
157 | if_rmap->routemap[IF_RMAP_OUT] | |
158 | = XSTRDUP (MTYPE_IF_RMAP_NAME, routemap_name); | |
718e3744 | 159 | } |
160 | ||
161 | if (if_rmap_add_hook) | |
162 | (*if_rmap_add_hook) (if_rmap); | |
163 | ||
164 | return if_rmap; | |
165 | } | |
166 | ||
8cc4198f | 167 | static int |
9035efaa | 168 | if_rmap_unset (const char *ifname, enum if_rmap_type type, |
169 | const char *routemap_name) | |
718e3744 | 170 | { |
171 | struct if_rmap *if_rmap; | |
172 | ||
173 | if_rmap = if_rmap_lookup (ifname); | |
174 | if (!if_rmap) | |
175 | return 0; | |
176 | ||
177 | if (type == IF_RMAP_IN) | |
178 | { | |
179 | if (!if_rmap->routemap[IF_RMAP_IN]) | |
180 | return 0; | |
181 | if (strcmp (if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0) | |
182 | return 0; | |
183 | ||
0241684e | 184 | XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); |
718e3744 | 185 | if_rmap->routemap[IF_RMAP_IN] = NULL; |
186 | } | |
187 | ||
188 | if (type == IF_RMAP_OUT) | |
189 | { | |
190 | if (!if_rmap->routemap[IF_RMAP_OUT]) | |
191 | return 0; | |
192 | if (strcmp (if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0) | |
193 | return 0; | |
194 | ||
0241684e | 195 | XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); |
718e3744 | 196 | if_rmap->routemap[IF_RMAP_OUT] = NULL; |
197 | } | |
198 | ||
199 | if (if_rmap_delete_hook) | |
200 | (*if_rmap_delete_hook) (if_rmap); | |
201 | ||
202 | if (if_rmap->routemap[IF_RMAP_IN] == NULL && | |
203 | if_rmap->routemap[IF_RMAP_OUT] == NULL) | |
204 | { | |
205 | hash_release (ifrmaphash, if_rmap); | |
206 | if_rmap_free (if_rmap); | |
207 | } | |
208 | ||
209 | return 1; | |
210 | } | |
211 | ||
0750d21f | 212 | DEFUN (if_rmap, |
213 | if_rmap_cmd, | |
718e3744 | 214 | "route-map RMAP_NAME (in|out) IFNAME", |
215 | "Route map set\n" | |
216 | "Route map name\n" | |
217 | "Route map set for input filtering\n" | |
218 | "Route map set for output filtering\n" | |
219 | "Route map interface name\n") | |
220 | { | |
221 | enum if_rmap_type type; | |
718e3744 | 222 | |
223 | if (strncmp (argv[1], "i", 1) == 0) | |
224 | type = IF_RMAP_IN; | |
225 | else if (strncmp (argv[1], "o", 1) == 0) | |
226 | type = IF_RMAP_OUT; | |
227 | else | |
228 | { | |
229 | vty_out (vty, "route-map direction must be [in|out]%s", VTY_NEWLINE); | |
230 | return CMD_WARNING; | |
231 | } | |
232 | ||
9206f9ec | 233 | if_rmap_set (argv[2], type, argv[0]); |
718e3744 | 234 | |
235 | return CMD_SUCCESS; | |
4f849479 | 236 | } |
237 | ||
238 | ALIAS (if_rmap, | |
239 | if_ipv6_rmap_cmd, | |
240 | "route-map RMAP_NAME (in|out) IFNAME", | |
241 | "Route map set\n" | |
242 | "Route map name\n" | |
243 | "Route map set for input filtering\n" | |
244 | "Route map set for output filtering\n" | |
245 | "Route map interface name\n") | |
718e3744 | 246 | |
0750d21f | 247 | DEFUN (no_if_rmap, |
248 | no_if_rmap_cmd, | |
718e3744 | 249 | "no route-map ROUTEMAP_NAME (in|out) IFNAME", |
250 | NO_STR | |
251 | "Route map unset\n" | |
252 | "Route map name\n" | |
253 | "Route map for input filtering\n" | |
254 | "Route map for output filtering\n" | |
255 | "Route map interface name\n") | |
256 | { | |
257 | int ret; | |
258 | enum if_rmap_type type; | |
259 | ||
260 | if (strncmp (argv[1], "i", 1) == 0) | |
261 | type = IF_RMAP_IN; | |
262 | else if (strncmp (argv[1], "o", 1) == 0) | |
263 | type = IF_RMAP_OUT; | |
264 | else | |
265 | { | |
266 | vty_out (vty, "route-map direction must be [in|out]%s", VTY_NEWLINE); | |
267 | return CMD_WARNING; | |
268 | } | |
269 | ||
270 | ret = if_rmap_unset (argv[2], type, argv[0]); | |
271 | if (! ret) | |
272 | { | |
273 | vty_out (vty, "route-map doesn't exist%s", VTY_NEWLINE); | |
274 | return CMD_WARNING; | |
275 | } | |
276 | return CMD_SUCCESS; | |
4f849479 | 277 | } |
278 | ||
279 | ALIAS (no_if_rmap, | |
280 | no_if_ipv6_rmap_cmd, | |
281 | "no route-map ROUTEMAP_NAME (in|out) IFNAME", | |
282 | NO_STR | |
283 | "Route map unset\n" | |
284 | "Route map name\n" | |
285 | "Route map for input filtering\n" | |
286 | "Route map for output filtering\n" | |
287 | "Route map interface name\n") | |
6b0655a2 | 288 | |
718e3744 | 289 | /* Configuration write function. */ |
290 | int | |
291 | config_write_if_rmap (struct vty *vty) | |
292 | { | |
8c328f11 | 293 | unsigned int i; |
718e3744 | 294 | struct hash_backet *mp; |
295 | int write = 0; | |
296 | ||
297 | for (i = 0; i < ifrmaphash->size; i++) | |
298 | for (mp = ifrmaphash->index[i]; mp; mp = mp->next) | |
299 | { | |
300 | struct if_rmap *if_rmap; | |
301 | ||
302 | if_rmap = mp->data; | |
303 | ||
304 | if (if_rmap->routemap[IF_RMAP_IN]) | |
305 | { | |
306 | vty_out (vty, " route-map %s in %s%s", | |
307 | if_rmap->routemap[IF_RMAP_IN], | |
308 | if_rmap->ifname, | |
309 | VTY_NEWLINE); | |
310 | write++; | |
311 | } | |
312 | ||
313 | if (if_rmap->routemap[IF_RMAP_OUT]) | |
314 | { | |
315 | vty_out (vty, " route-map %s out %s%s", | |
316 | if_rmap->routemap[IF_RMAP_OUT], | |
317 | if_rmap->ifname, | |
318 | VTY_NEWLINE); | |
319 | write++; | |
320 | } | |
321 | } | |
322 | return write; | |
323 | } | |
324 | ||
325 | void | |
326 | if_rmap_reset () | |
327 | { | |
328 | hash_clean (ifrmaphash, (void (*) (void *)) if_rmap_free); | |
329 | } | |
330 | ||
331 | void | |
0750d21f | 332 | if_rmap_init (int node) |
718e3744 | 333 | { |
334 | ifrmaphash = hash_create (if_rmap_hash_make, if_rmap_hash_cmp); | |
0750d21f | 335 | if (node == RIPNG_NODE) { |
4f849479 | 336 | install_element (RIPNG_NODE, &if_ipv6_rmap_cmd); |
337 | install_element (RIPNG_NODE, &no_if_ipv6_rmap_cmd); | |
338 | } else if (node == RIP_NODE) { | |
339 | install_element (RIP_NODE, &if_rmap_cmd); | |
340 | install_element (RIP_NODE, &no_if_rmap_cmd); | |
0750d21f | 341 | } |
718e3744 | 342 | } |