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_pbr.h"
31 #include "zebra/zapi_msg.h"
32 #include "zebra/zebra_memory.h"
33 #include "zebra/zserv.h"
36 DEFINE_MTYPE_STATIC(ZEBRA
, PBR_IPTABLE_IFNAME
, "PBR interface list")
39 static const struct message ipset_type_msg
[] = {
40 {IPSET_NET_PORT_NET
, "net,port,net"},
41 {IPSET_NET_PORT
, "net,port"},
42 {IPSET_NET_NET
, "net,net"},
47 const struct message icmp_typecode_str
[] = {
48 { 0 << 8, "echo-reply"},
50 { 3 << 8, "network-unreachable"},
51 { (3 << 8) + 1, "host-unreachable"},
52 { (3 << 8) + 2, "protocol-unreachable"},
53 { (3 << 8) + 3, "port-unreachable"},
54 { (3 << 8) + 4, "fragmentation-needed"},
55 { (3 << 8) + 5, "source-route-failed"},
56 { (3 << 8) + 6, "network-unknown"},
57 { (3 << 8) + 7, "host-unknown"},
58 { (3 << 8) + 9, "network-prohibited"},
59 { (3 << 8) + 10, "host-prohibited"},
60 { (3 << 8) + 11, "TOS-network-unreachable"},
61 { (3 << 8) + 12, "TOS-host-unreachable"},
62 { (3 << 8) + 13, "communication-prohibited"},
63 { (3 << 8) + 14, "host-precedence-violation"},
64 { (3 << 8) + 15, "precedence-cutoff"},
65 { 4 << 8, "source-quench"},
66 { 5 << 8, "network-redirect"},
67 { (5 << 8) + 1, "host-redirect"},
68 { (5 << 8) + 2, "TOS-network-redirect"},
69 { (5 << 8) + 3, "TOS-host-redirect"},
70 { 8 << 8, "echo-request"},
72 { 9 << 8, "router-advertisement"},
73 { 10 << 8, "router-solicitation"},
74 { 11 << 8, "ttl-zero-during-transit"},
75 { (11 << 8) + 1, "ttl-zero-during-reassembly"},
76 { 12 << 8, "ip-header-bad"},
77 { (12 << 8) + 1, "required-option-missing"},
78 { 13 << 8, "timestamp-request"},
79 { 14 << 8, "timestamp-reply"},
80 { 17 << 8, "address-mask-request"},
81 { 18 << 8, "address-mask-reply"},
86 static const struct message tcp_value_str
[] = {
87 {TCP_HEADER_FIN
, "FIN"},
88 {TCP_HEADER_SYN
, "SYN"},
89 {TCP_HEADER_RST
, "RST"},
90 {TCP_HEADER_PSH
, "PSH"},
91 {TCP_HEADER_ACK
, "ACK"},
92 {TCP_HEADER_URG
, "URG"},
96 static const struct message fragment_value_str
[] = {
99 {4, "first-fragment"},
100 {8, "last-fragment"},
104 /* static function declarations */
105 DEFINE_HOOK(zebra_pbr_ipset_entry_wrap_script_get_stat
, (struct zebra_ns
*zns
,
106 struct zebra_pbr_ipset_entry
*ipset
,
107 uint64_t *pkts
, uint64_t *bytes
),
108 (zns
, ipset
, pkts
, bytes
))
110 DEFINE_HOOK(zebra_pbr_iptable_wrap_script_get_stat
, (struct zebra_ns
*zns
,
111 struct zebra_pbr_iptable
*iptable
,
112 uint64_t *pkts
, uint64_t *bytes
),
113 (zns
, iptable
, pkts
, bytes
))
115 DEFINE_HOOK(zebra_pbr_iptable_wrap_script_update
, (struct zebra_ns
*zns
,
117 struct zebra_pbr_iptable
*iptable
),
118 (zns
, cmd
, iptable
));
120 DEFINE_HOOK(zebra_pbr_ipset_entry_wrap_script_update
, (struct zebra_ns
*zns
,
122 struct zebra_pbr_ipset_entry
*ipset
),
125 DEFINE_HOOK(zebra_pbr_ipset_wrap_script_update
, (struct zebra_ns
*zns
,
127 struct zebra_pbr_ipset
*ipset
),
130 /* Private functions */
132 /* Public functions */
133 void zebra_pbr_rules_free(void *arg
)
135 struct zebra_pbr_rule
*rule
;
137 rule
= (struct zebra_pbr_rule
*)arg
;
139 (void)kernel_del_pbr_rule(rule
);
140 XFREE(MTYPE_TMP
, rule
);
143 uint32_t zebra_pbr_rules_hash_key(void *arg
)
145 struct zebra_pbr_rule
*rule
;
148 rule
= (struct zebra_pbr_rule
*)arg
;
149 key
= jhash_3words(rule
->rule
.seq
, rule
->rule
.priority
,
150 rule
->rule
.action
.table
,
151 prefix_hash_key(&rule
->rule
.filter
.src_ip
));
153 key
= jhash_1word(rule
->ifp
->ifindex
, key
);
155 key
= jhash_1word(0, key
);
157 if (rule
->rule
.filter
.fwmark
)
158 key
= jhash_1word(rule
->rule
.filter
.fwmark
, key
);
160 key
= jhash_1word(0, key
);
161 return jhash_3words(rule
->rule
.filter
.src_port
,
162 rule
->rule
.filter
.dst_port
,
163 prefix_hash_key(&rule
->rule
.filter
.dst_ip
),
164 jhash_1word(rule
->rule
.unique
, key
));
167 int zebra_pbr_rules_hash_equal(const void *arg1
, const void *arg2
)
169 const struct zebra_pbr_rule
*r1
, *r2
;
171 r1
= (const struct zebra_pbr_rule
*)arg1
;
172 r2
= (const struct zebra_pbr_rule
*)arg2
;
174 if (r1
->rule
.seq
!= r2
->rule
.seq
)
177 if (r1
->rule
.priority
!= r2
->rule
.priority
)
180 if (r1
->rule
.unique
!= r2
->rule
.unique
)
183 if (r1
->rule
.action
.table
!= r2
->rule
.action
.table
)
186 if (r1
->rule
.filter
.src_port
!= r2
->rule
.filter
.src_port
)
189 if (r1
->rule
.filter
.dst_port
!= r2
->rule
.filter
.dst_port
)
192 if (r1
->rule
.filter
.fwmark
!= r2
->rule
.filter
.fwmark
)
195 if (!prefix_same(&r1
->rule
.filter
.src_ip
, &r2
->rule
.filter
.src_ip
))
198 if (!prefix_same(&r1
->rule
.filter
.dst_ip
, &r2
->rule
.filter
.dst_ip
))
201 if (r1
->ifp
!= r2
->ifp
)
207 struct pbr_rule_unique_lookup
{
208 struct zebra_pbr_rule
*rule
;
210 struct interface
*ifp
;
213 static int pbr_rule_lookup_unique_walker(struct hash_backet
*b
, void *data
)
215 struct pbr_rule_unique_lookup
*pul
= data
;
216 struct zebra_pbr_rule
*rule
= b
->data
;
218 if (pul
->unique
== rule
->rule
.unique
&& pul
->ifp
== rule
->ifp
) {
220 return HASHWALK_ABORT
;
223 return HASHWALK_CONTINUE
;
226 static struct zebra_pbr_rule
*pbr_rule_lookup_unique(struct zebra_ns
*zns
,
228 struct interface
*ifp
)
230 struct pbr_rule_unique_lookup pul
;
235 hash_walk(zns
->rules_hash
, &pbr_rule_lookup_unique_walker
, &pul
);
240 void zebra_pbr_ipset_free(void *arg
)
242 struct zebra_pbr_ipset
*ipset
;
243 struct zebra_ns
*zns
;
245 ipset
= (struct zebra_pbr_ipset
*)arg
;
246 if (vrf_is_backend_netns())
247 zns
= zebra_ns_lookup(ipset
->vrf_id
);
249 zns
= zebra_ns_lookup(NS_DEFAULT
);
250 hook_call(zebra_pbr_ipset_wrap_script_update
,
252 XFREE(MTYPE_TMP
, ipset
);
255 uint32_t zebra_pbr_ipset_hash_key(void *arg
)
257 struct zebra_pbr_ipset
*ipset
= (struct zebra_pbr_ipset
*)arg
;
258 uint32_t *pnt
= (uint32_t *)&ipset
->ipset_name
;
260 return jhash2(pnt
, ZEBRA_IPSET_NAME_HASH_SIZE
, 0x63ab42de);
263 int zebra_pbr_ipset_hash_equal(const void *arg1
, const void *arg2
)
265 const struct zebra_pbr_ipset
*r1
, *r2
;
267 r1
= (const struct zebra_pbr_ipset
*)arg1
;
268 r2
= (const struct zebra_pbr_ipset
*)arg2
;
270 if (r1
->type
!= r2
->type
)
272 if (r1
->unique
!= r2
->unique
)
274 if (strncmp(r1
->ipset_name
, r2
->ipset_name
,
275 ZEBRA_IPSET_NAME_SIZE
))
280 void zebra_pbr_ipset_entry_free(void *arg
)
282 struct zebra_pbr_ipset_entry
*ipset
;
283 struct zebra_ns
*zns
;
285 ipset
= (struct zebra_pbr_ipset_entry
*)arg
;
286 if (ipset
->backpointer
&& vrf_is_backend_netns()) {
287 struct zebra_pbr_ipset
*ips
= ipset
->backpointer
;
289 zns
= zebra_ns_lookup((ns_id_t
)ips
->vrf_id
);
291 zns
= zebra_ns_lookup(NS_DEFAULT
);
292 hook_call(zebra_pbr_ipset_entry_wrap_script_update
,
295 XFREE(MTYPE_TMP
, ipset
);
298 uint32_t zebra_pbr_ipset_entry_hash_key(void *arg
)
300 struct zebra_pbr_ipset_entry
*ipset
;
303 ipset
= (struct zebra_pbr_ipset_entry
*)arg
;
304 key
= prefix_hash_key(&ipset
->src
);
305 key
= jhash_1word(ipset
->unique
, key
);
306 key
= jhash_1word(prefix_hash_key(&ipset
->dst
), key
);
307 key
= jhash(&ipset
->dst_port_min
, 2, key
);
308 key
= jhash(&ipset
->dst_port_max
, 2, key
);
309 key
= jhash(&ipset
->src_port_min
, 2, key
);
310 key
= jhash(&ipset
->src_port_max
, 2, key
);
311 key
= jhash(&ipset
->proto
, 1, key
);
316 int zebra_pbr_ipset_entry_hash_equal(const void *arg1
, const void *arg2
)
318 const struct zebra_pbr_ipset_entry
*r1
, *r2
;
320 r1
= (const struct zebra_pbr_ipset_entry
*)arg1
;
321 r2
= (const struct zebra_pbr_ipset_entry
*)arg2
;
323 if (r1
->unique
!= r2
->unique
)
326 if (!prefix_same(&r1
->src
, &r2
->src
))
329 if (!prefix_same(&r1
->dst
, &r2
->dst
))
332 if (r1
->src_port_min
!= r2
->src_port_min
)
335 if (r1
->src_port_max
!= r2
->src_port_max
)
338 if (r1
->dst_port_min
!= r2
->dst_port_min
)
341 if (r1
->dst_port_max
!= r2
->dst_port_max
)
344 if (r1
->proto
!= r2
->proto
)
349 void zebra_pbr_iptable_free(void *arg
)
351 struct zebra_pbr_iptable
*iptable
;
352 struct listnode
*node
, *nnode
;
354 struct zebra_ns
*zns
;
356 iptable
= (struct zebra_pbr_iptable
*)arg
;
357 if (vrf_is_backend_netns())
358 zns
= zebra_ns_lookup((ns_id_t
)iptable
->vrf_id
);
360 zns
= zebra_ns_lookup(NS_DEFAULT
);
361 hook_call(zebra_pbr_iptable_wrap_script_update
,
364 for (ALL_LIST_ELEMENTS(iptable
->interface_name_list
,
365 node
, nnode
, name
)) {
366 XFREE(MTYPE_PBR_IPTABLE_IFNAME
, name
);
367 list_delete_node(iptable
->interface_name_list
,
370 XFREE(MTYPE_TMP
, iptable
);
373 uint32_t zebra_pbr_iptable_hash_key(void *arg
)
375 struct zebra_pbr_iptable
*iptable
= (struct zebra_pbr_iptable
*)arg
;
376 uint32_t *pnt
= (uint32_t *)&(iptable
->ipset_name
);
379 key
= jhash2(pnt
, ZEBRA_IPSET_NAME_HASH_SIZE
,
381 key
= jhash_1word(iptable
->fwmark
, key
);
382 key
= jhash_1word(iptable
->pkt_len_min
, key
);
383 key
= jhash_1word(iptable
->pkt_len_max
, key
);
384 key
= jhash_1word(iptable
->tcp_flags
, key
);
385 key
= jhash_1word(iptable
->tcp_mask_flags
, key
);
386 key
= jhash_1word(iptable
->dscp_value
, key
);
387 key
= jhash_1word(iptable
->fragment
, key
);
388 return jhash_3words(iptable
->filter_bm
, iptable
->type
,
389 iptable
->unique
, key
);
392 int zebra_pbr_iptable_hash_equal(const void *arg1
, const void *arg2
)
394 const struct zebra_pbr_iptable
*r1
, *r2
;
396 r1
= (const struct zebra_pbr_iptable
*)arg1
;
397 r2
= (const struct zebra_pbr_iptable
*)arg2
;
399 if (r1
->type
!= r2
->type
)
401 if (r1
->unique
!= r2
->unique
)
403 if (r1
->filter_bm
!= r2
->filter_bm
)
405 if (r1
->fwmark
!= r2
->fwmark
)
407 if (r1
->action
!= r2
->action
)
409 if (strncmp(r1
->ipset_name
, r2
->ipset_name
,
410 ZEBRA_IPSET_NAME_SIZE
))
412 if (r1
->pkt_len_min
!= r2
->pkt_len_min
)
414 if (r1
->pkt_len_max
!= r2
->pkt_len_max
)
416 if (r1
->tcp_flags
!= r2
->tcp_flags
)
418 if (r1
->tcp_mask_flags
!= r2
->tcp_mask_flags
)
420 if (r1
->dscp_value
!= r2
->dscp_value
)
422 if (r1
->fragment
!= r2
->fragment
)
427 static void *pbr_rule_alloc_intern(void *arg
)
429 struct zebra_pbr_rule
*zpr
;
430 struct zebra_pbr_rule
*new;
432 zpr
= (struct zebra_pbr_rule
*)arg
;
434 new = XCALLOC(MTYPE_TMP
, sizeof(*new));
436 memcpy(new, zpr
, sizeof(*zpr
));
441 void zebra_pbr_add_rule(struct zebra_ns
*zns
, struct zebra_pbr_rule
*rule
)
443 struct zebra_pbr_rule
*unique
=
444 pbr_rule_lookup_unique(zns
, rule
->rule
.unique
, rule
->ifp
);
446 (void)hash_get(zns
->rules_hash
, rule
, pbr_rule_alloc_intern
);
447 (void)kernel_add_pbr_rule(rule
);
449 * Rule Replace semantics, if we have an old, install the
450 * new rule, look above, and then delete the old
453 zebra_pbr_del_rule(zns
, unique
);
456 void zebra_pbr_del_rule(struct zebra_ns
*zns
, struct zebra_pbr_rule
*rule
)
458 struct zebra_pbr_rule
*lookup
;
460 lookup
= hash_lookup(zns
->rules_hash
, rule
);
461 (void)kernel_del_pbr_rule(rule
);
464 hash_release(zns
->rules_hash
, lookup
);
465 XFREE(MTYPE_TMP
, lookup
);
467 zlog_debug("%s: Rule being deleted we know nothing about",
468 __PRETTY_FUNCTION__
);
471 static void zebra_pbr_cleanup_rules(struct hash_backet
*b
, void *data
)
473 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
474 struct zebra_pbr_rule
*rule
= b
->data
;
477 if (rule
->sock
== *sock
) {
478 (void)kernel_del_pbr_rule(rule
);
479 hash_release(zns
->rules_hash
, rule
);
480 XFREE(MTYPE_TMP
, rule
);
484 static void zebra_pbr_cleanup_ipset(struct hash_backet
*b
, void *data
)
486 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
487 struct zebra_pbr_ipset
*ipset
= b
->data
;
490 if (ipset
->sock
== *sock
) {
491 hook_call(zebra_pbr_ipset_wrap_script_update
,
493 hash_release(zns
->ipset_hash
, ipset
);
497 static void zebra_pbr_cleanup_ipset_entry(struct hash_backet
*b
, void *data
)
499 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
500 struct zebra_pbr_ipset_entry
*ipset
= b
->data
;
503 if (ipset
->sock
== *sock
) {
504 hook_call(zebra_pbr_ipset_entry_wrap_script_update
,
506 hash_release(zns
->ipset_entry_hash
, ipset
);
510 static void zebra_pbr_cleanup_iptable(struct hash_backet
*b
, void *data
)
512 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
513 struct zebra_pbr_iptable
*iptable
= b
->data
;
516 if (iptable
->sock
== *sock
) {
517 hook_call(zebra_pbr_iptable_wrap_script_update
,
519 hash_release(zns
->iptable_hash
, iptable
);
523 static int zebra_pbr_client_close_cleanup(struct zserv
*client
)
525 int sock
= client
->sock
;
526 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
530 hash_iterate(zns
->rules_hash
, zebra_pbr_cleanup_rules
, &sock
);
531 hash_iterate(zns
->iptable_hash
,
532 zebra_pbr_cleanup_iptable
, &sock
);
533 hash_iterate(zns
->ipset_entry_hash
,
534 zebra_pbr_cleanup_ipset_entry
, &sock
);
535 hash_iterate(zns
->ipset_hash
,
536 zebra_pbr_cleanup_ipset
, &sock
);
540 void zebra_pbr_init(void)
542 hook_register(zserv_client_close
, zebra_pbr_client_close_cleanup
);
545 static void *pbr_ipset_alloc_intern(void *arg
)
547 struct zebra_pbr_ipset
*zpi
;
548 struct zebra_pbr_ipset
*new;
550 zpi
= (struct zebra_pbr_ipset
*)arg
;
552 new = XCALLOC(MTYPE_TMP
, sizeof(struct zebra_pbr_ipset
));
554 memcpy(new, zpi
, sizeof(*zpi
));
559 void zebra_pbr_create_ipset(struct zebra_ns
*zns
,
560 struct zebra_pbr_ipset
*ipset
)
564 (void)hash_get(zns
->ipset_hash
, ipset
, pbr_ipset_alloc_intern
);
565 ret
= hook_call(zebra_pbr_ipset_wrap_script_update
,
567 kernel_pbr_ipset_add_del_status(ipset
,
568 ret
? DP_INSTALL_SUCCESS
569 : DP_INSTALL_FAILURE
);
572 void zebra_pbr_destroy_ipset(struct zebra_ns
*zns
,
573 struct zebra_pbr_ipset
*ipset
)
575 struct zebra_pbr_ipset
*lookup
;
577 lookup
= hash_lookup(zns
->ipset_hash
, ipset
);
578 hook_call(zebra_pbr_ipset_wrap_script_update
,
581 hash_release(zns
->ipset_hash
, lookup
);
582 XFREE(MTYPE_TMP
, lookup
);
585 "%s: IPSet Entry being deleted we know nothing about",
586 __PRETTY_FUNCTION__
);
589 struct pbr_ipset_name_lookup
{
590 struct zebra_pbr_ipset
*ipset
;
591 char ipset_name
[ZEBRA_IPSET_NAME_SIZE
];
594 const char *zebra_pbr_ipset_type2str(uint32_t type
)
596 return lookup_msg(ipset_type_msg
, type
,
597 "Unrecognized IPset Type");
600 static int zebra_pbr_ipset_pername_walkcb(struct hash_backet
*backet
, void *arg
)
602 struct pbr_ipset_name_lookup
*pinl
=
603 (struct pbr_ipset_name_lookup
*)arg
;
604 struct zebra_pbr_ipset
*zpi
= (struct zebra_pbr_ipset
*)backet
->data
;
606 if (!strncmp(pinl
->ipset_name
, zpi
->ipset_name
,
607 ZEBRA_IPSET_NAME_SIZE
)) {
609 return HASHWALK_ABORT
;
611 return HASHWALK_CONTINUE
;
614 struct zebra_pbr_ipset
*zebra_pbr_lookup_ipset_pername(struct zebra_ns
*zns
,
617 struct pbr_ipset_name_lookup pinl
;
618 struct pbr_ipset_name_lookup
*ptr
= &pinl
;
622 memset(ptr
, 0, sizeof(struct pbr_ipset_name_lookup
));
623 snprintf((char *)ptr
->ipset_name
, ZEBRA_IPSET_NAME_SIZE
, "%s",
625 hash_walk(zns
->ipset_hash
, zebra_pbr_ipset_pername_walkcb
, ptr
);
629 static void *pbr_ipset_entry_alloc_intern(void *arg
)
631 struct zebra_pbr_ipset_entry
*zpi
;
632 struct zebra_pbr_ipset_entry
*new;
634 zpi
= (struct zebra_pbr_ipset_entry
*)arg
;
636 new = XCALLOC(MTYPE_TMP
, sizeof(struct zebra_pbr_ipset_entry
));
638 memcpy(new, zpi
, sizeof(*zpi
));
643 void zebra_pbr_add_ipset_entry(struct zebra_ns
*zns
,
644 struct zebra_pbr_ipset_entry
*ipset
)
648 (void)hash_get(zns
->ipset_entry_hash
, ipset
,
649 pbr_ipset_entry_alloc_intern
);
650 ret
= hook_call(zebra_pbr_ipset_entry_wrap_script_update
,
652 kernel_pbr_ipset_entry_add_del_status(ipset
,
653 ret
? DP_INSTALL_SUCCESS
654 : DP_INSTALL_FAILURE
);
657 void zebra_pbr_del_ipset_entry(struct zebra_ns
*zns
,
658 struct zebra_pbr_ipset_entry
*ipset
)
660 struct zebra_pbr_ipset_entry
*lookup
;
662 lookup
= hash_lookup(zns
->ipset_entry_hash
, ipset
);
663 hook_call(zebra_pbr_ipset_entry_wrap_script_update
,
666 hash_release(zns
->ipset_entry_hash
, lookup
);
667 XFREE(MTYPE_TMP
, lookup
);
669 zlog_debug("%s: IPSet being deleted we know nothing about",
670 __PRETTY_FUNCTION__
);
673 static void *pbr_iptable_alloc_intern(void *arg
)
675 struct zebra_pbr_iptable
*zpi
;
676 struct zebra_pbr_iptable
*new;
678 zpi
= (struct zebra_pbr_iptable
*)arg
;
680 new = XCALLOC(MTYPE_TMP
, sizeof(struct zebra_pbr_iptable
));
682 memcpy(new, zpi
, sizeof(*zpi
));
687 void zebra_pbr_add_iptable(struct zebra_ns
*zns
,
688 struct zebra_pbr_iptable
*iptable
)
692 (void)hash_get(zns
->iptable_hash
, iptable
,
693 pbr_iptable_alloc_intern
);
694 ret
= hook_call(zebra_pbr_iptable_wrap_script_update
, zns
, 1, iptable
);
695 kernel_pbr_iptable_add_del_status(iptable
,
696 ret
? DP_INSTALL_SUCCESS
697 : DP_INSTALL_FAILURE
);
700 void zebra_pbr_del_iptable(struct zebra_ns
*zns
,
701 struct zebra_pbr_iptable
*iptable
)
703 struct zebra_pbr_iptable
*lookup
;
705 lookup
= hash_lookup(zns
->iptable_hash
, iptable
);
706 hook_call(zebra_pbr_iptable_wrap_script_update
, zns
, 0, iptable
);
708 struct listnode
*node
, *nnode
;
711 hash_release(zns
->iptable_hash
, lookup
);
712 for (ALL_LIST_ELEMENTS(iptable
->interface_name_list
,
713 node
, nnode
, name
)) {
714 XFREE(MTYPE_PBR_IPTABLE_IFNAME
, name
);
715 list_delete_node(iptable
->interface_name_list
,
718 XFREE(MTYPE_TMP
, lookup
);
720 zlog_debug("%s: IPTable being deleted we know nothing about",
721 __PRETTY_FUNCTION__
);
725 * Handle success or failure of rule (un)install in the kernel.
727 void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule
*rule
,
731 case DP_INSTALL_SUCCESS
:
732 zsend_rule_notify_owner(rule
, ZAPI_RULE_INSTALLED
);
734 case DP_INSTALL_FAILURE
:
735 zsend_rule_notify_owner(rule
, ZAPI_RULE_FAIL_INSTALL
);
737 case DP_DELETE_SUCCESS
:
738 zsend_rule_notify_owner(rule
, ZAPI_RULE_REMOVED
);
740 case DP_DELETE_FAILURE
:
741 zsend_rule_notify_owner(rule
, ZAPI_RULE_FAIL_REMOVE
);
747 * Handle success or failure of ipset (un)install in the kernel.
749 void kernel_pbr_ipset_add_del_status(struct zebra_pbr_ipset
*ipset
,
753 case DP_INSTALL_SUCCESS
:
754 zsend_ipset_notify_owner(ipset
, ZAPI_IPSET_INSTALLED
);
756 case DP_INSTALL_FAILURE
:
757 zsend_ipset_notify_owner(ipset
, ZAPI_IPSET_FAIL_INSTALL
);
759 case DP_DELETE_SUCCESS
:
760 zsend_ipset_notify_owner(ipset
, ZAPI_IPSET_REMOVED
);
762 case DP_DELETE_FAILURE
:
763 zsend_ipset_notify_owner(ipset
, ZAPI_IPSET_FAIL_REMOVE
);
769 * Handle success or failure of ipset (un)install in the kernel.
771 void kernel_pbr_ipset_entry_add_del_status(
772 struct zebra_pbr_ipset_entry
*ipset
,
776 case DP_INSTALL_SUCCESS
:
777 zsend_ipset_entry_notify_owner(ipset
,
778 ZAPI_IPSET_ENTRY_INSTALLED
);
780 case DP_INSTALL_FAILURE
:
781 zsend_ipset_entry_notify_owner(ipset
,
782 ZAPI_IPSET_ENTRY_FAIL_INSTALL
);
784 case DP_DELETE_SUCCESS
:
785 zsend_ipset_entry_notify_owner(ipset
,
786 ZAPI_IPSET_ENTRY_REMOVED
);
788 case DP_DELETE_FAILURE
:
789 zsend_ipset_entry_notify_owner(ipset
,
790 ZAPI_IPSET_ENTRY_FAIL_REMOVE
);
796 * Handle success or failure of ipset (un)install in the kernel.
798 void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable
*iptable
,
802 case DP_INSTALL_SUCCESS
:
803 zsend_iptable_notify_owner(iptable
, ZAPI_IPTABLE_INSTALLED
);
805 case DP_INSTALL_FAILURE
:
806 zsend_iptable_notify_owner(iptable
, ZAPI_IPTABLE_FAIL_INSTALL
);
808 case DP_DELETE_SUCCESS
:
809 zsend_iptable_notify_owner(iptable
,
810 ZAPI_IPTABLE_REMOVED
);
812 case DP_DELETE_FAILURE
:
813 zsend_iptable_notify_owner(iptable
,
814 ZAPI_IPTABLE_FAIL_REMOVE
);
820 * Handle rule delete notification from kernel.
822 int kernel_pbr_rule_del(struct zebra_pbr_rule
*rule
)
827 struct zebra_pbr_ipset_entry_unique_display
{
828 struct zebra_pbr_ipset
*zpi
;
830 struct zebra_ns
*zns
;
833 struct zebra_pbr_env_display
{
834 struct zebra_ns
*zns
;
839 static const char *zebra_pbr_prefix2str(union prefixconstptr pu
,
842 const struct prefix
*p
= pu
.p
;
843 char buf
[PREFIX2STR_BUFFER
];
845 if (p
->family
== AF_INET
&& p
->prefixlen
== IPV4_MAX_PREFIXLEN
) {
846 snprintf(str
, size
, "%s", inet_ntop(p
->family
, &p
->u
.prefix
,
847 buf
, PREFIX2STR_BUFFER
));
850 return prefix2str(pu
, str
, size
);
853 static void zebra_pbr_display_icmp(struct vty
*vty
,
854 struct zebra_pbr_ipset_entry
*zpie
)
856 char decoded_str
[20];
859 /* range icmp type */
860 if (zpie
->src_port_max
|| zpie
->dst_port_max
) {
861 vty_out(vty
, ":icmp:[type <%d:%d>;code <%d:%d>",
862 zpie
->src_port_min
, zpie
->src_port_max
,
863 zpie
->dst_port_min
, zpie
->dst_port_max
);
865 port
= ((zpie
->src_port_min
<< 8) & 0xff00) +
866 (zpie
->dst_port_min
& 0xff);
867 memset(decoded_str
, 0, sizeof(decoded_str
));
868 sprintf(decoded_str
, "%d/%d",
871 vty_out(vty
, ":icmp:%s",
872 lookup_msg(icmp_typecode_str
,
877 static void zebra_pbr_display_port(struct vty
*vty
, uint32_t filter_bm
,
878 uint16_t port_min
, uint16_t port_max
,
881 if (!(filter_bm
& PBR_FILTER_PROTO
)) {
883 vty_out(vty
, ":udp/tcp:%d-%d",
886 vty_out(vty
, ":udp/tcp:%d",
890 vty_out(vty
, ":proto %d:%d-%d",
891 proto
, port_min
, port_max
);
893 vty_out(vty
, ":proto %d:%d",
898 static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet
*backet
,
901 struct zebra_pbr_ipset_entry_unique_display
*unique
=
902 (struct zebra_pbr_ipset_entry_unique_display
*)arg
;
903 struct zebra_pbr_ipset
*zpi
= unique
->zpi
;
904 struct vty
*vty
= unique
->vty
;
905 struct zebra_pbr_ipset_entry
*zpie
=
906 (struct zebra_pbr_ipset_entry
*)backet
->data
;
907 uint64_t pkts
= 0, bytes
= 0;
908 struct zebra_ns
*zns
= unique
->zns
;
911 if (zpie
->backpointer
!= zpi
)
912 return HASHWALK_CONTINUE
;
914 if ((zpi
->type
== IPSET_NET_NET
) ||
915 (zpi
->type
== IPSET_NET_PORT_NET
)) {
916 char buf
[PREFIX_STRLEN
];
918 zebra_pbr_prefix2str(&(zpie
->src
), buf
, sizeof(buf
));
919 vty_out(vty
, "\tfrom %s", buf
);
920 if (zpie
->filter_bm
& PBR_FILTER_SRC_PORT
&&
921 zpie
->proto
!= IPPROTO_ICMP
)
922 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
926 vty_out(vty
, " to ");
927 zebra_pbr_prefix2str(&(zpie
->dst
), buf
, sizeof(buf
));
928 vty_out(vty
, "%s", buf
);
929 if (zpie
->filter_bm
& PBR_FILTER_DST_PORT
&&
930 zpie
->proto
!= IPPROTO_ICMP
)
931 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
935 if (zpie
->proto
== IPPROTO_ICMP
)
936 zebra_pbr_display_icmp(vty
, zpie
);
937 } else if ((zpi
->type
== IPSET_NET
) ||
938 (zpi
->type
== IPSET_NET_PORT
)) {
939 char buf
[PREFIX_STRLEN
];
941 if (zpie
->filter_bm
& PBR_FILTER_SRC_IP
) {
942 zebra_pbr_prefix2str(&(zpie
->src
), buf
, sizeof(buf
));
943 vty_out(vty
, "\tfrom %s", buf
);
945 if (zpie
->filter_bm
& PBR_FILTER_SRC_PORT
&&
946 zpie
->proto
!= IPPROTO_ICMP
)
947 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
951 if (zpie
->filter_bm
& PBR_FILTER_DST_IP
) {
952 zebra_pbr_prefix2str(&(zpie
->dst
), buf
, sizeof(buf
));
953 vty_out(vty
, "\tto %s", buf
);
955 if (zpie
->filter_bm
& PBR_FILTER_DST_PORT
&&
956 zpie
->proto
!= IPPROTO_ICMP
)
957 zebra_pbr_display_port(vty
, zpie
->filter_bm
,
961 if (zpie
->proto
== IPPROTO_ICMP
)
962 zebra_pbr_display_icmp(vty
, zpie
);
964 vty_out(vty
, " (%u)\n", zpie
->unique
);
966 ret
= hook_call(zebra_pbr_ipset_entry_wrap_script_get_stat
,
967 zns
, zpie
, &pkts
, &bytes
);
969 vty_out(vty
, "\t pkts %" PRIu64
", bytes %" PRIu64
"\n",
971 return HASHWALK_CONTINUE
;
974 static int zebra_pbr_show_ipset_walkcb(struct hash_backet
*backet
, void *arg
)
976 struct zebra_pbr_env_display
*uniqueipset
=
977 (struct zebra_pbr_env_display
*)arg
;
978 struct zebra_pbr_ipset
*zpi
= (struct zebra_pbr_ipset
*)backet
->data
;
979 struct zebra_pbr_ipset_entry_unique_display unique
;
980 struct vty
*vty
= uniqueipset
->vty
;
981 struct zebra_ns
*zns
= uniqueipset
->zns
;
983 vty_out(vty
, "IPset %s type %s\n", zpi
->ipset_name
,
984 zebra_pbr_ipset_type2str(zpi
->type
));
988 hash_walk(zns
->ipset_entry_hash
, zebra_pbr_show_ipset_entry_walkcb
,
991 return HASHWALK_CONTINUE
;
994 size_t zebra_pbr_tcpflags_snprintf(char *buffer
, size_t len
,
997 size_t len_written
= 0;
998 static struct message nt
= {0};
999 const struct message
*pnt
;
1002 for (pnt
= tcp_value_str
;
1003 memcmp(pnt
, &nt
, sizeof(struct message
)); pnt
++)
1004 if (pnt
->key
& tcp_val
) {
1005 len_written
+= snprintf(buffer
+ len_written
,
1016 void zebra_pbr_show_ipset_list(struct vty
*vty
, char *ipsetname
)
1018 struct zebra_pbr_ipset
*zpi
;
1019 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1020 struct zebra_pbr_ipset_entry_unique_display unique
;
1021 struct zebra_pbr_env_display uniqueipset
;
1024 zpi
= zebra_pbr_lookup_ipset_pername(zns
, ipsetname
);
1026 vty_out(vty
, "No IPset %s found\n", ipsetname
);
1029 vty_out(vty
, "IPset %s type %s\n", ipsetname
,
1030 zebra_pbr_ipset_type2str(zpi
->type
));
1035 hash_walk(zns
->ipset_entry_hash
,
1036 zebra_pbr_show_ipset_entry_walkcb
,
1040 uniqueipset
.zns
= zns
;
1041 uniqueipset
.vty
= vty
;
1042 uniqueipset
.name
= NULL
;
1043 hash_walk(zns
->ipset_hash
, zebra_pbr_show_ipset_walkcb
,
1047 struct pbr_rule_fwmark_lookup
{
1048 struct zebra_pbr_rule
*ptr
;
1052 static int zebra_pbr_rule_lookup_fwmark_walkcb(struct hash_backet
*backet
,
1055 struct pbr_rule_fwmark_lookup
*iprule
=
1056 (struct pbr_rule_fwmark_lookup
*)arg
;
1057 struct zebra_pbr_rule
*zpr
= (struct zebra_pbr_rule
*)backet
->data
;
1059 if (iprule
->fwmark
== zpr
->rule
.filter
.fwmark
) {
1061 return HASHWALK_ABORT
;
1063 return HASHWALK_CONTINUE
;
1066 static void zebra_pbr_show_iptable_unit(struct zebra_pbr_iptable
*iptable
,
1068 struct zebra_ns
*zns
)
1071 uint64_t pkts
= 0, bytes
= 0;
1073 vty_out(vty
, "IPtable %s action %s (%u)\n", iptable
->ipset_name
,
1074 iptable
->action
== ZEBRA_IPTABLES_DROP
? "drop" : "redirect",
1076 if (iptable
->type
== IPSET_NET_PORT
||
1077 iptable
->type
== IPSET_NET_PORT_NET
) {
1078 if (!(iptable
->filter_bm
& MATCH_ICMP_SET
)) {
1079 if (iptable
->filter_bm
& PBR_FILTER_DST_PORT
)
1080 vty_out(vty
, "\t lookup dst port\n");
1081 else if (iptable
->filter_bm
& PBR_FILTER_SRC_PORT
)
1082 vty_out(vty
, "\t lookup src port\n");
1085 if (iptable
->pkt_len_min
|| iptable
->pkt_len_max
) {
1086 if (!iptable
->pkt_len_max
)
1087 vty_out(vty
, "\t pkt len %u\n",
1088 iptable
->pkt_len_min
);
1090 vty_out(vty
, "\t pkt len [%u;%u]\n",
1091 iptable
->pkt_len_min
,
1092 iptable
->pkt_len_max
);
1094 if (iptable
->tcp_flags
|| iptable
->tcp_mask_flags
) {
1095 char tcp_flag_str
[64];
1096 char tcp_flag_mask_str
[64];
1098 zebra_pbr_tcpflags_snprintf(tcp_flag_str
,
1099 sizeof(tcp_flag_str
),
1100 iptable
->tcp_flags
);
1101 zebra_pbr_tcpflags_snprintf(tcp_flag_mask_str
,
1102 sizeof(tcp_flag_mask_str
),
1103 iptable
->tcp_mask_flags
);
1104 vty_out(vty
, "\t tcpflags [%s/%s]\n",
1105 tcp_flag_str
, tcp_flag_mask_str
);
1107 if (iptable
->filter_bm
& (MATCH_DSCP_SET
| MATCH_DSCP_INVERSE_SET
)) {
1108 vty_out(vty
, "\t dscp %s %d\n",
1109 iptable
->filter_bm
& MATCH_DSCP_INVERSE_SET
?
1110 "not" : "", iptable
->dscp_value
);
1112 if (iptable
->fragment
) {
1115 sprintf(val_str
, "%d", iptable
->fragment
);
1116 vty_out(vty
, "\t fragment%s %s\n",
1117 iptable
->filter_bm
& MATCH_FRAGMENT_INVERSE_SET
?
1118 " not" : "", lookup_msg(fragment_value_str
,
1119 iptable
->fragment
, val_str
));
1121 ret
= hook_call(zebra_pbr_iptable_wrap_script_get_stat
,
1122 zns
, iptable
, &pkts
, &bytes
);
1123 if (ret
&& pkts
> 0)
1124 vty_out(vty
, "\t pkts %" PRIu64
", bytes %" PRIu64
"\n",
1126 if (iptable
->action
!= ZEBRA_IPTABLES_DROP
) {
1127 struct pbr_rule_fwmark_lookup prfl
;
1129 prfl
.fwmark
= iptable
->fwmark
;
1131 hash_walk(zns
->rules_hash
,
1132 &zebra_pbr_rule_lookup_fwmark_walkcb
, &prfl
);
1134 struct zebra_pbr_rule
*zpr
= prfl
.ptr
;
1136 vty_out(vty
, "\t table %u, fwmark %u\n",
1137 zpr
->rule
.action
.table
,
1143 static int zebra_pbr_show_iptable_walkcb(struct hash_backet
*backet
, void *arg
)
1145 struct zebra_pbr_iptable
*iptable
=
1146 (struct zebra_pbr_iptable
*)backet
->data
;
1147 struct zebra_pbr_env_display
*env
= (struct zebra_pbr_env_display
*)arg
;
1148 struct vty
*vty
= env
->vty
;
1149 struct zebra_ns
*zns
= env
->zns
;
1150 char *iptable_name
= env
->name
;
1153 zebra_pbr_show_iptable_unit(iptable
, vty
, zns
);
1154 else if (!strncmp(iptable_name
,
1155 iptable
->ipset_name
,
1156 ZEBRA_IPSET_NAME_SIZE
))
1157 zebra_pbr_show_iptable_unit(iptable
, vty
, zns
);
1158 return HASHWALK_CONTINUE
;
1161 void zebra_pbr_show_iptable(struct vty
*vty
, char *iptable_name
)
1163 struct zebra_ns
*zns
= zebra_ns_lookup(NS_DEFAULT
);
1164 struct zebra_pbr_env_display env
;
1168 env
.name
= iptable_name
;
1169 hash_walk(zns
->iptable_hash
, zebra_pbr_show_iptable_walkcb
,
1173 void zebra_pbr_iptable_update_interfacelist(struct stream
*s
,
1174 struct zebra_pbr_iptable
*zpi
)
1176 uint32_t i
= 0, index
;
1177 struct interface
*ifp
;
1180 for (i
= 0; i
< zpi
->nb_interface
; i
++) {
1181 STREAM_GETL(s
, index
);
1182 ifp
= if_lookup_by_index(index
, zpi
->vrf_id
);
1185 name
= XSTRDUP(MTYPE_PBR_IPTABLE_IFNAME
, ifp
->name
);
1186 listnode_add(zpi
->interface_name_list
, name
);