]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_pbr.c
zebra: pbr vty show command for ipset and iptables
[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 static const struct message ipset_type_msg[] = {
33 {IPSET_NET_PORT_NET, "net,port,net"},
34 {IPSET_NET_PORT, "net,port"},
35 {IPSET_NET_NET, "net,net"},
36 {IPSET_NET, "net"},
37 {0}
38 };
39
40 /* static function declarations */
41
42 /* Private functions */
43
44 /* Public functions */
45 void zebra_pbr_rules_free(void *arg)
46 {
47 struct zebra_pbr_rule *rule;
48
49 rule = (struct zebra_pbr_rule *)arg;
50
51 kernel_del_pbr_rule(rule);
52 XFREE(MTYPE_TMP, rule);
53 }
54
55 uint32_t zebra_pbr_rules_hash_key(void *arg)
56 {
57 struct zebra_pbr_rule *rule;
58 uint32_t key;
59
60 rule = (struct zebra_pbr_rule *)arg;
61 key = jhash_3words(rule->rule.seq, rule->rule.priority,
62 rule->rule.action.table,
63 prefix_hash_key(&rule->rule.filter.src_ip));
64 if (rule->ifp)
65 key = jhash_1word(rule->ifp->ifindex, key);
66 else
67 key = jhash_1word(0, key);
68
69 if (rule->rule.filter.fwmark)
70 key = jhash_1word(rule->rule.filter.fwmark, key);
71 else
72 key = jhash_1word(0, key);
73 return jhash_3words(rule->rule.filter.src_port,
74 rule->rule.filter.dst_port,
75 prefix_hash_key(&rule->rule.filter.dst_ip),
76 jhash_1word(rule->rule.unique, key));
77 }
78
79 int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
80 {
81 const struct zebra_pbr_rule *r1, *r2;
82
83 r1 = (const struct zebra_pbr_rule *)arg1;
84 r2 = (const struct zebra_pbr_rule *)arg2;
85
86 if (r1->rule.seq != r2->rule.seq)
87 return 0;
88
89 if (r1->rule.priority != r2->rule.priority)
90 return 0;
91
92 if (r1->rule.unique != r2->rule.unique)
93 return 0;
94
95 if (r1->rule.action.table != r2->rule.action.table)
96 return 0;
97
98 if (r1->rule.filter.src_port != r2->rule.filter.src_port)
99 return 0;
100
101 if (r1->rule.filter.dst_port != r2->rule.filter.dst_port)
102 return 0;
103
104 if (r1->rule.filter.fwmark != r2->rule.filter.fwmark)
105 return 0;
106
107 if (!prefix_same(&r1->rule.filter.src_ip, &r2->rule.filter.src_ip))
108 return 0;
109
110 if (!prefix_same(&r1->rule.filter.dst_ip, &r2->rule.filter.dst_ip))
111 return 0;
112
113 if (r1->ifp != r2->ifp)
114 return 0;
115
116 return 1;
117 }
118
119 struct pbr_rule_unique_lookup {
120 struct zebra_pbr_rule *rule;
121 uint32_t unique;
122 struct interface *ifp;
123 };
124
125 static int pbr_rule_lookup_unique_walker(struct hash_backet *b, void *data)
126 {
127 struct pbr_rule_unique_lookup *pul = data;
128 struct zebra_pbr_rule *rule = b->data;
129
130 if (pul->unique == rule->rule.unique && pul->ifp == rule->ifp) {
131 pul->rule = rule;
132 return HASHWALK_ABORT;
133 }
134
135 return HASHWALK_CONTINUE;
136 }
137
138 static struct zebra_pbr_rule *pbr_rule_lookup_unique(struct zebra_ns *zns,
139 uint32_t unique,
140 struct interface *ifp)
141 {
142 struct pbr_rule_unique_lookup pul;
143
144 pul.unique = unique;
145 pul.ifp = ifp;
146 pul.rule = NULL;
147 hash_walk(zns->rules_hash, &pbr_rule_lookup_unique_walker, &pul);
148
149 return pul.rule;
150 }
151
152 void zebra_pbr_ipset_free(void *arg)
153 {
154 struct zebra_pbr_ipset *ipset;
155
156 ipset = (struct zebra_pbr_ipset *)arg;
157
158 XFREE(MTYPE_TMP, ipset);
159 }
160
161 uint32_t zebra_pbr_ipset_hash_key(void *arg)
162 {
163 struct zebra_pbr_ipset *ipset = (struct zebra_pbr_ipset *)arg;
164 uint32_t *pnt = (uint32_t *)&ipset->ipset_name;
165
166 return jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE, 0x63ab42de);
167 }
168
169 int zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2)
170 {
171 const struct zebra_pbr_ipset *r1, *r2;
172
173 r1 = (const struct zebra_pbr_ipset *)arg1;
174 r2 = (const struct zebra_pbr_ipset *)arg2;
175
176 if (r1->type != r2->type)
177 return 0;
178 if (r1->unique != r2->unique)
179 return 0;
180 if (strncmp(r1->ipset_name, r2->ipset_name,
181 ZEBRA_IPSET_NAME_SIZE))
182 return 0;
183 return 1;
184 }
185
186 void zebra_pbr_ipset_entry_free(void *arg)
187 {
188 struct zebra_pbr_ipset_entry *ipset;
189
190 ipset = (struct zebra_pbr_ipset_entry *)arg;
191
192 XFREE(MTYPE_TMP, ipset);
193 }
194
195 uint32_t zebra_pbr_ipset_entry_hash_key(void *arg)
196 {
197 struct zebra_pbr_ipset_entry *ipset;
198 uint32_t key;
199
200 ipset = (struct zebra_pbr_ipset_entry *)arg;
201 key = prefix_hash_key(&ipset->src);
202 key = jhash_1word(ipset->unique, key);
203 key = jhash_1word(prefix_hash_key(&ipset->dst), key);
204
205 return key;
206 }
207
208 int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2)
209 {
210 const struct zebra_pbr_ipset_entry *r1, *r2;
211
212 r1 = (const struct zebra_pbr_ipset_entry *)arg1;
213 r2 = (const struct zebra_pbr_ipset_entry *)arg2;
214
215 if (r1->unique != r2->unique)
216 return 0;
217
218 if (!prefix_same(&r1->src, &r2->src))
219 return 0;
220
221 if (!prefix_same(&r1->dst, &r2->dst))
222 return 0;
223
224 return 1;
225 }
226
227 void zebra_pbr_iptable_free(void *arg)
228 {
229 struct zebra_pbr_iptable *iptable;
230
231 iptable = (struct zebra_pbr_iptable *)arg;
232
233 XFREE(MTYPE_TMP, iptable);
234 }
235
236 uint32_t zebra_pbr_iptable_hash_key(void *arg)
237 {
238 struct zebra_pbr_iptable *iptable = (struct zebra_pbr_iptable *)arg;
239 uint32_t *pnt = (uint32_t *)&(iptable->ipset_name);
240 uint32_t key;
241
242 key = jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE,
243 0x63ab42de);
244 key = jhash_1word(iptable->fwmark, key);
245 return jhash_3words(iptable->filter_bm, iptable->type,
246 iptable->unique, key);
247 }
248
249 int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2)
250 {
251 const struct zebra_pbr_iptable *r1, *r2;
252
253 r1 = (const struct zebra_pbr_iptable *)arg1;
254 r2 = (const struct zebra_pbr_iptable *)arg2;
255
256 if (r1->type != r2->type)
257 return 0;
258 if (r1->unique != r2->unique)
259 return 0;
260 if (r1->filter_bm != r2->filter_bm)
261 return 0;
262 if (r1->fwmark != r2->fwmark)
263 return 0;
264 if (r1->action != r2->action)
265 return 0;
266 if (strncmp(r1->ipset_name, r2->ipset_name,
267 ZEBRA_IPSET_NAME_SIZE))
268 return 0;
269 return 1;
270 }
271
272 static void *pbr_rule_alloc_intern(void *arg)
273 {
274 struct zebra_pbr_rule *zpr;
275 struct zebra_pbr_rule *new;
276
277 zpr = (struct zebra_pbr_rule *)arg;
278
279 new = XCALLOC(MTYPE_TMP, sizeof(*new));
280
281 memcpy(new, zpr, sizeof(*zpr));
282
283 return new;
284 }
285
286 void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule)
287 {
288 struct zebra_pbr_rule *unique =
289 pbr_rule_lookup_unique(zns, rule->rule.unique, rule->ifp);
290
291 (void)hash_get(zns->rules_hash, rule, pbr_rule_alloc_intern);
292 kernel_add_pbr_rule(rule);
293
294 /*
295 * Rule Replace semantics, if we have an old, install the
296 * new rule, look above, and then delete the old
297 */
298 if (unique)
299 zebra_pbr_del_rule(zns, unique);
300 }
301
302 void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule)
303 {
304 struct zebra_pbr_rule *lookup;
305
306 lookup = hash_lookup(zns->rules_hash, rule);
307 kernel_del_pbr_rule(rule);
308
309 if (lookup) {
310 hash_release(zns->rules_hash, lookup);
311 XFREE(MTYPE_TMP, lookup);
312 } else
313 zlog_warn("%s: Rule being deleted we know nothing about",
314 __PRETTY_FUNCTION__);
315 }
316
317 static void zebra_pbr_cleanup_rules(struct hash_backet *b, void *data)
318 {
319 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
320 struct zebra_pbr_rule *rule = b->data;
321 int *sock = data;
322
323 if (rule->sock == *sock) {
324 kernel_del_pbr_rule(rule);
325 hash_release(zns->rules_hash, rule);
326 XFREE(MTYPE_TMP, rule);
327 }
328 }
329
330 static void zebra_pbr_cleanup_ipset(struct hash_backet *b, void *data)
331 {
332 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
333 struct zebra_pbr_ipset *ipset = b->data;
334 int *sock = data;
335
336 if (ipset->sock == *sock)
337 hash_release(zns->ipset_hash, ipset);
338 }
339
340 static void zebra_pbr_cleanup_ipset_entry(struct hash_backet *b, void *data)
341 {
342 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
343 struct zebra_pbr_ipset_entry *ipset = b->data;
344 int *sock = data;
345
346 if (ipset->sock == *sock)
347 hash_release(zns->ipset_entry_hash, ipset);
348 }
349
350 static void zebra_pbr_cleanup_iptable(struct hash_backet *b, void *data)
351 {
352 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
353 struct zebra_pbr_iptable *iptable = b->data;
354 int *sock = data;
355
356 if (iptable->sock == *sock)
357 hash_release(zns->iptable_hash, iptable);
358 }
359
360 static int zebra_pbr_client_close_cleanup(struct zserv *client)
361 {
362 int sock = client->sock;
363 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
364
365 if (!sock)
366 return 0;
367 hash_iterate(zns->rules_hash, zebra_pbr_cleanup_rules, &sock);
368 hash_iterate(zns->iptable_hash,
369 zebra_pbr_cleanup_iptable, &sock);
370 hash_iterate(zns->ipset_entry_hash,
371 zebra_pbr_cleanup_ipset_entry, &sock);
372 hash_iterate(zns->ipset_hash,
373 zebra_pbr_cleanup_ipset, &sock);
374 return 1;
375 }
376
377 void zebra_pbr_init(void)
378 {
379 hook_register(zapi_client_close, zebra_pbr_client_close_cleanup);
380 }
381
382 static void *pbr_ipset_alloc_intern(void *arg)
383 {
384 struct zebra_pbr_ipset *zpi;
385 struct zebra_pbr_ipset *new;
386
387 zpi = (struct zebra_pbr_ipset *)arg;
388
389 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset));
390
391 memcpy(new, zpi, sizeof(*zpi));
392
393 return new;
394 }
395
396 void zebra_pbr_create_ipset(struct zebra_ns *zns,
397 struct zebra_pbr_ipset *ipset)
398 {
399 (void)hash_get(zns->ipset_hash, ipset, pbr_ipset_alloc_intern);
400 /* TODO:
401 * - Netlink call
402 */
403 }
404
405 void zebra_pbr_destroy_ipset(struct zebra_ns *zns,
406 struct zebra_pbr_ipset *ipset)
407 {
408 struct zebra_pbr_ipset *lookup;
409
410 lookup = hash_lookup(zns->ipset_hash, ipset);
411 /* TODO:
412 * - Netlink destroy from kernel
413 * - ?? destroy ipset entries before
414 */
415 if (lookup) {
416 hash_release(zns->ipset_hash, lookup);
417 XFREE(MTYPE_TMP, lookup);
418 } else
419 zlog_warn("%s: IPSet Entry being deleted we know nothing about",
420 __PRETTY_FUNCTION__);
421 }
422
423 struct pbr_ipset_name_lookup {
424 struct zebra_pbr_ipset *ipset;
425 char ipset_name[ZEBRA_IPSET_NAME_SIZE];
426 };
427
428 static const char *zebra_pbr_ipset_type2str(uint32_t type)
429 {
430 return lookup_msg(ipset_type_msg, type,
431 "Unrecognized IPset Type");
432 }
433
434 static int zebra_pbr_ipset_pername_walkcb(struct hash_backet *backet, void *arg)
435 {
436 struct pbr_ipset_name_lookup *pinl =
437 (struct pbr_ipset_name_lookup *)arg;
438 struct zebra_pbr_ipset *zpi = (struct zebra_pbr_ipset *)backet->data;
439
440 if (!strncmp(pinl->ipset_name, zpi->ipset_name,
441 ZEBRA_IPSET_NAME_SIZE)) {
442 pinl->ipset = zpi;
443 return HASHWALK_ABORT;
444 }
445 return HASHWALK_CONTINUE;
446 }
447
448 struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(struct zebra_ns *zns,
449 char *ipsetname)
450 {
451 struct pbr_ipset_name_lookup pinl;
452 struct pbr_ipset_name_lookup *ptr = &pinl;
453
454 if (!ipsetname)
455 return NULL;
456 memset(ptr, 0, sizeof(struct pbr_ipset_name_lookup));
457 snprintf((char *)ptr->ipset_name, ZEBRA_IPSET_NAME_SIZE, "%s",
458 ipsetname);
459 hash_walk(zns->ipset_hash, zebra_pbr_ipset_pername_walkcb, ptr);
460 return ptr->ipset;
461 }
462
463 static void *pbr_ipset_entry_alloc_intern(void *arg)
464 {
465 struct zebra_pbr_ipset_entry *zpi;
466 struct zebra_pbr_ipset_entry *new;
467
468 zpi = (struct zebra_pbr_ipset_entry *)arg;
469
470 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset_entry));
471
472 memcpy(new, zpi, sizeof(*zpi));
473
474 return new;
475 }
476
477 void zebra_pbr_add_ipset_entry(struct zebra_ns *zns,
478 struct zebra_pbr_ipset_entry *ipset)
479 {
480 (void)hash_get(zns->ipset_entry_hash, ipset,
481 pbr_ipset_entry_alloc_intern);
482 /* TODO:
483 * - attach to ipset list
484 * - Netlink add to kernel
485 */
486 }
487
488 void zebra_pbr_del_ipset_entry(struct zebra_ns *zns,
489 struct zebra_pbr_ipset_entry *ipset)
490 {
491 struct zebra_pbr_ipset_entry *lookup;
492
493 lookup = hash_lookup(zns->ipset_entry_hash, ipset);
494 /* TODO:
495 * - Netlink destroy
496 * - detach from ipset list
497 * - ?? if no more entres, delete ipset
498 */
499 if (lookup) {
500 hash_release(zns->ipset_entry_hash, lookup);
501 XFREE(MTYPE_TMP, lookup);
502 } else
503 zlog_warn("%s: IPSet being deleted we know nothing about",
504 __PRETTY_FUNCTION__);
505 }
506
507 static void *pbr_iptable_alloc_intern(void *arg)
508 {
509 struct zebra_pbr_iptable *zpi;
510 struct zebra_pbr_iptable *new;
511
512 zpi = (struct zebra_pbr_iptable *)arg;
513
514 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable));
515
516 memcpy(new, zpi, sizeof(*zpi));
517
518 return new;
519 }
520
521 void zebra_pbr_add_iptable(struct zebra_ns *zns,
522 struct zebra_pbr_iptable *iptable)
523 {
524 (void)hash_get(zns->iptable_hash, iptable,
525 pbr_iptable_alloc_intern);
526 /* TODO call netlink layer */
527 }
528
529 void zebra_pbr_del_iptable(struct zebra_ns *zns,
530 struct zebra_pbr_iptable *iptable)
531 {
532 struct zebra_pbr_ipset_entry *lookup;
533
534 lookup = hash_lookup(zns->iptable_hash, iptable);
535 /* TODO:
536 * - call netlink layer
537 * - detach from iptable list
538 */
539 if (lookup)
540 XFREE(MTYPE_TMP, lookup);
541 else
542 zlog_warn("%s: IPTable being deleted we know nothing about",
543 __PRETTY_FUNCTION__);
544 }
545
546 /*
547 * Handle success or failure of rule (un)install in the kernel.
548 */
549 void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule,
550 enum southbound_results res)
551 {
552 switch (res) {
553 case SOUTHBOUND_INSTALL_SUCCESS:
554 zsend_rule_notify_owner(rule, ZAPI_RULE_INSTALLED);
555 break;
556 case SOUTHBOUND_INSTALL_FAILURE:
557 zsend_rule_notify_owner(rule, ZAPI_RULE_FAIL_INSTALL);
558 break;
559 case SOUTHBOUND_DELETE_SUCCESS:
560 zsend_rule_notify_owner(rule, ZAPI_RULE_REMOVED);
561 break;
562 case SOUTHBOUND_DELETE_FAILURE:
563 zsend_rule_notify_owner(rule, ZAPI_RULE_REMOVED);
564 break;
565 }
566 }
567
568 /*
569 * Handle success or failure of ipset (un)install in the kernel.
570 */
571 void kernel_pbr_ipset_add_del_status(struct zebra_pbr_ipset *ipset,
572 enum southbound_results res)
573 {
574 switch (res) {
575 case SOUTHBOUND_INSTALL_SUCCESS:
576 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_INSTALLED);
577 break;
578 case SOUTHBOUND_INSTALL_FAILURE:
579 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_INSTALL);
580 break;
581 case SOUTHBOUND_DELETE_SUCCESS:
582 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_REMOVED);
583 break;
584 case SOUTHBOUND_DELETE_FAILURE:
585 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_REMOVED);
586 break;
587 }
588 }
589
590 /*
591 * Handle success or failure of ipset (un)install in the kernel.
592 */
593 void kernel_pbr_ipset_entry_add_del_status(
594 struct zebra_pbr_ipset_entry *ipset,
595 enum southbound_results res)
596 {
597 switch (res) {
598 case SOUTHBOUND_INSTALL_SUCCESS:
599 zsend_ipset_entry_notify_owner(ipset,
600 ZAPI_IPSET_ENTRY_INSTALLED);
601 break;
602 case SOUTHBOUND_INSTALL_FAILURE:
603 zsend_ipset_entry_notify_owner(ipset,
604 ZAPI_IPSET_ENTRY_FAIL_INSTALL);
605 break;
606 case SOUTHBOUND_DELETE_SUCCESS:
607 zsend_ipset_entry_notify_owner(ipset,
608 ZAPI_IPSET_ENTRY_REMOVED);
609 break;
610 case SOUTHBOUND_DELETE_FAILURE:
611 zsend_ipset_entry_notify_owner(ipset,
612 ZAPI_IPSET_ENTRY_REMOVED);
613 break;
614 }
615 }
616
617 /*
618 * Handle success or failure of ipset (un)install in the kernel.
619 */
620 void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable,
621 enum southbound_results res)
622 {
623 switch (res) {
624 case SOUTHBOUND_INSTALL_SUCCESS:
625 zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_INSTALLED);
626 break;
627 case SOUTHBOUND_INSTALL_FAILURE:
628 zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_FAIL_INSTALL);
629 break;
630 case SOUTHBOUND_DELETE_SUCCESS:
631 zsend_iptable_notify_owner(iptable,
632 ZAPI_IPTABLE_REMOVED);
633 break;
634 case SOUTHBOUND_DELETE_FAILURE:
635 zsend_iptable_notify_owner(iptable,
636 ZAPI_IPTABLE_REMOVED);
637 break;
638 }
639 }
640
641 /*
642 * Handle rule delete notification from kernel.
643 */
644 int kernel_pbr_rule_del(struct zebra_pbr_rule *rule)
645 {
646 return 0;
647 }
648
649 struct zebra_pbr_ipset_entry_unique_display {
650 struct zebra_pbr_ipset *zpi;
651 struct vty *vty;
652 };
653
654 struct zebra_pbr_env_display {
655 struct zebra_ns *zns;
656 struct vty *vty;
657 };
658
659 static const char *zebra_pbr_prefix2str(union prefixconstptr pu,
660 char *str, int size)
661 {
662 const struct prefix *p = pu.p;
663 char buf[PREFIX2STR_BUFFER];
664
665 if (p->family == AF_INET && p->prefixlen == IPV4_MAX_PREFIXLEN) {
666 snprintf(str, size, "%s", inet_ntop(p->family, &p->u.prefix,
667 buf, PREFIX2STR_BUFFER));
668 return str;
669 }
670 return prefix2str(pu, str, size);
671 }
672
673 static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
674 void *arg)
675 {
676 struct zebra_pbr_ipset_entry_unique_display *unique =
677 (struct zebra_pbr_ipset_entry_unique_display *)arg;
678 struct zebra_pbr_ipset *zpi = unique->zpi;
679 struct vty *vty = unique->vty;
680 struct zebra_pbr_ipset_entry *zpie =
681 (struct zebra_pbr_ipset_entry *)backet->data;
682
683 if (zpie->backpointer != zpi)
684 return HASHWALK_CONTINUE;
685
686 if (zpi->type == IPSET_NET_NET) {
687 char buf[PREFIX_STRLEN];
688
689 zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
690 vty_out(vty, "\tfrom %s", buf);
691 vty_out(vty, " to ");
692 zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
693 vty_out(vty, "%s", buf);
694 } else if (zpi->type == IPSET_NET) {
695 char buf[PREFIX_STRLEN];
696
697 if (zpie->filter_bm & PBR_FILTER_SRC_IP) {
698 zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
699 vty_out(vty, "\tfrom %s", buf);
700 }
701 if (zpie->filter_bm & PBR_FILTER_DST_IP) {
702 zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
703 vty_out(vty, "\tto %s", buf);
704 }
705 }
706 vty_out(vty, " (%u)\n", zpie->unique);
707
708 return HASHWALK_CONTINUE;
709 }
710
711 static int zebra_pbr_show_ipset_walkcb(struct hash_backet *backet, void *arg)
712 {
713 struct zebra_pbr_env_display *uniqueipset =
714 (struct zebra_pbr_env_display *)arg;
715 struct zebra_pbr_ipset *zpi = (struct zebra_pbr_ipset *)backet->data;
716 struct zebra_pbr_ipset_entry_unique_display unique;
717 struct vty *vty = uniqueipset->vty;
718 struct zebra_ns *zns = uniqueipset->zns;
719
720 vty_out(vty, "IPset %s type %s\n", zpi->ipset_name,
721 zebra_pbr_ipset_type2str(zpi->type));
722 unique.vty = vty;
723 unique.zpi = zpi;
724
725 hash_walk(zns->ipset_entry_hash, zebra_pbr_show_ipset_entry_walkcb,
726 &unique);
727 vty_out(vty, "\n");
728 return HASHWALK_CONTINUE;
729 }
730
731 /*
732 */
733 void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname)
734 {
735 struct zebra_pbr_ipset *zpi;
736 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
737 struct zebra_pbr_ipset_entry_unique_display unique;
738 struct zebra_pbr_env_display uniqueipset;
739
740 if (ipsetname) {
741 zpi = zebra_pbr_lookup_ipset_pername(zns, ipsetname);
742 if (!zpi) {
743 vty_out(vty, "No IPset %s found\n", ipsetname);
744 return;
745 }
746 vty_out(vty, "IPset %s type %s\n", ipsetname,
747 zebra_pbr_ipset_type2str(zpi->type));
748
749 unique.vty = vty;
750 unique.zpi = zpi;
751
752 hash_walk(zns->ipset_entry_hash,
753 zebra_pbr_show_ipset_entry_walkcb,
754 &unique);
755 return;
756 }
757 uniqueipset.zns = zns;
758 uniqueipset.vty = vty;
759 hash_walk(zns->ipset_hash, zebra_pbr_show_ipset_walkcb,
760 &uniqueipset);
761 }
762
763 struct pbr_rule_fwmark_lookup {
764 struct zebra_pbr_rule *ptr;
765 uint32_t fwmark;
766 };
767
768 static int zebra_pbr_rule_lookup_fwmark_walkcb(struct hash_backet *backet,
769 void *arg)
770 {
771 struct pbr_rule_fwmark_lookup *iprule =
772 (struct pbr_rule_fwmark_lookup *)arg;
773 struct zebra_pbr_rule *zpr = (struct zebra_pbr_rule *)backet->data;
774
775 if (iprule->fwmark == zpr->rule.filter.fwmark) {
776 iprule->ptr = zpr;
777 return HASHWALK_ABORT;
778 }
779 return HASHWALK_CONTINUE;
780 }
781
782 static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg)
783 {
784 struct zebra_pbr_iptable *iptable =
785 (struct zebra_pbr_iptable *)backet->data;
786 struct zebra_pbr_env_display *env = (struct zebra_pbr_env_display *)arg;
787 struct vty *vty = env->vty;
788 struct zebra_ns *zns = env->zns;
789
790 vty_out(vty, "IPtable %s action %s (%u)\n", iptable->ipset_name,
791 iptable->action == ZEBRA_IPTABLES_DROP ? "drop" : "redirect",
792 iptable->unique);
793
794 if (iptable->action != ZEBRA_IPTABLES_DROP) {
795 struct pbr_rule_fwmark_lookup prfl;
796
797 prfl.fwmark = iptable->fwmark;
798 prfl.ptr = NULL;
799 hash_walk(zns->rules_hash,
800 &zebra_pbr_rule_lookup_fwmark_walkcb, &prfl);
801 if (prfl.ptr) {
802 struct zebra_pbr_rule *zpr = prfl.ptr;
803
804 vty_out(vty, "\t table %u, fwmark %u\n",
805 zpr->rule.action.table,
806 prfl.fwmark);
807 }
808 }
809 return HASHWALK_CONTINUE;
810 }
811
812 void zebra_pbr_show_iptable(struct vty *vty)
813 {
814 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
815 struct zebra_pbr_env_display env;
816
817 env.vty = vty;
818 env.zns = zns;
819
820 hash_walk(zns->iptable_hash, zebra_pbr_show_iptable_walkcb,
821 &env);
822 }