-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Mohamed Mahmoud <mmahmoud@redhat.com>
- Loading branch information
1 parent
b4122b0
commit 07aa040
Showing
14 changed files
with
328 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
/* | ||
* IPsec monitoring kretprobe eBPF hook. | ||
*/ | ||
|
||
#ifndef __IPSEC_H__ | ||
#define __IPSEC_H__ | ||
|
||
#include "utils.h" | ||
|
||
static inline int ipsec_lookup_and_update_flow(flow_id *id, bool flow_encrypted) { | ||
additional_metrics *extra_metrics = bpf_map_lookup_elem(&additional_flow_metrics, id); | ||
if (extra_metrics != NULL) { | ||
extra_metrics->end_mono_time_ts = bpf_ktime_get_ns(); | ||
extra_metrics->flow_encrypted = flow_encrypted; | ||
return 0; | ||
} | ||
return -1; | ||
} | ||
|
||
static inline int update_flow_with_ipsec_return(bool flow_encrypted, direction dir) { | ||
u64 pid_tgid = bpf_get_current_pid_tgid(); | ||
u16 family = 0, flags = 0, eth_protocol = 0; | ||
struct sk_buff *skb = NULL; | ||
u8 dscp = 0, protocol = 0; | ||
u32 tid = pid_tgid; | ||
int ret = 0; | ||
flow_id id; | ||
|
||
if (dir == INGRESS) { | ||
skb = bpf_map_lookup_elem(&sk_buffs_ingress_map, &tid); | ||
} else { | ||
skb = bpf_map_lookup_elem(&sk_buffs_egress_map, &tid); | ||
} | ||
|
||
if (!skb) | ||
return 0; | ||
|
||
__builtin_memset(&id, 0, sizeof(id)); | ||
|
||
// read L2 info | ||
core_fill_in_l2(skb, ð_protocol, &family); | ||
|
||
// read L3 info | ||
core_fill_in_l3(skb, &id, family, &protocol, &dscp); | ||
|
||
// read L4 info | ||
switch (protocol) { | ||
case IPPROTO_TCP: | ||
core_fill_in_tcp(skb, &id, &flags); | ||
break; | ||
case IPPROTO_UDP: | ||
core_fill_in_udp(skb, &id); | ||
break; | ||
case IPPROTO_SCTP: | ||
core_fill_in_sctp(skb, &id); | ||
break; | ||
case IPPROTO_ICMP: | ||
core_fill_in_icmpv4(skb, &id); | ||
break; | ||
case IPPROTO_ICMPV6: | ||
core_fill_in_icmpv6(skb, &id); | ||
break; | ||
default: | ||
fill_in_others_protocol(&id, protocol); | ||
} | ||
|
||
// check if this packet need to be filtered if filtering feature is enabled | ||
bool skip = check_and_do_flow_filtering(&id, flags, 0, eth_protocol, NULL, 0); | ||
if (skip) { | ||
return 0; | ||
} | ||
|
||
// update flow with ipsec info | ||
ret = ipsec_lookup_and_update_flow(&id, flow_encrypted); | ||
if (ret == 0) { | ||
goto end; | ||
} | ||
|
||
u64 current_time = bpf_ktime_get_ns(); | ||
additional_metrics new_flow; | ||
__builtin_memset(&new_flow, 0, sizeof(new_flow)); | ||
new_flow.start_mono_time_ts = current_time; | ||
new_flow.end_mono_time_ts = current_time; | ||
new_flow.eth_protocol = eth_protocol; | ||
new_flow.flow_encrypted = flow_encrypted; | ||
ret = bpf_map_update_elem(&additional_flow_metrics, &id, &new_flow, BPF_NOEXIST); | ||
if (ret != 0) { | ||
if (trace_messages && ret != -EEXIST) { | ||
bpf_printk("error ipsec track creating flow %d\n", ret); | ||
} | ||
if (ret == -EEXIST) { | ||
ret = ipsec_lookup_and_update_flow(&id, flow_encrypted); | ||
if (trace_messages && ret != 0) { | ||
bpf_printk("error ipsec track updating an existing flow %d\n", ret); | ||
} | ||
} | ||
} | ||
end: | ||
if (dir == INGRESS) { | ||
bpf_map_delete_elem(&sk_buffs_ingress_map, &tid); | ||
} else { | ||
bpf_map_delete_elem(&sk_buffs_egress_map, &tid); | ||
} | ||
return 0; | ||
} | ||
|
||
static inline int enter_xfrm_func(struct sk_buff *skb, direction dir) { | ||
u64 pid_tgid = bpf_get_current_pid_tgid(); | ||
u16 family = 0, flags = 0, eth_protocol = 0; | ||
u8 dscp = 0, protocol = 0; | ||
u32 tid = pid_tgid; | ||
flow_id id; | ||
int ret = 0; | ||
|
||
__builtin_memset(&id, 0, sizeof(id)); | ||
|
||
// read L2 info | ||
core_fill_in_l2(skb, ð_protocol, &family); | ||
|
||
// read L3 info | ||
core_fill_in_l3(skb, &id, family, &protocol, &dscp); | ||
|
||
// read L4 info | ||
switch (protocol) { | ||
case IPPROTO_TCP: | ||
core_fill_in_tcp(skb, &id, &flags); | ||
break; | ||
case IPPROTO_UDP: | ||
core_fill_in_udp(skb, &id); | ||
break; | ||
case IPPROTO_SCTP: | ||
core_fill_in_sctp(skb, &id); | ||
break; | ||
case IPPROTO_ICMP: | ||
core_fill_in_icmpv4(skb, &id); | ||
break; | ||
case IPPROTO_ICMPV6: | ||
core_fill_in_icmpv6(skb, &id); | ||
break; | ||
default: | ||
fill_in_others_protocol(&id, protocol); | ||
} | ||
|
||
// check if this packet need to be filtered if filtering feature is enabled | ||
bool skip = check_and_do_flow_filtering(&id, flags, 0, eth_protocol, NULL, 0); | ||
if (skip) { | ||
return 0; | ||
} | ||
|
||
if (dir == INGRESS) { | ||
ret = bpf_map_update_elem(&sk_buffs_ingress_map, &tid, &skb, 0); | ||
} else { | ||
ret = bpf_map_update_elem(&sk_buffs_egress_map, &tid, &skb, 0); | ||
} | ||
if (ret != 0) { | ||
if (trace_messages) { | ||
bpf_printk("error updating dir: %d sk_buff map err: %d\n", dir, ret); | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
SEC("kprobe/xfrm_input") | ||
int BPF_KPROBE(xfrm_input_kprobe) { | ||
if (do_sampling == 0 || enable_ipsec == 0) { | ||
return 0; | ||
} | ||
struct sk_buff *skb = (struct sk_buff *)PT_REGS_PARM1(ctx); | ||
if (!skb) | ||
return 0; | ||
return enter_xfrm_func(skb, INGRESS); | ||
} | ||
|
||
SEC("kretprobe/xfrm_input") | ||
int BPF_KRETPROBE(xfrm_input_kretprobe) { | ||
if (do_sampling == 0 || enable_ipsec == 0) { | ||
return 0; | ||
} | ||
int xfrm_ret = PT_REGS_RC(ctx); | ||
bool flow_encrypted = xfrm_ret == 0 ? 1 : 0; | ||
return update_flow_with_ipsec_return(flow_encrypted, INGRESS); | ||
} | ||
|
||
SEC("kprobe/xfrm_output") | ||
int BPF_KPROBE(xfrm_output_kprobe) { | ||
if (do_sampling == 0 || enable_ipsec == 0) { | ||
return 0; | ||
} | ||
struct sk_buff *skb = (struct sk_buff *)PT_REGS_PARM2(ctx); | ||
if (!skb) | ||
return 0; | ||
return enter_xfrm_func(skb, EGRESS); | ||
} | ||
|
||
SEC("kretprobe/xfrm_output") | ||
int BPF_KRETPROBE(xfrm_output_kretprobe) { | ||
if (do_sampling == 0 || enable_ipsec == 0) { | ||
return 0; | ||
} | ||
int xfrm_ret = PT_REGS_RC(ctx); | ||
bool flow_encrypted = xfrm_ret == 0 ? 1 : 0; | ||
return update_flow_with_ipsec_return(flow_encrypted, EGRESS); | ||
} | ||
|
||
#endif /* __IPSEC_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Binary file not shown.
Oops, something went wrong.