]>
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 | * | |
896014f4 DL |
16 | * You should have received a copy of the GNU General Public License along |
17 | * with this program; see the file COPYING; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
718e3744 | 19 | */ |
20 | ||
21 | #include <zebra.h> | |
22 | ||
23 | #include "hash.h" | |
24 | #include "command.h" | |
25 | #include "memory.h" | |
26 | #include "if.h" | |
0750d21f | 27 | #include "if_rmap.h" |
718e3744 | 28 | |
d62a17ae | 29 | DEFINE_MTYPE_STATIC(LIB, IF_RMAP, "Interface route map") |
4a1ab8e4 DL |
30 | DEFINE_MTYPE_STATIC(LIB, IF_RMAP_NAME, "I.f. route map name") |
31 | ||
718e3744 | 32 | struct hash *ifrmaphash; |
33 | ||
34 | /* Hook functions. */ | |
d62a17ae | 35 | static void (*if_rmap_add_hook)(struct if_rmap *) = NULL; |
36 | static void (*if_rmap_delete_hook)(struct if_rmap *) = NULL; | |
6b0655a2 | 37 | |
d62a17ae | 38 | static struct if_rmap *if_rmap_new(void) |
718e3744 | 39 | { |
d62a17ae | 40 | struct if_rmap *new; |
718e3744 | 41 | |
d62a17ae | 42 | new = XCALLOC(MTYPE_IF_RMAP, sizeof(struct if_rmap)); |
718e3744 | 43 | |
d62a17ae | 44 | return new; |
718e3744 | 45 | } |
46 | ||
d62a17ae | 47 | static void if_rmap_free(struct if_rmap *if_rmap) |
718e3744 | 48 | { |
d62a17ae | 49 | if (if_rmap->ifname) |
50 | XFREE(MTYPE_IF_RMAP_NAME, if_rmap->ifname); | |
718e3744 | 51 | |
d62a17ae | 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]); | |
718e3744 | 56 | |
d62a17ae | 57 | XFREE(MTYPE_IF_RMAP, if_rmap); |
718e3744 | 58 | } |
59 | ||
d62a17ae | 60 | struct if_rmap *if_rmap_lookup(const char *ifname) |
718e3744 | 61 | { |
d62a17ae | 62 | struct if_rmap key; |
63 | struct if_rmap *if_rmap; | |
718e3744 | 64 | |
d62a17ae | 65 | /* temporary copy */ |
66 | key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; | |
718e3744 | 67 | |
d62a17ae | 68 | if_rmap = hash_lookup(ifrmaphash, &key); |
3a7c85d1 | 69 | |
d62a17ae | 70 | if (key.ifname) |
71 | XFREE(MTYPE_IF_RMAP_NAME, key.ifname); | |
72 | ||
73 | return if_rmap; | |
718e3744 | 74 | } |
75 | ||
d62a17ae | 76 | void if_rmap_hook_add(void (*func)(struct if_rmap *)) |
718e3744 | 77 | { |
d62a17ae | 78 | if_rmap_add_hook = func; |
718e3744 | 79 | } |
80 | ||
d62a17ae | 81 | void if_rmap_hook_delete(void (*func)(struct if_rmap *)) |
718e3744 | 82 | { |
d62a17ae | 83 | if_rmap_delete_hook = func; |
718e3744 | 84 | } |
85 | ||
d62a17ae | 86 | static void *if_rmap_hash_alloc(void *arg) |
718e3744 | 87 | { |
d62a17ae | 88 | struct if_rmap *ifarg = (struct if_rmap *)arg; |
89 | struct if_rmap *if_rmap; | |
718e3744 | 90 | |
d62a17ae | 91 | if_rmap = if_rmap_new(); |
92 | if_rmap->ifname = XSTRDUP(MTYPE_IF_RMAP_NAME, ifarg->ifname); | |
718e3744 | 93 | |
d62a17ae | 94 | return if_rmap; |
718e3744 | 95 | } |
96 | ||
d62a17ae | 97 | static struct if_rmap *if_rmap_get(const char *ifname) |
718e3744 | 98 | { |
d62a17ae | 99 | struct if_rmap key; |
100 | struct if_rmap *ret; | |
718e3744 | 101 | |
d62a17ae | 102 | /* temporary copy */ |
103 | key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; | |
718e3744 | 104 | |
d62a17ae | 105 | ret = hash_get(ifrmaphash, &key, if_rmap_hash_alloc); |
3a7c85d1 | 106 | |
d62a17ae | 107 | if (key.ifname) |
108 | XFREE(MTYPE_IF_RMAP_NAME, key.ifname); | |
24873f0c | 109 | |
d62a17ae | 110 | return ret; |
718e3744 | 111 | } |
112 | ||
d62a17ae | 113 | static unsigned int if_rmap_hash_make(void *data) |
718e3744 | 114 | { |
d62a17ae | 115 | const struct if_rmap *if_rmap = data; |
718e3744 | 116 | |
d62a17ae | 117 | return string_hash_make(if_rmap->ifname); |
718e3744 | 118 | } |
119 | ||
d62a17ae | 120 | static int if_rmap_hash_cmp(const void *arg1, const void *arg2) |
718e3744 | 121 | { |
d62a17ae | 122 | const struct if_rmap *if_rmap1 = arg1; |
123 | const struct if_rmap *if_rmap2 = arg2; | |
ffe11cfb | 124 | |
d62a17ae | 125 | return strcmp(if_rmap1->ifname, if_rmap2->ifname) == 0; |
718e3744 | 126 | } |
6b0655a2 | 127 | |
d62a17ae | 128 | static struct if_rmap *if_rmap_set(const char *ifname, enum if_rmap_type type, |
129 | const char *routemap_name) | |
718e3744 | 130 | { |
d62a17ae | 131 | struct if_rmap *if_rmap; |
132 | ||
133 | if_rmap = if_rmap_get(ifname); | |
134 | ||
135 | if (type == IF_RMAP_IN) { | |
136 | if (if_rmap->routemap[IF_RMAP_IN]) | |
137 | XFREE(MTYPE_IF_RMAP_NAME, | |
138 | if_rmap->routemap[IF_RMAP_IN]); | |
139 | if_rmap->routemap[IF_RMAP_IN] = | |
140 | XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); | |
141 | } | |
142 | if (type == IF_RMAP_OUT) { | |
143 | if (if_rmap->routemap[IF_RMAP_OUT]) | |
144 | XFREE(MTYPE_IF_RMAP_NAME, | |
145 | if_rmap->routemap[IF_RMAP_OUT]); | |
146 | if_rmap->routemap[IF_RMAP_OUT] = | |
147 | XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); | |
148 | } | |
149 | ||
150 | if (if_rmap_add_hook) | |
151 | (*if_rmap_add_hook)(if_rmap); | |
152 | ||
153 | return if_rmap; | |
718e3744 | 154 | } |
155 | ||
d62a17ae | 156 | static int if_rmap_unset(const char *ifname, enum if_rmap_type type, |
157 | const char *routemap_name) | |
718e3744 | 158 | { |
d62a17ae | 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 | if (!if_rmap->routemap[IF_RMAP_IN]) | |
167 | return 0; | |
168 | if (strcmp(if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0) | |
169 | return 0; | |
170 | ||
171 | XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); | |
172 | if_rmap->routemap[IF_RMAP_IN] = NULL; | |
173 | } | |
174 | ||
175 | if (type == IF_RMAP_OUT) { | |
176 | if (!if_rmap->routemap[IF_RMAP_OUT]) | |
177 | return 0; | |
178 | if (strcmp(if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0) | |
179 | return 0; | |
180 | ||
181 | XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); | |
182 | if_rmap->routemap[IF_RMAP_OUT] = NULL; | |
183 | } | |
184 | ||
185 | if (if_rmap_delete_hook) | |
186 | (*if_rmap_delete_hook)(if_rmap); | |
187 | ||
188 | if (if_rmap->routemap[IF_RMAP_IN] == NULL | |
189 | && if_rmap->routemap[IF_RMAP_OUT] == NULL) { | |
190 | hash_release(ifrmaphash, if_rmap); | |
191 | if_rmap_free(if_rmap); | |
192 | } | |
193 | ||
194 | return 1; | |
718e3744 | 195 | } |
196 | ||
0750d21f | 197 | DEFUN (if_rmap, |
198 | if_rmap_cmd, | |
6147e2c6 | 199 | "route-map RMAP_NAME <in|out> IFNAME", |
718e3744 | 200 | "Route map set\n" |
201 | "Route map name\n" | |
202 | "Route map set for input filtering\n" | |
203 | "Route map set for output filtering\n" | |
204 | "Route map interface name\n") | |
205 | { | |
d62a17ae | 206 | int idx_rmap_name = 1; |
207 | int idx_in_out = 2; | |
208 | int idx_ifname = 3; | |
209 | enum if_rmap_type type; | |
210 | ||
211 | if (strncmp(argv[idx_in_out]->text, "in", 1) == 0) | |
212 | type = IF_RMAP_IN; | |
213 | else if (strncmp(argv[idx_in_out]->text, "out", 1) == 0) | |
214 | type = IF_RMAP_OUT; | |
215 | else { | |
216 | vty_out(vty, "route-map direction must be [in|out]\n"); | |
217 | return CMD_WARNING_CONFIG_FAILED; | |
218 | } | |
219 | ||
220 | if_rmap_set(argv[idx_ifname]->arg, type, argv[idx_rmap_name]->arg); | |
221 | ||
222 | return CMD_SUCCESS; | |
c349116d | 223 | } |
4f849479 | 224 | |
0750d21f | 225 | DEFUN (no_if_rmap, |
226 | no_if_rmap_cmd, | |
6147e2c6 | 227 | "no route-map ROUTEMAP_NAME <in|out> IFNAME", |
718e3744 | 228 | NO_STR |
229 | "Route map unset\n" | |
230 | "Route map name\n" | |
231 | "Route map for input filtering\n" | |
232 | "Route map for output filtering\n" | |
233 | "Route map interface name\n") | |
234 | { | |
d62a17ae | 235 | int idx_routemap_name = 2; |
236 | int idx_in_out = 3; | |
237 | int idx_ifname = 4; | |
238 | int ret; | |
239 | enum if_rmap_type type; | |
240 | ||
241 | if (strncmp(argv[idx_in_out]->arg, "i", 1) == 0) | |
242 | type = IF_RMAP_IN; | |
243 | else if (strncmp(argv[idx_in_out]->arg, "o", 1) == 0) | |
244 | type = IF_RMAP_OUT; | |
245 | else { | |
246 | vty_out(vty, "route-map direction must be [in|out]\n"); | |
247 | return CMD_WARNING_CONFIG_FAILED; | |
248 | } | |
249 | ||
250 | ret = if_rmap_unset(argv[idx_ifname]->arg, type, | |
251 | argv[idx_routemap_name]->arg); | |
252 | if (!ret) { | |
253 | vty_out(vty, "route-map doesn't exist\n"); | |
254 | return CMD_WARNING_CONFIG_FAILED; | |
255 | } | |
256 | return CMD_SUCCESS; | |
c349116d | 257 | } |
4f849479 | 258 | |
6b0655a2 | 259 | |
718e3744 | 260 | /* Configuration write function. */ |
d62a17ae | 261 | int config_write_if_rmap(struct vty *vty) |
718e3744 | 262 | { |
d62a17ae | 263 | unsigned int i; |
264 | struct hash_backet *mp; | |
265 | int write = 0; | |
266 | ||
267 | for (i = 0; i < ifrmaphash->size; i++) | |
268 | for (mp = ifrmaphash->index[i]; mp; mp = mp->next) { | |
269 | struct if_rmap *if_rmap; | |
270 | ||
271 | if_rmap = mp->data; | |
272 | ||
273 | if (if_rmap->routemap[IF_RMAP_IN]) { | |
274 | vty_out(vty, " route-map %s in %s\n", | |
275 | if_rmap->routemap[IF_RMAP_IN], | |
276 | if_rmap->ifname); | |
277 | write++; | |
278 | } | |
279 | ||
280 | if (if_rmap->routemap[IF_RMAP_OUT]) { | |
281 | vty_out(vty, " route-map %s out %s\n", | |
282 | if_rmap->routemap[IF_RMAP_OUT], | |
283 | if_rmap->ifname); | |
284 | write++; | |
285 | } | |
286 | } | |
287 | return write; | |
718e3744 | 288 | } |
289 | ||
d62a17ae | 290 | void if_rmap_reset() |
718e3744 | 291 | { |
d62a17ae | 292 | hash_clean(ifrmaphash, (void (*)(void *))if_rmap_free); |
718e3744 | 293 | } |
294 | ||
d62a17ae | 295 | void if_rmap_init(int node) |
718e3744 | 296 | { |
996c9314 | 297 | ifrmaphash = hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp, |
bd74dc61 | 298 | "Interface Route-Map Hash"); |
d62a17ae | 299 | if (node == RIPNG_NODE) { |
300 | } else if (node == RIP_NODE) { | |
301 | install_element(RIP_NODE, &if_rmap_cmd); | |
302 | install_element(RIP_NODE, &no_if_rmap_cmd); | |
303 | } | |
718e3744 | 304 | } |