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