• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #[allow(dead_code)]
2 mod common;
3 
4 use std::net::IpAddr;
5 use std::net::Ipv4Addr;
6 use std::net::Ipv6Addr;
7 use std::net::TcpListener;
8 use std::net::TcpStream;
9 
10 use libbpf_rs::NetfilterOpts;
11 use libbpf_rs::Object;
12 
13 use libbpf_rs::NFPROTO_IPV4;
14 use libbpf_rs::NFPROTO_IPV6;
15 
16 use libbpf_rs::NF_INET_POST_ROUTING;
17 use libbpf_rs::NF_INET_PRE_ROUTING;
18 
19 use crate::common::bump_rlimit_mlock;
20 use crate::common::get_map_mut;
21 use crate::common::get_prog_mut;
22 use crate::common::get_test_object;
23 use crate::common::with_ringbuffer;
24 use test_tag::tag;
25 
26 
test_attach_and_detach(obj: &mut Object, protocol_family: i32, hooknum: i32, hook_desc: &str)27 fn test_attach_and_detach(obj: &mut Object, protocol_family: i32, hooknum: i32, hook_desc: &str) {
28     let prog = get_prog_mut(obj, "handle_netfilter");
29     let netfilter_opt = libbpf_rs::NetfilterOpts {
30         protocol_family,
31         hooknum,
32         ..NetfilterOpts::default()
33     };
34     let link = prog
35         .attach_netfilter_with_opts(netfilter_opt)
36         .unwrap_or_else(|err| {
37             panic!(
38                 "Failed to attach netfilter protocol {}, hook: {}: {err}",
39                 protocol_family, hook_desc
40             )
41         });
42 
43     let map = get_map_mut(obj, "ringbuf");
44 
45     let addr = match protocol_family {
46         NFPROTO_IPV4 => IpAddr::V4(Ipv4Addr::LOCALHOST),
47         NFPROTO_IPV6 => IpAddr::V6(Ipv6Addr::LOCALHOST),
48         _ => panic!("unknow protocol family: {protocol_family}"),
49     };
50     // We let the kernel decide what port to bind to.
51     let listener = TcpListener::bind((addr, 0)).unwrap();
52     let trigger_addr = listener.local_addr().unwrap();
53 
54     let result = match hooknum {
55         NF_INET_PRE_ROUTING | NF_INET_POST_ROUTING => {
56             let action = || {
57                 let _ = TcpStream::connect(trigger_addr);
58             };
59             with_ringbuffer(&map, action)
60         }
61         _ => panic!("unsupported hook: {hooknum} ({hook_desc})"),
62     };
63     assert_eq!(result, 1);
64     assert!(link.detach().is_ok());
65 }
66 
67 #[tag(root)]
68 #[test]
test_netfilter()69 fn test_netfilter() {
70     bump_rlimit_mlock();
71     let mut obj = get_test_object("netfilter.bpf.o");
72 
73     // We don't test all hooks here, because support for some may be
74     // more limited.
75 
76     // IPv4 hook
77     test_attach_and_detach(&mut obj, NFPROTO_IPV4, NF_INET_PRE_ROUTING, "PRE_ROUTING");
78     test_attach_and_detach(&mut obj, NFPROTO_IPV4, NF_INET_POST_ROUTING, "POST_ROUTING");
79 
80     // IPv6 hook
81     test_attach_and_detach(&mut obj, NFPROTO_IPV6, NF_INET_PRE_ROUTING, "PRE_ROUTING");
82     test_attach_and_detach(&mut obj, NFPROTO_IPV6, NF_INET_POST_ROUTING, "POST_ROUTING");
83 }
84 
85 #[tag(root)]
86 #[test]
test_invalid_netfilter_opts()87 fn test_invalid_netfilter_opts() {
88     let mut obj = get_test_object("netfilter.bpf.o");
89     let prog = get_prog_mut(&mut obj, "handle_netfilter");
90 
91     let invalid_opts = NetfilterOpts {
92         protocol_family: 999,
93         hooknum: 999,
94         ..NetfilterOpts::default()
95     };
96 
97     let result = prog.attach_netfilter_with_opts(invalid_opts);
98     assert!(
99         result.is_err(),
100         "Expected error for invalid NetfilterOpts, but got Ok."
101     );
102 }
103