1 /* Zebra Policy Based Routing (PBR) main handling.
2 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * This file is part of FRR.
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
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.
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
29 #include "zebra/zebra_router.h"
30 #include "zebra/zebra_pbr.h"
32 #include "zebra/zapi_msg.h"
33 #include "zebra/zserv.h"
34 #include "zebra/debug.h"
35 #include "zebra/zebra_neigh.h"
38 DEFINE_MTYPE_STATIC(ZEBRA
, PBR_IPTABLE_IFNAME
, "PBR interface list");
41 static const struct message ipset_type_msg
[] = {
42 {IPSET_NET_PORT_NET
, "net,port,net"},
43 {IPSET_NET_PORT
, "net,port"},
44 {IPSET_NET_NET
, "net,net"},
49 const struct message icmp_typecode_str
[] = {
50 { 0 << 8, "echo-reply"},
52 { 3 << 8, "network-unreachable"},
53 { (3 << 8) + 1, "host-unreachable"},
54 { (3 << 8) + 2, "protocol-unreachable"},
55 { (3 << 8) + 3, "port-unreachable"},
56 { (3 << 8) + 4, "fragmentation-needed"},
57 { (3 << 8) + 5, "source-route-failed"},
58 { (3 << 8) + 6, "network-unknown"},
59 { (3 << 8) + 7, "host-unknown"},
60 { (3 << 8) + 9, "network-prohibited"},
61 { (3 << 8) + 10, "host-prohibited"},
62 { (3 << 8) + 11, "TOS-network-unreachable"},
63 { (3 << 8) + 12, "TOS-host-unreachable"},
64 { (3 << 8) + 13, "communication-prohibited"},
65 { (3 << 8) + 14, "host-precedence-violation"},
66 { (3 << 8) + 15, "precedence-cutoff"},
67 { 4 << 8, "source-quench"},
68 { 5 << 8, "network-redirect"},
69 { (5 << 8) + 1, "host-redirect"},
70 { (5 << 8) + 2, "TOS-network-redirect"},
71 { (5 << 8) + 3, "TOS-host-redirect"},
72 { 8 << 8, "echo-request"},
74 { 9 << 8, "router-advertisement"},
75 { 10 << 8, "router-solicitation"},
76 { 11 << 8, "ttl-zero-during-transit"},
77 { (11 << 8) + 1, "ttl-zero-during-reassembly"},
78 { 12 << 8, "ip-header-bad"},
79 { (12 << 8) + 1, "required-option-missing"},
80 { 13 << 8, "timestamp-request"},
81 { 14 << 8, "timestamp-reply"},
82 { 17 << 8, "address-mask-request"},
83 { 18 << 8, "address-mask-reply"},
87 const struct message icmpv6_typecode_str
[] = {
88 { 128 << 8, "echo-request"},
89 { 129 << 8, "echo-reply"},
90 { 1 << 8, "no-route"},
91 { (1 << 8) + 1, "communication-prohibited"},
92 { (1 << 8) + 3, "address-unreachable"},
93 { (1 << 8) + 4, "port-unreachable"},
94 { (2 << 8), "packet-too-big"},
95 { 3 << 0, "ttl-zero-during-transit"},
96 { (3 << 8) + 1, "ttl-zero-during-reassembly"},
97 { 4 << 0, "bad-header"},
98 { (4 << 0) + 1, "unknown-header-type"},
99 { (4 << 0) + 2, "unknown-option"},
100 { 133 << 8, "router-solicitation"},
101 { 134 << 8, "router-advertisement"},
102 { 135 << 8, "neighbor-solicitation"},
103 { 136 << 8, "neighbor-advertisement"},
104 { 137 << 8, "redirect"},
109 static const struct message tcp_value_str
[] = {
110 {TCP_HEADER_FIN
, "FIN"},
111 {TCP_HEADER_SYN
, "SYN"},
112 {TCP_HEADER_RST
, "RST"},
113 {TCP_HEADER_PSH
, "PSH"},
114 {TCP_HEADER_ACK
, "ACK"},
115 {TCP_HEADER_URG
, "URG"},
119 static const struct message fragment_value_str
[] = {
120 {1, "dont-fragment"},
122 {4, "first-fragment"},
123 {8, "last-fragment"},
127 struct zebra_pbr_env_display
{
128 struct zebra_ns
*zns
;
133 /* static function declarations */
134 DEFINE_HOOK(zebra_pbr_ipset_entry_get_stat
,
135 (struct zebra_pbr_ipset_entry
*ipset
, uint64_t *pkts
,
137 (ipset
, pkts
, bytes
));
139 DEFINE_HOOK(zebra_pbr_iptable_get_stat
,
140 (struct zebra_pbr_iptable
*iptable
, uint64_t *pkts
,
142 (iptable
, pkts
, bytes
));
144 DEFINE_HOOK(zebra_pbr_iptable_update
,
145 (int cmd
, struct zebra_pbr_iptable
*iptable
), (cmd
, iptable
));
147 DEFINE_HOOK(zebra_pbr_ipset_entry_update
,
148 (int cmd
, struct zebra_pbr_ipset_entry
*ipset
), (cmd
, ipset
));
150 DEFINE_HOOK(zebra_pbr_ipset_update
,
151 (int cmd
, struct zebra_pbr_ipset
*ipset
), (cmd
, ipset
));
153 /* resolve nexthop for dataplane (dpdk) programming */
154 static bool zebra_pbr_expand_action
;
156 /* Private functions */
158 /* Public functions */
159 void zebra_pbr_rules_free(void *arg
)
161 struct zebra_pbr_rule
*rule
;
163 rule
= (struct zebra_pbr_rule
*)arg
;
165 (void)dplane_pbr_rule_delete(rule
);
166 XFREE(MTYPE_TMP
, rule
);
169 uint32_t zebra_pbr_rules_hash_key(const void *arg
)
171 const struct zebra_pbr_rule
*rule
;
175 key
= jhash_3words(rule
->rule
.seq
, rule
->rule
.priority
,
176 rule
->rule
.action
.table
,
177 prefix_hash_key(&rule
->rule
.filter
.src_ip
));
179 key
= jhash_3words(rule
->rule
.filter
.fwmark
, rule
->vrf_id
,
180 rule
->rule
.filter
.ip_proto
, key
);
182 key
= jhash(rule
->ifname
, strlen(rule
->ifname
), key
);
184 return jhash_3words(rule
->rule
.filter
.src_port
,
185 rule
->rule
.filter
.dst_port
,
186 prefix_hash_key(&rule
->rule
.filter
.dst_ip
),
187 jhash_1word(rule
->rule
.unique
, key
));
190 bool zebra_pbr_rules_hash_equal(const void *arg1
, const void *arg2
)
192 const struct zebra_pbr_rule
*r1
, *r2
;
194 r1
= (const struct zebra_pbr_rule
*)arg1
;
195 r2
= (const struct zebra_pbr_rule
*)arg2
;
197 if (r1
->rule
.seq
!= r2
->rule
.seq
)
200 if (r1
->rule
.priority
!= r2
->rule
.priority
)
203 if (r1
->rule
.unique
!= r2
->rule
.unique
)
206 if (r1
->rule
.action
.table
!= r2
->rule
.action
.table
)
209 if (r1
->rule
.filter
.src_port
!= r2
->rule
.filter
.src_port
)
212 if (r1
->rule
.filter
.dst_port
!= r2
->rule
.filter
.dst_port
)
215 if (r1
->rule
.filter
.fwmark
!= r2
->rule
.filter
.fwmark
)
218 if (r1
->rule
.filter
.ip_proto
!= r2
->rule
.filter
.ip_proto
)
221 if (!prefix_same(&r1
->rule
.filter
.src_ip
, &r2
->rule
.filter
.src_ip
))
224 if (!prefix_same(&r1
->rule
.filter
.dst_ip
, &r2
->rule
.filter
.dst_ip
))
227 if (strcmp(r1
->rule
.ifname
, r2
->rule
.ifname
) != 0)
230 if (r1
->vrf_id
!= r2
->vrf_id
)
236 struct pbr_rule_unique_lookup
{
237 struct zebra_pbr_rule
*rule
;
239 char ifname
[INTERFACE_NAMSIZ
+ 1];
243 static int pbr_rule_lookup_unique_walker(struct hash_bucket
*b
, void *data
)
245 struct pbr_rule_unique_lookup
*pul
= data
;
246 struct zebra_pbr_rule
*rule
= b
->data
;
248 if (pul
->unique
== rule
->rule
.unique
249 && strncmp(pul
->ifname
, rule
->rule
.ifname
, INTERFACE_NAMSIZ
) == 0
250 && pul
->vrf_id
== rule
->vrf_id
) {
252 return HASHWALK_ABORT
;
255 return HASHWALK_CONTINUE
;
258 static struct zebra_pbr_rule
*
259 pbr_rule_lookup_unique(struct zebra_pbr_rule
*zrule
)
261 struct pbr_rule_unique_lookup pul
;
263 pul
.unique
= zrule
->rule
.unique
;
264 strlcpy(pul
.ifname
, zrule
->rule
.ifname
, INTERFACE_NAMSIZ
);
266 pul
.vrf_id
= zrule
->vrf_id
;
267 hash_walk(zrouter
.rules_hash
, &pbr_rule_lookup_unique_walker
, &pul
);
272 void zebra_pbr_ipset_free(void *arg
)
274 struct zebra_pbr_ipset
*ipset
;
276 ipset
= (struct zebra_pbr_ipset
*)arg
;
277 hook_call(zebra_pbr_ipset_update
, 0, ipset
);
278 XFREE(MTYPE_TMP
, ipset
);
281 uint32_t zebra_pbr_ipset_hash_key(const void *arg
)
283 const struct zebra_pbr_ipset
*ipset
= arg
;
284 uint32_t *pnt
= (uint32_t *)&ipset
->ipset_name
;
285 uint32_t key
= jhash_1word(ipset
->vrf_id
, 0x63ab42de);
287 key
= jhash_1word(ipset
->family
, key
);
289 return jhash2(pnt
, ZEBRA_IPSET_NAME_HASH_SIZE
, key
);
292 bool zebra_pbr_ipset_hash_equal(const void *arg1
, const void *arg2
)
294 const struct zebra_pbr_ipset
*r1
, *r2
;
296 r1
= (const struct zebra_pbr_ipset
*)arg1
;
297 r2
= (const struct zebra_pbr_ipset
*)arg2
;
299 if (r1
->type
!= r2
->type
)
301 if (r1
->unique
!= r2
->unique
)
303 if (r1
->vrf_id
!= r2
->vrf_id
)
305 if (r1
->family
!= r2
->family
)
308 if (strncmp(r1
->ipset_name
, r2
->ipset_name
,
309 ZEBRA_IPSET_NAME_SIZE
))
314 void zebra_pbr_ipset_entry_free(void *arg
)
316 struct zebra_pbr_ipset_entry
*ipset
;
318 ipset
= (struct zebra_pbr_ipset_entry
*)arg
;
320 hook_call(zebra_pbr_ipset_entry_update
, 0, ipset
);
322 XFREE(MTYPE_TMP
, ipset
);
325 uint32_t zebra_pbr_ipset_entry_hash_key(const void *arg
)
327 const struct zebra_pbr_ipset_entry
*ipset
;
331 key
= prefix_hash_key(&ipset
->src
);
332 key
= jhash_1word(ipset
->unique
, key
);
333 key
= jhash_1word(prefix_hash_key(&ipset
->dst
), key
);
334 key
= jhash(&ipset
->dst_port_min
, 2, key
);
335 key
= jhash(&ipset
->dst_port_max
, 2, key
);
336 key
= jhash(&ipset
->src_port_min
, 2, key
);
337 key
= jhash(&ipset
->src_port_max
, 2, key
);
338 key
= jhash(&ipset
->proto
, 1, key
);
343 bool zebra_pbr_ipset_entry_hash_equal(const void *arg1
, const void *arg2
)
345 const struct zebra_pbr_ipset_entry
*r1
, *r2
;
347 r1
= (const struct zebra_pbr_ipset_entry
*)arg1
;
348 r2
= (const struct zebra_pbr_ipset_entry
*)arg2
;
350 if (r1
->unique
!= r2
->unique
)
353 if (!prefix_same(&r1
->src
, &r2
->src
))
356 if (!prefix_same(&r1
->dst
, &r2
->dst
))
359 if (r1
->src_port_min
!= r2
->src_port_min
)
362 if (r1
->src_port_max
!= r2
->src_port_max
)
365 if (r1
->dst_port_min
!= r2
->dst_port_min
)
368 if (r1
->dst_port_max
!= r2
->dst_port_max
)
371 if (r1
->proto
!= r2
->proto
)
376 /* this function gives option to flush plugin memory contexts
377 * with all parameter. set it to true to flush all
378 * set it to false to flush only passed arg argument
380 static void _zebra_pbr_iptable_free_all(void *arg
, bool all
)
382 struct zebra_pbr_iptable
*iptable
;
383 struct listnode
*node
, *nnode
;
386 iptable
= (struct zebra_pbr_iptable
*)arg
;
389 hook_call(zebra_pbr_iptable_update
, 0, iptable
);
391 if (iptable
->interface_name_list
) {
392 for (ALL_LIST_ELEMENTS(iptable
->interface_name_list
, node
,
394 XFREE(MTYPE_PBR_IPTABLE_IFNAME
, name
);
395 list_delete_node(iptable
->interface_name_list
, node
);
397 list_delete(&iptable
->interface_name_list
);
399 XFREE(MTYPE_TMP
, iptable
);
402 void zebra_pbr_iptable_free(void *arg
)
404 _zebra_pbr_iptable_free_all(arg
, false);
407 uint32_t zebra_pbr_iptable_hash_key(const void *arg
)
409 const struct zebra_pbr_iptable
*iptable
= arg
;
410 uint32_t *pnt
= (uint32_t *)&(iptable
->ipset_name
);
413 key
= jhash2(pnt
, ZEBRA_IPSET_NAME_HASH_SIZE
,
415 key
= jhash_1word(iptable
->fwmark
, key
);
416 key
= jhash_1word(iptable
->family
, key
);
417 key
= jhash_1word(iptable
->flow_label
, key
);
418 key
= jhash_1word(iptable
->pkt_len_min
, key
);
419 key
= jhash_1word(iptable
->pkt_len_max
, key
);
420 key
= jhash_1word(iptable
->tcp_flags
, key
);
421 key
= jhash_1word(iptable
->tcp_mask_flags
, key
);
422 key
= jhash_1word(iptable
->dscp_value
, key
);
423 key
= jhash_1word(iptable
->protocol
, key
);
424 key
= jhash_1word(iptable
->fragment
, key
);
425 key
= jhash_1word(iptable
->vrf_id
, key
);
427 return jhash_3words(iptable
->filter_bm
, iptable
->type
,
428 iptable
->unique
, key
);
431 bool zebra_pbr_iptable_hash_equal(const void *arg1
, const void *arg2
)
433 const struct zebra_pbr_iptable
*r1
, *r2
;
435 r1
= (const struct zebra_pbr_iptable
*)arg1
;
436 r2
= (const struct zebra_pbr_iptable
*)arg2
;
438 if (r1
->vrf_id
!= r2
->vrf_id
)
440 if (r1
->type
!= r2
->type
)
442 if (r1
->unique
!= r2
->unique
)
444 if (r1
->filter_bm
!= r2
->filter_bm
)
446 if (r1
->fwmark
!= r2
->fwmark
)
448 if (r1
->action
!= r2
->action
)
450 if (strncmp(r1
->ipset_name
, r2
->ipset_name
,
451 ZEBRA_IPSET_NAME_SIZE
))
453 if (r1
->family
!= r2
->family
)
455 if (r1
->flow_label
!= r2
->flow_label
)
457 if (r1
->pkt_len_min
!= r2
->pkt_len_min
)
459 if (r1
->pkt_len_max
!= r2
->pkt_len_max
)
461 if (r1
->tcp_flags
!= r2
->tcp_flags
)
463 if (r1
->tcp_mask_flags
!= r2
->tcp_mask_flags
)
465 if (r1
->dscp_value
!= r2
->dscp_value
)
467 if (r1
->fragment
!= r2
->fragment
)
469 if (r1
->protocol
!= r2
->protocol
)
474 static void *pbr_rule_alloc_intern(void *arg
)
476 struct zebra_pbr_rule
*zpr
;
477 struct zebra_pbr_rule
*new;
479 zpr
= (struct zebra_pbr_rule
*)arg
;
481 new = XCALLOC(MTYPE_TMP
, sizeof(*new));
483 memcpy(new, zpr
, sizeof(*zpr
));
488 static struct zebra_pbr_rule
*pbr_rule_free(struct zebra_pbr_rule
*hash_data
,
491 if (hash_data
->action
.neigh
)
492 zebra_neigh_deref(hash_data
);
493 hash_release(zrouter
.rules_hash
, hash_data
);
495 XFREE(MTYPE_TMP
, hash_data
);
502 static struct zebra_pbr_rule
*pbr_rule_release(struct zebra_pbr_rule
*rule
,
505 struct zebra_pbr_rule
*lookup
;
507 lookup
= hash_lookup(zrouter
.rules_hash
, rule
);
512 return pbr_rule_free(lookup
, free_data
);
515 void zebra_pbr_show_rule_unit(struct zebra_pbr_rule
*rule
, struct vty
*vty
)
517 struct pbr_rule
*prule
= &rule
->rule
;
518 struct zebra_pbr_action
*zaction
= &rule
->action
;
520 vty_out(vty
, "Rules if %s\n", rule
->ifname
);
521 vty_out(vty
, " Seq %u pri %u\n", prule
->seq
, prule
->priority
);
522 if (prule
->filter
.filter_bm
& PBR_FILTER_SRC_IP
)
523 vty_out(vty
, " SRC IP Match: %pFX\n", &prule
->filter
.src_ip
);
524 if (prule
->filter
.filter_bm
& PBR_FILTER_DST_IP
)
525 vty_out(vty
, " DST IP Match: %pFX\n", &prule
->filter
.dst_ip
);
526 if (prule
->filter
.filter_bm
& PBR_FILTER_IP_PROTOCOL
)
527 vty_out(vty
, " IP protocol Match: %u\n",
528 prule
->filter
.ip_proto
);
529 if (prule
->filter
.filter_bm
& PBR_FILTER_SRC_PORT
)
530 vty_out(vty
, " SRC Port Match: %u\n", prule
->filter
.src_port
);
531 if (prule
->filter
.filter_bm
& PBR_FILTER_DST_PORT
)
532 vty_out(vty
, " DST Port Match: %u\n", prule
->filter
.dst_port
);
534 if (prule
->filter
.filter_bm
& PBR_FILTER_DSFIELD
) {
535 vty_out(vty
, " DSCP Match: %u\n",
536 (prule
->filter
.dsfield
& PBR_DSFIELD_DSCP
) >> 2);
537 vty_out(vty
, " ECN Match: %u\n",
538 prule
->filter
.dsfield
& PBR_DSFIELD_ECN
);
541 if (prule
->filter
.filter_bm
& PBR_FILTER_FWMARK
)
542 vty_out(vty
, " MARK Match: %u\n", prule
->filter
.fwmark
);
544 vty_out(vty
, " Tableid: %u\n", prule
->action
.table
);
545 if (zaction
->afi
== AFI_IP
)
546 vty_out(vty
, " Action: nh: %pI4 intf: %s\n",
548 ifindex2ifname(zaction
->ifindex
, rule
->vrf_id
));
549 if (zaction
->afi
== AFI_IP6
)
550 vty_out(vty
, " Action: nh: %pI6 intf: %s\n",
552 ifindex2ifname(zaction
->ifindex
, rule
->vrf_id
));
553 if (zaction
->neigh
&& (zaction
->neigh
->flags
& ZEBRA_NEIGH_ENT_ACTIVE
))
554 vty_out(vty
, " Action: mac: %pEA\n", &zaction
->neigh
->mac
);
557 static int zebra_pbr_show_rules_walkcb(struct hash_bucket
*bucket
, void *arg
)
559 struct zebra_pbr_rule
*rule
= (struct zebra_pbr_rule
*)bucket
->data
;
560 struct zebra_pbr_env_display
*env
= (struct zebra_pbr_env_display
*)arg
;
561 struct vty
*vty
= env
->vty
;
563 zebra_pbr_show_rule_unit(rule
, vty
);
565 return HASHWALK_CONTINUE
;
568 void zebra_pbr_show_rule(struct vty
*vty
)
570 struct zebra_pbr_env_display env
;
573 hash_walk(zrouter
.rules_hash
, zebra_pbr_show_rules_walkcb
, &env
);
576 void zebra_pbr_config_write(struct vty
*vty
)
578 if (zebra_pbr_expand_action
)
579 vty_out(vty
, "pbr nexthop-resolve\n");
582 void zebra_pbr_expand_action_update(bool enable
)
584 zebra_pbr_expand_action
= enable
;
587 static void zebra_pbr_expand_rule(struct zebra_pbr_rule
*rule
)
590 struct route_table
*table
;
591 struct route_node
*rn
;
593 struct route_entry
*re
;
594 const struct nexthop_group
*nhg
;
595 const struct nexthop
*nexthop
;
596 struct zebra_pbr_action
*action
= &rule
->action
;
599 if (!zebra_pbr_expand_action
)
602 table
= zebra_vrf_get_table_with_table_id(
603 AFI_IP
, SAFI_UNICAST
, VRF_DEFAULT
, rule
->rule
.action
.table
);
607 memset(&p
, 0, sizeof(p
));
610 rn
= route_node_lookup(table
, &p
);
614 dest
= rib_dest_from_rnode(rn
);
615 re
= dest
->selected_fib
;
617 route_unlock_node(rn
);
621 nhg
= rib_get_fib_nhg(re
);
623 route_unlock_node(rn
);
627 nexthop
= nhg
->nexthop
;
629 switch (nexthop
->type
) {
630 case NEXTHOP_TYPE_IPV4
:
631 case NEXTHOP_TYPE_IPV4_IFINDEX
:
632 action
->afi
= AFI_IP
;
633 action
->gate
.ipv4
= nexthop
->gate
.ipv4
;
634 action
->ifindex
= nexthop
->ifindex
;
635 ip
.ipa_type
= AF_INET
;
636 ip
.ipaddr_v4
= action
->gate
.ipv4
;
637 zebra_neigh_ref(action
->ifindex
, &ip
, rule
);
640 case NEXTHOP_TYPE_IPV6
:
641 case NEXTHOP_TYPE_IPV6_IFINDEX
:
642 action
->afi
= AFI_IP6
;
643 action
->gate
.ipv6
= nexthop
->gate
.ipv6
;
644 action
->ifindex
= nexthop
->ifindex
;
645 ip
.ipa_type
= AF_INET6
;
646 ip
.ipaddr_v6
= action
->gate
.ipv6
;
647 zebra_neigh_ref(action
->ifindex
, &ip
, rule
);
651 action
->afi
= AFI_UNSPEC
;
655 route_unlock_node(rn
);
658 void zebra_pbr_add_rule(struct zebra_pbr_rule
*rule
)
660 struct zebra_pbr_rule
*found
;
661 struct zebra_pbr_rule
*old
;
662 struct zebra_pbr_rule
*new;
665 * Check if we already have it (this checks via a unique ID, walking
666 * over the hash table, not via a hash operation).
668 found
= pbr_rule_lookup_unique(rule
);
670 /* If found, this is an update */
672 if (IS_ZEBRA_DEBUG_PBR
)
674 "%s: seq: %d, prior: %d, unique: %d, ifname: %s -- update",
675 __func__
, rule
->rule
.seq
, rule
->rule
.priority
,
676 rule
->rule
.unique
, rule
->rule
.ifname
);
678 /* remove the old entry from the hash but don't free the hash
679 * data yet as we need it for the dplane update
681 old
= pbr_rule_release(found
, false);
683 /* insert new entry into hash */
684 new = hash_get(zrouter
.rules_hash
, rule
, pbr_rule_alloc_intern
);
685 /* expand the action if needed */
686 zebra_pbr_expand_rule(new);
687 /* update dataplane */
688 (void)dplane_pbr_rule_update(found
, new);
689 /* release the old hash data */
691 XFREE(MTYPE_TMP
, old
);
693 if (IS_ZEBRA_DEBUG_PBR
)
695 "%s: seq: %d, prior: %d, unique: %d, ifname: %s -- new",
696 __func__
, rule
->rule
.seq
, rule
->rule
.priority
,
697 rule
->rule
.unique
, rule
->rule
.ifname
);
699 /* insert new entry into hash */
700 new = hash_get(zrouter
.rules_hash
, rule
, pbr_rule_alloc_intern
);
701 /* expand the action if needed */
702 zebra_pbr_expand_rule(new);
703 (void)dplane_pbr_rule_add(new);
708 void zebra_pbr_del_rule(struct zebra_pbr_rule
*rule
)
710 if (IS_ZEBRA_DEBUG_PBR
)
711 zlog_debug("%s: seq: %d, prior: %d, unique: %d, ifname: %s",
712 __func__
, rule
->rule
.seq
, rule
->rule
.priority
,
713 rule
->rule
.unique
, rule
->rule
.ifname
);
715 (void)dplane_pbr_rule_delete(rule
);
717 if (pbr_rule_release(rule
, true))
718 zlog_debug("%s: Rule being deleted we know nothing about",
722 void zebra_pbr_process_iptable(struct zebra_dplane_ctx
*ctx
)
725 struct zebra_pbr_iptable ipt
;
727 if (dplane_ctx_get_op(ctx
) == DPLANE_OP_IPTABLE_ADD
)
732 dplane_ctx_get_pbr_iptable(ctx
, &ipt
);
734 ret
= hook_call(zebra_pbr_iptable_update
, mode
, &ipt
);
736 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_SUCCESS
);
738 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_FAILURE
);
741 void zebra_pbr_process_ipset(struct zebra_dplane_ctx
*ctx
)
744 struct zebra_pbr_ipset ipset
;
746 if (dplane_ctx_get_op(ctx
) == DPLANE_OP_IPSET_ADD
)
751 dplane_ctx_get_pbr_ipset(ctx
, &ipset
);
753 ret
= hook_call(zebra_pbr_ipset_update
, mode
, &ipset
);
755 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_SUCCESS
);
757 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_FAILURE
);
760 void zebra_pbr_process_ipset_entry(struct zebra_dplane_ctx
*ctx
)
763 struct zebra_pbr_ipset_entry ipset_entry
;
764 struct zebra_pbr_ipset ipset
;
766 if (dplane_ctx_get_op(ctx
) == DPLANE_OP_IPSET_ENTRY_ADD
)
771 dplane_ctx_get_pbr_ipset_entry(ctx
, &ipset_entry
);
772 dplane_ctx_get_pbr_ipset(ctx
, &ipset
);
774 ipset_entry
.backpointer
= &ipset
;
776 ret
= hook_call(zebra_pbr_ipset_entry_update
, mode
, &ipset_entry
);
778 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_SUCCESS
);
780 dplane_ctx_set_status(ctx
, ZEBRA_DPLANE_REQUEST_FAILURE
);
783 static void zebra_pbr_cleanup_rules(struct hash_bucket
*b
, void *data
)
785 struct zebra_pbr_rule
*rule
= b
->data
;
788 if (rule
->sock
== *sock
) {
789 (void)dplane_pbr_rule_delete(rule
);
790 pbr_rule_free(rule
, true);
794 static void zebra_pbr_cleanup_ipset(struct hash_bucket
*b
, void *data
)
796 struct zebra_pbr_ipset
*ipset
= b
->data
;
799 if (ipset
->sock
== *sock
) {
800 if (hash_release(zrouter
.ipset_hash
, ipset
))
801 zebra_pbr_ipset_free(ipset
);
803 hook_call(zebra_pbr_ipset_update
, 0, ipset
);
807 static void zebra_pbr_cleanup_ipset_entry(struct hash_bucket
*b
, void *data
)
809 struct zebra_pbr_ipset_entry
*ipset
= b
->data
;
812 if (ipset
->sock
== *sock
) {
813 if (hash_release(zrouter
.ipset_entry_hash
, ipset
))
814 zebra_pbr_ipset_entry_free(ipset
);
816 hook_call(zebra_pbr_ipset_entry_update
, 0, ipset
);
820 static void zebra_pbr_cleanup_iptable(struct hash_bucket
*b
, void *data
)
822 struct zebra_pbr_iptable
*iptable
= b
->data
;
825 if (iptable
->sock
== *sock
) {
826 if (hash_release(zrouter
.iptable_hash
, iptable
))
827 _zebra_pbr_iptable_free_all(iptable
, true);
829 hook_call(zebra_pbr_iptable_update
, 0, iptable
);
833 static int zebra_pbr_client_close_cleanup(struct zserv
*client
)
835 int sock
= client
->sock
;
839 hash_iterate(zrouter
.rules_hash
, zebra_pbr_cleanup_rules
, &sock
);
840 hash_iterate(zrouter
.iptable_hash
, zebra_pbr_cleanup_iptable
, &sock
);
841 hash_iterate(zrouter
.ipset_entry_hash
, zebra_pbr_cleanup_ipset_entry
,
843 hash_iterate(zrouter
.ipset_hash
, zebra_pbr_cleanup_ipset
, &sock
);
847 void zebra_pbr_init(void)
849 hook_register(zserv_client_close
, zebra_pbr_client_close_cleanup
);
852 static void *pbr_ipset_alloc_intern(void *arg
)
854 struct zebra_pbr_ipset
*zpi
;
855 struct zebra_pbr_ipset
*new;
857 zpi
= (struct zebra_pbr_ipset
*)arg
;
859 new = XCALLOC(MTYPE_TMP
, sizeof(struct zebra_pbr_ipset
));
861 memcpy(new, zpi
, sizeof(*zpi
));
866 void zebra_pbr_create_ipset(struct zebra_pbr_ipset
*ipset
)
868 (void)hash_get(zrouter
.ipset_hash
, ipset
, pbr_ipset_alloc_intern
);
869 (void)dplane_pbr_ipset_add(ipset
);
872 void zebra_pbr_destroy_ipset(struct zebra_pbr_ipset
*ipset
)
874 struct zebra_pbr_ipset
*lookup
;
876 lookup
= hash_lookup(zrouter
.ipset_hash
, ipset
);
877 (void)dplane_pbr_ipset_delete(ipset
);
879 hash_release(zrouter
.ipset_hash
, lookup
);
880 XFREE(MTYPE_TMP
, lookup
);
883 "%s: IPSet Entry being deleted we know nothing about",
887 struct pbr_ipset_name_lookup
{
888 struct zebra_pbr_ipset
*ipset
;
889 char ipset_name
[ZEBRA_IPSET_NAME_SIZE
];
892 const char *zebra_pbr_ipset_type2str(uint32_t type
)
894 return lookup_msg(ipset_type_msg
, type
,
895 "Unrecognized IPset Type");
898 static int zebra_pbr_ipset_pername_walkcb(struct hash_bucket
*bucket
, void *arg
)
900 struct pbr_ipset_name_lookup
*pinl
=
901 (struct pbr_ipset_name_lookup
*)arg
;
902 struct zebra_pbr_ipset
*zpi
= (struct zebra_pbr_ipset
*)bucket
->data
;
904 if (!strncmp(pinl
->ipset_name
, zpi
->ipset_name
,
905 ZEBRA_IPSET_NAME_SIZE
)) {
907 return HASHWALK_ABORT
;
909 return HASHWALK_CONTINUE
;
912 struct zebra_pbr_ipset
*zebra_pbr_lookup_ipset_pername(char *ipsetname
)
914 struct pbr_ipset_name_lookup pinl
;
915 struct pbr_ipset_name_lookup
*ptr
= &pinl
;
919 memset(ptr
, 0, sizeof(struct pbr_ipset_name_lookup
));
920 snprintf((char *)ptr
->ipset_name
, ZEBRA_IPSET_NAME_SIZE
, "%s",
922 hash_walk(zrouter
.ipset_hash
, zebra_pbr_ipset_pername_walkcb
, ptr
);
926 static void *pbr_ipset_entry_alloc_intern(void *arg
)
928 struct zebra_pbr_ipset_entry
*zpi
;
929 struct zebra_pbr_ipset_entry
*new;
931 zpi
= (struct zebra_pbr_ipset_entry
*)arg
;
933 new = XCALLOC(MTYPE_TMP
, sizeof(struct zebra_pbr_ipset_entry
));
935 memcpy(new, zpi
, sizeof(*zpi
));
940 void zebra_pbr_add_ipset_entry(struct zebra_pbr_ipset_entry
*ipset
)
942 (void)hash_get(zrouter
.ipset_entry_hash
, ipset
,
943 pbr_ipset_entry_alloc_intern
);
944 (void)dplane_pbr_ipset_entry_add(ipset
);
947 void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry
*ipset
)
949 struct zebra_pbr_ipset_entry
*lookup
;
951 lookup
= hash_lookup(zrouter
.ipset_entry_hash
, ipset
);
952 (void)dplane_pbr_ipset_entry_delete(ipset
);
954 hash_release(zrouter
.ipset_entry_hash
, lookup
);
955 XFREE(MTYPE_TMP
, lookup
);
957 zlog_debug("%s: IPSet being deleted we know nothing about",
961 static void *pbr_iptable_alloc_intern(void *arg
)
963 struct zebra_pbr_iptable
*zpi
;
964 struct zebra_pbr_iptable
*new;
968 zpi
= (struct zebra_pbr_iptable
*)arg
;
970 new = XCALLOC(MTYPE_TMP
, sizeof(struct zebra_pbr_iptable
));
972 /* Deep structure copy */
973 memcpy(new, zpi
, sizeof(*zpi
));
974 new->interface_name_list
= list_new();
976 if (zpi
->interface_name_list
) {
977 for (ALL_LIST_ELEMENTS_RO(zpi
->interface_name_list
, ln
, ifname
))
978 listnode_add(new->interface_name_list
,
979 XSTRDUP(MTYPE_PBR_IPTABLE_IFNAME
, ifname
));
985 void zebra_pbr_add_iptable(struct zebra_pbr_iptable
*iptable
)
987 struct zebra_pbr_iptable
*ipt_hash
;
989 ipt_hash
= hash_get(zrouter
.iptable_hash
, iptable
,
990 pbr_iptable_alloc_intern
);
991 (void)dplane_pbr_iptable_add(ipt_hash
);
994 void zebra_pbr_del_iptable(struct zebra_pbr_iptable
*iptable
)
996 struct zebra_pbr_iptable
*lookup
;
998 lookup
= hash_lookup(zrouter
.iptable_hash
, iptable
);
999 (void)dplane_pbr_iptable_delete(iptable
);
1001 struct listnode
*node
, *nnode
;
1004 hash_release(zrouter
.iptable_hash
, lookup
);
1005 for (ALL_LIST_ELEMENTS(iptable
->interface_name_list
,
1006 node
, nnode
, name
)) {
1007 XFREE(MTYPE_PBR_IPTABLE_IFNAME
, name
);
1008 list_delete_node(iptable
->interface_name_list
,
1011 list_delete(&iptable
->interface_name_list
);
1012 XFREE(MTYPE_TMP
, lookup
);
1014 zlog_debug("%s: IPTable being deleted we know nothing about",
1019 * Handle success or failure of rule (un)install in the kernel.
1021 void zebra_pbr_dplane_result(struct zebra_dplane_ctx
*ctx
)
1023 enum zebra_dplane_result res
;
1024 enum dplane_op_e op
;
1026 res
= dplane_ctx_get_status(ctx
);
1027 op
= dplane_ctx_get_op(ctx
);
1028 if (op
== DPLANE_OP_RULE_ADD
|| op
== DPLANE_OP_RULE_UPDATE
)
1029 zsend_rule_notify_owner(ctx
, res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1030 ? ZAPI_RULE_INSTALLED
1031 : ZAPI_RULE_FAIL_INSTALL
);
1032 else if (op
== DPLANE_OP_RULE_DELETE
)
1033 zsend_rule_notify_owner(ctx
, res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1035 : ZAPI_RULE_FAIL_REMOVE
);
1036 else if (op
== DPLANE_OP_IPTABLE_ADD
)
1037 zsend_iptable_notify_owner(ctx
,
1038 res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1039 ? ZAPI_IPTABLE_INSTALLED
1040 : ZAPI_IPTABLE_FAIL_INSTALL
);
1041 else if (op
== DPLANE_OP_IPTABLE_DELETE
)
1042 zsend_iptable_notify_owner(ctx
,
1043 res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1044 ? ZAPI_IPTABLE_REMOVED
1045 : ZAPI_IPTABLE_FAIL_REMOVE
);
1046 else if (op
== DPLANE_OP_IPSET_ADD
)
1047 zsend_ipset_notify_owner(ctx
,
1048 res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1049 ? ZAPI_IPSET_INSTALLED
1050 : ZAPI_IPSET_FAIL_INSTALL
);
1051 else if (op
== DPLANE_OP_IPSET_DELETE
)
1052 zsend_ipset_notify_owner(ctx
,
1053 res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1054 ? ZAPI_IPSET_REMOVED
1055 : ZAPI_IPSET_FAIL_REMOVE
);
1056 else if (op
== DPLANE_OP_IPSET_ENTRY_ADD
)
1057 zsend_ipset_entry_notify_owner(
1058 ctx
, res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1059 ? ZAPI_IPSET_ENTRY_INSTALLED
1060 : ZAPI_IPSET_ENTRY_FAIL_INSTALL
);
1061 else if (op
== DPLANE_OP_IPSET_ENTRY_DELETE
)
1062 zsend_ipset_entry_notify_owner(
1063 ctx
, res
== ZEBRA_DPLANE_REQUEST_SUCCESS
1064 ? ZAPI_IPSET_ENTRY_REMOVED
1065 : ZAPI_IPSET_ENTRY_FAIL_REMOVE
);
1068 EC_ZEBRA_PBR_RULE_UPDATE
,
1069 "Context received in pbr rule dplane result handler with incorrect OP code (%u)",
1073 dplane_ctx_fini(&ctx
);
1077 * Handle rule delete notification from kernel.
1079 int kernel_pbr_rule_del(struct zebra_pbr_rule
*rule
)
1084 struct zebra_pbr_ipset_entry_unique_display
{
1085 struct zebra_pbr_ipset
*zpi
;
1087 struct zebra_ns
*zns
;
1091 static const char *zebra_pbr_prefix2str(union prefixconstptr pu
,
1092 char *str
, int size
)
1094 const struct prefix
*p
= pu
.p
;
1095 char buf
[PREFIX2STR_BUFFER
];
1097 if ((p
->family
== AF_INET
&& p
->prefixlen
== IPV4_MAX_BITLEN
)
1098 || (p
->family
== AF_INET6
&& p
->prefixlen
== IPV6_MAX_BITLEN
)) {
1099 snprintf(str
, size
, "%s", inet_ntop(p
->family
, &p
->u
.prefix
,
1100 buf
, PREFIX2STR_BUFFER
));
1103 return prefix2str(pu
, str
, size
);
1106 static void zebra_pbr_display_icmp(struct vty
*vty
,
1107 struct zebra_pbr_ipset_entry
*zpie
)
1109 char decoded_str
[20];
1111 struct zebra_pbr_ipset
*zpi
;
1113 zpi
= zpie
->backpointer
;
1115 /* range icmp type */
1116 if (zpie
->src_port_max
|| zpie
->dst_port_max
) {
1117 vty_out(vty
, ":icmp:[type <%u:%u>;code <%u:%u>",
1118 zpie
->src_port_min
, zpie
->src_port_max
,
1119 zpie
->dst_port_min
, zpie
->dst_port_max
);
1121 port
= ((zpie
->src_port_min
<< 8) & 0xff00) +
1122 (zpie
->dst_port_min
& 0xff);
1123 memset(decoded_str
, 0, sizeof(decoded_str
));
1124 snprintf(decoded_str
, sizeof(decoded_str
), "%u/%u",
1125 zpie
->src_port_min
, zpie
->dst_port_min
);
1126 vty_out(vty
, ":%s:%s",
1127 zpi
->family
== AF_INET6
? "ipv6-icmp" : "icmp",
1128 lookup_msg(zpi
->family
== AF_INET6
?
1129 icmpv6_typecode_str
: icmp_typecode_str
,
1130 port
, decoded_str
));
1134 static void zebra_pbr_display_port(struct vty
*vty
, uint32_t filter_bm
,
1135 uint16_t port_min
, uint16_t port_max
,
1138 if (!(filter_bm
& PBR_FILTER_PROTO
)) {
1140 vty_out(vty
, ":udp/tcp:%d-%d",
1141 port_min
, port_max
);
1143 vty_out(vty
, ":udp/tcp:%d",
1147 vty_out(vty
, ":proto %d:%d-%d",
1148 proto
, port_min
, port_max
);
1150 vty_out(vty
, ":proto %d:%d",
1155 static int zebra_pbr_show_ipset_entry_walkcb(struct hash_bucket
*bucket
,
1158 struct zebra_pbr_ipset_entry_unique_display
*unique
=
1159 (struct zebra_pbr_ipset_entry_unique_display
*)arg
;
1160 struct zebra_pbr_ipset
*zpi
= unique
->zpi
;
1161 struct vty
*vty
= unique
->vty
;
1162 struct zebra_pbr_ipset_entry
*zpie
=
1163 (struct zebra_pbr_ipset_entry
*)bucket
->data
;
1164 uint64_t pkts
= 0, bytes
= 0;
1167 if (zpie
->backpointer
!= zpi
)
1168 return HASHWALK_CONTINUE
;
1170 if ((zpi
->type
== IPSET_NET_NET
) ||
1171 (zpi
->type
== IPSET_NET_PORT_NET
)) {
1172 char buf
[PREFIX_STRLEN
];
1174 zebra_pbr_prefix2str(&(zpie
->src
), buf
, sizeof(buf
));
1175 vty_out(vty
, "\tfrom %s", buf
);
1176 if (zpie
->filter_bm
& PBR_FILTER_SRC_PORT
&&
1177 zpie
->proto
!= IPPROTO_ICMP
)
1178 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
1182 vty_out(vty
, " to ");
1183 zebra_pbr_prefix2str(&(zpie
->dst
), buf
, sizeof(buf
));
1184 vty_out(vty
, "%s", buf
);
1185 if (zpie
->filter_bm
& PBR_FILTER_DST_PORT
&&
1186 zpie
->proto
!= IPPROTO_ICMP
)
1187 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
1191 if (zpie
->proto
== IPPROTO_ICMP
)
1192 zebra_pbr_display_icmp(vty
, zpie
);
1193 } else if ((zpi
->type
== IPSET_NET
) ||
1194 (zpi
->type
== IPSET_NET_PORT
)) {
1195 char buf
[PREFIX_STRLEN
];
1197 if (zpie
->filter_bm
& PBR_FILTER_SRC_IP
) {
1198 zebra_pbr_prefix2str(&(zpie
->src
), buf
, sizeof(buf
));
1199 vty_out(vty
, "\tfrom %s", buf
);
1201 if (zpie
->filter_bm
& PBR_FILTER_SRC_PORT
&&
1202 zpie
->proto
!= IPPROTO_ICMP
)
1203 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
1207 if (zpie
->filter_bm
& PBR_FILTER_DST_IP
) {
1208 zebra_pbr_prefix2str(&(zpie
->dst
), buf
, sizeof(buf
));
1209 vty_out(vty
, "\tto %s", buf
);
1211 if (zpie
->filter_bm
& PBR_FILTER_DST_PORT
&&
1212 zpie
->proto
!= IPPROTO_ICMP
)
1213 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
1217 if (zpie
->proto
== IPPROTO_ICMP
)
1218 zebra_pbr_display_icmp(vty
, zpie
);
1220 vty_out(vty
, " (%u)\n", zpie
->unique
);
1222 ret
= hook_call(zebra_pbr_ipset_entry_get_stat
, zpie
, &pkts
,
1224 if (ret
&& pkts
> 0)
1225 vty_out(vty
, "\t pkts %" PRIu64
", bytes %" PRIu64
"\n",
1227 return HASHWALK_CONTINUE
;
1230 static int zebra_pbr_show_ipset_walkcb(struct hash_bucket
*bucket
, void *arg
)
1232 struct zebra_pbr_env_display
*uniqueipset
=
1233 (struct zebra_pbr_env_display
*)arg
;
1234 struct zebra_pbr_ipset
*zpi
= (struct zebra_pbr_ipset
*)bucket
->data
;
1235 struct zebra_pbr_ipset_entry_unique_display unique
;
1236 struct vty
*vty
= uniqueipset
->vty
;
1237 struct zebra_ns
*zns
= uniqueipset
->zns
;
1239 vty_out(vty
, "IPset %s type %s family %s\n", zpi
->ipset_name
,
1240 zebra_pbr_ipset_type2str(zpi
->type
),
1241 family2str(zpi
->family
));
1245 hash_walk(zrouter
.ipset_entry_hash
, zebra_pbr_show_ipset_entry_walkcb
,
1248 return HASHWALK_CONTINUE
;
1251 size_t zebra_pbr_tcpflags_snprintf(char *buffer
, size_t len
,
1254 size_t len_written
= 0;
1255 static struct message nt
= {0};
1256 const struct message
*pnt
;
1259 for (pnt
= tcp_value_str
;
1260 memcmp(pnt
, &nt
, sizeof(struct message
)); pnt
++)
1261 if (pnt
->key
& tcp_val
) {
1262 len_written
+= snprintf(buffer
+ len_written
,
1273 void zebra_pbr_show_ipset_list(struct vty
*vty
, char *ipsetname
)
1275 struct zebra_pbr_ipset
*zpi
;
1276 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1277 struct zebra_pbr_ipset_entry_unique_display unique
;
1278 struct zebra_pbr_env_display uniqueipset
;
1281 zpi
= zebra_pbr_lookup_ipset_pername(ipsetname
);
1283 vty_out(vty
, "No IPset %s found\n", ipsetname
);
1286 vty_out(vty
, "IPset %s type %s family %s\n", ipsetname
,
1287 zebra_pbr_ipset_type2str(zpi
->type
),
1288 family2str(zpi
->family
));
1292 hash_walk(zrouter
.ipset_entry_hash
,
1293 zebra_pbr_show_ipset_entry_walkcb
, &unique
);
1296 uniqueipset
.zns
= zns
;
1297 uniqueipset
.vty
= vty
;
1298 uniqueipset
.name
= NULL
;
1299 hash_walk(zrouter
.ipset_hash
, zebra_pbr_show_ipset_walkcb
,
1303 struct pbr_rule_fwmark_lookup
{
1304 struct zebra_pbr_rule
*ptr
;
1308 static int zebra_pbr_rule_lookup_fwmark_walkcb(struct hash_bucket
*bucket
,
1311 struct pbr_rule_fwmark_lookup
*iprule
=
1312 (struct pbr_rule_fwmark_lookup
*)arg
;
1313 struct zebra_pbr_rule
*zpr
= (struct zebra_pbr_rule
*)bucket
->data
;
1315 if (iprule
->fwmark
== zpr
->rule
.filter
.fwmark
) {
1317 return HASHWALK_ABORT
;
1319 return HASHWALK_CONTINUE
;
1322 static void zebra_pbr_show_iptable_unit(struct zebra_pbr_iptable
*iptable
,
1324 struct zebra_ns
*zns
)
1327 uint64_t pkts
= 0, bytes
= 0;
1329 vty_out(vty
, "IPtable %s family %s action %s (%u)\n",
1330 iptable
->ipset_name
,
1331 family2str(iptable
->family
),
1332 iptable
->action
== ZEBRA_IPTABLES_DROP
? "drop" : "redirect",
1334 if (iptable
->type
== IPSET_NET_PORT
||
1335 iptable
->type
== IPSET_NET_PORT_NET
) {
1336 if (!(iptable
->filter_bm
& MATCH_ICMP_SET
)) {
1337 if (iptable
->filter_bm
& PBR_FILTER_DST_PORT
)
1338 vty_out(vty
, "\t lookup dst port\n");
1339 else if (iptable
->filter_bm
& PBR_FILTER_SRC_PORT
)
1340 vty_out(vty
, "\t lookup src port\n");
1343 if (iptable
->pkt_len_min
|| iptable
->pkt_len_max
) {
1344 if (!iptable
->pkt_len_max
)
1345 vty_out(vty
, "\t pkt len %u\n",
1346 iptable
->pkt_len_min
);
1348 vty_out(vty
, "\t pkt len [%u;%u]\n",
1349 iptable
->pkt_len_min
,
1350 iptable
->pkt_len_max
);
1352 if (iptable
->tcp_flags
|| iptable
->tcp_mask_flags
) {
1353 char tcp_flag_str
[64];
1354 char tcp_flag_mask_str
[64];
1356 zebra_pbr_tcpflags_snprintf(tcp_flag_str
,
1357 sizeof(tcp_flag_str
),
1358 iptable
->tcp_flags
);
1359 zebra_pbr_tcpflags_snprintf(tcp_flag_mask_str
,
1360 sizeof(tcp_flag_mask_str
),
1361 iptable
->tcp_mask_flags
);
1362 vty_out(vty
, "\t tcpflags [%s/%s]\n",
1363 tcp_flag_str
, tcp_flag_mask_str
);
1365 if (iptable
->filter_bm
& (MATCH_DSCP_SET
| MATCH_DSCP_INVERSE_SET
)) {
1366 vty_out(vty
, "\t dscp %s %d\n",
1367 iptable
->filter_bm
& MATCH_DSCP_INVERSE_SET
?
1368 "not" : "", iptable
->dscp_value
);
1370 if (iptable
->filter_bm
& (MATCH_FLOW_LABEL_SET
|
1371 MATCH_FLOW_LABEL_INVERSE_SET
)) {
1372 vty_out(vty
, "\t flowlabel %s %d\n",
1373 iptable
->filter_bm
& MATCH_FLOW_LABEL_INVERSE_SET
?
1374 "not" : "", iptable
->flow_label
);
1376 if (iptable
->fragment
) {
1379 snprintf(val_str
, sizeof(val_str
), "%d", iptable
->fragment
);
1380 vty_out(vty
, "\t fragment%s %s\n",
1381 iptable
->filter_bm
& MATCH_FRAGMENT_INVERSE_SET
?
1382 " not" : "", lookup_msg(fragment_value_str
,
1383 iptable
->fragment
, val_str
));
1385 if (iptable
->protocol
) {
1386 vty_out(vty
, "\t protocol %d\n",
1389 ret
= hook_call(zebra_pbr_iptable_get_stat
, iptable
, &pkts
,
1391 if (ret
&& pkts
> 0)
1392 vty_out(vty
, "\t pkts %" PRIu64
", bytes %" PRIu64
"\n",
1394 if (iptable
->action
!= ZEBRA_IPTABLES_DROP
) {
1395 struct pbr_rule_fwmark_lookup prfl
;
1397 prfl
.fwmark
= iptable
->fwmark
;
1399 hash_walk(zrouter
.rules_hash
,
1400 &zebra_pbr_rule_lookup_fwmark_walkcb
, &prfl
);
1402 struct zebra_pbr_rule
*zpr
= prfl
.ptr
;
1404 vty_out(vty
, "\t table %u, fwmark %u\n",
1405 zpr
->rule
.action
.table
,
1411 static int zebra_pbr_show_iptable_walkcb(struct hash_bucket
*bucket
, void *arg
)
1413 struct zebra_pbr_iptable
*iptable
=
1414 (struct zebra_pbr_iptable
*)bucket
->data
;
1415 struct zebra_pbr_env_display
*env
= (struct zebra_pbr_env_display
*)arg
;
1416 struct vty
*vty
= env
->vty
;
1417 struct zebra_ns
*zns
= env
->zns
;
1418 char *iptable_name
= env
->name
;
1421 zebra_pbr_show_iptable_unit(iptable
, vty
, zns
);
1422 else if (!strncmp(iptable_name
,
1423 iptable
->ipset_name
,
1424 ZEBRA_IPSET_NAME_SIZE
))
1425 zebra_pbr_show_iptable_unit(iptable
, vty
, zns
);
1426 return HASHWALK_CONTINUE
;
1429 void zebra_pbr_show_iptable(struct vty
*vty
, char *iptable_name
)
1431 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1432 struct zebra_pbr_env_display env
;
1436 env
.name
= iptable_name
;
1437 hash_walk(zrouter
.iptable_hash
, zebra_pbr_show_iptable_walkcb
, &env
);
1440 void zebra_pbr_iptable_update_interfacelist(struct stream
*s
,
1441 struct zebra_pbr_iptable
*zpi
)
1443 uint32_t i
= 0, index
;
1444 struct interface
*ifp
;
1447 for (i
= 0; i
< zpi
->nb_interface
; i
++) {
1448 STREAM_GETL(s
, index
);
1449 ifp
= if_lookup_by_index(index
, zpi
->vrf_id
);
1452 name
= XSTRDUP(MTYPE_PBR_IPTABLE_IFNAME
, ifp
->name
);
1453 listnode_add(zpi
->interface_name_list
, name
);