]> git.proxmox.com Git - mirror_frr.git/blame - lib/if_rmap.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / lib / if_rmap.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/* route-map for interface.
3 * Copyright (C) 1999 Kunihiro Ishiguro
718e3744 4 */
5
6#include <zebra.h>
7
8#include "hash.h"
9#include "command.h"
10#include "memory.h"
11#include "if.h"
0750d21f 12#include "if_rmap.h"
718e3744 13
bf8d3d6a
DL
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");
4a1ab8e4 19
c17faa4b 20static struct list *if_rmap_ctx_list;
6b0655a2 21
d62a17ae 22static struct if_rmap *if_rmap_new(void)
718e3744 23{
d62a17ae 24 struct if_rmap *new;
718e3744 25
d62a17ae 26 new = XCALLOC(MTYPE_IF_RMAP, sizeof(struct if_rmap));
718e3744 27
d62a17ae 28 return new;
718e3744 29}
30
d62a17ae 31static void if_rmap_free(struct if_rmap *if_rmap)
718e3744 32{
0a22ddfb 33 XFREE(MTYPE_IF_RMAP_NAME, if_rmap->ifname);
718e3744 34
0a22ddfb
QY
35 XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
36 XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]);
718e3744 37
d62a17ae 38 XFREE(MTYPE_IF_RMAP, if_rmap);
718e3744 39}
40
4b23867c 41struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx, const char *ifname)
718e3744 42{
d62a17ae 43 struct if_rmap key;
44 struct if_rmap *if_rmap;
718e3744 45
d62a17ae 46 /* temporary copy */
47 key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL;
718e3744 48
4b23867c 49 if_rmap = hash_lookup(ctx->ifrmaphash, &key);
3a7c85d1 50
0a22ddfb 51 XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
d62a17ae 52
53 return if_rmap;
718e3744 54}
55
4b23867c
PG
56void if_rmap_hook_add(struct if_rmap_ctx *ctx,
57 void (*func)(struct if_rmap_ctx *ctx,
58 struct if_rmap *))
718e3744 59{
4b23867c 60 ctx->if_rmap_add_hook = func;
718e3744 61}
62
4b23867c
PG
63void if_rmap_hook_delete(struct if_rmap_ctx *ctx,
64 void (*func)(struct if_rmap_ctx *ctx,
65 struct if_rmap *))
718e3744 66{
4b23867c 67 ctx->if_rmap_delete_hook = func;
718e3744 68}
69
d62a17ae 70static void *if_rmap_hash_alloc(void *arg)
718e3744 71{
d62a17ae 72 struct if_rmap *ifarg = (struct if_rmap *)arg;
73 struct if_rmap *if_rmap;
718e3744 74
d62a17ae 75 if_rmap = if_rmap_new();
76 if_rmap->ifname = XSTRDUP(MTYPE_IF_RMAP_NAME, ifarg->ifname);
718e3744 77
d62a17ae 78 return if_rmap;
718e3744 79}
80
4b23867c 81static struct if_rmap *if_rmap_get(struct if_rmap_ctx *ctx, const char *ifname)
718e3744 82{
d62a17ae 83 struct if_rmap key;
84 struct if_rmap *ret;
718e3744 85
d62a17ae 86 /* temporary copy */
87 key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL;
718e3744 88
4b23867c 89 ret = hash_get(ctx->ifrmaphash, &key, if_rmap_hash_alloc);
3a7c85d1 90
0a22ddfb 91 XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
24873f0c 92
d62a17ae 93 return ret;
718e3744 94}
95
d8b87afe 96static unsigned int if_rmap_hash_make(const void *data)
718e3744 97{
d62a17ae 98 const struct if_rmap *if_rmap = data;
718e3744 99
d62a17ae 100 return string_hash_make(if_rmap->ifname);
718e3744 101}
102
74df8d6d 103static bool if_rmap_hash_cmp(const void *arg1, const void *arg2)
718e3744 104{
d62a17ae 105 const struct if_rmap *if_rmap1 = arg1;
106 const struct if_rmap *if_rmap2 = arg2;
ffe11cfb 107
d62a17ae 108 return strcmp(if_rmap1->ifname, if_rmap2->ifname) == 0;
718e3744 109}
6b0655a2 110
4b23867c
PG
111static struct if_rmap *if_rmap_set(struct if_rmap_ctx *ctx,
112 const char *ifname, enum if_rmap_type type,
d62a17ae 113 const char *routemap_name)
718e3744 114{
d62a17ae 115 struct if_rmap *if_rmap;
116
4b23867c 117 if_rmap = if_rmap_get(ctx, ifname);
d62a17ae 118
119 if (type == IF_RMAP_IN) {
0a22ddfb 120 XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
d62a17ae 121 if_rmap->routemap[IF_RMAP_IN] =
122 XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name);
123 }
124 if (type == IF_RMAP_OUT) {
0a22ddfb 125 XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]);
d62a17ae 126 if_rmap->routemap[IF_RMAP_OUT] =
127 XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name);
128 }
129
4b23867c
PG
130 if (ctx->if_rmap_add_hook)
131 (ctx->if_rmap_add_hook)(ctx, if_rmap);
d62a17ae 132
133 return if_rmap;
718e3744 134}
135
4b23867c
PG
136static int if_rmap_unset(struct if_rmap_ctx *ctx,
137 const char *ifname, enum if_rmap_type type,
d62a17ae 138 const char *routemap_name)
718e3744 139{
d62a17ae 140 struct if_rmap *if_rmap;
141
4b23867c 142 if_rmap = if_rmap_lookup(ctx, ifname);
d62a17ae 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]);
d62a17ae 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]);
d62a17ae 162 }
163
4b23867c
PG
164 if (ctx->if_rmap_delete_hook)
165 ctx->if_rmap_delete_hook(ctx, if_rmap);
d62a17ae 166
167 if (if_rmap->routemap[IF_RMAP_IN] == NULL
168 && if_rmap->routemap[IF_RMAP_OUT] == NULL) {
4b23867c 169 hash_release(ctx->ifrmaphash, if_rmap);
d62a17ae 170 if_rmap_free(if_rmap);
171 }
172
173 return 1;
718e3744 174}
175
0750d21f 176DEFUN (if_rmap,
177 if_rmap_cmd,
6147e2c6 178 "route-map RMAP_NAME <in|out> IFNAME",
718e3744 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{
d62a17ae 185 int idx_rmap_name = 1;
186 int idx_in_out = 2;
187 int idx_ifname = 3;
188 enum if_rmap_type type;
4b23867c
PG
189 struct if_rmap_ctx *ctx =
190 (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list);
d62a17ae 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
4b23867c
PG
201 if_rmap_set(ctx, argv[idx_ifname]->arg,
202 type, argv[idx_rmap_name]->arg);
d62a17ae 203
204 return CMD_SUCCESS;
c349116d 205}
4f849479 206
0750d21f 207DEFUN (no_if_rmap,
208 no_if_rmap_cmd,
6147e2c6 209 "no route-map ROUTEMAP_NAME <in|out> IFNAME",
718e3744 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{
d62a17ae 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;
4b23867c
PG
222 struct if_rmap_ctx *ctx =
223 (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list);
d62a17ae 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
4b23867c 234 ret = if_rmap_unset(ctx, argv[idx_ifname]->arg, type,
d62a17ae 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;
c349116d 241}
4f849479 242
6b0655a2 243
718e3744 244/* Configuration write function. */
4b23867c
PG
245int config_write_if_rmap(struct vty *vty,
246 struct if_rmap_ctx *ctx)
718e3744 247{
d62a17ae 248 unsigned int i;
e3b78da8 249 struct hash_bucket *mp;
d62a17ae 250 int write = 0;
4b23867c 251 struct hash *ifrmaphash = ctx->ifrmaphash;
d62a17ae 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;
718e3744 274}
275
4b23867c
PG
276void if_rmap_ctx_delete(struct if_rmap_ctx *ctx)
277{
cbcbac45 278 listnode_delete(if_rmap_ctx_list, ctx);
4b23867c 279 hash_clean(ctx->ifrmaphash, (void (*)(void *))if_rmap_free);
aec0d756
PG
280 if (ctx->name)
281 XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx);
4b23867c
PG
282 XFREE(MTYPE_IF_RMAP_CTX, ctx);
283}
284
aec0d756
PG
285/* name is optional: either vrf name, or other */
286struct if_rmap_ctx *if_rmap_ctx_create(const char *name)
718e3744 287{
4b23867c
PG
288 struct if_rmap_ctx *ctx;
289
290 ctx = XCALLOC(MTYPE_IF_RMAP_CTX, sizeof(struct if_rmap_ctx));
aec0d756
PG
291
292 if (ctx->name)
293 ctx->name = XSTRDUP(MTYPE_IF_RMAP_CTX_NAME, name);
4b23867c
PG
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;
718e3744 300}
301
d62a17ae 302void if_rmap_init(int node)
718e3744 303{
d62a17ae 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 }
4b23867c
PG
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);
718e3744 317}