1
1
#[ allow( dead_code) ]
2
2
mod common;
3
3
4
+ use std:: net:: IpAddr ;
5
+ use std:: net:: Ipv4Addr ;
6
+ use std:: net:: Ipv6Addr ;
7
+ use std:: net:: TcpListener ;
4
8
use std:: net:: TcpStream ;
5
9
6
10
use libbpf_rs:: NetfilterOpts ;
@@ -9,7 +13,6 @@ use libbpf_rs::Object;
9
13
use libbpf_rs:: NFPROTO_IPV4 ;
10
14
use libbpf_rs:: NFPROTO_IPV6 ;
11
15
12
- use libbpf_rs:: NF_INET_LOCAL_IN ;
13
16
use libbpf_rs:: NF_INET_POST_ROUTING ;
14
17
use libbpf_rs:: NF_INET_PRE_ROUTING ;
15
18
@@ -28,63 +31,54 @@ fn test_attach_and_detach(obj: &mut Object, protocol_family: i32, hooknum: i32,
28
31
hooknum,
29
32
..NetfilterOpts :: default ( )
30
33
} ;
31
- let error_message = format ! (
32
- "Failed to attach netfilter protocol {}, hook: {}" ,
33
- protocol_family, hook_desc
34
- ) ;
35
34
let link = prog
36
35
. attach_netfilter_with_opts ( netfilter_opt)
37
- . expect ( & error_message) ;
36
+ . unwrap_or_else ( |err| {
37
+ panic ! (
38
+ "Failed to attach netfilter protocol {}, hook: {}: {err}" ,
39
+ protocol_family, hook_desc
40
+ )
41
+ } ) ;
38
42
39
43
let map = get_map_mut ( obj, "ringbuf" ) ;
40
44
41
- let trigger_addr = match protocol_family {
42
- NFPROTO_IPV4 => Some ( "127.0.0.1:12345" ) ,
43
- NFPROTO_IPV6 => Some ( "[::1]:12345" ) ,
44
- _ => {
45
- println ! ( "unknow protocol family" ) ;
46
- None
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)
47
60
}
61
+ _ => panic ! ( "unsupported hook: {hooknum} ({hook_desc})" ) ,
48
62
} ;
49
-
50
- if let Some ( trigger_addr) = trigger_addr {
51
- let result = match hook_desc {
52
- "PRE_ROUTING" | "LOCAL_IN" | "LOCAL_OUT" | "POST_ROUTING" => {
53
- let action = || {
54
- let _ = TcpStream :: connect ( trigger_addr) ;
55
- } ;
56
- with_ringbuffer ( & map, action)
57
- }
58
- "FORWARD" => 1 ,
59
- _ => {
60
- panic ! ( "unknow hook" )
61
- }
62
- } ;
63
- assert_eq ! ( result, 1 ) ;
64
- }
63
+ assert_eq ! ( result, 1 ) ;
65
64
assert ! ( link. detach( ) . is_ok( ) ) ;
66
65
}
67
66
68
- // Only selected hooks are tested due to CI failures on certain hooks (e.g., FORWARD, LOCAL_OUT).
69
- // Although these hooks might work in actual use, they were removed from automated testing to
70
- // ensure consistent CI results and maintainability. This approach allows the focus to remain
71
- // on primary netfilter paths (e.g., PRE_ROUTING, LOCAL_IN, POST_ROUTING) that have stable CI
72
- // support. These hooks may be re-added for automated testing in the future if CI compatibility
73
- // improves or specific needs arise.
74
67
#[ tag( root) ]
75
68
#[ test]
76
69
fn test_netfilter ( ) {
77
70
bump_rlimit_mlock ( ) ;
78
71
let mut obj = get_test_object ( "netfilter.bpf.o" ) ;
79
72
73
+ // We don't test all hooks here, because support for some may be
74
+ // more limited.
75
+
80
76
// IPv4 hook
81
77
test_attach_and_detach ( & mut obj, NFPROTO_IPV4 , NF_INET_PRE_ROUTING , "PRE_ROUTING" ) ;
82
- test_attach_and_detach ( & mut obj, NFPROTO_IPV4 , NF_INET_LOCAL_IN , "LOCAL_IN" ) ;
83
78
test_attach_and_detach ( & mut obj, NFPROTO_IPV4 , NF_INET_POST_ROUTING , "POST_ROUTING" ) ;
84
79
85
80
// IPv6 hook
86
81
test_attach_and_detach ( & mut obj, NFPROTO_IPV6 , NF_INET_PRE_ROUTING , "PRE_ROUTING" ) ;
87
- test_attach_and_detach ( & mut obj, NFPROTO_IPV6 , NF_INET_LOCAL_IN , "LOCAL_IN" ) ;
88
82
test_attach_and_detach ( & mut obj, NFPROTO_IPV6 , NF_INET_POST_ROUTING , "POST_ROUTING" ) ;
89
83
}
90
84
0 commit comments