Commit 0ae8ba7a authored by James Cook's avatar James Cook
Browse files

Fix Wireguard.

With this change, I'm able to connect to a wireguard peer by running
	doas wg-quick up /usr/local/etc/wireguard/wg0.conf
where the content of wg0.conf, with some parts censored as "XXX", is:
	[Interface]
	PrivateKey = XXX
	Address=10.167.1.5

	[Peer]
	PublicKey = XXX
	EndPoint = exoco.falsifian.org:791
	AllowedIps = 10.167.1.0/24
	PersistentKeepalive = 25

Essentially, there are three changes, all of which will hopefully
appear upstream eventually:

1. Fix DragonflyBSD support in the x/net go library.

   This change is under review upstream at
   https://go-review.googlesource.com/c/net/+/328331/

   Here, I'm actually patching the vendored copy of x/net used by
   lang/go and lang/go-devel, because the problem manefests via the
   "net" library, which is provided directly by go (or go-devel).
   (Specifically, net.InterfaceByName doesn't work without this patch.)

2. Fix wireguard-go's DragonflyBSD support.

   This change, originally by Aaron Li, is under review at
   https://github.com/WireGuard/wireguard-go/pull/49

   I added GO_ENV to MAKE_ENV to fix wireguard-go vendoring, based on
   commit 7a2ae184 from FreeBSD ports.

3. A small fix to net/wireguard to be compatible with the newer
   wireguard-go.

   This change is cherry-picked from upstream net/wireguard.
parent f50d0f5e
--- src/vendor/golang.org/x/net/route/interface_classic.go.orig 2021-02-16 18:08:40 UTC
+++ src/vendor/golang.org/x/net/route/interface_classic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly netbsd
+// +build darwin netbsd
package route
--- src/vendor/golang.org/x/net/route/interface_dragonfly.go.orig 2021-06-20 23:08:14 UTC
+++ src/vendor/golang.org/x/net/route/interface_dragonfly.go
@@ -0,0 +1,68 @@
+// Copyright 2021 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.
+
+// Implementation for DragonflyBSD. This is unlikely to work for
+// RTM_VERSION != 7.
+
+package route
+
+func (w *wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) {
+ // b is a struct if_msghdr
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ attrs := uint(nativeEndian.Uint32(b[12:16]))
+ if attrs&sysRTA_IFP == 0 {
+ return nil, nil
+ }
+ if attrs != sysRTA_IFP {
+ // The call to parseLinkAddr below assumes there's exactly one
+ // address.
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Addrs: make([]Addr, sysRTAX_MAX),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[4:6])),
+ extOff: w.extOff,
+ raw: b[:l],
+ }
+ a, err := parseLinkAddr(b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ m.Addrs[sysRTAX_IFP] = a
+ m.Name = a.(*LinkAddr).Name
+ return m, nil
+}
+
+func (w *wireFormat) parseInterfaceAddrMessage(_ RIBType, b []byte) (Message, error) {
+ // b is a struct ifa_msghdr
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceAddrMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[4:6])),
+ raw: b[:l],
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
--- src/vendor/golang.org/x/net/route/interface_classic.go.orig 2021-05-06 15:06:00 UTC
+++ src/vendor/golang.org/x/net/route/interface_classic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly netbsd
+// +build darwin netbsd
package route
--- src/vendor/golang.org/x/net/route/interface_dragonfly.go.orig 2021-06-21 01:54:56 UTC
+++ src/vendor/golang.org/x/net/route/interface_dragonfly.go
@@ -0,0 +1,68 @@
+// Copyright 2021 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.
+
+// Implementation for DragonflyBSD. This is unlikely to work for
+// RTM_VERSION != 7.
+
+package route
+
+func (w *wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) {
+ // b is a struct if_msghdr
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ attrs := uint(nativeEndian.Uint32(b[12:16]))
+ if attrs&sysRTA_IFP == 0 {
+ return nil, nil
+ }
+ if attrs != sysRTA_IFP {
+ // The call to parseLinkAddr below assumes there's exactly one
+ // address.
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Addrs: make([]Addr, sysRTAX_MAX),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[4:6])),
+ extOff: w.extOff,
+ raw: b[:l],
+ }
+ a, err := parseLinkAddr(b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ m.Addrs[sysRTAX_IFP] = a
+ m.Name = a.(*LinkAddr).Name
+ return m, nil
+}
+
+func (w *wireFormat) parseInterfaceAddrMessage(_ RIBType, b []byte) (Message, error) {
+ // b is a struct ifa_msghdr
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceAddrMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[4:6])),
+ raw: b[:l],
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
# $FreeBSD$
PORTNAME= wireguard-go
PORTVERSION= 0.0.20200320
# A git commit dated 2021-06-19, after the 0.0.20210424 release.
PORTVERSION= 0.0.20210424g20210619
CATEGORIES= net net-vpn
MASTER_SITES= https://git.zx2c4.com/wireguard-go/snapshot/
DISTFILES= ${PORTNAME}-${PORTVERSION}${EXTRACT_SUFX}
MAINTAINER= decke@FreeBSD.org
COMMENT= WireGuard implementation in Go
LICENSE= MIT
LICENSE_FILE= ${WRKSRC}/COPYING
LICENSE_FILE= ${WRKSRC}/LICENSE
USES= gmake go:modules,no_targets tar:xz
USE_GITHUB= nodefault
GH_TUPLE= golang:crypto:34f69633bfdc:golang_crypto/vendor/golang.org/x/crypto \
golang:net:83d349e8ac1a:golang_net/vendor/golang.org/x/net \
golang:sys:5c8b2ff67527:golang_sys/vendor/golang.org/x/sys \
golang:text:v0.3.2:golang_text/vendor/golang.org/x/text
USE_GITHUB= yes
GH_ACCOUNT= falsifian
GH_TAGNAME= 31b062bb211e86a4f88bec287110938968748346
# Output of make gomod-vendor
GH_TUPLE= golang:crypto:5ea612d1eb83:golang_crypto/vendor/golang.org/x/crypto \
golang:net:e18ecbb05110:golang_net/vendor/golang.org/x/net \
golang:sys:5e06dd20ab57:golang_sys/vendor/golang.org/x/sys
MAKE_ENV+= GOFLAGS="${GO_BUILDFLAGS}"
MAKE_ENV+= ${GO_ENV} GOFLAGS="${GO_BUILDFLAGS}"
PLIST_FILES= bin/${PORTNAME}
......
TIMESTAMP = 1584881073
SHA256 (wireguard-go-0.0.20200320.tar.xz) = c8262da949043976d092859843d3c0cdffe225ec6f1398ba119858b6c1b3552f
SIZE (wireguard-go-0.0.20200320.tar.xz) = 80556
SHA256 (golang-crypto-34f69633bfdc_GH0.tar.gz) = c3fa0760971622af64c3b7a3319291d997f2f0d53a5c90c17d25eaeba7f0371a
SIZE (golang-crypto-34f69633bfdc_GH0.tar.gz) = 1708053
SHA256 (golang-net-83d349e8ac1a_GH0.tar.gz) = 5752c376bc6383bf2055281336101c062b881f17ded2e960d718c8256023f9c7
SIZE (golang-net-83d349e8ac1a_GH0.tar.gz) = 1103298
SHA256 (golang-sys-5c8b2ff67527_GH0.tar.gz) = 9f8cc5b07a664262b956c4f687e6078da265e119a093bb542d3bd132afef2db6
SIZE (golang-sys-5c8b2ff67527_GH0.tar.gz) = 1040138
SHA256 (golang-text-v0.3.2_GH0.tar.gz) = 0b9309698f5708531c5377ab1e29b423a6d9e20c55a8d386c3b8283428212f22
SIZE (golang-text-v0.3.2_GH0.tar.gz) = 7168069
TIMESTAMP = 1624239518
SHA256 (falsifian-wireguard-go-0.0.20210424g20210619-31b062bb211e86a4f88bec287110938968748346_GH0.tar.gz) = e7659ef3f8d350a10dc7898b777661c8849aac5f4053063cbd06a376053f39c3
SIZE (falsifian-wireguard-go-0.0.20210424g20210619-31b062bb211e86a4f88bec287110938968748346_GH0.tar.gz) = 127268
SHA256 (golang-crypto-5ea612d1eb83_GH0.tar.gz) = ab4d88d6121195632d006705a950adebaf4fa99dd15ea0c508297a17c5d3277e
SIZE (golang-crypto-5ea612d1eb83_GH0.tar.gz) = 1726242
SHA256 (golang-net-e18ecbb05110_GH0.tar.gz) = c30374f6fd34c6b77d53224aa3ba7458e3773d7e6e4fa16d88fb05c7d05e0e89
SIZE (golang-net-e18ecbb05110_GH0.tar.gz) = 1253124
SHA256 (golang-sys-5e06dd20ab57_GH0.tar.gz) = 97d8695750a15cef175f72c6573cf64027600dda28243c311017c77ae71696e3
SIZE (golang-sys-5e06dd20ab57_GH0.tar.gz) = 1218868
--- device/mark_default.go.orig 2019-05-17 08:28:04 UTC
+++ device/mark_default.go
@@ -1,4 +1,4 @@
-// +build !linux,!openbsd,!freebsd
+// +build !linux,!openbsd,!freebsd,!dragonfly
/* SPDX-License-Identifier: MIT
*
--- device/mark_unix.go.orig 2019-05-17 08:28:04 UTC
+++ device/mark_unix.go
@@ -1,4 +1,4 @@
-// +build android openbsd freebsd
+// +build android openbsd freebsd dragonfly
/* SPDX-License-Identifier: MIT
*
--- ipc/uapi_bsd.go.orig 2019-05-17 08:28:04 UTC
+++ ipc/uapi_bsd.go
@@ -1,4 +1,4 @@
-// +build darwin freebsd openbsd
+// +build darwin freebsd openbsd dragonfly
/* SPDX-License-Identifier: MIT
*
+++ tun/tun_dragonfly.go.orig 2019-08-10 13:38:10 UTC
+++ tun/tun_dragonfly.go
@@ -0,0 +1,332 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package tun
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net"
+ "os"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/net/ipv6"
+ "golang.org/x/sys/unix"
+)
+
+// Structure for iface mtu get/set ioctls
+type ifreq_mtu struct {
+ Name [unix.IFNAMSIZ]byte
+ MTU uint32
+ Pad0 [12]byte
+}
+
+const _TUNSIFMODE = 0x8004745d
+
+type NativeTun struct {
+ name string
+ tunFile *os.File
+ events chan Event
+ errors chan error
+ routeSocket int
+}
+
+func (tun *NativeTun) routineRouteListener(tunIfindex int) {
+ var (
+ statusUp bool
+ statusMTU int
+ )
+
+ defer close(tun.events)
+
+ data := make([]byte, os.Getpagesize())
+ for {
+ retry:
+ n, err := unix.Read(tun.routeSocket, data)
+ if err != nil {
+ if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
+ goto retry
+ }
+ tun.errors <- err
+ return
+ }
+
+ if n < 8 {
+ continue
+ }
+
+ if data[3 /* type */] != unix.RTM_IFINFO {
+ continue
+ }
+ ifindex := int(*(*uint16)(unsafe.Pointer(&data[6 /* ifindex */])))
+ if ifindex != tunIfindex {
+ continue
+ }
+
+ iface, err := net.InterfaceByIndex(ifindex)
+ if err != nil {
+ tun.errors <- err
+ return
+ }
+
+ // Up / Down event
+ up := (iface.Flags & net.FlagUp) != 0
+ if up != statusUp && up {
+ tun.events <- EventUp
+ }
+ if up != statusUp && !up {
+ tun.events <- EventDown
+ }
+ statusUp = up
+
+ // MTU changes
+ if iface.MTU != statusMTU {
+ tun.events <- EventMTUUpdate
+ }
+ statusMTU = iface.MTU
+ }
+}
+
+func errorIsEBUSY(err error) bool {
+ if pe, ok := err.(*os.PathError); ok {
+ err = pe.Err
+ }
+ if errno, ok := err.(syscall.Errno); ok && errno == syscall.EBUSY {
+ return true
+ }
+ return false
+}
+
+func CreateTUN(name string, mtu int) (Device, error) {
+ ifIndex := -1
+ if name != "tun" {
+ _, err := fmt.Sscanf(name, "tun%d", &ifIndex)
+ if err != nil || ifIndex < 0 {
+ return nil, fmt.Errorf("Interface name must be tun[0-9]*")
+ }
+ }
+
+ var tunfile *os.File
+ var err error
+
+ if ifIndex != -1 {
+ tunfile, err = os.OpenFile(fmt.Sprintf("/dev/tun%d", ifIndex), unix.O_RDWR, 0)
+ } else {
+ for ifIndex = 0; ifIndex < 256; ifIndex += 1 {
+ tunfile, err = os.OpenFile(fmt.Sprintf("/dev/tun%d", ifIndex), unix.O_RDWR, 0)
+ if err == nil || !errorIsEBUSY(err) {
+ break
+ }
+ }
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ tun, err := CreateTUNFromFile(tunfile, mtu)
+
+ if err == nil && name == "tun" {
+ fname := os.Getenv("WG_TUN_NAME_FILE")
+ if fname != "" {
+ ioutil.WriteFile(fname, []byte(tun.(*NativeTun).name+"\n"), 0400)
+ }
+ }
+
+ return tun, err
+}
+
+func CreateTUNFromFile(file *os.File, mtu int) (Device, error) {
+
+ tun := &NativeTun{
+ tunFile: file,
+ events: make(chan Event, 10),
+ errors: make(chan error, 1),
+ }
+
+ name, err := tun.Name()
+ if err != nil {
+ tun.tunFile.Close()
+ return nil, err
+ }
+
+ tunIfindex, err := func() (int, error) {
+ iface, err := net.InterfaceByName(name)
+ if err != nil {
+ return -1, err
+ }
+ return iface.Index, nil
+ }()
+ if err != nil {
+ tun.tunFile.Close()
+ return nil, err
+ }
+
+ tun.routeSocket, err = unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC)
+ if err != nil {
+ tun.tunFile.Close()
+ return nil, err
+ }
+
+ go tun.routineRouteListener(tunIfindex)
+
+ currentMTU, err := tun.MTU()
+ if err != nil || currentMTU != mtu {
+ err = tun.setMTU(mtu)
+ if err != nil {
+ tun.Close()
+ return nil, err
+ }
+ }
+
+ return tun, nil
+}
+
+func (tun *NativeTun) Name() (string, error) {
+ gostat, err := tun.tunFile.Stat()
+ if err != nil {
+ tun.name = ""
+ return "", err
+ }
+ stat := gostat.Sys().(*syscall.Stat_t)
+ tun.name = fmt.Sprintf("tun%d", stat.Rdev%256)
+ return tun.name, nil
+}
+
+func (tun *NativeTun) File() *os.File {
+ return tun.tunFile
+}
+
+func (tun *NativeTun) Events() chan Event {
+ return tun.events
+}
+
+func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
+ select {
+ case err := <-tun.errors:
+ return 0, err
+ default:
+ buff := buff[offset-4:]
+ n, err := tun.tunFile.Read(buff[:])
+ if n < 4 {
+ return 0, err
+ }
+ return n - 4, err
+ }
+}
+
+func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
+
+ // reserve space for header
+
+ buff = buff[offset-4:]
+
+ // add packet information header
+
+ buff[0] = 0x00
+ buff[1] = 0x00
+ buff[2] = 0x00
+
+ if buff[4]>>4 == ipv6.Version {
+ buff[3] = unix.AF_INET6
+ } else {
+ buff[3] = unix.AF_INET
+ }
+
+ // write
+
+ return tun.tunFile.Write(buff)
+}
+
+func (tun *NativeTun) Flush() error {
+ // TODO: can flushing be implemented by buffering and using sendmmsg?
+ return nil
+}
+
+func (tun *NativeTun) Close() error {
+ var err2 error
+ err1 := tun.tunFile.Close()
+ if tun.routeSocket != -1 {
+ unix.Shutdown(tun.routeSocket, unix.SHUT_RDWR)
+ err2 = unix.Close(tun.routeSocket)
+ tun.routeSocket = -1
+ } else if tun.events != nil {
+ close(tun.events)
+ }
+ if err1 != nil {
+ return err1
+ }
+ return err2
+}
+
+func (tun *NativeTun) setMTU(n int) error {
+ // open datagram socket
+
+ var fd int
+
+ fd, err := unix.Socket(
+ unix.AF_INET,
+ unix.SOCK_DGRAM,
+ 0,
+ )
+
+ if err != nil {
+ return err
+ }
+
+ defer unix.Close(fd)
+
+ // do ioctl call
+
+ var ifr ifreq_mtu
+ copy(ifr.Name[:], tun.name)
+ ifr.MTU = uint32(n)
+
+ _, _, errno := unix.Syscall(
+ unix.SYS_IOCTL,
+ uintptr(fd),
+ uintptr(unix.SIOCSIFMTU),
+ uintptr(unsafe.Pointer(&ifr)),
+ )
+
+ if errno != 0 {
+ return fmt.Errorf("failed to set MTU on %s", tun.name)
+ }
+
+ return nil
+}
+
+func (tun *NativeTun) MTU() (int, error) {
+ // open datagram socket
+
+ fd, err := unix.Socket(
+ unix.AF_INET,
+ unix.SOCK_DGRAM,
+ 0,
+ )
+
+ if err != nil {
+ return 0, err
+ }
+
+ defer unix.Close(fd)