@@ -5,11 +5,11 @@ use crate::{
55 MAX_PACKET_SIZE ,
66} ;
77use parking_lot:: RwLock ;
8- use std:: { mem:: MaybeUninit , sync:: Arc } ;
8+ use std:: { mem:: MaybeUninit , net :: SocketAddr , sync:: Arc } ;
99
1010#[ derive( Debug ) ]
1111pub struct IcmpPoll {
12- pub is_ipv6 : bool ,
12+ pub remote_addr : SocketAddr ,
1313}
1414
1515impl Poll for IcmpPoll {
@@ -22,18 +22,28 @@ impl Poll for IcmpPoll {
2222 peers : Arc < RwLock < PeerManager > > ,
2323 on_peer_recv : Box < dyn Fn ( & Peer , & mut [ u8 ] ) > ,
2424 ) -> anyhow:: Result < ( ) > {
25- let listen_addr = crate :: peer:: create_any_addr ( self . is_ipv6 ) ;
25+ let is_ipv6 = self . remote_addr . is_ipv6 ( ) ;
26+ let listen_addr = crate :: peer:: create_any_addr ( is_ipv6) ;
2627 let socket: socket2:: Socket = IcmpSocket :: inner_bind ( listen_addr) ?;
2728 let mut buffer = [ 0u8 ; MAX_PACKET_SIZE ] ;
2829
30+ #[ cfg( target_os = "linux" ) ]
31+ if !is_ipv6 {
32+ let filter = create_bpf_filter ( self . remote_addr . port ( ) ) ;
33+ if let Err ( error) = socket. attach_filter ( & filter) {
34+ // filter is not required so continue if it errors
35+ log:: warn!( "couldn't attach bpf filter to socket: {error:?}" ) ;
36+ }
37+ }
38+
2939 loop {
3040 let Ok ( size) =
3141 socket. recv ( unsafe { & mut * ( & mut buffer as * mut [ u8 ] as * mut [ MaybeUninit < u8 > ] ) } )
3242 else {
3343 continue ;
3444 } ;
3545 let Some ( icmp_packet) =
36- crate :: socket:: icmp:: parse_icmp_packet ( & mut buffer[ ..size] , self . is_ipv6 )
46+ crate :: socket:: icmp:: parse_icmp_packet ( & mut buffer[ ..size] , is_ipv6)
3747 else {
3848 continue ;
3949 } ;
@@ -47,6 +57,17 @@ impl Poll for IcmpPoll {
4757 }
4858}
4959
60+ #[ cfg( target_os = "linux" ) ]
61+ fn create_bpf_filter ( remote_port : u16 ) -> [ libc:: sock_filter ; 4 ] {
62+ [
63+ ( 0x28 , 0 , 0 , 0x0000001a ) , // ldh [26] ; icmp sequence
64+ ( 0x15 , 0 , 1 , remote_port as u32 ) , // jne #port, drop
65+ ( 0x06 , 0 , 0 , 0xffffffff ) , // ret #-1
66+ ( 0x06 , 0 , 0 , 0000000000 ) , // drop: ret #0
67+ ]
68+ . map ( |( code, jt, jf, k) | libc:: sock_filter { code, jt, jf, k } )
69+ }
70+
5071#[ derive( Debug ) ]
5172pub struct IcmpRegistry ;
5273// icmp doesn't need a registry because we manage it's poll ourself
0 commit comments