Open
Description
Go version
go version go1.22.1 openbsd/amd64
Output of go env
in your module/workspace:
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/coder/.cache/go-build'
GOENV='/home/coder/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/coder/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/coder/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/coder/sdk/go1.22.1'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/coder/sdk/go1.22.1/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.22.1'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build3938717940=/tmp/go-build -gno-record-gcc-switches
What did you do?
Consider the following program:
package main
import (
"flag"
"fmt"
"net"
"os"
)
var (
iface = flag.String("bindto", "127.0.0.1", "Interface to bind to")
proto = flag.String("proto", "1" , "Proto family")
)
func main() {
flag.Parse()
addrFamily := fmt.Sprintf("ip4:%s", *proto)
conn, err := net.ListenPacket(addrFamily, *iface)
if err != nil {
fmt.Printf("Failed to listen: %v\n", err)
os.Exit(1)
}
buf := make([]byte, 50)
_, _, err = conn.ReadFrom(buf)
if err != nil {
fmt.Printf("Failed to read from socket: %v\n", err)
os.Exit(1)
}
fmt.Printf("Got: %#v\n", buf)
}
What did you see happen?
On OpenBSD, 7.4, amd64 (Cross compiling from Linux/amd64 on 1.22.1), I did not see the packet arrive on the Listening Socket(Addresses retracted):
$ tcpdump -i vio0 -n -s1200 -c1 "icmp" &
[1] 64166
tcpdump: listening on vio0, link-type EN10MB
$ ./main -proto 1 -bindto XX.XX.XX.XX
15:34:39.618333 YY.YY.YY.YY > XX.XX.XX.XX: icmp: echo request
^C
[1]+ Done tcpdump -i vio0 -n -s1200 -c1 "icmp"
Note the lack of output. However if the traffic is generated on the same box, then we see packets arrive as expected:
$ tcpdump -i vio0 -n -s1200 -c1 "icmp" &
[1] 17457
tcpdump: listening on vio0, link-type EN10MB
$ ./main -proto 1 -bindto XX.XX.XX.XX &
[2] 65692
$ ping -c1 XX.XX.XX.XX
PING XX.XX.XX.XX(XX.XX.XX.XX): 56 data bytes
64 bytes from XX.XX.XX.XX: icmp_seq=0 ttl=255 time=0.918 ms
Got: []byte{0x0, 0x0, 0x98, 0x31, 0x39, 0xae, 0x0, 0x0, 0x5a, 0xc8, 0xbd, 0xa0, 0x80, 0x1d, 0x3c, 0x52, 0xae, 0xeb, 0x4c, 0x83, 0x69, 0xf5, 0x38, 0x42, 0xa7, 0x13, 0xf3, 0x65, 0x96, 0x42, 0xbd, 0xa0, 0x80, 0x1d, 0x3c, 0x52, 0xae, 0xeb, 0x4c, 0x83, 0x69, 0xf5, 0x38, 0x42, 0xa7, 0x13, 0xf3, 0x65, 0x96, 0x42}
--- XX.XX.XX.XX ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.918/0.918/0.918/0.000 ms
[2]+ Done ./main -proto 1 -bindto XX.XX.XX.XX
15:37:06.399667 YY.YY.YY.YY > XX.XX.XX.XX: icmp: echo request (DF)
This is unexpected, as we know the packet is arriving in userspace. If tcpdump
can see the packet, and we can see the packets in Linux without issues, then we should also see a packet from net.ListenPacket
in OpenBSD.
What did you expect to see?
This works as expected on Linux, where we bind to an external IP, and we see the ICMP (proto 1) packet arrive in both userspace, and at the connection:
$ sudo tcpdump -i any -n -s0 -c 1 "icmp" &
[1] 2049689
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
$ sudo ./main -proto 1 -bindto "192.168.0.254"
Got: []byte{0x8, 0x0, 0xdd, 0x53, 0x2, 0x2f, 0x0, 0x1, 0x27, 0x59, 0xd, 0x66, 0x0, 0x0, 0x0, 0x0, 0x18, 0xea, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0xd, 0x66, 0x0, 0x0, 0x0, 0x0, 0x18, 0xea, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15}
$ 13:27:00.732378 net1 In IP 192.168.0.187 > 192.168.0.254: ICMP echo request, id 559, seq 1, length 64
1 packet captured
2 packets received by filter
0 packets dropped by kernel
^C
[1]+ Done sudo tcpdump -i any -n -s0 -c 1 "icmp"