mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-12-23 00:17:35 +00:00
Fix ioctl(2) code for OpenBSD (#1175)
This cleans up the mess to configure an IP address on a tun(4) device. Handrolling a hardcoded ioctl(2) request is far from perfect, but Go (golang.org/sys/unix) is to blame here. Tested on OpenBSD 7.6 -current where yggdrasil now drives the interface would use of ifconfig or other helpers.
This commit is contained in:
parent
6d5243bd9a
commit
ccda1075c0
@ -1,5 +1,5 @@
|
||||
//go:build openbsd || freebsd
|
||||
// +build openbsd freebsd
|
||||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
package tun
|
||||
|
122
src/tun/tun_openbsd.go
Normal file
122
src/tun/tun_openbsd.go
Normal file
@ -0,0 +1,122 @@
|
||||
//go:build openbsd
|
||||
// +build openbsd
|
||||
|
||||
package tun
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
wgtun "golang.zx2c4.com/wireguard/tun"
|
||||
)
|
||||
|
||||
const (
|
||||
SIOCAIFADDR_IN6 = 0x8080691a
|
||||
ND6_INFINITE_LIFETIME = 0xffffffff
|
||||
)
|
||||
|
||||
type in6_addrlifetime struct {
|
||||
ia6t_expire int64
|
||||
ia6t_preferred int64
|
||||
ia6t_vltime uint32
|
||||
ia6t_pltime uint32
|
||||
}
|
||||
|
||||
// Match types from the net package, effectively being [16]byte for IPv6 addresses.
|
||||
type in6_addr [16]uint8
|
||||
|
||||
type sockaddr_in6 struct {
|
||||
sin6_len uint8
|
||||
sin6_family uint8
|
||||
sin6_port uint16
|
||||
sin6_flowinfo uint32
|
||||
sin6_addr in6_addr
|
||||
sin6_scope_id uint32
|
||||
}
|
||||
|
||||
func (sa6 *sockaddr_in6) setSockaddr(addr [/*16*/]byte /* net.IP or net.IPMask */) {
|
||||
sa6.sin6_len = uint8(unsafe.Sizeof(*sa6))
|
||||
sa6.sin6_family = unix.AF_INET6
|
||||
|
||||
for i := range sa6.sin6_addr {
|
||||
sa6.sin6_addr[i] = addr[i]
|
||||
}
|
||||
}
|
||||
|
||||
type in6_aliasreq struct {
|
||||
ifra_name [syscall.IFNAMSIZ]byte
|
||||
ifra_addr sockaddr_in6
|
||||
ifra_dstaddr sockaddr_in6
|
||||
ifra_prefixmask sockaddr_in6
|
||||
ifra_flags int32
|
||||
ifra_lifetime in6_addrlifetime
|
||||
}
|
||||
|
||||
// Configures the TUN adapter with the correct IPv6 address and MTU.
|
||||
func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||
iface, err := wgtun.CreateTUN(ifname, int(mtu))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create TUN: %w", err)
|
||||
}
|
||||
tun.iface = iface
|
||||
if mtu, err := iface.MTU(); err == nil {
|
||||
tun.mtu = getSupportedMTU(uint64(mtu))
|
||||
} else {
|
||||
tun.mtu = 0
|
||||
}
|
||||
if addr != "" {
|
||||
return tun.setupAddress(addr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Configures the "utun" adapter from an existing file descriptor.
|
||||
func (tun *TunAdapter) setupFD(fd int32, addr string, mtu uint64) error {
|
||||
return fmt.Errorf("setup via FD not supported on this platform")
|
||||
}
|
||||
|
||||
func (tun *TunAdapter) setupAddress(addr string) error {
|
||||
var sfd int
|
||||
var err error
|
||||
|
||||
ip, prefix, err := net.ParseCIDR(addr)
|
||||
if err != nil {
|
||||
tun.log.Errorf("Error in ParseCIDR: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Create system socket
|
||||
if sfd, err = unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, 0); err != nil {
|
||||
tun.log.Printf("Create AF_INET6 socket failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Friendly output
|
||||
tun.log.Infof("Interface name: %s", tun.Name())
|
||||
tun.log.Infof("Interface IPv6: %s", addr)
|
||||
tun.log.Infof("Interface MTU: %d", tun.mtu)
|
||||
|
||||
// Create the address request
|
||||
var ar in6_aliasreq
|
||||
copy(ar.ifra_name[:], tun.Name())
|
||||
|
||||
ar.ifra_addr.setSockaddr(ip)
|
||||
|
||||
prefixmask := net.CIDRMask(prefix.Mask.Size())
|
||||
ar.ifra_prefixmask.setSockaddr(prefixmask)
|
||||
|
||||
ar.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME
|
||||
ar.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME
|
||||
|
||||
// Set the interface address
|
||||
if err = unix.IoctlSetInt(sfd, SIOCAIFADDR_IN6, int(uintptr(unsafe.Pointer(&ar)))); err != nil {
|
||||
tun.log.Errorf("Error in SIOCAIFADDR_IN6: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user