Files
golang.net/ipv6/bpf_test.go
Cuong Manh Le 2aa82152a5 nettest: use RoutedInterface for probing network stack capability
The ipv4/ipv6 support capability is done by explicitly listening on
loopback interface. However, it can lead to false positive, especially
for ipv6 case. For example, ipv6 can be enabled, but explicitly disable
for loopback interface (for security, policy ...).

This CL changes probeStack to use another approach, by looking for any
interface that can route IP traffic and in "UP" state. If there's one,
then the platform can do ipv4/ipv6 networking functionality.

Fixes golang/go#57386

Change-Id: If911bc223b52c5a4562d3f61b4ee1032bdbec47c
Reviewed-on: https://go-review.googlesource.com/c/net/+/458096
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Benny Siegert <bsiegert@gmail.com>
Reviewed-by: Matt Layher <mdlayher@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
2022-12-23 17:16:06 +00:00

98 lines
2.0 KiB
Go

// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv6_test
import (
"net"
"runtime"
"testing"
"time"
"golang.org/x/net/bpf"
"golang.org/x/net/ipv6"
"golang.org/x/net/nettest"
)
func TestBPF(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skipf("not supported on %s", runtime.GOOS)
}
if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil {
t.Skip("ipv6 is not enabled for loopback interface")
}
l, err := net.ListenPacket("udp6", "[::1]:0")
if err != nil {
t.Fatal(err)
}
defer l.Close()
p := ipv6.NewPacketConn(l)
// This filter accepts UDP packets whose first payload byte is
// even.
prog, err := bpf.Assemble([]bpf.Instruction{
// Load the first byte of the payload (skipping UDP header).
bpf.LoadAbsolute{Off: 8, Size: 1},
// Select LSB of the byte.
bpf.ALUOpConstant{Op: bpf.ALUOpAnd, Val: 1},
// Byte is even?
bpf.JumpIf{Cond: bpf.JumpEqual, Val: 0, SkipFalse: 1},
// Accept.
bpf.RetConstant{Val: 4096},
// Ignore.
bpf.RetConstant{Val: 0},
})
if err != nil {
t.Fatalf("compiling BPF: %s", err)
}
if err = p.SetBPF(prog); err != nil {
t.Fatalf("attaching filter to Conn: %s", err)
}
s, err := net.Dial("udp6", l.LocalAddr().String())
if err != nil {
t.Fatal(err)
}
defer s.Close()
go func() {
for i := byte(0); i < 10; i++ {
s.Write([]byte{i})
}
}()
l.SetDeadline(time.Now().Add(2 * time.Second))
seen := make([]bool, 5)
for {
var b [512]byte
n, _, err := l.ReadFrom(b[:])
if err != nil {
t.Fatalf("reading from listener: %s", err)
}
if n != 1 {
t.Fatalf("unexpected packet length, want 1, got %d", n)
}
if b[0] >= 10 {
t.Fatalf("unexpected byte, want 0-9, got %d", b[0])
}
if b[0]%2 != 0 {
t.Fatalf("got odd byte %d, wanted only even bytes", b[0])
}
seen[b[0]/2] = true
seenAll := true
for _, v := range seen {
if !v {
seenAll = false
break
}
}
if seenAll {
break
}
}
}