1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Zebra Policy Based Routing (PBR) main handling.
3 * Copyright (C) 2018 Cumulus Networks, Inc.
13 #include "zebra/zebra_router.h"
14 #include "zebra/zebra_pbr.h"
16 #include "zebra/zapi_msg.h"
17 #include "zebra/zserv.h"
18 #include "zebra/debug.h"
19 #include "zebra/zebra_neigh.h"
22 DEFINE_MTYPE_STATIC(ZEBRA
, PBR_IPTABLE_IFNAME
, "PBR interface list");
23 DEFINE_MTYPE(ZEBRA
, PBR_OBJ
, "PBR");
26 static const struct message ipset_type_msg
[] = {
27 {IPSET_NET_PORT_NET
, "net,port,net"},
28 {IPSET_NET_PORT
, "net,port"},
29 {IPSET_NET_NET
, "net,net"},
34 const struct message icmp_typecode_str
[] = {
35 { 0 << 8, "echo-reply"},
37 { 3 << 8, "network-unreachable"},
38 { (3 << 8) + 1, "host-unreachable"},
39 { (3 << 8) + 2, "protocol-unreachable"},
40 { (3 << 8) + 3, "port-unreachable"},
41 { (3 << 8) + 4, "fragmentation-needed"},
42 { (3 << 8) + 5, "source-route-failed"},
43 { (3 << 8) + 6, "network-unknown"},
44 { (3 << 8) + 7, "host-unknown"},
45 { (3 << 8) + 9, "network-prohibited"},
46 { (3 << 8) + 10, "host-prohibited"},
47 { (3 << 8) + 11, "TOS-network-unreachable"},
48 { (3 << 8) + 12, "TOS-host-unreachable"},
49 { (3 << 8) + 13, "communication-prohibited"},
50 { (3 << 8) + 14, "host-precedence-violation"},
51 { (3 << 8) + 15, "precedence-cutoff"},
52 { 4 << 8, "source-quench"},
53 { 5 << 8, "network-redirect"},
54 { (5 << 8) + 1, "host-redirect"},
55 { (5 << 8) + 2, "TOS-network-redirect"},
56 { (5 << 8) + 3, "TOS-host-redirect"},
57 { 8 << 8, "echo-request"},
59 { 9 << 8, "router-advertisement"},
60 { 10 << 8, "router-solicitation"},
61 { 11 << 8, "ttl-zero-during-transit"},
62 { (11 << 8) + 1, "ttl-zero-during-reassembly"},
63 { 12 << 8, "ip-header-bad"},
64 { (12 << 8) + 1, "required-option-missing"},
65 { 13 << 8, "timestamp-request"},
66 { 14 << 8, "timestamp-reply"},
67 { 17 << 8, "address-mask-request"},
68 { 18 << 8, "address-mask-reply"},
72 const struct message icmpv6_typecode_str
[] = {
73 { 128 << 8, "echo-request"},
74 { 129 << 8, "echo-reply"},
75 { 1 << 8, "no-route"},
76 { (1 << 8) + 1, "communication-prohibited"},
77 { (1 << 8) + 3, "address-unreachable"},
78 { (1 << 8) + 4, "port-unreachable"},
79 { (2 << 8), "packet-too-big"},
80 { 3 << 0, "ttl-zero-during-transit"},
81 { (3 << 8) + 1, "ttl-zero-during-reassembly"},
82 { 4 << 0, "bad-header"},
83 { (4 << 0) + 1, "unknown-header-type"},
84 { (4 << 0) + 2, "unknown-option"},
85 { 133 << 8, "router-solicitation"},
86 { 134 << 8, "router-advertisement"},
87 { 135 << 8, "neighbor-solicitation"},
88 { 136 << 8, "neighbor-advertisement"},
89 { 137 << 8, "redirect"},
94 static const struct message tcp_value_str
[] = {
95 {TCP_HEADER_FIN
, "FIN"},
96 {TCP_HEADER_SYN
, "SYN"},
97 {TCP_HEADER_RST
, "RST"},
98 {TCP_HEADER_PSH
, "PSH"},
99 {TCP_HEADER_ACK
, "ACK"},
100 {TCP_HEADER_URG
, "URG"},
104 static const struct message fragment_value_str
[] = {
105 {1, "dont-fragment"},
107 {4, "first-fragment"},
108 {8, "last-fragment"},
112 struct zebra_pbr_env_display
{
113 struct zebra_ns
*zns
;
118 /* static function declarations */
119 DEFINE_HOOK(zebra_pbr_ipset_entry_get_stat
,
120 (struct zebra_pbr_ipset_entry
*ipset
, uint64_t *pkts
,
122 (ipset
, pkts
, bytes
));
124 DEFINE_HOOK(zebra_pbr_iptable_get_stat
,
125 (struct zebra_pbr_iptable
*iptable
, uint64_t *pkts
,
127 (iptable
, pkts
, bytes
));
129 DEFINE_HOOK(zebra_pbr_iptable_update
,
130 (int cmd
, struct zebra_pbr_iptable
*iptable
), (cmd
, iptable
));
132 DEFINE_HOOK(zebra_pbr_ipset_entry_update
,
133 (int cmd
, struct zebra_pbr_ipset_entry
*ipset
), (cmd
, ipset
));
135 DEFINE_HOOK(zebra_pbr_ipset_update
,
136 (int cmd
, struct zebra_pbr_ipset
*ipset
), (cmd
, ipset
));
138 /* resolve nexthop for dataplane (dpdk) programming */
139 static bool zebra_pbr_expand_action
;
141 /* Private functions */
143 /* Public functions */
144 void zebra_pbr_rules_free(void *arg
)
146 struct zebra_pbr_rule
*rule
;
148 rule
= (struct zebra_pbr_rule
*)arg
;
150 (void)dplane_pbr_rule_delete(rule
);
151 XFREE(MTYPE_PBR_OBJ
, rule
);
154 uint32_t zebra_pbr_rules_hash_key(const void *arg
)
156 const struct zebra_pbr_rule
*rule
;
160 key
= jhash_3words(rule
->rule
.seq
, rule
->rule
.priority
,
161 rule
->rule
.action
.table
,
162 prefix_hash_key(&rule
->rule
.filter
.src_ip
));
164 key
= jhash_3words(rule
->rule
.filter
.fwmark
, rule
->vrf_id
,
165 rule
->rule
.filter
.ip_proto
, key
);
167 key
= jhash(rule
->ifname
, strlen(rule
->ifname
), key
);
169 return jhash_3words(rule
->rule
.filter
.src_port
,
170 rule
->rule
.filter
.dst_port
,
171 prefix_hash_key(&rule
->rule
.filter
.dst_ip
),
172 jhash_1word(rule
->rule
.unique
, key
));
175 bool zebra_pbr_rules_hash_equal(const void *arg1
, const void *arg2
)
177 const struct zebra_pbr_rule
*r1
, *r2
;
179 r1
= (const struct zebra_pbr_rule
*)arg1
;
180 r2
= (const struct zebra_pbr_rule
*)arg2
;
182 if (r1
->rule
.seq
!= r2
->rule
.seq
)
185 if (r1
->rule
.priority
!= r2
->rule
.priority
)
188 if (r1
->rule
.unique
!= r2
->rule
.unique
)
191 if (r1
->rule
.action
.table
!= r2
->rule
.action
.table
)
194 if (r1
->rule
.filter
.src_port
!= r2
->rule
.filter
.src_port
)
197 if (r1
->rule
.filter
.dst_port
!= r2
->rule
.filter
.dst_port
)
200 if (r1
->rule
.filter
.fwmark
!= r2
->rule
.filter
.fwmark
)
203 if (r1
->rule
.filter
.ip_proto
!= r2
->rule
.filter
.ip_proto
)
206 if (!prefix_same(&r1
->rule
.filter
.src_ip
, &r2
->rule
.filter
.src_ip
))
209 if (!prefix_same(&r1
->rule
.filter
.dst_ip
, &r2
->rule
.filter
.dst_ip
))
212 if (strcmp(r1
->rule
.ifname
, r2
->rule
.ifname
) != 0)
215 if (r1
->vrf_id
!= r2
->vrf_id
)
221 struct pbr_rule_unique_lookup
{
222 struct zebra_pbr_rule
*rule
;
224 char ifname
[INTERFACE_NAMSIZ
+ 1];
228 static int pbr_rule_lookup_unique_walker(struct hash_bucket
*b
, void *data
)
230 struct pbr_rule_unique_lookup
*pul
= data
;
231 struct zebra_pbr_rule
*rule
= b
->data
;
233 if (pul
->unique
== rule
->rule
.unique
234 && strncmp(pul
->ifname
, rule
->rule
.ifname
, INTERFACE_NAMSIZ
) == 0
235 && pul
->vrf_id
== rule
->vrf_id
) {
237 return HASHWALK_ABORT
;
240 return HASHWALK_CONTINUE
;
243 static struct zebra_pbr_rule
*
244 pbr_rule_lookup_unique(struct zebra_pbr_rule
*zrule
)
246 struct pbr_rule_unique_lookup pul
;
248 pul
.unique
= zrule
->rule
.unique
;
249 strlcpy(pul
.ifname
, zrule
->rule
.ifname
, INTERFACE_NAMSIZ
);
251 pul
.vrf_id
= zrule
->vrf_id
;
252 hash_walk(zrouter
.rules_hash
, &pbr_rule_lookup_unique_walker
, &pul
);
257 void zebra_pbr_ipset_free(void *arg
)
259 struct zebra_pbr_ipset
*ipset
;
261 ipset
= (struct zebra_pbr_ipset
*)arg
;
262 hook_call(zebra_pbr_ipset_update
, 0, ipset
);
263 XFREE(MTYPE_PBR_OBJ
, ipset
);
266 uint32_t zebra_pbr_ipset_hash_key(const void *arg
)
268 const struct zebra_pbr_ipset
*ipset
= arg
;
269 uint32_t *pnt
= (uint32_t *)&ipset
->ipset_name
;
270 uint32_t key
= jhash_1word(ipset
->vrf_id
, 0x63ab42de);
272 key
= jhash_1word(ipset
->family
, key
);
274 return jhash2(pnt
, ZEBRA_IPSET_NAME_HASH_SIZE
, key
);
277 bool zebra_pbr_ipset_hash_equal(const void *arg1
, const void *arg2
)
279 const struct zebra_pbr_ipset
*r1
, *r2
;
281 r1
= (const struct zebra_pbr_ipset
*)arg1
;
282 r2
= (const struct zebra_pbr_ipset
*)arg2
;
284 if (r1
->type
!= r2
->type
)
286 if (r1
->unique
!= r2
->unique
)
288 if (r1
->vrf_id
!= r2
->vrf_id
)
290 if (r1
->family
!= r2
->family
)
293 if (strncmp(r1
->ipset_name
, r2
->ipset_name
,
294 ZEBRA_IPSET_NAME_SIZE
))
299 void zebra_pbr_ipset_entry_free(void *arg
)
301 struct zebra_pbr_ipset_entry
*ipset
;
303 ipset
= (struct zebra_pbr_ipset_entry
*)arg
;
305 hook_call(zebra_pbr_ipset_entry_update
, 0, ipset
);
307 XFREE(MTYPE_PBR_OBJ
, ipset
);
310 uint32_t zebra_pbr_ipset_entry_hash_key(const void *arg
)
312 const struct zebra_pbr_ipset_entry
*ipset
;
316 key
= prefix_hash_key(&ipset
->src
);
317 key
= jhash_1word(ipset
->unique
, key
);
318 key
= jhash_1word(prefix_hash_key(&ipset
->dst
), key
);
319 key
= jhash(&ipset
->dst_port_min
, 2, key
);
320 key
= jhash(&ipset
->dst_port_max
, 2, key
);
321 key
= jhash(&ipset
->src_port_min
, 2, key
);
322 key
= jhash(&ipset
->src_port_max
, 2, key
);
323 key
= jhash(&ipset
->proto
, 1, key
);
328 bool zebra_pbr_ipset_entry_hash_equal(const void *arg1
, const void *arg2
)
330 const struct zebra_pbr_ipset_entry
*r1
, *r2
;
332 r1
= (const struct zebra_pbr_ipset_entry
*)arg1
;
333 r2
= (const struct zebra_pbr_ipset_entry
*)arg2
;
335 if (r1
->unique
!= r2
->unique
)
338 if (!prefix_same(&r1
->src
, &r2
->src
))
341 if (!prefix_same(&r1
->dst
, &r2
->dst
))
344 if (r1
->src_port_min
!= r2
->src_port_min
)
347 if (r1
->src_port_max
!= r2
->src_port_max
)
350 if (r1
->dst_port_min
!= r2
->dst_port_min
)
353 if (r1
->dst_port_max
!= r2
->dst_port_max
)
356 if (r1
->proto
!= r2
->proto
)
361 /* this function gives option to flush plugin memory contexts
362 * with all parameter. set it to true to flush all
363 * set it to false to flush only passed arg argument
365 static void _zebra_pbr_iptable_free_all(void *arg
, bool all
)
367 struct zebra_pbr_iptable
*iptable
;
368 struct listnode
*node
, *nnode
;
371 iptable
= (struct zebra_pbr_iptable
*)arg
;
374 hook_call(zebra_pbr_iptable_update
, 0, iptable
);
376 if (iptable
->interface_name_list
) {
377 for (ALL_LIST_ELEMENTS(iptable
->interface_name_list
, node
,
379 XFREE(MTYPE_PBR_IPTABLE_IFNAME
, name
);
380 list_delete_node(iptable
->interface_name_list
, node
);
382 list_delete(&iptable
->interface_name_list
);
384 XFREE(MTYPE_PBR_OBJ
, iptable
);
387 void zebra_pbr_iptable_free(void *arg
)
389 _zebra_pbr_iptable_free_all(arg
, false);
392 uint32_t zebra_pbr_iptable_hash_key(const void *arg
)
394 const struct zebra_pbr_iptable
*iptable
= arg
;
395 uint32_t *pnt
= (uint32_t *)&(iptable
->ipset_name
);
398 key
= jhash2(pnt
, ZEBRA_IPSET_NAME_HASH_SIZE
,
400 key
= jhash_1word(iptable
->fwmark
, key
);
401 key
= jhash_1word(iptable
->family
, key
);
402 key
= jhash_1word(iptable
->flow_label
, key
);
403 key
= jhash_1word(iptable
->pkt_len_min
, key
);
404 key
= jhash_1word(iptable
->pkt_len_max
, key
);
405 key
= jhash_1word(iptable
->tcp_flags
, key
);
406 key
= jhash_1word(iptable
->tcp_mask_flags
, key
);
407 key
= jhash_1word(iptable
->dscp_value
, key
);
408 key
= jhash_1word(iptable
->protocol
, key
);
409 key
= jhash_1word(iptable
->fragment
, key
);
410 key
= jhash_1word(iptable
->vrf_id
, key
);
412 return jhash_3words(iptable
->filter_bm
, iptable
->type
,
413 iptable
->unique
, key
);
416 bool zebra_pbr_iptable_hash_equal(const void *arg1
, const void *arg2
)
418 const struct zebra_pbr_iptable
*r1
, *r2
;
420 r1
= (const struct zebra_pbr_iptable
*)arg1
;
421 r2
= (const struct zebra_pbr_iptable
*)arg2
;
423 if (r1
->vrf_id
!= r2
->vrf_id
)
425 if (r1
->type
!= r2
->type
)
427 if (r1
->unique
!= r2
->unique
)
429 if (r1
->filter_bm
!= r2
->filter_bm
)
431 if (r1
->fwmark
!= r2
->fwmark
)
433 if (r1
->action
!= r2
->action
)
435 if (strncmp(r1
->ipset_name
, r2
->ipset_name
,
436 ZEBRA_IPSET_NAME_SIZE
))
438 if (r1
->family
!= r2
->family
)
440 if (r1
->flow_label
!= r2
->flow_label
)
442 if (r1
->pkt_len_min
!= r2
->pkt_len_min
)
444 if (r1
->pkt_len_max
!= r2
->pkt_len_max
)
446 if (r1
->tcp_flags
!= r2
->tcp_flags
)
448 if (r1
->tcp_mask_flags
!= r2
->tcp_mask_flags
)
450 if (r1
->dscp_value
!= r2
->dscp_value
)
452 if (r1
->fragment
!= r2
->fragment
)
454 if (r1
->protocol
!= r2
->protocol
)
459 static void *pbr_rule_alloc_intern(void *arg
)
461 struct zebra_pbr_rule
*zpr
;
462 struct zebra_pbr_rule
*new;
464 zpr
= (struct zebra_pbr_rule
*)arg
;
466 new = XCALLOC(MTYPE_PBR_OBJ
, sizeof(*new));
468 memcpy(new, zpr
, sizeof(*zpr
));
473 static struct zebra_pbr_rule
*pbr_rule_free(struct zebra_pbr_rule
*hash_data
,
476 if (hash_data
->action
.neigh
)
477 zebra_neigh_deref(hash_data
);
478 hash_release(zrouter
.rules_hash
, hash_data
);
480 XFREE(MTYPE_PBR_OBJ
, hash_data
);
487 static struct zebra_pbr_rule
*pbr_rule_release(struct zebra_pbr_rule
*rule
,
490 struct zebra_pbr_rule
*lookup
;
492 lookup
= hash_lookup(zrouter
.rules_hash
, rule
);
497 return pbr_rule_free(lookup
, free_data
);
500 void zebra_pbr_show_rule_unit(struct zebra_pbr_rule
*rule
, struct vty
*vty
)
502 struct pbr_rule
*prule
= &rule
->rule
;
503 struct zebra_pbr_action
*zaction
= &rule
->action
;
505 vty_out(vty
, "Rules if %s\n", rule
->ifname
);
506 vty_out(vty
, " Seq %u pri %u\n", prule
->seq
, prule
->priority
);
507 if (prule
->filter
.filter_bm
& PBR_FILTER_SRC_IP
)
508 vty_out(vty
, " SRC IP Match: %pFX\n", &prule
->filter
.src_ip
);
509 if (prule
->filter
.filter_bm
& PBR_FILTER_DST_IP
)
510 vty_out(vty
, " DST IP Match: %pFX\n", &prule
->filter
.dst_ip
);
511 if (prule
->filter
.filter_bm
& PBR_FILTER_IP_PROTOCOL
)
512 vty_out(vty
, " IP protocol Match: %u\n",
513 prule
->filter
.ip_proto
);
514 if (prule
->filter
.filter_bm
& PBR_FILTER_SRC_PORT
)
515 vty_out(vty
, " SRC Port Match: %u\n", prule
->filter
.src_port
);
516 if (prule
->filter
.filter_bm
& PBR_FILTER_DST_PORT
)
517 vty_out(vty
, " DST Port Match: %u\n", prule
->filter
.dst_port
);
519 if (prule
->filter
.filter_bm
& PBR_FILTER_DSFIELD
) {
520 vty_out(vty
, " DSCP Match: %u\n",
521 (prule
->filter
.dsfield
& PBR_DSFIELD_DSCP
) >> 2);
522 vty_out(vty
, " ECN Match: %u\n",
523 prule
->filter
.dsfield
& PBR_DSFIELD_ECN
);
526 if (prule
->filter
.filter_bm
& PBR_FILTER_FWMARK
)
527 vty_out(vty
, " MARK Match: %u\n", prule
->filter
.fwmark
);
529 vty_out(vty
, " Tableid: %u\n", prule
->action
.table
);
530 if (zaction
->afi
== AFI_IP
)
531 vty_out(vty
, " Action: nh: %pI4 intf: %s\n",
533 ifindex2ifname(zaction
->ifindex
, rule
->vrf_id
));
534 if (zaction
->afi
== AFI_IP6
)
535 vty_out(vty
, " Action: nh: %pI6 intf: %s\n",
537 ifindex2ifname(zaction
->ifindex
, rule
->vrf_id
));
538 if (zaction
->neigh
&& (zaction
->neigh
->flags
& ZEBRA_NEIGH_ENT_ACTIVE
))
539 vty_out(vty
, " Action: mac: %pEA\n", &zaction
->neigh
->mac
);
542 static int zebra_pbr_show_rules_walkcb(struct hash_bucket
*bucket
, void *arg
)
544 struct zebra_pbr_rule
*rule
= (struct zebra_pbr_rule
*)bucket
->data
;
545 struct zebra_pbr_env_display
*env
= (struct zebra_pbr_env_display
*)arg
;
546 struct vty
*vty
= env
->vty
;
548 zebra_pbr_show_rule_unit(rule
, vty
);
550 return HASHWALK_CONTINUE
;
553 void zebra_pbr_show_rule(struct vty
*vty
)
555 struct zebra_pbr_env_display env
;
558 hash_walk(zrouter
.rules_hash
, zebra_pbr_show_rules_walkcb
, &env
);
561 void zebra_pbr_config_write(struct vty
*vty
)
563 if (zebra_pbr_expand_action
)
564 vty_out(vty
, "pbr nexthop-resolve\n");
567 void zebra_pbr_expand_action_update(bool enable
)
569 zebra_pbr_expand_action
= enable
;
572 static void zebra_pbr_expand_rule(struct zebra_pbr_rule
*rule
)
575 struct route_table
*table
;
576 struct route_node
*rn
;
578 struct route_entry
*re
;
579 const struct nexthop_group
*nhg
;
580 const struct nexthop
*nexthop
;
581 struct zebra_pbr_action
*action
= &rule
->action
;
584 if (!zebra_pbr_expand_action
)
587 table
= zebra_vrf_get_table_with_table_id(
588 AFI_IP
, SAFI_UNICAST
, VRF_DEFAULT
, rule
->rule
.action
.table
);
592 memset(&p
, 0, sizeof(p
));
595 rn
= route_node_lookup(table
, &p
);
599 dest
= rib_dest_from_rnode(rn
);
600 re
= dest
->selected_fib
;
602 route_unlock_node(rn
);
606 nhg
= rib_get_fib_nhg(re
);
608 route_unlock_node(rn
);
612 nexthop
= nhg
->nexthop
;
614 switch (nexthop
->type
) {
615 case NEXTHOP_TYPE_IPV4
:
616 case NEXTHOP_TYPE_IPV4_IFINDEX
:
617 action
->afi
= AFI_IP
;
618 action
->gate
.ipv4
= nexthop
->gate
.ipv4
;
619 action
->ifindex
= nexthop
->ifindex
;
620 ip
.ipa_type
= AF_INET
;
621 ip
.ipaddr_v4
= action
->gate
.ipv4
;
622 zebra_neigh_ref(action
->ifindex
, &ip
, rule
);
625 case NEXTHOP_TYPE_IPV6
:
626 case NEXTHOP_TYPE_IPV6_IFINDEX
:
627 action
->afi
= AFI_IP6
;
628 action
->gate
.ipv6
= nexthop
->gate
.ipv6
;
629 action
->ifindex
= nexthop
->ifindex
;
630 ip
.ipa_type
= AF_INET6
;
631 ip
.ipaddr_v6
= action
->gate
.ipv6
;
632 zebra_neigh_ref(action
->ifindex
, &ip
, rule
);
635 case NEXTHOP_TYPE_BLACKHOLE
:
636 case NEXTHOP_TYPE_IFINDEX
:
637 action
->afi
= AFI_UNSPEC
;
641 route_unlock_node(rn
);
644 void zebra_pbr_add_rule(struct zebra_pbr_rule
*rule
)
646 struct zebra_pbr_rule
*found
;
647 struct zebra_pbr_rule
*old
;
648 struct zebra_pbr_rule
*new;
651 * Check if we already have it (this checks via a unique ID, walking
652 * over the hash table, not via a hash operation).
654 found
= pbr_rule_lookup_unique(rule
);
656 /* If found, this is an update */
658 if (IS_ZEBRA_DEBUG_PBR
)
660 "%s: seq: %d, prior: %d, unique: %d, ifname: %s -- update",
661 __func__
, rule
->rule
.seq
, rule
->rule
.priority
,
662 rule
->rule
.unique
, rule
->rule
.ifname
);
664 /* remove the old entry from the hash but don't free the hash
665 * data yet as we need it for the dplane update
667 old
= pbr_rule_release(found
, false);
669 /* insert new entry into hash */
670 new = hash_get(zrouter
.rules_hash
, rule
, pbr_rule_alloc_intern
);
671 /* expand the action if needed */
672 zebra_pbr_expand_rule(new);
673 /* update dataplane */
674 (void)dplane_pbr_rule_update(found
, new);
675 /* release the old hash data */
677 XFREE(MTYPE_PBR_OBJ
, old
);
679 if (IS_ZEBRA_DEBUG_PBR
)
681 "%s: seq: %d, prior: %d, unique: %d, ifname: %s -- new",
682 __func__
, rule
->rule
.seq
, rule
->rule
.priority
,
683 rule
->rule
.unique
, rule
->rule
.ifname
);
685 /* insert new entry into hash */
686 new = hash_get(zrouter
.rules_hash
, rule
, pbr_rule_alloc_intern
);
687 /* expand the action if needed */
688 zebra_pbr_expand_rule(new);
689 (void)dplane_pbr_rule_add(new);
694 void zebra_pbr_del_rule(struct zebra_pbr_rule
*rule
)
696 if (IS_ZEBRA_DEBUG_PBR
)
697 zlog_debug("%s: seq: %d, prior: %d, unique: %d, ifname: %s",
698 __func__
, rule
->rule
.seq
, rule
->rule
.priority
,
699 rule
->rule
.unique
, rule
->rule
.ifname
);
701 (void)dplane_pbr_rule_delete(rule
);
703 if (pbr_rule_release(rule
, true))
704 zlog_debug("%s: Rule being deleted we know nothing about",
708 void zebra_pbr_process_iptable(struct zebra_dplane_ctx
*ctx
)
711 struct zebra_pbr_iptable ipt
;
713 if (dplane_ctx_get_op(ctx
) == DPLANE_OP_IPTABLE_ADD
)
718 dplane_ctx_get_pbr_iptable(ctx
, &ipt
);
720 ret
= hook_call(zebra_pbr_iptable_update
, mode
, &ipt
);
722 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_SUCCESS
);
724 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_FAILURE
);
727 void zebra_pbr_process_ipset(struct zebra_dplane_ctx
*ctx
)
730 struct zebra_pbr_ipset ipset
;
732 if (dplane_ctx_get_op(ctx
) == DPLANE_OP_IPSET_ADD
)
737 dplane_ctx_get_pbr_ipset(ctx
, &ipset
);
739 ret
= hook_call(zebra_pbr_ipset_update
, mode
, &ipset
);
741 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_SUCCESS
);
743 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_FAILURE
);
746 void zebra_pbr_process_ipset_entry(struct zebra_dplane_ctx
*ctx
)
749 struct zebra_pbr_ipset_entry ipset_entry
;
750 struct zebra_pbr_ipset ipset
;
752 if (dplane_ctx_get_op(ctx
) == DPLANE_OP_IPSET_ENTRY_ADD
)
757 dplane_ctx_get_pbr_ipset_entry(ctx
, &ipset_entry
);
758 dplane_ctx_get_pbr_ipset(ctx
, &ipset
);
760 ipset_entry
.backpointer
= &ipset
;
762 ret
= hook_call(zebra_pbr_ipset_entry_update
, mode
, &ipset_entry
);
764 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_SUCCESS
);
766 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_FAILURE
);
769 static void zebra_pbr_cleanup_rules(struct hash_bucket
*b
, void *data
)
771 struct zebra_pbr_rule
*rule
= b
->data
;
774 if (rule
->sock
== *sock
) {
775 (void)dplane_pbr_rule_delete(rule
);
776 pbr_rule_free(rule
, true);
780 static void zebra_pbr_cleanup_ipset(struct hash_bucket
*b
, void *data
)
782 struct zebra_pbr_ipset
*ipset
= b
->data
;
785 if (ipset
->sock
== *sock
) {
786 if (hash_release(zrouter
.ipset_hash
, ipset
))
787 zebra_pbr_ipset_free(ipset
);
789 hook_call(zebra_pbr_ipset_update
, 0, ipset
);
793 static void zebra_pbr_cleanup_ipset_entry(struct hash_bucket
*b
, void *data
)
795 struct zebra_pbr_ipset_entry
*ipset
= b
->data
;
798 if (ipset
->sock
== *sock
) {
799 if (hash_release(zrouter
.ipset_entry_hash
, ipset
))
800 zebra_pbr_ipset_entry_free(ipset
);
802 hook_call(zebra_pbr_ipset_entry_update
, 0, ipset
);
806 static void zebra_pbr_cleanup_iptable(struct hash_bucket
*b
, void *data
)
808 struct zebra_pbr_iptable
*iptable
= b
->data
;
811 if (iptable
->sock
== *sock
) {
812 if (hash_release(zrouter
.iptable_hash
, iptable
))
813 _zebra_pbr_iptable_free_all(iptable
, true);
815 hook_call(zebra_pbr_iptable_update
, 0, iptable
);
819 static int zebra_pbr_client_close_cleanup(struct zserv
*client
)
821 int sock
= client
->sock
;
825 hash_iterate(zrouter
.rules_hash
, zebra_pbr_cleanup_rules
, &sock
);
826 hash_iterate(zrouter
.iptable_hash
, zebra_pbr_cleanup_iptable
, &sock
);
827 hash_iterate(zrouter
.ipset_entry_hash
, zebra_pbr_cleanup_ipset_entry
,
829 hash_iterate(zrouter
.ipset_hash
, zebra_pbr_cleanup_ipset
, &sock
);
833 void zebra_pbr_init(void)
835 hook_register(zserv_client_close
, zebra_pbr_client_close_cleanup
);
838 static void *pbr_ipset_alloc_intern(void *arg
)
840 struct zebra_pbr_ipset
*zpi
;
841 struct zebra_pbr_ipset
*new;
843 zpi
= (struct zebra_pbr_ipset
*)arg
;
845 new = XCALLOC(MTYPE_PBR_OBJ
, sizeof(struct zebra_pbr_ipset
));
847 memcpy(new, zpi
, sizeof(*zpi
));
852 void zebra_pbr_create_ipset(struct zebra_pbr_ipset
*ipset
)
854 (void)hash_get(zrouter
.ipset_hash
, ipset
, pbr_ipset_alloc_intern
);
855 (void)dplane_pbr_ipset_add(ipset
);
858 void zebra_pbr_destroy_ipset(struct zebra_pbr_ipset
*ipset
)
860 struct zebra_pbr_ipset
*lookup
;
862 lookup
= hash_lookup(zrouter
.ipset_hash
, ipset
);
863 (void)dplane_pbr_ipset_delete(ipset
);
865 hash_release(zrouter
.ipset_hash
, lookup
);
866 XFREE(MTYPE_PBR_OBJ
, lookup
);
869 "%s: IPSet Entry being deleted we know nothing about",
873 struct pbr_ipset_name_lookup
{
874 struct zebra_pbr_ipset
*ipset
;
875 char ipset_name
[ZEBRA_IPSET_NAME_SIZE
];
878 const char *zebra_pbr_ipset_type2str(uint32_t type
)
880 return lookup_msg(ipset_type_msg
, type
,
881 "Unrecognized IPset Type");
884 static int zebra_pbr_ipset_pername_walkcb(struct hash_bucket
*bucket
, void *arg
)
886 struct pbr_ipset_name_lookup
*pinl
=
887 (struct pbr_ipset_name_lookup
*)arg
;
888 struct zebra_pbr_ipset
*zpi
= (struct zebra_pbr_ipset
*)bucket
->data
;
890 if (!strncmp(pinl
->ipset_name
, zpi
->ipset_name
,
891 ZEBRA_IPSET_NAME_SIZE
)) {
893 return HASHWALK_ABORT
;
895 return HASHWALK_CONTINUE
;
898 struct zebra_pbr_ipset
*zebra_pbr_lookup_ipset_pername(char *ipsetname
)
900 struct pbr_ipset_name_lookup pinl
;
901 struct pbr_ipset_name_lookup
*ptr
= &pinl
;
905 memset(ptr
, 0, sizeof(struct pbr_ipset_name_lookup
));
906 snprintf((char *)ptr
->ipset_name
, ZEBRA_IPSET_NAME_SIZE
, "%s",
908 hash_walk(zrouter
.ipset_hash
, zebra_pbr_ipset_pername_walkcb
, ptr
);
912 static void *pbr_ipset_entry_alloc_intern(void *arg
)
914 struct zebra_pbr_ipset_entry
*zpi
;
915 struct zebra_pbr_ipset_entry
*new;
917 zpi
= (struct zebra_pbr_ipset_entry
*)arg
;
919 new = XCALLOC(MTYPE_PBR_OBJ
, sizeof(struct zebra_pbr_ipset_entry
));
921 memcpy(new, zpi
, sizeof(*zpi
));
926 void zebra_pbr_add_ipset_entry(struct zebra_pbr_ipset_entry
*ipset
)
928 (void)hash_get(zrouter
.ipset_entry_hash
, ipset
,
929 pbr_ipset_entry_alloc_intern
);
930 (void)dplane_pbr_ipset_entry_add(ipset
);
933 void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry
*ipset
)
935 struct zebra_pbr_ipset_entry
*lookup
;
937 lookup
= hash_lookup(zrouter
.ipset_entry_hash
, ipset
);
938 (void)dplane_pbr_ipset_entry_delete(ipset
);
940 hash_release(zrouter
.ipset_entry_hash
, lookup
);
941 XFREE(MTYPE_PBR_OBJ
, lookup
);
943 zlog_debug("%s: IPSet being deleted we know nothing about",
947 static void *pbr_iptable_alloc_intern(void *arg
)
949 struct zebra_pbr_iptable
*zpi
;
950 struct zebra_pbr_iptable
*new;
954 zpi
= (struct zebra_pbr_iptable
*)arg
;
956 new = XCALLOC(MTYPE_PBR_OBJ
, sizeof(struct zebra_pbr_iptable
));
958 /* Deep structure copy */
959 memcpy(new, zpi
, sizeof(*zpi
));
960 new->interface_name_list
= list_new();
962 if (zpi
->interface_name_list
) {
963 for (ALL_LIST_ELEMENTS_RO(zpi
->interface_name_list
, ln
, ifname
))
964 listnode_add(new->interface_name_list
,
965 XSTRDUP(MTYPE_PBR_IPTABLE_IFNAME
, ifname
));
971 void zebra_pbr_add_iptable(struct zebra_pbr_iptable
*iptable
)
973 struct zebra_pbr_iptable
*ipt_hash
;
975 ipt_hash
= hash_get(zrouter
.iptable_hash
, iptable
,
976 pbr_iptable_alloc_intern
);
977 (void)dplane_pbr_iptable_add(ipt_hash
);
980 void zebra_pbr_del_iptable(struct zebra_pbr_iptable
*iptable
)
982 struct zebra_pbr_iptable
*lookup
;
984 lookup
= hash_lookup(zrouter
.iptable_hash
, iptable
);
985 (void)dplane_pbr_iptable_delete(iptable
);
987 struct listnode
*node
, *nnode
;
990 hash_release(zrouter
.iptable_hash
, lookup
);
991 for (ALL_LIST_ELEMENTS(iptable
->interface_name_list
,
992 node
, nnode
, name
)) {
993 XFREE(MTYPE_PBR_IPTABLE_IFNAME
, name
);
994 list_delete_node(iptable
->interface_name_list
,
997 list_delete(&iptable
->interface_name_list
);
998 XFREE(MTYPE_PBR_OBJ
, lookup
);
1000 zlog_debug("%s: IPTable being deleted we know nothing about",
1005 * Handle success or failure of rule (un)install in the kernel.
1007 void zebra_pbr_dplane_result(struct zebra_dplane_ctx
*ctx
)
1009 enum zebra_dplane_result res
;
1010 enum dplane_op_e op
;
1012 res
= dplane_ctx_get_status(ctx
);
1013 op
= dplane_ctx_get_op(ctx
);
1014 if (op
== DPLANE_OP_RULE_ADD
|| op
== DPLANE_OP_RULE_UPDATE
)
1015 zsend_rule_notify_owner(ctx
, res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1016 ? ZAPI_RULE_INSTALLED
1017 : ZAPI_RULE_FAIL_INSTALL
);
1018 else if (op
== DPLANE_OP_RULE_DELETE
)
1019 zsend_rule_notify_owner(ctx
, res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1021 : ZAPI_RULE_FAIL_REMOVE
);
1022 else if (op
== DPLANE_OP_IPTABLE_ADD
)
1023 zsend_iptable_notify_owner(ctx
,
1024 res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1025 ? ZAPI_IPTABLE_INSTALLED
1026 : ZAPI_IPTABLE_FAIL_INSTALL
);
1027 else if (op
== DPLANE_OP_IPTABLE_DELETE
)
1028 zsend_iptable_notify_owner(ctx
,
1029 res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1030 ? ZAPI_IPTABLE_REMOVED
1031 : ZAPI_IPTABLE_FAIL_REMOVE
);
1032 else if (op
== DPLANE_OP_IPSET_ADD
)
1033 zsend_ipset_notify_owner(ctx
,
1034 res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1035 ? ZAPI_IPSET_INSTALLED
1036 : ZAPI_IPSET_FAIL_INSTALL
);
1037 else if (op
== DPLANE_OP_IPSET_DELETE
)
1038 zsend_ipset_notify_owner(ctx
,
1039 res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1040 ? ZAPI_IPSET_REMOVED
1041 : ZAPI_IPSET_FAIL_REMOVE
);
1042 else if (op
== DPLANE_OP_IPSET_ENTRY_ADD
)
1043 zsend_ipset_entry_notify_owner(
1044 ctx
, res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1045 ? ZAPI_IPSET_ENTRY_INSTALLED
1046 : ZAPI_IPSET_ENTRY_FAIL_INSTALL
);
1047 else if (op
== DPLANE_OP_IPSET_ENTRY_DELETE
)
1048 zsend_ipset_entry_notify_owner(
1049 ctx
, res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1050 ? ZAPI_IPSET_ENTRY_REMOVED
1051 : ZAPI_IPSET_ENTRY_FAIL_REMOVE
);
1054 EC_ZEBRA_PBR_RULE_UPDATE
,
1055 "Context received in pbr rule dplane result handler with incorrect OP code (%u)",
1060 * Handle rule delete notification from kernel.
1062 int kernel_pbr_rule_del(struct zebra_pbr_rule
*rule
)
1067 struct zebra_pbr_ipset_entry_unique_display
{
1068 struct zebra_pbr_ipset
*zpi
;
1070 struct zebra_ns
*zns
;
1074 static const char *zebra_pbr_prefix2str(union prefixconstptr pu
,
1075 char *str
, int size
)
1077 const struct prefix
*p
= pu
.p
;
1078 char buf
[PREFIX2STR_BUFFER
];
1080 if ((p
->family
== AF_INET
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
1081 || (p
->family
== AF_INET6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)) {
1082 snprintf(str
, size
, "%s", inet_ntop(p
->family
, &p
->u
.prefix
,
1083 buf
, PREFIX2STR_BUFFER
));
1086 return prefix2str(pu
, str
, size
);
1089 static void zebra_pbr_display_icmp(struct vty
*vty
,
1090 struct zebra_pbr_ipset_entry
*zpie
)
1092 char decoded_str
[20];
1094 struct zebra_pbr_ipset
*zpi
;
1096 zpi
= zpie
->backpointer
;
1098 /* range icmp type */
1099 if (zpie
->src_port_max
|| zpie
->dst_port_max
) {
1100 vty_out(vty
, ":icmp:[type <%u:%u>;code <%u:%u>",
1101 zpie
->src_port_min
, zpie
->src_port_max
,
1102 zpie
->dst_port_min
, zpie
->dst_port_max
);
1104 port
= ((zpie
->src_port_min
<< 8) & 0xff00) +
1105 (zpie
->dst_port_min
& 0xff);
1106 memset(decoded_str
, 0, sizeof(decoded_str
));
1107 snprintf(decoded_str
, sizeof(decoded_str
), "%u/%u",
1108 zpie
->src_port_min
, zpie
->dst_port_min
);
1109 vty_out(vty
, ":%s:%s",
1110 zpi
->family
== AF_INET6
? "ipv6-icmp" : "icmp",
1111 lookup_msg(zpi
->family
== AF_INET6
?
1112 icmpv6_typecode_str
: icmp_typecode_str
,
1113 port
, decoded_str
));
1117 static void zebra_pbr_display_port(struct vty
*vty
, uint32_t filter_bm
,
1118 uint16_t port_min
, uint16_t port_max
,
1121 if (!(filter_bm
& PBR_FILTER_PROTO
)) {
1123 vty_out(vty
, ":udp/tcp:%d-%d",
1124 port_min
, port_max
);
1126 vty_out(vty
, ":udp/tcp:%d",
1130 vty_out(vty
, ":proto %d:%d-%d",
1131 proto
, port_min
, port_max
);
1133 vty_out(vty
, ":proto %d:%d",
1138 static int zebra_pbr_show_ipset_entry_walkcb(struct hash_bucket
*bucket
,
1141 struct zebra_pbr_ipset_entry_unique_display
*unique
=
1142 (struct zebra_pbr_ipset_entry_unique_display
*)arg
;
1143 struct zebra_pbr_ipset
*zpi
= unique
->zpi
;
1144 struct vty
*vty
= unique
->vty
;
1145 struct zebra_pbr_ipset_entry
*zpie
=
1146 (struct zebra_pbr_ipset_entry
*)bucket
->data
;
1147 uint64_t pkts
= 0, bytes
= 0;
1150 if (zpie
->backpointer
!= zpi
)
1151 return HASHWALK_CONTINUE
;
1153 if ((zpi
->type
== IPSET_NET_NET
) ||
1154 (zpi
->type
== IPSET_NET_PORT_NET
)) {
1155 char buf
[PREFIX_STRLEN
];
1157 zebra_pbr_prefix2str(&(zpie
->src
), buf
, sizeof(buf
));
1158 vty_out(vty
, "\tfrom %s", buf
);
1159 if (zpie
->filter_bm
& PBR_FILTER_SRC_PORT
&&
1160 zpie
->proto
!= IPPROTO_ICMP
)
1161 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
1165 vty_out(vty
, " to ");
1166 zebra_pbr_prefix2str(&(zpie
->dst
), buf
, sizeof(buf
));
1167 vty_out(vty
, "%s", buf
);
1168 if (zpie
->filter_bm
& PBR_FILTER_DST_PORT
&&
1169 zpie
->proto
!= IPPROTO_ICMP
)
1170 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
1174 if (zpie
->proto
== IPPROTO_ICMP
)
1175 zebra_pbr_display_icmp(vty
, zpie
);
1176 } else if ((zpi
->type
== IPSET_NET
) ||
1177 (zpi
->type
== IPSET_NET_PORT
)) {
1178 char buf
[PREFIX_STRLEN
];
1180 if (zpie
->filter_bm
& PBR_FILTER_SRC_IP
) {
1181 zebra_pbr_prefix2str(&(zpie
->src
), buf
, sizeof(buf
));
1182 vty_out(vty
, "\tfrom %s", buf
);
1184 if (zpie
->filter_bm
& PBR_FILTER_SRC_PORT
&&
1185 zpie
->proto
!= IPPROTO_ICMP
)
1186 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
1190 if (zpie
->filter_bm
& PBR_FILTER_DST_IP
) {
1191 zebra_pbr_prefix2str(&(zpie
->dst
), buf
, sizeof(buf
));
1192 vty_out(vty
, "\tto %s", buf
);
1194 if (zpie
->filter_bm
& PBR_FILTER_DST_PORT
&&
1195 zpie
->proto
!= IPPROTO_ICMP
)
1196 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
1200 if (zpie
->proto
== IPPROTO_ICMP
)
1201 zebra_pbr_display_icmp(vty
, zpie
);
1203 vty_out(vty
, " (%u)\n", zpie
->unique
);
1205 ret
= hook_call(zebra_pbr_ipset_entry_get_stat
, zpie
, &pkts
,
1207 if (ret
&& pkts
> 0)
1208 vty_out(vty
, "\t pkts %" PRIu64
", bytes %" PRIu64
"\n",
1210 return HASHWALK_CONTINUE
;
1213 static int zebra_pbr_show_ipset_walkcb(struct hash_bucket
*bucket
, void *arg
)
1215 struct zebra_pbr_env_display
*uniqueipset
=
1216 (struct zebra_pbr_env_display
*)arg
;
1217 struct zebra_pbr_ipset
*zpi
= (struct zebra_pbr_ipset
*)bucket
->data
;
1218 struct zebra_pbr_ipset_entry_unique_display unique
;
1219 struct vty
*vty
= uniqueipset
->vty
;
1220 struct zebra_ns
*zns
= uniqueipset
->zns
;
1222 vty_out(vty
, "IPset %s type %s family %s\n", zpi
->ipset_name
,
1223 zebra_pbr_ipset_type2str(zpi
->type
),
1224 family2str(zpi
->family
));
1228 hash_walk(zrouter
.ipset_entry_hash
, zebra_pbr_show_ipset_entry_walkcb
,
1231 return HASHWALK_CONTINUE
;
1234 size_t zebra_pbr_tcpflags_snprintf(char *buffer
, size_t len
,
1237 size_t len_written
= 0;
1238 static struct message nt
= {0};
1239 const struct message
*pnt
;
1242 for (pnt
= tcp_value_str
;
1243 memcmp(pnt
, &nt
, sizeof(struct message
)); pnt
++)
1244 if (pnt
->key
& tcp_val
) {
1245 len_written
+= snprintf(buffer
+ len_written
,
1256 void zebra_pbr_show_ipset_list(struct vty
*vty
, char *ipsetname
)
1258 struct zebra_pbr_ipset
*zpi
;
1259 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1260 struct zebra_pbr_ipset_entry_unique_display unique
;
1261 struct zebra_pbr_env_display uniqueipset
;
1264 zpi
= zebra_pbr_lookup_ipset_pername(ipsetname
);
1266 vty_out(vty
, "No IPset %s found\n", ipsetname
);
1269 vty_out(vty
, "IPset %s type %s family %s\n", ipsetname
,
1270 zebra_pbr_ipset_type2str(zpi
->type
),
1271 family2str(zpi
->family
));
1275 hash_walk(zrouter
.ipset_entry_hash
,
1276 zebra_pbr_show_ipset_entry_walkcb
, &unique
);
1279 uniqueipset
.zns
= zns
;
1280 uniqueipset
.vty
= vty
;
1281 uniqueipset
.name
= NULL
;
1282 hash_walk(zrouter
.ipset_hash
, zebra_pbr_show_ipset_walkcb
,
1286 struct pbr_rule_fwmark_lookup
{
1287 struct zebra_pbr_rule
*ptr
;
1291 static int zebra_pbr_rule_lookup_fwmark_walkcb(struct hash_bucket
*bucket
,
1294 struct pbr_rule_fwmark_lookup
*iprule
=
1295 (struct pbr_rule_fwmark_lookup
*)arg
;
1296 struct zebra_pbr_rule
*zpr
= (struct zebra_pbr_rule
*)bucket
->data
;
1298 if (iprule
->fwmark
== zpr
->rule
.filter
.fwmark
) {
1300 return HASHWALK_ABORT
;
1302 return HASHWALK_CONTINUE
;
1305 static void zebra_pbr_show_iptable_unit(struct zebra_pbr_iptable
*iptable
,
1307 struct zebra_ns
*zns
)
1310 uint64_t pkts
= 0, bytes
= 0;
1312 vty_out(vty
, "IPtable %s family %s action %s (%u)\n",
1313 iptable
->ipset_name
,
1314 family2str(iptable
->family
),
1315 iptable
->action
== ZEBRA_IPTABLES_DROP
? "drop" : "redirect",
1317 if (iptable
->type
== IPSET_NET_PORT
||
1318 iptable
->type
== IPSET_NET_PORT_NET
) {
1319 if (!(iptable
->filter_bm
& MATCH_ICMP_SET
)) {
1320 if (iptable
->filter_bm
& PBR_FILTER_DST_PORT
)
1321 vty_out(vty
, "\t lookup dst port\n");
1322 else if (iptable
->filter_bm
& PBR_FILTER_SRC_PORT
)
1323 vty_out(vty
, "\t lookup src port\n");
1326 if (iptable
->pkt_len_min
|| iptable
->pkt_len_max
) {
1327 if (!iptable
->pkt_len_max
)
1328 vty_out(vty
, "\t pkt len %u\n",
1329 iptable
->pkt_len_min
);
1331 vty_out(vty
, "\t pkt len [%u;%u]\n",
1332 iptable
->pkt_len_min
,
1333 iptable
->pkt_len_max
);
1335 if (iptable
->tcp_flags
|| iptable
->tcp_mask_flags
) {
1336 char tcp_flag_str
[64];
1337 char tcp_flag_mask_str
[64];
1339 zebra_pbr_tcpflags_snprintf(tcp_flag_str
,
1340 sizeof(tcp_flag_str
),
1341 iptable
->tcp_flags
);
1342 zebra_pbr_tcpflags_snprintf(tcp_flag_mask_str
,
1343 sizeof(tcp_flag_mask_str
),
1344 iptable
->tcp_mask_flags
);
1345 vty_out(vty
, "\t tcpflags [%s/%s]\n",
1346 tcp_flag_str
, tcp_flag_mask_str
);
1348 if (iptable
->filter_bm
& (MATCH_DSCP_SET
| MATCH_DSCP_INVERSE_SET
)) {
1349 vty_out(vty
, "\t dscp %s %d\n",
1350 iptable
->filter_bm
& MATCH_DSCP_INVERSE_SET
?
1351 "not" : "", iptable
->dscp_value
);
1353 if (iptable
->filter_bm
& (MATCH_FLOW_LABEL_SET
|
1354 MATCH_FLOW_LABEL_INVERSE_SET
)) {
1355 vty_out(vty
, "\t flowlabel %s %d\n",
1356 iptable
->filter_bm
& MATCH_FLOW_LABEL_INVERSE_SET
?
1357 "not" : "", iptable
->flow_label
);
1359 if (iptable
->fragment
) {
1362 snprintf(val_str
, sizeof(val_str
), "%d", iptable
->fragment
);
1363 vty_out(vty
, "\t fragment%s %s\n",
1364 iptable
->filter_bm
& MATCH_FRAGMENT_INVERSE_SET
?
1365 " not" : "", lookup_msg(fragment_value_str
,
1366 iptable
->fragment
, val_str
));
1368 if (iptable
->protocol
) {
1369 vty_out(vty
, "\t protocol %d\n",
1372 ret
= hook_call(zebra_pbr_iptable_get_stat
, iptable
, &pkts
,
1374 if (ret
&& pkts
> 0)
1375 vty_out(vty
, "\t pkts %" PRIu64
", bytes %" PRIu64
"\n",
1377 if (iptable
->action
!= ZEBRA_IPTABLES_DROP
) {
1378 struct pbr_rule_fwmark_lookup prfl
;
1380 prfl
.fwmark
= iptable
->fwmark
;
1382 hash_walk(zrouter
.rules_hash
,
1383 &zebra_pbr_rule_lookup_fwmark_walkcb
, &prfl
);
1385 struct zebra_pbr_rule
*zpr
= prfl
.ptr
;
1387 vty_out(vty
, "\t table %u, fwmark %u\n",
1388 zpr
->rule
.action
.table
,
1394 static int zebra_pbr_show_iptable_walkcb(struct hash_bucket
*bucket
, void *arg
)
1396 struct zebra_pbr_iptable
*iptable
=
1397 (struct zebra_pbr_iptable
*)bucket
->data
;
1398 struct zebra_pbr_env_display
*env
= (struct zebra_pbr_env_display
*)arg
;
1399 struct vty
*vty
= env
->vty
;
1400 struct zebra_ns
*zns
= env
->zns
;
1401 char *iptable_name
= env
->name
;
1404 zebra_pbr_show_iptable_unit(iptable
, vty
, zns
);
1405 else if (!strncmp(iptable_name
,
1406 iptable
->ipset_name
,
1407 ZEBRA_IPSET_NAME_SIZE
))
1408 zebra_pbr_show_iptable_unit(iptable
, vty
, zns
);
1409 return HASHWALK_CONTINUE
;
1412 void zebra_pbr_show_iptable(struct vty
*vty
, char *iptable_name
)
1414 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1415 struct zebra_pbr_env_display env
;
1419 env
.name
= iptable_name
;
1420 hash_walk(zrouter
.iptable_hash
, zebra_pbr_show_iptable_walkcb
, &env
);
1423 void zebra_pbr_iptable_update_interfacelist(struct stream
*s
,
1424 struct zebra_pbr_iptable
*zpi
)
1426 uint32_t i
= 0, index
;
1427 struct interface
*ifp
;
1430 for (i
= 0; i
< zpi
->nb_interface
; i
++) {
1431 STREAM_GETL(s
, index
);
1432 ifp
= if_lookup_by_index(index
, zpi
->vrf_id
);
1435 name
= XSTRDUP(MTYPE_PBR_IPTABLE_IFNAME
, ifp
->name
);
1436 listnode_add(zpi
->interface_name_list
, name
);