]>
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 | |
4b23867c | 29 | DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX, "Interface route map container") |
aec0d756 | 30 | DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX_NAME, "Interface route map container name") |
d62a17ae | 31 | DEFINE_MTYPE_STATIC(LIB, IF_RMAP, "Interface route map") |
4a1ab8e4 DL |
32 | DEFINE_MTYPE_STATIC(LIB, IF_RMAP_NAME, "I.f. route map name") |
33 | ||
c17faa4b | 34 | static struct list *if_rmap_ctx_list; |
6b0655a2 | 35 | |
d62a17ae | 36 | static struct if_rmap *if_rmap_new(void) |
718e3744 | 37 | { |
d62a17ae | 38 | struct if_rmap *new; |
718e3744 | 39 | |
d62a17ae | 40 | new = XCALLOC(MTYPE_IF_RMAP, sizeof(struct if_rmap)); |
718e3744 | 41 | |
d62a17ae | 42 | return new; |
718e3744 | 43 | } |
44 | ||
d62a17ae | 45 | static void if_rmap_free(struct if_rmap *if_rmap) |
718e3744 | 46 | { |
0a22ddfb | 47 | XFREE(MTYPE_IF_RMAP_NAME, if_rmap->ifname); |
718e3744 | 48 | |
0a22ddfb QY |
49 | XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); |
50 | XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); | |
718e3744 | 51 | |
d62a17ae | 52 | XFREE(MTYPE_IF_RMAP, if_rmap); |
718e3744 | 53 | } |
54 | ||
4b23867c | 55 | struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx, const char *ifname) |
718e3744 | 56 | { |
d62a17ae | 57 | struct if_rmap key; |
58 | struct if_rmap *if_rmap; | |
718e3744 | 59 | |
d62a17ae | 60 | /* temporary copy */ |
61 | key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; | |
718e3744 | 62 | |
4b23867c | 63 | if_rmap = hash_lookup(ctx->ifrmaphash, &key); |
3a7c85d1 | 64 | |
0a22ddfb | 65 | XFREE(MTYPE_IF_RMAP_NAME, key.ifname); |
d62a17ae | 66 | |
67 | return if_rmap; | |
718e3744 | 68 | } |
69 | ||
4b23867c PG |
70 | void if_rmap_hook_add(struct if_rmap_ctx *ctx, |
71 | void (*func)(struct if_rmap_ctx *ctx, | |
72 | struct if_rmap *)) | |
718e3744 | 73 | { |
4b23867c | 74 | ctx->if_rmap_add_hook = func; |
718e3744 | 75 | } |
76 | ||
4b23867c PG |
77 | void if_rmap_hook_delete(struct if_rmap_ctx *ctx, |
78 | void (*func)(struct if_rmap_ctx *ctx, | |
79 | struct if_rmap *)) | |
718e3744 | 80 | { |
4b23867c | 81 | ctx->if_rmap_delete_hook = func; |
718e3744 | 82 | } |
83 | ||
d62a17ae | 84 | static void *if_rmap_hash_alloc(void *arg) |
718e3744 | 85 | { |
d62a17ae | 86 | struct if_rmap *ifarg = (struct if_rmap *)arg; |
87 | struct if_rmap *if_rmap; | |
718e3744 | 88 | |
d62a17ae | 89 | if_rmap = if_rmap_new(); |
90 | if_rmap->ifname = XSTRDUP(MTYPE_IF_RMAP_NAME, ifarg->ifname); | |
718e3744 | 91 | |
d62a17ae | 92 | return if_rmap; |
718e3744 | 93 | } |
94 | ||
4b23867c | 95 | static struct if_rmap *if_rmap_get(struct if_rmap_ctx *ctx, const char *ifname) |
718e3744 | 96 | { |
d62a17ae | 97 | struct if_rmap key; |
98 | struct if_rmap *ret; | |
718e3744 | 99 | |
d62a17ae | 100 | /* temporary copy */ |
101 | key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; | |
718e3744 | 102 | |
4b23867c | 103 | ret = hash_get(ctx->ifrmaphash, &key, if_rmap_hash_alloc); |
3a7c85d1 | 104 | |
0a22ddfb | 105 | XFREE(MTYPE_IF_RMAP_NAME, key.ifname); |
24873f0c | 106 | |
d62a17ae | 107 | return ret; |
718e3744 | 108 | } |
109 | ||
d8b87afe | 110 | static unsigned int if_rmap_hash_make(const void *data) |
718e3744 | 111 | { |
d62a17ae | 112 | const struct if_rmap *if_rmap = data; |
718e3744 | 113 | |
d62a17ae | 114 | return string_hash_make(if_rmap->ifname); |
718e3744 | 115 | } |
116 | ||
74df8d6d | 117 | static bool if_rmap_hash_cmp(const void *arg1, const void *arg2) |
718e3744 | 118 | { |
d62a17ae | 119 | const struct if_rmap *if_rmap1 = arg1; |
120 | const struct if_rmap *if_rmap2 = arg2; | |
ffe11cfb | 121 | |
d62a17ae | 122 | return strcmp(if_rmap1->ifname, if_rmap2->ifname) == 0; |
718e3744 | 123 | } |
6b0655a2 | 124 | |
4b23867c PG |
125 | static struct if_rmap *if_rmap_set(struct if_rmap_ctx *ctx, |
126 | const char *ifname, enum if_rmap_type type, | |
d62a17ae | 127 | const char *routemap_name) |
718e3744 | 128 | { |
d62a17ae | 129 | struct if_rmap *if_rmap; |
130 | ||
4b23867c | 131 | if_rmap = if_rmap_get(ctx, ifname); |
d62a17ae | 132 | |
133 | if (type == IF_RMAP_IN) { | |
0a22ddfb | 134 | XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); |
d62a17ae | 135 | if_rmap->routemap[IF_RMAP_IN] = |
136 | XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); | |
137 | } | |
138 | if (type == IF_RMAP_OUT) { | |
0a22ddfb | 139 | XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); |
d62a17ae | 140 | if_rmap->routemap[IF_RMAP_OUT] = |
141 | XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); | |
142 | } | |
143 | ||
4b23867c PG |
144 | if (ctx->if_rmap_add_hook) |
145 | (ctx->if_rmap_add_hook)(ctx, if_rmap); | |
d62a17ae | 146 | |
147 | return if_rmap; | |
718e3744 | 148 | } |
149 | ||
4b23867c PG |
150 | static int if_rmap_unset(struct if_rmap_ctx *ctx, |
151 | const char *ifname, enum if_rmap_type type, | |
d62a17ae | 152 | const char *routemap_name) |
718e3744 | 153 | { |
d62a17ae | 154 | struct if_rmap *if_rmap; |
155 | ||
4b23867c | 156 | if_rmap = if_rmap_lookup(ctx, ifname); |
d62a17ae | 157 | if (!if_rmap) |
158 | return 0; | |
159 | ||
160 | if (type == IF_RMAP_IN) { | |
161 | if (!if_rmap->routemap[IF_RMAP_IN]) | |
162 | return 0; | |
163 | if (strcmp(if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0) | |
164 | return 0; | |
165 | ||
166 | XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); | |
167 | if_rmap->routemap[IF_RMAP_IN] = NULL; | |
168 | } | |
169 | ||
170 | if (type == IF_RMAP_OUT) { | |
171 | if (!if_rmap->routemap[IF_RMAP_OUT]) | |
172 | return 0; | |
173 | if (strcmp(if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0) | |
174 | return 0; | |
175 | ||
176 | XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); | |
177 | if_rmap->routemap[IF_RMAP_OUT] = NULL; | |
178 | } | |
179 | ||
4b23867c PG |
180 | if (ctx->if_rmap_delete_hook) |
181 | ctx->if_rmap_delete_hook(ctx, if_rmap); | |
d62a17ae | 182 | |
183 | if (if_rmap->routemap[IF_RMAP_IN] == NULL | |
184 | && if_rmap->routemap[IF_RMAP_OUT] == NULL) { | |
4b23867c | 185 | hash_release(ctx->ifrmaphash, if_rmap); |
d62a17ae | 186 | if_rmap_free(if_rmap); |
187 | } | |
188 | ||
189 | return 1; | |
718e3744 | 190 | } |
191 | ||
0750d21f | 192 | DEFUN (if_rmap, |
193 | if_rmap_cmd, | |
6147e2c6 | 194 | "route-map RMAP_NAME <in|out> IFNAME", |
718e3744 | 195 | "Route map set\n" |
196 | "Route map name\n" | |
197 | "Route map set for input filtering\n" | |
198 | "Route map set for output filtering\n" | |
199 | "Route map interface name\n") | |
200 | { | |
d62a17ae | 201 | int idx_rmap_name = 1; |
202 | int idx_in_out = 2; | |
203 | int idx_ifname = 3; | |
204 | enum if_rmap_type type; | |
4b23867c PG |
205 | struct if_rmap_ctx *ctx = |
206 | (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list); | |
d62a17ae | 207 | |
208 | if (strncmp(argv[idx_in_out]->text, "in", 1) == 0) | |
209 | type = IF_RMAP_IN; | |
210 | else if (strncmp(argv[idx_in_out]->text, "out", 1) == 0) | |
211 | type = IF_RMAP_OUT; | |
212 | else { | |
213 | vty_out(vty, "route-map direction must be [in|out]\n"); | |
214 | return CMD_WARNING_CONFIG_FAILED; | |
215 | } | |
216 | ||
4b23867c PG |
217 | if_rmap_set(ctx, argv[idx_ifname]->arg, |
218 | type, argv[idx_rmap_name]->arg); | |
d62a17ae | 219 | |
220 | return CMD_SUCCESS; | |
c349116d | 221 | } |
4f849479 | 222 | |
0750d21f | 223 | DEFUN (no_if_rmap, |
224 | no_if_rmap_cmd, | |
6147e2c6 | 225 | "no route-map ROUTEMAP_NAME <in|out> IFNAME", |
718e3744 | 226 | NO_STR |
227 | "Route map unset\n" | |
228 | "Route map name\n" | |
229 | "Route map for input filtering\n" | |
230 | "Route map for output filtering\n" | |
231 | "Route map interface name\n") | |
232 | { | |
d62a17ae | 233 | int idx_routemap_name = 2; |
234 | int idx_in_out = 3; | |
235 | int idx_ifname = 4; | |
236 | int ret; | |
237 | enum if_rmap_type type; | |
4b23867c PG |
238 | struct if_rmap_ctx *ctx = |
239 | (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list); | |
d62a17ae | 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 | ||
4b23867c | 250 | ret = if_rmap_unset(ctx, argv[idx_ifname]->arg, type, |
d62a17ae | 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. */ |
4b23867c PG |
261 | int config_write_if_rmap(struct vty *vty, |
262 | struct if_rmap_ctx *ctx) | |
718e3744 | 263 | { |
d62a17ae | 264 | unsigned int i; |
e3b78da8 | 265 | struct hash_bucket *mp; |
d62a17ae | 266 | int write = 0; |
4b23867c | 267 | struct hash *ifrmaphash = ctx->ifrmaphash; |
d62a17ae | 268 | |
269 | for (i = 0; i < ifrmaphash->size; i++) | |
270 | for (mp = ifrmaphash->index[i]; mp; mp = mp->next) { | |
271 | struct if_rmap *if_rmap; | |
272 | ||
273 | if_rmap = mp->data; | |
274 | ||
275 | if (if_rmap->routemap[IF_RMAP_IN]) { | |
276 | vty_out(vty, " route-map %s in %s\n", | |
277 | if_rmap->routemap[IF_RMAP_IN], | |
278 | if_rmap->ifname); | |
279 | write++; | |
280 | } | |
281 | ||
282 | if (if_rmap->routemap[IF_RMAP_OUT]) { | |
283 | vty_out(vty, " route-map %s out %s\n", | |
284 | if_rmap->routemap[IF_RMAP_OUT], | |
285 | if_rmap->ifname); | |
286 | write++; | |
287 | } | |
288 | } | |
289 | return write; | |
718e3744 | 290 | } |
291 | ||
4b23867c PG |
292 | void if_rmap_ctx_delete(struct if_rmap_ctx *ctx) |
293 | { | |
cbcbac45 | 294 | listnode_delete(if_rmap_ctx_list, ctx); |
4b23867c | 295 | hash_clean(ctx->ifrmaphash, (void (*)(void *))if_rmap_free); |
aec0d756 PG |
296 | if (ctx->name) |
297 | XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx); | |
4b23867c PG |
298 | XFREE(MTYPE_IF_RMAP_CTX, ctx); |
299 | } | |
300 | ||
aec0d756 PG |
301 | /* name is optional: either vrf name, or other */ |
302 | struct if_rmap_ctx *if_rmap_ctx_create(const char *name) | |
718e3744 | 303 | { |
4b23867c PG |
304 | struct if_rmap_ctx *ctx; |
305 | ||
306 | ctx = XCALLOC(MTYPE_IF_RMAP_CTX, sizeof(struct if_rmap_ctx)); | |
aec0d756 PG |
307 | |
308 | if (ctx->name) | |
309 | ctx->name = XSTRDUP(MTYPE_IF_RMAP_CTX_NAME, name); | |
4b23867c PG |
310 | ctx->ifrmaphash = hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp, |
311 | "Interface Route-Map Hash"); | |
312 | if (!if_rmap_ctx_list) | |
313 | if_rmap_ctx_list = list_new(); | |
314 | listnode_add(if_rmap_ctx_list, ctx); | |
315 | return ctx; | |
718e3744 | 316 | } |
317 | ||
d62a17ae | 318 | void if_rmap_init(int node) |
718e3744 | 319 | { |
d62a17ae | 320 | if (node == RIPNG_NODE) { |
321 | } else if (node == RIP_NODE) { | |
322 | install_element(RIP_NODE, &if_rmap_cmd); | |
323 | install_element(RIP_NODE, &no_if_rmap_cmd); | |
324 | } | |
4b23867c PG |
325 | if_rmap_ctx_list = list_new(); |
326 | } | |
327 | ||
328 | void if_rmap_terminate(void) | |
329 | { | |
330 | if (!if_rmap_ctx_list) | |
331 | return; | |
332 | list_delete(&if_rmap_ctx_list); | |
718e3744 | 333 | } |