]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_pbr.c
zebra: handle entry pointfs for ipset creation/destruction
[mirror_frr.git] / zebra / zebra_pbr.c
CommitLineData
942bf97b 1/* Zebra Policy Based Routing (PBR) main handling.
2 * Copyright (C) 2018 Cumulus Networks, Inc.
3 *
4 * This file is part of FRR.
5 *
6 * FRR 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 * FRR 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
17 * along with FRR; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
43fe6a2a
DS
24#include <jhash.h>
25#include <hash.h>
26
942bf97b 27#include "zebra/zebra_pbr.h"
28#include "zebra/rt.h"
29
30/* definitions */
31
32/* static function declarations */
33
34/* Private functions */
35
36/* Public functions */
43fe6a2a 37void zebra_pbr_rules_free(void *arg)
1fbfe5a5 38{
43fe6a2a
DS
39 struct zebra_pbr_rule *rule;
40
41 rule = (struct zebra_pbr_rule *)arg;
42
a0321978 43 kernel_del_pbr_rule(rule);
43fe6a2a
DS
44 XFREE(MTYPE_TMP, rule);
45}
46
47uint32_t zebra_pbr_rules_hash_key(void *arg)
48{
49 struct zebra_pbr_rule *rule;
50 uint32_t key;
51
52 rule = (struct zebra_pbr_rule *)arg;
53 key = jhash_3words(rule->seq, rule->priority, rule->action.table,
54 prefix_hash_key(&rule->filter.src_ip));
a0321978
DS
55 if (rule->ifp)
56 key = jhash_1word(rule->ifp->ifindex, key);
57 else
58 key = jhash_1word(0, key);
59
43fe6a2a 60 return jhash_3words(rule->filter.src_port, rule->filter.dst_port,
b6c5d343
DS
61 prefix_hash_key(&rule->filter.dst_ip),
62 jhash_1word(rule->unique, key));
43fe6a2a
DS
63}
64
65int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
66{
67 const struct zebra_pbr_rule *r1, *r2;
68
69 r1 = (const struct zebra_pbr_rule *)arg1;
70 r2 = (const struct zebra_pbr_rule *)arg2;
71
72 if (r1->seq != r2->seq)
73 return 0;
74
75 if (r1->priority != r2->priority)
76 return 0;
77
b6c5d343
DS
78 if (r1->unique != r2->unique)
79 return 0;
80
43fe6a2a
DS
81 if (r1->action.table != r2->action.table)
82 return 0;
83
84 if (r1->filter.src_port != r2->filter.src_port)
85 return 0;
86
87 if (r1->filter.dst_port != r2->filter.dst_port)
88 return 0;
89
90 if (!prefix_same(&r1->filter.src_ip, &r2->filter.src_ip))
91 return 0;
92
93 if (!prefix_same(&r1->filter.dst_ip, &r2->filter.dst_ip))
94 return 0;
95
a0321978
DS
96 if (r1->ifp != r2->ifp)
97 return 0;
98
43fe6a2a
DS
99 return 1;
100}
101
8c3cd6c6
DS
102struct pbr_unique_lookup {
103 struct zebra_pbr_rule *rule;
104 uint32_t unique;
105};
106
107static int pbr_rule_lookup_unique_walker(struct hash_backet *b, void *data)
108{
109 struct pbr_unique_lookup *pul = data;
110 struct zebra_pbr_rule *rule = b->data;
111
112 if (pul->unique == rule->unique) {
113 pul->rule = rule;
114 return HASHWALK_ABORT;
115 }
116
117 return HASHWALK_CONTINUE;
118}
119
120static struct zebra_pbr_rule *pbr_rule_lookup_unique(struct zebra_ns *zns,
121 uint32_t unique)
122{
123 struct pbr_unique_lookup pul;
124
125 pul.unique = unique;
126 pul.rule = NULL;
127 hash_walk(zns->rules_hash, &pbr_rule_lookup_unique_walker, &pul);
128
129 return pul.rule;
130}
131
7661461a
PG
132void zebra_pbr_ipset_free(void *arg)
133{
134 struct zebra_pbr_ipset *ipset;
135
136 ipset = (struct zebra_pbr_ipset *)arg;
137
138 XFREE(MTYPE_TMP, ipset);
139}
140
141uint32_t zebra_pbr_ipset_hash_key(void *arg)
142{
143 struct zebra_pbr_ipset *ipset = (struct zebra_pbr_ipset *)arg;
144 uint32_t *pnt = (uint32_t *)ipset->ipset_name;
145
146 return jhash2(pnt, ZEBRA_IPSET_NAME_SIZE, 0x63ab42de);
147}
148
149int zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2)
150{
151 const struct zebra_pbr_ipset *r1, *r2;
152
153 r1 = (const struct zebra_pbr_ipset *)arg1;
154 r2 = (const struct zebra_pbr_ipset *)arg2;
155
156 if (r1->type != r2->type)
157 return 0;
158 if (r1->unique != r2->unique)
159 return 0;
160 if (strncmp(r1->ipset_name, r2->ipset_name,
161 ZEBRA_IPSET_NAME_SIZE))
162 return 0;
163 return 1;
164}
165
166void zebra_pbr_ipset_entry_free(void *arg)
167{
168 struct zebra_pbr_ipset_entry *ipset;
169
170 ipset = (struct zebra_pbr_ipset_entry *)arg;
171
172 XFREE(MTYPE_TMP, ipset);
173}
174
175uint32_t zebra_pbr_ipset_entry_hash_key(void *arg)
176{
177 struct zebra_pbr_ipset_entry *ipset;
178 uint32_t key;
179
180 ipset = (struct zebra_pbr_ipset_entry *)arg;
181 key = prefix_hash_key(&ipset->src);
182 key = jhash_1word(ipset->unique, key);
183 key = jhash_1word(prefix_hash_key(&ipset->dst), key);
184
185 return key;
186}
187
188int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2)
189{
190 const struct zebra_pbr_ipset_entry *r1, *r2;
191
192 r1 = (const struct zebra_pbr_ipset_entry *)arg1;
193 r2 = (const struct zebra_pbr_ipset_entry *)arg2;
194
195 if (r1->unique != r2->unique)
196 return 0;
197
198 if (!prefix_same(&r1->src, &r2->src))
199 return 0;
200
201 if (!prefix_same(&r1->dst, &r2->dst))
202 return 0;
203
204 return 1;
205}
206
43fe6a2a
DS
207static void *pbr_rule_alloc_intern(void *arg)
208{
209 struct zebra_pbr_rule *zpr;
210 struct zebra_pbr_rule *new;
211
212 zpr = (struct zebra_pbr_rule *)arg;
213
214 new = XCALLOC(MTYPE_TMP, sizeof(*new));
215
216 memcpy(new, zpr, sizeof(*zpr));
217
218 return new;
219}
220
a0321978 221void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule)
43fe6a2a 222{
8c3cd6c6
DS
223 struct zebra_pbr_rule *unique =
224 pbr_rule_lookup_unique(zns, rule->unique);
225
43fe6a2a 226 (void)hash_get(zns->rules_hash, rule, pbr_rule_alloc_intern);
a0321978 227 kernel_add_pbr_rule(rule);
8c3cd6c6
DS
228
229 /*
230 * Rule Replace semantics, if we have an old, install the
231 * new rule, look above, and then delete the old
232 */
233 if (unique)
234 zebra_pbr_del_rule(zns, unique);
1fbfe5a5
DS
235}
236
a0321978 237void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule)
1fbfe5a5 238{
43fe6a2a
DS
239 struct zebra_pbr_rule *lookup;
240
241 lookup = hash_lookup(zns->rules_hash, rule);
a0321978 242 kernel_del_pbr_rule(rule);
43fe6a2a 243
d5c52f76
DS
244 if (lookup) {
245 hash_release(zns->rules_hash, lookup);
43fe6a2a 246 XFREE(MTYPE_TMP, lookup);
d5c52f76 247 } else
43fe6a2a
DS
248 zlog_warn("%s: Rule being deleted we know nothing about",
249 __PRETTY_FUNCTION__);
1fbfe5a5
DS
250}
251
e69aa084
DS
252static void zebra_pbr_cleanup_rules(struct hash_backet *b, void *data)
253{
254 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
255 struct zebra_pbr_rule *rule = b->data;
256 int *sock = data;
257
258 if (rule->sock == *sock) {
259 kernel_del_pbr_rule(rule);
260 hash_release(zns->rules_hash, rule);
d5c52f76 261 XFREE(MTYPE_TMP, rule);
e69aa084
DS
262 }
263}
264
265void zebra_pbr_client_close_cleanup(int sock)
266{
267 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
268
269 hash_iterate(zns->rules_hash, zebra_pbr_cleanup_rules, &sock);
270}
271
7661461a
PG
272static void *pbr_ipset_alloc_intern(void *arg)
273{
274 struct zebra_pbr_ipset *zpi;
275 struct zebra_pbr_ipset *new;
276
277 zpi = (struct zebra_pbr_ipset *)arg;
278
279 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset));
280
281 memcpy(new, zpi, sizeof(*zpi));
282
283 return new;
284}
285
286void zebra_pbr_create_ipset(struct zebra_ns *zns,
287 struct zebra_pbr_ipset *ipset)
288{
289 (void)hash_get(zns->ipset_hash, ipset, pbr_ipset_alloc_intern);
290 /* TODO:
291 * - Netlink call
292 */
293}
294
295void zebra_pbr_destroy_ipset(struct zebra_ns *zns,
296 struct zebra_pbr_ipset *ipset)
297{
298 struct zebra_pbr_ipset *lookup;
299
300 lookup = hash_lookup(zns->ipset_hash, ipset);
301 /* TODO:
302 * - Netlink destroy from kernel
303 * - ?? destroy ipset entries before
304 */
305 if (lookup)
306 XFREE(MTYPE_TMP, lookup);
307 else
308 zlog_warn("%s: IPSet being deleted we know nothing about",
309 __PRETTY_FUNCTION__);
310}
311
312static void *pbr_ipset_entry_alloc_intern(void *arg)
313{
314 struct zebra_pbr_ipset_entry *zpi;
315 struct zebra_pbr_ipset_entry *new;
316
317 zpi = (struct zebra_pbr_ipset_entry *)arg;
318
319 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset_entry));
320
321 memcpy(new, zpi, sizeof(*zpi));
322
323 return new;
324}
325
326void zebra_pbr_add_ipset_entry(struct zebra_ns *zns,
327 struct zebra_pbr_ipset_entry *ipset)
328{
329 (void)hash_get(zns->ipset_entry_hash, ipset,
330 pbr_ipset_entry_alloc_intern);
331 /* TODO:
332 * - attach to ipset list
333 * - Netlink add to kernel
334 */
335}
336
337void zebra_pbr_del_ipset_entry(struct zebra_ns *zns,
338 struct zebra_pbr_ipset_entry *ipset)
339{
340 struct zebra_pbr_ipset_entry *lookup;
341
342 lookup = hash_lookup(zns->ipset_hash, ipset);
343 /* TODO:
344 * - Netlink destroy
345 * - detach from ipset list
346 * - ?? if no more entres, delete ipset
347 */
348 if (lookup)
349 XFREE(MTYPE_TMP, lookup);
350 else
351 zlog_warn("%s: IPSet being deleted we know nothing about",
352 __PRETTY_FUNCTION__);
353}
354
942bf97b 355/*
356 * Handle success or failure of rule (un)install in the kernel.
357 */
358void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule,
942bf97b 359 enum southbound_results res)
360{
b6c5d343
DS
361 switch (res) {
362 case SOUTHBOUND_INSTALL_SUCCESS:
363 zsend_rule_notify_owner(rule, ZAPI_RULE_INSTALLED);
364 break;
365 case SOUTHBOUND_INSTALL_FAILURE:
366 zsend_rule_notify_owner(rule, ZAPI_RULE_FAIL_INSTALL);
367 break;
368 case SOUTHBOUND_DELETE_SUCCESS:
369 break;
370 case SOUTHBOUND_DELETE_FAILURE:
371 break;
372 }
942bf97b 373}
374
375/*
376 * Handle rule delete notification from kernel.
377 */
a0321978 378int kernel_pbr_rule_del(struct zebra_pbr_rule *rule)
942bf97b 379{
380 return 0;
381}