]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_pbr.c
93c523bf5026300b22d83039492bc9e90ce4bdde
[mirror_frr.git] / zebra / zebra_pbr.c
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
24 #include <jhash.h>
25 #include <hash.h>
26
27 #include "zebra/zebra_pbr.h"
28 #include "zebra/rt.h"
29 #include "zebra/zapi_msg.h"
30
31 /* definitions */
32
33 /* static function declarations */
34
35 /* Private functions */
36
37 /* Public functions */
38 void zebra_pbr_rules_free(void *arg)
39 {
40 struct zebra_pbr_rule *rule;
41
42 rule = (struct zebra_pbr_rule *)arg;
43
44 kernel_del_pbr_rule(rule);
45 XFREE(MTYPE_TMP, rule);
46 }
47
48 uint32_t zebra_pbr_rules_hash_key(void *arg)
49 {
50 struct zebra_pbr_rule *rule;
51 uint32_t key;
52
53 rule = (struct zebra_pbr_rule *)arg;
54 key = jhash_3words(rule->rule.seq, rule->rule.priority,
55 rule->rule.action.table,
56 prefix_hash_key(&rule->rule.filter.src_ip));
57 if (rule->ifp)
58 key = jhash_1word(rule->ifp->ifindex, key);
59 else
60 key = jhash_1word(0, key);
61
62 if (rule->rule.filter.fwmark)
63 key = jhash_1word(rule->rule.filter.fwmark, key);
64 else
65 key = jhash_1word(0, key);
66 return jhash_3words(rule->rule.filter.src_port,
67 rule->rule.filter.dst_port,
68 prefix_hash_key(&rule->rule.filter.dst_ip),
69 jhash_1word(rule->rule.unique, key));
70 }
71
72 int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
73 {
74 const struct zebra_pbr_rule *r1, *r2;
75
76 r1 = (const struct zebra_pbr_rule *)arg1;
77 r2 = (const struct zebra_pbr_rule *)arg2;
78
79 if (r1->rule.seq != r2->rule.seq)
80 return 0;
81
82 if (r1->rule.priority != r2->rule.priority)
83 return 0;
84
85 if (r1->rule.unique != r2->rule.unique)
86 return 0;
87
88 if (r1->rule.action.table != r2->rule.action.table)
89 return 0;
90
91 if (r1->rule.filter.src_port != r2->rule.filter.src_port)
92 return 0;
93
94 if (r1->rule.filter.dst_port != r2->rule.filter.dst_port)
95 return 0;
96
97 if (r1->rule.filter.fwmark != r2->rule.filter.fwmark)
98 return 0;
99
100 if (!prefix_same(&r1->rule.filter.src_ip, &r2->rule.filter.src_ip))
101 return 0;
102
103 if (!prefix_same(&r1->rule.filter.dst_ip, &r2->rule.filter.dst_ip))
104 return 0;
105
106 if (r1->ifp != r2->ifp)
107 return 0;
108
109 return 1;
110 }
111
112 struct pbr_rule_unique_lookup {
113 struct zebra_pbr_rule *rule;
114 uint32_t unique;
115 struct interface *ifp;
116 };
117
118 static int pbr_rule_lookup_unique_walker(struct hash_backet *b, void *data)
119 {
120 struct pbr_rule_unique_lookup *pul = data;
121 struct zebra_pbr_rule *rule = b->data;
122
123 if (pul->unique == rule->rule.unique && pul->ifp == rule->ifp) {
124 pul->rule = rule;
125 return HASHWALK_ABORT;
126 }
127
128 return HASHWALK_CONTINUE;
129 }
130
131 static struct zebra_pbr_rule *pbr_rule_lookup_unique(struct zebra_ns *zns,
132 uint32_t unique,
133 struct interface *ifp)
134 {
135 struct pbr_rule_unique_lookup pul;
136
137 pul.unique = unique;
138 pul.ifp = ifp;
139 pul.rule = NULL;
140 hash_walk(zns->rules_hash, &pbr_rule_lookup_unique_walker, &pul);
141
142 return pul.rule;
143 }
144
145 void zebra_pbr_ipset_free(void *arg)
146 {
147 struct zebra_pbr_ipset *ipset;
148
149 ipset = (struct zebra_pbr_ipset *)arg;
150
151 XFREE(MTYPE_TMP, ipset);
152 }
153
154 uint32_t zebra_pbr_ipset_hash_key(void *arg)
155 {
156 struct zebra_pbr_ipset *ipset = (struct zebra_pbr_ipset *)arg;
157 uint32_t *pnt = (uint32_t *)&ipset->ipset_name;
158
159 return jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE, 0x63ab42de);
160 }
161
162 int zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2)
163 {
164 const struct zebra_pbr_ipset *r1, *r2;
165
166 r1 = (const struct zebra_pbr_ipset *)arg1;
167 r2 = (const struct zebra_pbr_ipset *)arg2;
168
169 if (r1->type != r2->type)
170 return 0;
171 if (r1->unique != r2->unique)
172 return 0;
173 if (strncmp(r1->ipset_name, r2->ipset_name,
174 ZEBRA_IPSET_NAME_SIZE))
175 return 0;
176 return 1;
177 }
178
179 void zebra_pbr_ipset_entry_free(void *arg)
180 {
181 struct zebra_pbr_ipset_entry *ipset;
182
183 ipset = (struct zebra_pbr_ipset_entry *)arg;
184
185 XFREE(MTYPE_TMP, ipset);
186 }
187
188 uint32_t zebra_pbr_ipset_entry_hash_key(void *arg)
189 {
190 struct zebra_pbr_ipset_entry *ipset;
191 uint32_t key;
192
193 ipset = (struct zebra_pbr_ipset_entry *)arg;
194 key = prefix_hash_key(&ipset->src);
195 key = jhash_1word(ipset->unique, key);
196 key = jhash_1word(prefix_hash_key(&ipset->dst), key);
197
198 return key;
199 }
200
201 int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2)
202 {
203 const struct zebra_pbr_ipset_entry *r1, *r2;
204
205 r1 = (const struct zebra_pbr_ipset_entry *)arg1;
206 r2 = (const struct zebra_pbr_ipset_entry *)arg2;
207
208 if (r1->unique != r2->unique)
209 return 0;
210
211 if (!prefix_same(&r1->src, &r2->src))
212 return 0;
213
214 if (!prefix_same(&r1->dst, &r2->dst))
215 return 0;
216
217 return 1;
218 }
219
220 void zebra_pbr_iptable_free(void *arg)
221 {
222 struct zebra_pbr_iptable *iptable;
223
224 iptable = (struct zebra_pbr_iptable *)arg;
225
226 XFREE(MTYPE_TMP, iptable);
227 }
228
229 uint32_t zebra_pbr_iptable_hash_key(void *arg)
230 {
231 struct zebra_pbr_iptable *iptable = (struct zebra_pbr_iptable *)arg;
232 uint32_t *pnt = (uint32_t *)&(iptable->ipset_name);
233 uint32_t key;
234
235 key = jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE,
236 0x63ab42de);
237 key = jhash_1word(iptable->fwmark, key);
238 return jhash_3words(iptable->filter_bm, iptable->type,
239 iptable->unique, key);
240 }
241
242 int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2)
243 {
244 const struct zebra_pbr_iptable *r1, *r2;
245
246 r1 = (const struct zebra_pbr_iptable *)arg1;
247 r2 = (const struct zebra_pbr_iptable *)arg2;
248
249 if (r1->type != r2->type)
250 return 0;
251 if (r1->unique != r2->unique)
252 return 0;
253 if (r1->filter_bm != r2->filter_bm)
254 return 0;
255 if (r1->fwmark != r2->fwmark)
256 return 0;
257 if (r1->action != r2->action)
258 return 0;
259 if (strncmp(r1->ipset_name, r2->ipset_name,
260 ZEBRA_IPSET_NAME_SIZE))
261 return 0;
262 return 1;
263 }
264
265 static void *pbr_rule_alloc_intern(void *arg)
266 {
267 struct zebra_pbr_rule *zpr;
268 struct zebra_pbr_rule *new;
269
270 zpr = (struct zebra_pbr_rule *)arg;
271
272 new = XCALLOC(MTYPE_TMP, sizeof(*new));
273
274 memcpy(new, zpr, sizeof(*zpr));
275
276 return new;
277 }
278
279 void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule)
280 {
281 struct zebra_pbr_rule *unique =
282 pbr_rule_lookup_unique(zns, rule->rule.unique, rule->ifp);
283
284 (void)hash_get(zns->rules_hash, rule, pbr_rule_alloc_intern);
285 kernel_add_pbr_rule(rule);
286
287 /*
288 * Rule Replace semantics, if we have an old, install the
289 * new rule, look above, and then delete the old
290 */
291 if (unique)
292 zebra_pbr_del_rule(zns, unique);
293 }
294
295 void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule)
296 {
297 struct zebra_pbr_rule *lookup;
298
299 lookup = hash_lookup(zns->rules_hash, rule);
300 kernel_del_pbr_rule(rule);
301
302 if (lookup) {
303 hash_release(zns->rules_hash, lookup);
304 XFREE(MTYPE_TMP, lookup);
305 } else
306 zlog_warn("%s: Rule being deleted we know nothing about",
307 __PRETTY_FUNCTION__);
308 }
309
310 static void zebra_pbr_cleanup_rules(struct hash_backet *b, void *data)
311 {
312 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
313 struct zebra_pbr_rule *rule = b->data;
314 int *sock = data;
315
316 if (rule->sock == *sock) {
317 kernel_del_pbr_rule(rule);
318 hash_release(zns->rules_hash, rule);
319 XFREE(MTYPE_TMP, rule);
320 }
321 }
322
323 void zebra_pbr_client_close_cleanup(int sock)
324 {
325 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
326
327 hash_iterate(zns->rules_hash, zebra_pbr_cleanup_rules, &sock);
328 }
329
330 static void *pbr_ipset_alloc_intern(void *arg)
331 {
332 struct zebra_pbr_ipset *zpi;
333 struct zebra_pbr_ipset *new;
334
335 zpi = (struct zebra_pbr_ipset *)arg;
336
337 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset));
338
339 memcpy(new, zpi, sizeof(*zpi));
340
341 return new;
342 }
343
344 void zebra_pbr_create_ipset(struct zebra_ns *zns,
345 struct zebra_pbr_ipset *ipset)
346 {
347 (void)hash_get(zns->ipset_hash, ipset, pbr_ipset_alloc_intern);
348 /* TODO:
349 * - Netlink call
350 */
351 }
352
353 void zebra_pbr_destroy_ipset(struct zebra_ns *zns,
354 struct zebra_pbr_ipset *ipset)
355 {
356 struct zebra_pbr_ipset *lookup;
357
358 lookup = hash_lookup(zns->ipset_hash, ipset);
359 /* TODO:
360 * - Netlink destroy from kernel
361 * - ?? destroy ipset entries before
362 */
363 if (lookup)
364 XFREE(MTYPE_TMP, lookup);
365 else
366 zlog_warn("%s: IPSet Entry being deleted we know nothing about",
367 __PRETTY_FUNCTION__);
368 }
369
370 struct pbr_ipset_name_lookup {
371 struct zebra_pbr_ipset *ipset;
372 char ipset_name[ZEBRA_IPSET_NAME_SIZE];
373 };
374
375 static int zebra_pbr_ipset_pername_walkcb(struct hash_backet *backet, void *arg)
376 {
377 struct pbr_ipset_name_lookup *pinl =
378 (struct pbr_ipset_name_lookup *)arg;
379 struct zebra_pbr_ipset *zpi = (struct zebra_pbr_ipset *)backet->data;
380
381 if (!strncmp(pinl->ipset_name, zpi->ipset_name,
382 ZEBRA_IPSET_NAME_SIZE)) {
383 pinl->ipset = zpi;
384 return HASHWALK_ABORT;
385 }
386 return HASHWALK_CONTINUE;
387 }
388
389 struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(struct zebra_ns *zns,
390 char *ipsetname)
391 {
392 struct pbr_ipset_name_lookup pinl;
393 struct pbr_ipset_name_lookup *ptr = &pinl;
394
395 if (!ipsetname)
396 return NULL;
397 memset(ptr, 0, sizeof(struct pbr_ipset_name_lookup));
398 snprintf((char *)ptr->ipset_name, ZEBRA_IPSET_NAME_SIZE, "%s",
399 ipsetname);
400 hash_walk(zns->ipset_hash, zebra_pbr_ipset_pername_walkcb, ptr);
401 return ptr->ipset;
402 }
403
404 static void *pbr_ipset_entry_alloc_intern(void *arg)
405 {
406 struct zebra_pbr_ipset_entry *zpi;
407 struct zebra_pbr_ipset_entry *new;
408
409 zpi = (struct zebra_pbr_ipset_entry *)arg;
410
411 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset_entry));
412
413 memcpy(new, zpi, sizeof(*zpi));
414
415 return new;
416 }
417
418 void zebra_pbr_add_ipset_entry(struct zebra_ns *zns,
419 struct zebra_pbr_ipset_entry *ipset)
420 {
421 (void)hash_get(zns->ipset_entry_hash, ipset,
422 pbr_ipset_entry_alloc_intern);
423 /* TODO:
424 * - attach to ipset list
425 * - Netlink add to kernel
426 */
427 }
428
429 void zebra_pbr_del_ipset_entry(struct zebra_ns *zns,
430 struct zebra_pbr_ipset_entry *ipset)
431 {
432 struct zebra_pbr_ipset_entry *lookup;
433
434 lookup = hash_lookup(zns->ipset_entry_hash, ipset);
435 /* TODO:
436 * - Netlink destroy
437 * - detach from ipset list
438 * - ?? if no more entres, delete ipset
439 */
440 if (lookup)
441 XFREE(MTYPE_TMP, lookup);
442 else
443 zlog_warn("%s: IPSet being deleted we know nothing about",
444 __PRETTY_FUNCTION__);
445 }
446
447 static void *pbr_iptable_alloc_intern(void *arg)
448 {
449 struct zebra_pbr_iptable *zpi;
450 struct zebra_pbr_iptable *new;
451
452 zpi = (struct zebra_pbr_iptable *)arg;
453
454 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable));
455
456 memcpy(new, zpi, sizeof(*zpi));
457
458 return new;
459 }
460
461 void zebra_pbr_add_iptable(struct zebra_ns *zns,
462 struct zebra_pbr_iptable *iptable)
463 {
464 (void)hash_get(zns->iptable_hash, iptable,
465 pbr_iptable_alloc_intern);
466 /* TODO call netlink layer */
467 }
468
469 void zebra_pbr_del_iptable(struct zebra_ns *zns,
470 struct zebra_pbr_iptable *iptable)
471 {
472 struct zebra_pbr_ipset_entry *lookup;
473
474 lookup = hash_lookup(zns->iptable_hash, iptable);
475 /* TODO:
476 * - call netlink layer
477 * - detach from iptable list
478 */
479 if (lookup)
480 XFREE(MTYPE_TMP, lookup);
481 else
482 zlog_warn("%s: IPTable being deleted we know nothing about",
483 __PRETTY_FUNCTION__);
484 }
485
486 /*
487 * Handle success or failure of rule (un)install in the kernel.
488 */
489 void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule,
490 enum southbound_results res)
491 {
492 switch (res) {
493 case SOUTHBOUND_INSTALL_SUCCESS:
494 zsend_rule_notify_owner(rule, ZAPI_RULE_INSTALLED);
495 break;
496 case SOUTHBOUND_INSTALL_FAILURE:
497 zsend_rule_notify_owner(rule, ZAPI_RULE_FAIL_INSTALL);
498 break;
499 case SOUTHBOUND_DELETE_SUCCESS:
500 zsend_rule_notify_owner(rule, ZAPI_RULE_REMOVED);
501 break;
502 case SOUTHBOUND_DELETE_FAILURE:
503 zsend_rule_notify_owner(rule, ZAPI_RULE_REMOVED);
504 break;
505 }
506 }
507
508 /*
509 * Handle success or failure of ipset (un)install in the kernel.
510 */
511 void kernel_pbr_ipset_add_del_status(struct zebra_pbr_ipset *ipset,
512 enum southbound_results res)
513 {
514 switch (res) {
515 case SOUTHBOUND_INSTALL_SUCCESS:
516 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_INSTALLED);
517 break;
518 case SOUTHBOUND_INSTALL_FAILURE:
519 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_INSTALL);
520 break;
521 case SOUTHBOUND_DELETE_SUCCESS:
522 case SOUTHBOUND_DELETE_FAILURE:
523 /* TODO : handling of delete event */
524 break;
525 }
526 }
527
528 /*
529 * Handle success or failure of ipset (un)install in the kernel.
530 */
531 void kernel_pbr_ipset_entry_add_del_status(
532 struct zebra_pbr_ipset_entry *ipset,
533 enum southbound_results res)
534 {
535 switch (res) {
536 case SOUTHBOUND_INSTALL_SUCCESS:
537 zsend_ipset_entry_notify_owner(ipset,
538 ZAPI_IPSET_ENTRY_INSTALLED);
539 break;
540 case SOUTHBOUND_INSTALL_FAILURE:
541 zsend_ipset_entry_notify_owner(ipset,
542 ZAPI_IPSET_ENTRY_FAIL_INSTALL);
543 break;
544 case SOUTHBOUND_DELETE_SUCCESS:
545 case SOUTHBOUND_DELETE_FAILURE:
546 /* TODO : handling of delete event */
547 break;
548 }
549 }
550
551 /*
552 * Handle success or failure of ipset (un)install in the kernel.
553 */
554 void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable,
555 enum southbound_results res)
556 {
557 switch (res) {
558 case SOUTHBOUND_INSTALL_SUCCESS:
559 zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_INSTALLED);
560 break;
561 case SOUTHBOUND_INSTALL_FAILURE:
562 zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_FAIL_INSTALL);
563 break;
564 case SOUTHBOUND_DELETE_SUCCESS:
565 case SOUTHBOUND_DELETE_FAILURE:
566 /* TODO : handling of delete event */
567 break;
568 }
569 }
570
571 /*
572 * Handle rule delete notification from kernel.
573 */
574 int kernel_pbr_rule_del(struct zebra_pbr_rule *rule)
575 {
576 return 0;
577 }