@ -9,6 +9,7 @@ import (
"net/netip"
"testing"
"golang.org/x/net/bpf"
"golang.org/x/sys/cpu"
"golang.org/x/sys/unix"
"tailscale.com/disco"
@ -146,3 +147,78 @@ func TestEthernetProto(t *testing.T) {
}
}
}
func TestBpfDiscardV4 ( t * testing . T ) {
// Good packet as a reference for what should not be rejected
udp4Packet := [ ] byte {
// IPv4 header
0x45 , 0x00 , 0x00 , 0x26 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x40 , 0x11 , 0x00 , 0x00 ,
0x7f , 0x00 , 0x00 , 0x01 , // source ip
0x7f , 0x00 , 0x00 , 0x02 , // dest ip
// UDP header
0x30 , 0x39 , // src port
0xd4 , 0x31 , // dest port
0x00 , 0x12 , // length; 8 bytes header + 10 bytes payload = 18 bytes
0x00 , 0x00 , // checksum; unused
// Payload: disco magic plus 32 bytes for key and 24 bytes for nonce
0x54 , 0x53 , 0xf0 , 0x9f , 0x92 , 0xac , 0x00 , 0x01 , 0x02 , 0x03 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
}
vm , err := bpf . NewVM ( magicsockFilterV4 )
if err != nil {
t . Fatalf ( "failed creating BPF VM: %v" , err )
}
tests := [ ] struct {
name string
replace map [ int ] byte
accept bool
} {
{
name : "base accepted datagram" ,
replace : map [ int ] byte { } ,
accept : true ,
} ,
{
name : "more fragments" ,
replace : map [ int ] byte {
6 : 0x20 ,
} ,
accept : false ,
} ,
{
name : "some fragment" ,
replace : map [ int ] byte {
7 : 0x01 ,
} ,
accept : false ,
} ,
}
udp4PacketChanged := make ( [ ] byte , len ( udp4Packet ) )
copy ( udp4PacketChanged , udp4Packet )
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
for k , v := range tt . replace {
udp4PacketChanged [ k ] = v
}
ret , err := vm . Run ( udp4PacketChanged )
if err != nil {
t . Fatalf ( "BPF VM error: %v" , err )
}
if ( ret != 0 ) != tt . accept {
t . Errorf ( "expected accept=%v, got ret=%v" , tt . accept , ret )
}
} )
}
}