]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_pbr.c
zebra: rebase zserv-mt
[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 #include <memory.h>
27 #include <hook.h>
28
29 #include "zebra/zebra_pbr.h"
30 #include "zebra/rt.h"
31 #include "zebra/zapi_msg.h"
32 #include "zebra/zebra_memory.h"
33 #include "zebra/zserv.h"
34
35 /* definitions */
36 DEFINE_MTYPE_STATIC(ZEBRA, PBR_IPTABLE_IFNAME, "PBR interface list")
37
38 /* definitions */
39 static const struct message ipset_type_msg[] = {
40 {IPSET_NET_PORT_NET, "net,port,net"},
41 {IPSET_NET_PORT, "net,port"},
42 {IPSET_NET_NET, "net,net"},
43 {IPSET_NET, "net"},
44 {0}
45 };
46
47 /* static function declarations */
48 DEFINE_HOOK(zebra_pbr_ipset_entry_wrap_script_get_stat, (struct zebra_ns *zns,
49 struct zebra_pbr_ipset_entry *ipset,
50 uint64_t *pkts, uint64_t *bytes),
51 (zns, ipset, pkts, bytes))
52
53 DEFINE_HOOK(zebra_pbr_iptable_wrap_script_get_stat, (struct zebra_ns *zns,
54 struct zebra_pbr_iptable *iptable,
55 uint64_t *pkts, uint64_t *bytes),
56 (zns, iptable, pkts, bytes))
57
58 DEFINE_HOOK(zebra_pbr_iptable_wrap_script_update, (struct zebra_ns *zns,
59 int cmd,
60 struct zebra_pbr_iptable *iptable),
61 (zns, cmd, iptable));
62
63 DEFINE_HOOK(zebra_pbr_ipset_entry_wrap_script_update, (struct zebra_ns *zns,
64 int cmd,
65 struct zebra_pbr_ipset_entry *ipset),
66 (zns, cmd, ipset));
67
68 DEFINE_HOOK(zebra_pbr_ipset_wrap_script_update, (struct zebra_ns *zns,
69 int cmd,
70 struct zebra_pbr_ipset *ipset),
71 (zns, cmd, ipset));
72
73 /* Private functions */
74
75 /* Public functions */
76 void zebra_pbr_rules_free(void *arg)
77 {
78 struct zebra_pbr_rule *rule;
79
80 rule = (struct zebra_pbr_rule *)arg;
81
82 kernel_del_pbr_rule(rule);
83 XFREE(MTYPE_TMP, rule);
84 }
85
86 uint32_t zebra_pbr_rules_hash_key(void *arg)
87 {
88 struct zebra_pbr_rule *rule;
89 uint32_t key;
90
91 rule = (struct zebra_pbr_rule *)arg;
92 key = jhash_3words(rule->rule.seq, rule->rule.priority,
93 rule->rule.action.table,
94 prefix_hash_key(&rule->rule.filter.src_ip));
95 if (rule->ifp)
96 key = jhash_1word(rule->ifp->ifindex, key);
97 else
98 key = jhash_1word(0, key);
99
100 if (rule->rule.filter.fwmark)
101 key = jhash_1word(rule->rule.filter.fwmark, key);
102 else
103 key = jhash_1word(0, key);
104 return jhash_3words(rule->rule.filter.src_port,
105 rule->rule.filter.dst_port,
106 prefix_hash_key(&rule->rule.filter.dst_ip),
107 jhash_1word(rule->rule.unique, key));
108 }
109
110 int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
111 {
112 const struct zebra_pbr_rule *r1, *r2;
113
114 r1 = (const struct zebra_pbr_rule *)arg1;
115 r2 = (const struct zebra_pbr_rule *)arg2;
116
117 if (r1->rule.seq != r2->rule.seq)
118 return 0;
119
120 if (r1->rule.priority != r2->rule.priority)
121 return 0;
122
123 if (r1->rule.unique != r2->rule.unique)
124 return 0;
125
126 if (r1->rule.action.table != r2->rule.action.table)
127 return 0;
128
129 if (r1->rule.filter.src_port != r2->rule.filter.src_port)
130 return 0;
131
132 if (r1->rule.filter.dst_port != r2->rule.filter.dst_port)
133 return 0;
134
135 if (r1->rule.filter.fwmark != r2->rule.filter.fwmark)
136 return 0;
137
138 if (!prefix_same(&r1->rule.filter.src_ip, &r2->rule.filter.src_ip))
139 return 0;
140
141 if (!prefix_same(&r1->rule.filter.dst_ip, &r2->rule.filter.dst_ip))
142 return 0;
143
144 if (r1->ifp != r2->ifp)
145 return 0;
146
147 return 1;
148 }
149
150 struct pbr_rule_unique_lookup {
151 struct zebra_pbr_rule *rule;
152 uint32_t unique;
153 struct interface *ifp;
154 };
155
156 static int pbr_rule_lookup_unique_walker(struct hash_backet *b, void *data)
157 {
158 struct pbr_rule_unique_lookup *pul = data;
159 struct zebra_pbr_rule *rule = b->data;
160
161 if (pul->unique == rule->rule.unique && pul->ifp == rule->ifp) {
162 pul->rule = rule;
163 return HASHWALK_ABORT;
164 }
165
166 return HASHWALK_CONTINUE;
167 }
168
169 static struct zebra_pbr_rule *pbr_rule_lookup_unique(struct zebra_ns *zns,
170 uint32_t unique,
171 struct interface *ifp)
172 {
173 struct pbr_rule_unique_lookup pul;
174
175 pul.unique = unique;
176 pul.ifp = ifp;
177 pul.rule = NULL;
178 hash_walk(zns->rules_hash, &pbr_rule_lookup_unique_walker, &pul);
179
180 return pul.rule;
181 }
182
183 void zebra_pbr_ipset_free(void *arg)
184 {
185 struct zebra_pbr_ipset *ipset;
186 struct zebra_ns *zns;
187
188 ipset = (struct zebra_pbr_ipset *)arg;
189 if (vrf_is_backend_netns())
190 zns = zebra_ns_lookup(ipset->vrf_id);
191 else
192 zns = zebra_ns_lookup(NS_DEFAULT);
193 hook_call(zebra_pbr_ipset_wrap_script_update,
194 zns, 0, ipset);
195 XFREE(MTYPE_TMP, ipset);
196 }
197
198 uint32_t zebra_pbr_ipset_hash_key(void *arg)
199 {
200 struct zebra_pbr_ipset *ipset = (struct zebra_pbr_ipset *)arg;
201 uint32_t *pnt = (uint32_t *)&ipset->ipset_name;
202
203 return jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE, 0x63ab42de);
204 }
205
206 int zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2)
207 {
208 const struct zebra_pbr_ipset *r1, *r2;
209
210 r1 = (const struct zebra_pbr_ipset *)arg1;
211 r2 = (const struct zebra_pbr_ipset *)arg2;
212
213 if (r1->type != r2->type)
214 return 0;
215 if (r1->unique != r2->unique)
216 return 0;
217 if (strncmp(r1->ipset_name, r2->ipset_name,
218 ZEBRA_IPSET_NAME_SIZE))
219 return 0;
220 return 1;
221 }
222
223 void zebra_pbr_ipset_entry_free(void *arg)
224 {
225 struct zebra_pbr_ipset_entry *ipset;
226 struct zebra_ns *zns;
227
228 ipset = (struct zebra_pbr_ipset_entry *)arg;
229 if (ipset->backpointer && vrf_is_backend_netns()) {
230 struct zebra_pbr_ipset *ips = ipset->backpointer;
231
232 zns = zebra_ns_lookup((ns_id_t)ips->vrf_id);
233 } else
234 zns = zebra_ns_lookup(NS_DEFAULT);
235 hook_call(zebra_pbr_ipset_entry_wrap_script_update,
236 zns, 0, ipset);
237
238 XFREE(MTYPE_TMP, ipset);
239 }
240
241 uint32_t zebra_pbr_ipset_entry_hash_key(void *arg)
242 {
243 struct zebra_pbr_ipset_entry *ipset;
244 uint32_t key;
245
246 ipset = (struct zebra_pbr_ipset_entry *)arg;
247 key = prefix_hash_key(&ipset->src);
248 key = jhash_1word(ipset->unique, key);
249 key = jhash_1word(prefix_hash_key(&ipset->dst), key);
250 key = jhash(&ipset->dst_port_min, 2, key);
251 key = jhash(&ipset->dst_port_max, 2, key);
252 key = jhash(&ipset->src_port_min, 2, key);
253 key = jhash(&ipset->src_port_max, 2, key);
254 key = jhash(&ipset->proto, 1, key);
255
256 return key;
257 }
258
259 int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2)
260 {
261 const struct zebra_pbr_ipset_entry *r1, *r2;
262
263 r1 = (const struct zebra_pbr_ipset_entry *)arg1;
264 r2 = (const struct zebra_pbr_ipset_entry *)arg2;
265
266 if (r1->unique != r2->unique)
267 return 0;
268
269 if (!prefix_same(&r1->src, &r2->src))
270 return 0;
271
272 if (!prefix_same(&r1->dst, &r2->dst))
273 return 0;
274
275 if (r1->src_port_min != r2->src_port_min)
276 return 0;
277
278 if (r1->src_port_max != r2->src_port_max)
279 return 0;
280
281 if (r1->dst_port_min != r2->dst_port_min)
282 return 0;
283
284 if (r1->dst_port_max != r2->dst_port_max)
285 return 0;
286
287 if (r1->proto != r2->proto)
288 return 0;
289 return 1;
290 }
291
292 void zebra_pbr_iptable_free(void *arg)
293 {
294 struct zebra_pbr_iptable *iptable;
295 struct listnode *node, *nnode;
296 char *name;
297 struct zebra_ns *zns;
298
299 iptable = (struct zebra_pbr_iptable *)arg;
300 if (vrf_is_backend_netns())
301 zns = zebra_ns_lookup((ns_id_t)iptable->vrf_id);
302 else
303 zns = zebra_ns_lookup(NS_DEFAULT);
304 hook_call(zebra_pbr_iptable_wrap_script_update,
305 zns, 0, iptable);
306
307 for (ALL_LIST_ELEMENTS(iptable->interface_name_list,
308 node, nnode, name)) {
309 XFREE(MTYPE_PBR_IPTABLE_IFNAME, name);
310 list_delete_node(iptable->interface_name_list,
311 node);
312 }
313 XFREE(MTYPE_TMP, iptable);
314 }
315
316 uint32_t zebra_pbr_iptable_hash_key(void *arg)
317 {
318 struct zebra_pbr_iptable *iptable = (struct zebra_pbr_iptable *)arg;
319 uint32_t *pnt = (uint32_t *)&(iptable->ipset_name);
320 uint32_t key;
321
322 key = jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE,
323 0x63ab42de);
324 key = jhash_1word(iptable->fwmark, key);
325 return jhash_3words(iptable->filter_bm, iptable->type,
326 iptable->unique, key);
327 }
328
329 int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2)
330 {
331 const struct zebra_pbr_iptable *r1, *r2;
332
333 r1 = (const struct zebra_pbr_iptable *)arg1;
334 r2 = (const struct zebra_pbr_iptable *)arg2;
335
336 if (r1->type != r2->type)
337 return 0;
338 if (r1->unique != r2->unique)
339 return 0;
340 if (r1->filter_bm != r2->filter_bm)
341 return 0;
342 if (r1->fwmark != r2->fwmark)
343 return 0;
344 if (r1->action != r2->action)
345 return 0;
346 if (strncmp(r1->ipset_name, r2->ipset_name,
347 ZEBRA_IPSET_NAME_SIZE))
348 return 0;
349 return 1;
350 }
351
352 static void *pbr_rule_alloc_intern(void *arg)
353 {
354 struct zebra_pbr_rule *zpr;
355 struct zebra_pbr_rule *new;
356
357 zpr = (struct zebra_pbr_rule *)arg;
358
359 new = XCALLOC(MTYPE_TMP, sizeof(*new));
360
361 memcpy(new, zpr, sizeof(*zpr));
362
363 return new;
364 }
365
366 void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule)
367 {
368 struct zebra_pbr_rule *unique =
369 pbr_rule_lookup_unique(zns, rule->rule.unique, rule->ifp);
370
371 (void)hash_get(zns->rules_hash, rule, pbr_rule_alloc_intern);
372 kernel_add_pbr_rule(rule);
373 /*
374 * Rule Replace semantics, if we have an old, install the
375 * new rule, look above, and then delete the old
376 */
377 if (unique)
378 zebra_pbr_del_rule(zns, unique);
379 }
380
381 void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule)
382 {
383 struct zebra_pbr_rule *lookup;
384
385 lookup = hash_lookup(zns->rules_hash, rule);
386 kernel_del_pbr_rule(rule);
387
388 if (lookup) {
389 hash_release(zns->rules_hash, lookup);
390 XFREE(MTYPE_TMP, lookup);
391 } else
392 zlog_warn("%s: Rule being deleted we know nothing about",
393 __PRETTY_FUNCTION__);
394 }
395
396 static void zebra_pbr_cleanup_rules(struct hash_backet *b, void *data)
397 {
398 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
399 struct zebra_pbr_rule *rule = b->data;
400 int *sock = data;
401
402 if (rule->sock == *sock) {
403 kernel_del_pbr_rule(rule);
404 hash_release(zns->rules_hash, rule);
405 XFREE(MTYPE_TMP, rule);
406 }
407 }
408
409 static void zebra_pbr_cleanup_ipset(struct hash_backet *b, void *data)
410 {
411 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
412 struct zebra_pbr_ipset *ipset = b->data;
413 int *sock = data;
414
415 if (ipset->sock == *sock) {
416 hook_call(zebra_pbr_ipset_wrap_script_update,
417 zns, 0, ipset);
418 hash_release(zns->ipset_hash, ipset);
419 }
420 }
421
422 static void zebra_pbr_cleanup_ipset_entry(struct hash_backet *b, void *data)
423 {
424 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
425 struct zebra_pbr_ipset_entry *ipset = b->data;
426 int *sock = data;
427
428 if (ipset->sock == *sock) {
429 hook_call(zebra_pbr_ipset_entry_wrap_script_update,
430 zns, 0, ipset);
431 hash_release(zns->ipset_entry_hash, ipset);
432 }
433 }
434
435 static void zebra_pbr_cleanup_iptable(struct hash_backet *b, void *data)
436 {
437 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
438 struct zebra_pbr_iptable *iptable = b->data;
439 int *sock = data;
440
441 if (iptable->sock == *sock) {
442 hook_call(zebra_pbr_iptable_wrap_script_update,
443 zns, 0, iptable);
444 hash_release(zns->iptable_hash, iptable);
445 }
446 }
447
448 static int zebra_pbr_client_close_cleanup(struct zserv *client)
449 {
450 int sock = client->sock;
451 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
452
453 if (!sock)
454 return 0;
455 hash_iterate(zns->rules_hash, zebra_pbr_cleanup_rules, &sock);
456 hash_iterate(zns->iptable_hash,
457 zebra_pbr_cleanup_iptable, &sock);
458 hash_iterate(zns->ipset_entry_hash,
459 zebra_pbr_cleanup_ipset_entry, &sock);
460 hash_iterate(zns->ipset_hash,
461 zebra_pbr_cleanup_ipset, &sock);
462 return 1;
463 }
464
465 void zebra_pbr_init(void)
466 {
467 hook_register(zserv_client_close, zebra_pbr_client_close_cleanup);
468 }
469
470 static void *pbr_ipset_alloc_intern(void *arg)
471 {
472 struct zebra_pbr_ipset *zpi;
473 struct zebra_pbr_ipset *new;
474
475 zpi = (struct zebra_pbr_ipset *)arg;
476
477 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset));
478
479 memcpy(new, zpi, sizeof(*zpi));
480
481 return new;
482 }
483
484 void zebra_pbr_create_ipset(struct zebra_ns *zns,
485 struct zebra_pbr_ipset *ipset)
486 {
487 int ret;
488
489 (void)hash_get(zns->ipset_hash, ipset, pbr_ipset_alloc_intern);
490 ret = hook_call(zebra_pbr_ipset_wrap_script_update,
491 zns, 1, ipset);
492 kernel_pbr_ipset_add_del_status(ipset,
493 ret ? SOUTHBOUND_INSTALL_SUCCESS
494 : SOUTHBOUND_INSTALL_FAILURE);
495 }
496
497 void zebra_pbr_destroy_ipset(struct zebra_ns *zns,
498 struct zebra_pbr_ipset *ipset)
499 {
500 struct zebra_pbr_ipset *lookup;
501
502 lookup = hash_lookup(zns->ipset_hash, ipset);
503 hook_call(zebra_pbr_ipset_wrap_script_update,
504 zns, 0, ipset);
505 if (lookup) {
506 hash_release(zns->ipset_hash, lookup);
507 XFREE(MTYPE_TMP, lookup);
508 } else
509 zlog_warn("%s: IPSet Entry being deleted we know nothing about",
510 __PRETTY_FUNCTION__);
511 }
512
513 struct pbr_ipset_name_lookup {
514 struct zebra_pbr_ipset *ipset;
515 char ipset_name[ZEBRA_IPSET_NAME_SIZE];
516 };
517
518 static const char *zebra_pbr_ipset_type2str(uint32_t type)
519 {
520 return lookup_msg(ipset_type_msg, type,
521 "Unrecognized IPset Type");
522 }
523
524 static int zebra_pbr_ipset_pername_walkcb(struct hash_backet *backet, void *arg)
525 {
526 struct pbr_ipset_name_lookup *pinl =
527 (struct pbr_ipset_name_lookup *)arg;
528 struct zebra_pbr_ipset *zpi = (struct zebra_pbr_ipset *)backet->data;
529
530 if (!strncmp(pinl->ipset_name, zpi->ipset_name,
531 ZEBRA_IPSET_NAME_SIZE)) {
532 pinl->ipset = zpi;
533 return HASHWALK_ABORT;
534 }
535 return HASHWALK_CONTINUE;
536 }
537
538 struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(struct zebra_ns *zns,
539 char *ipsetname)
540 {
541 struct pbr_ipset_name_lookup pinl;
542 struct pbr_ipset_name_lookup *ptr = &pinl;
543
544 if (!ipsetname)
545 return NULL;
546 memset(ptr, 0, sizeof(struct pbr_ipset_name_lookup));
547 snprintf((char *)ptr->ipset_name, ZEBRA_IPSET_NAME_SIZE, "%s",
548 ipsetname);
549 hash_walk(zns->ipset_hash, zebra_pbr_ipset_pername_walkcb, ptr);
550 return ptr->ipset;
551 }
552
553 static void *pbr_ipset_entry_alloc_intern(void *arg)
554 {
555 struct zebra_pbr_ipset_entry *zpi;
556 struct zebra_pbr_ipset_entry *new;
557
558 zpi = (struct zebra_pbr_ipset_entry *)arg;
559
560 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset_entry));
561
562 memcpy(new, zpi, sizeof(*zpi));
563
564 return new;
565 }
566
567 void zebra_pbr_add_ipset_entry(struct zebra_ns *zns,
568 struct zebra_pbr_ipset_entry *ipset)
569 {
570 int ret;
571
572 (void)hash_get(zns->ipset_entry_hash, ipset,
573 pbr_ipset_entry_alloc_intern);
574 ret = hook_call(zebra_pbr_ipset_entry_wrap_script_update,
575 zns, 1, ipset);
576 kernel_pbr_ipset_entry_add_del_status(ipset,
577 ret ? SOUTHBOUND_INSTALL_SUCCESS
578 : SOUTHBOUND_INSTALL_FAILURE);
579 }
580
581 void zebra_pbr_del_ipset_entry(struct zebra_ns *zns,
582 struct zebra_pbr_ipset_entry *ipset)
583 {
584 struct zebra_pbr_ipset_entry *lookup;
585
586 lookup = hash_lookup(zns->ipset_entry_hash, ipset);
587 hook_call(zebra_pbr_ipset_entry_wrap_script_update,
588 zns, 0, ipset);
589 if (lookup) {
590 hash_release(zns->ipset_entry_hash, lookup);
591 XFREE(MTYPE_TMP, lookup);
592 } else
593 zlog_warn("%s: IPSet being deleted we know nothing about",
594 __PRETTY_FUNCTION__);
595 }
596
597 static void *pbr_iptable_alloc_intern(void *arg)
598 {
599 struct zebra_pbr_iptable *zpi;
600 struct zebra_pbr_iptable *new;
601
602 zpi = (struct zebra_pbr_iptable *)arg;
603
604 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable));
605
606 memcpy(new, zpi, sizeof(*zpi));
607
608 return new;
609 }
610
611 void zebra_pbr_add_iptable(struct zebra_ns *zns,
612 struct zebra_pbr_iptable *iptable)
613 {
614 int ret;
615
616 (void)hash_get(zns->iptable_hash, iptable,
617 pbr_iptable_alloc_intern);
618 ret = hook_call(zebra_pbr_iptable_wrap_script_update, zns, 1, iptable);
619 kernel_pbr_iptable_add_del_status(iptable,
620 ret ? SOUTHBOUND_INSTALL_SUCCESS
621 : SOUTHBOUND_INSTALL_FAILURE);
622 }
623
624 void zebra_pbr_del_iptable(struct zebra_ns *zns,
625 struct zebra_pbr_iptable *iptable)
626 {
627 struct zebra_pbr_iptable *lookup;
628
629 lookup = hash_lookup(zns->iptable_hash, iptable);
630 hook_call(zebra_pbr_iptable_wrap_script_update, zns, 0, iptable);
631 if (lookup) {
632 struct listnode *node, *nnode;
633 char *name;
634
635 hash_release(zns->iptable_hash, lookup);
636 for (ALL_LIST_ELEMENTS(iptable->interface_name_list,
637 node, nnode, name)) {
638 XFREE(MTYPE_PBR_IPTABLE_IFNAME, name);
639 list_delete_node(iptable->interface_name_list,
640 node);
641 }
642 XFREE(MTYPE_TMP, lookup);
643 } else
644 zlog_warn("%s: IPTable being deleted we know nothing about",
645 __PRETTY_FUNCTION__);
646 }
647
648 /*
649 * Handle success or failure of rule (un)install in the kernel.
650 */
651 void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule,
652 enum southbound_results res)
653 {
654 switch (res) {
655 case SOUTHBOUND_INSTALL_SUCCESS:
656 zsend_rule_notify_owner(rule, ZAPI_RULE_INSTALLED);
657 break;
658 case SOUTHBOUND_INSTALL_FAILURE:
659 zsend_rule_notify_owner(rule, ZAPI_RULE_FAIL_INSTALL);
660 break;
661 case SOUTHBOUND_DELETE_SUCCESS:
662 zsend_rule_notify_owner(rule, ZAPI_RULE_REMOVED);
663 break;
664 case SOUTHBOUND_DELETE_FAILURE:
665 zsend_rule_notify_owner(rule, ZAPI_RULE_FAIL_REMOVE);
666 break;
667 }
668 }
669
670 /*
671 * Handle success or failure of ipset (un)install in the kernel.
672 */
673 void kernel_pbr_ipset_add_del_status(struct zebra_pbr_ipset *ipset,
674 enum southbound_results res)
675 {
676 switch (res) {
677 case SOUTHBOUND_INSTALL_SUCCESS:
678 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_INSTALLED);
679 break;
680 case SOUTHBOUND_INSTALL_FAILURE:
681 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_INSTALL);
682 break;
683 case SOUTHBOUND_DELETE_SUCCESS:
684 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_REMOVED);
685 break;
686 case SOUTHBOUND_DELETE_FAILURE:
687 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_REMOVE);
688 break;
689 }
690 }
691
692 /*
693 * Handle success or failure of ipset (un)install in the kernel.
694 */
695 void kernel_pbr_ipset_entry_add_del_status(
696 struct zebra_pbr_ipset_entry *ipset,
697 enum southbound_results res)
698 {
699 switch (res) {
700 case SOUTHBOUND_INSTALL_SUCCESS:
701 zsend_ipset_entry_notify_owner(ipset,
702 ZAPI_IPSET_ENTRY_INSTALLED);
703 break;
704 case SOUTHBOUND_INSTALL_FAILURE:
705 zsend_ipset_entry_notify_owner(ipset,
706 ZAPI_IPSET_ENTRY_FAIL_INSTALL);
707 break;
708 case SOUTHBOUND_DELETE_SUCCESS:
709 zsend_ipset_entry_notify_owner(ipset,
710 ZAPI_IPSET_ENTRY_REMOVED);
711 break;
712 case SOUTHBOUND_DELETE_FAILURE:
713 zsend_ipset_entry_notify_owner(ipset,
714 ZAPI_IPSET_ENTRY_FAIL_REMOVE);
715 break;
716 }
717 }
718
719 /*
720 * Handle success or failure of ipset (un)install in the kernel.
721 */
722 void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable,
723 enum southbound_results res)
724 {
725 switch (res) {
726 case SOUTHBOUND_INSTALL_SUCCESS:
727 zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_INSTALLED);
728 break;
729 case SOUTHBOUND_INSTALL_FAILURE:
730 zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_FAIL_INSTALL);
731 break;
732 case SOUTHBOUND_DELETE_SUCCESS:
733 zsend_iptable_notify_owner(iptable,
734 ZAPI_IPTABLE_REMOVED);
735 break;
736 case SOUTHBOUND_DELETE_FAILURE:
737 zsend_iptable_notify_owner(iptable,
738 ZAPI_IPTABLE_FAIL_REMOVE);
739 break;
740 }
741 }
742
743 /*
744 * Handle rule delete notification from kernel.
745 */
746 int kernel_pbr_rule_del(struct zebra_pbr_rule *rule)
747 {
748 return 0;
749 }
750
751 struct zebra_pbr_ipset_entry_unique_display {
752 struct zebra_pbr_ipset *zpi;
753 struct vty *vty;
754 struct zebra_ns *zns;
755 };
756
757 struct zebra_pbr_env_display {
758 struct zebra_ns *zns;
759 struct vty *vty;
760 };
761
762 static const char *zebra_pbr_prefix2str(union prefixconstptr pu,
763 char *str, int size)
764 {
765 const struct prefix *p = pu.p;
766 char buf[PREFIX2STR_BUFFER];
767
768 if (p->family == AF_INET && p->prefixlen == IPV4_MAX_PREFIXLEN) {
769 snprintf(str, size, "%s", inet_ntop(p->family, &p->u.prefix,
770 buf, PREFIX2STR_BUFFER));
771 return str;
772 }
773 return prefix2str(pu, str, size);
774 }
775
776 static void zebra_pbr_display_port(struct vty *vty, uint32_t filter_bm,
777 uint16_t port_min, uint16_t port_max,
778 uint8_t proto)
779 {
780 if (!(filter_bm & PBR_FILTER_PROTO)) {
781 if (port_max)
782 vty_out(vty, ":udp/tcp:%d-%d",
783 port_min, port_max);
784 else
785 vty_out(vty, ":udp/tcp:%d",
786 port_min);
787 } else {
788 if (port_max)
789 vty_out(vty, ":proto %d:%d-%d",
790 proto, port_min, port_max);
791 else
792 vty_out(vty, ":proto %d:%d",
793 proto, port_min);
794 }
795 }
796
797 static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
798 void *arg)
799 {
800 struct zebra_pbr_ipset_entry_unique_display *unique =
801 (struct zebra_pbr_ipset_entry_unique_display *)arg;
802 struct zebra_pbr_ipset *zpi = unique->zpi;
803 struct vty *vty = unique->vty;
804 struct zebra_pbr_ipset_entry *zpie =
805 (struct zebra_pbr_ipset_entry *)backet->data;
806 uint64_t pkts = 0, bytes = 0;
807 struct zebra_ns *zns = unique->zns;
808 int ret = 0;
809
810 if (zpie->backpointer != zpi)
811 return HASHWALK_CONTINUE;
812
813 if ((zpi->type == IPSET_NET_NET) ||
814 (zpi->type == IPSET_NET_PORT_NET)) {
815 char buf[PREFIX_STRLEN];
816
817 zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
818 vty_out(vty, "\tfrom %s", buf);
819 if (zpie->filter_bm & PBR_FILTER_SRC_PORT)
820 zebra_pbr_display_port(vty, zpie->filter_bm,
821 zpie->src_port_min,
822 zpie->src_port_max,
823 zpie->proto);
824 vty_out(vty, " to ");
825 zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
826 vty_out(vty, "%s", buf);
827 if (zpie->filter_bm & PBR_FILTER_DST_PORT)
828 zebra_pbr_display_port(vty, zpie->filter_bm,
829 zpie->dst_port_min,
830 zpie->dst_port_max,
831 zpie->proto);
832 } else if ((zpi->type == IPSET_NET) ||
833 (zpi->type == IPSET_NET_PORT)) {
834 char buf[PREFIX_STRLEN];
835
836 if (zpie->filter_bm & PBR_FILTER_SRC_IP) {
837 zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
838 vty_out(vty, "\tfrom %s", buf);
839 }
840 if (zpie->filter_bm & PBR_FILTER_SRC_PORT)
841 zebra_pbr_display_port(vty, zpie->filter_bm,
842 zpie->src_port_min,
843 zpie->src_port_max,
844 zpie->proto);
845 if (zpie->filter_bm & PBR_FILTER_DST_IP) {
846 zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
847 vty_out(vty, "\tto %s", buf);
848 }
849 if (zpie->filter_bm & PBR_FILTER_DST_PORT)
850 zebra_pbr_display_port(vty, zpie->filter_bm,
851 zpie->dst_port_min,
852 zpie->dst_port_max,
853 zpie->proto);
854 }
855 vty_out(vty, " (%u)\n", zpie->unique);
856
857 ret = hook_call(zebra_pbr_ipset_entry_wrap_script_get_stat,
858 zns, zpie, &pkts, &bytes);
859 if (ret && pkts > 0)
860 vty_out(vty, "\t pkts %" PRIu64 ", bytes %" PRIu64"\n",
861 pkts, bytes);
862 return HASHWALK_CONTINUE;
863 }
864
865 static int zebra_pbr_show_ipset_walkcb(struct hash_backet *backet, void *arg)
866 {
867 struct zebra_pbr_env_display *uniqueipset =
868 (struct zebra_pbr_env_display *)arg;
869 struct zebra_pbr_ipset *zpi = (struct zebra_pbr_ipset *)backet->data;
870 struct zebra_pbr_ipset_entry_unique_display unique;
871 struct vty *vty = uniqueipset->vty;
872 struct zebra_ns *zns = uniqueipset->zns;
873
874 vty_out(vty, "IPset %s type %s\n", zpi->ipset_name,
875 zebra_pbr_ipset_type2str(zpi->type));
876 unique.vty = vty;
877 unique.zpi = zpi;
878 unique.zns = zns;
879 hash_walk(zns->ipset_entry_hash, zebra_pbr_show_ipset_entry_walkcb,
880 &unique);
881 vty_out(vty, "\n");
882 return HASHWALK_CONTINUE;
883 }
884
885 /*
886 */
887 void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname)
888 {
889 struct zebra_pbr_ipset *zpi;
890 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
891 struct zebra_pbr_ipset_entry_unique_display unique;
892 struct zebra_pbr_env_display uniqueipset;
893
894 if (ipsetname) {
895 zpi = zebra_pbr_lookup_ipset_pername(zns, ipsetname);
896 if (!zpi) {
897 vty_out(vty, "No IPset %s found\n", ipsetname);
898 return;
899 }
900 vty_out(vty, "IPset %s type %s\n", ipsetname,
901 zebra_pbr_ipset_type2str(zpi->type));
902
903 unique.vty = vty;
904 unique.zpi = zpi;
905 unique.zns = zns;
906 hash_walk(zns->ipset_entry_hash,
907 zebra_pbr_show_ipset_entry_walkcb,
908 &unique);
909 return;
910 }
911 uniqueipset.zns = zns;
912 uniqueipset.vty = vty;
913 hash_walk(zns->ipset_hash, zebra_pbr_show_ipset_walkcb,
914 &uniqueipset);
915 }
916
917 struct pbr_rule_fwmark_lookup {
918 struct zebra_pbr_rule *ptr;
919 uint32_t fwmark;
920 };
921
922 static int zebra_pbr_rule_lookup_fwmark_walkcb(struct hash_backet *backet,
923 void *arg)
924 {
925 struct pbr_rule_fwmark_lookup *iprule =
926 (struct pbr_rule_fwmark_lookup *)arg;
927 struct zebra_pbr_rule *zpr = (struct zebra_pbr_rule *)backet->data;
928
929 if (iprule->fwmark == zpr->rule.filter.fwmark) {
930 iprule->ptr = zpr;
931 return HASHWALK_ABORT;
932 }
933 return HASHWALK_CONTINUE;
934 }
935
936 static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg)
937 {
938 struct zebra_pbr_iptable *iptable =
939 (struct zebra_pbr_iptable *)backet->data;
940 struct zebra_pbr_env_display *env = (struct zebra_pbr_env_display *)arg;
941 struct vty *vty = env->vty;
942 struct zebra_ns *zns = env->zns;
943 int ret;
944 uint64_t pkts = 0, bytes = 0;
945
946 vty_out(vty, "IPtable %s action %s (%u)\n", iptable->ipset_name,
947 iptable->action == ZEBRA_IPTABLES_DROP ? "drop" : "redirect",
948 iptable->unique);
949
950 ret = hook_call(zebra_pbr_iptable_wrap_script_get_stat,
951 zns, iptable, &pkts, &bytes);
952 if (ret && pkts > 0)
953 vty_out(vty, "\t pkts %" PRIu64 ", bytes %" PRIu64"\n",
954 pkts, bytes);
955 if (iptable->action != ZEBRA_IPTABLES_DROP) {
956 struct pbr_rule_fwmark_lookup prfl;
957
958 prfl.fwmark = iptable->fwmark;
959 prfl.ptr = NULL;
960 hash_walk(zns->rules_hash,
961 &zebra_pbr_rule_lookup_fwmark_walkcb, &prfl);
962 if (prfl.ptr) {
963 struct zebra_pbr_rule *zpr = prfl.ptr;
964
965 vty_out(vty, "\t table %u, fwmark %u\n",
966 zpr->rule.action.table,
967 prfl.fwmark);
968 }
969 }
970 return HASHWALK_CONTINUE;
971 }
972
973 void zebra_pbr_show_iptable(struct vty *vty)
974 {
975 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
976 struct zebra_pbr_env_display env;
977
978 env.vty = vty;
979 env.zns = zns;
980
981 hash_walk(zns->iptable_hash, zebra_pbr_show_iptable_walkcb,
982 &env);
983 }
984
985 void zebra_pbr_iptable_update_interfacelist(struct stream *s,
986 struct zebra_pbr_iptable *zpi)
987 {
988 uint32_t i = 0, index;
989 struct interface *ifp;
990 char *name;
991
992 for (i = 0; i < zpi->nb_interface; i++) {
993 STREAM_GETL(s, index);
994 ifp = if_lookup_by_index(index, zpi->vrf_id);
995 if (!ifp)
996 continue;
997 name = XSTRDUP(MTYPE_PBR_IPTABLE_IFNAME, ifp->name);
998 listnode_add(zpi->interface_name_list, name);
999 }
1000 stream_failure:
1001 return;
1002 }