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