Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rationalise wgTurnOn(,Multihop,IAN), deduplicating repeated code #17

Open
wants to merge 1 commit into
base: mullvad-master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 94 additions & 133 deletions Sources/WireGuardKitGo/api-apple.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,43 +102,56 @@ func wgSetLogger(context, loggerFn uintptr) {
loggerFunc = unsafe.Pointer(loggerFn)
}

func wgTurnOnMultihopInner(tun tun.Device, exitSettings *C.char, entrySettings *C.char, privateIp *C.char, exitMtu int, logger *device.Logger) int32 {
ip, err := netip.ParseAddr(C.GoString(privateIp))
func openTUNFromSocket(tunFd int32, logger *device.Logger) (tun.Device, int32) {

dupTunFd, err := unix.Dup(int(tunFd))
if err != nil {
logger.Errorf("Failed to parse private IP: %v", err)
tun.Close()
return errBadIPString
logger.Errorf("Unable to dup tun fd: %v", err)
return nil, errDup
}

exitConfigString := C.GoString(exitSettings)
exitEndpoint := parseEndpointFromGoConfig(exitConfigString)
if exitEndpoint == nil {
tun.Close()
return errNoEndpointInConfig
err = unix.SetNonblock(dupTunFd, true)
if err != nil {
logger.Errorf("Unable to set tun fd as non blocking: %v", err)
unix.Close(dupTunFd)
return nil, errSetNonblock
}
tun, err := tun.CreateTUNFromFile(os.NewFile(uintptr(dupTunFd), "/dev/tun"), 0)
if err != nil {
logger.Errorf("Unable to create new tun device from fd: %v", err)
unix.Close(dupTunFd)
return nil, errCreateTun
}

singletun := multihoptun.NewMultihopTun(ip, exitEndpoint.Addr(), exitEndpoint.Port(), exitMtu+80)

exitDev := device.NewDevice(tun, singletun.Binder(), logger)
entryDev := device.NewDevice(&singletun, conn.NewStdNetBind(), logger)
return tun, 0
}

err = entryDev.IpcSet(C.GoString(entrySettings))
func bringUpDevice(dev *device.Device, settings string, logger *device.Logger) error {
err := dev.IpcSet(settings)
if err != nil {
logger.Errorf("Unable to set IPC settings for entry: %v", err)
tun.Close()
return errBadWgConfig
logger.Errorf("Unable to set IPC settings: %v", err)
dev.Close()
return err
}

err = exitDev.IpcSet(exitConfigString)
dev.Up()
logger.Verbosef("Device started")
return nil
}

func addTunnelFromDevice(dev *device.Device, entryDev *device.Device, settings string, entrySettings string, virtualNet *netstack.Net, logger *device.Logger) int32 {
err := bringUpDevice(dev, settings, logger)
if err != nil {
logger.Errorf("Unable to set IPC settings for exit: %v", err)
tun.Close()
return errBadWgConfig
}

exitDev.Up()
entryDev.Up()
logger.Verbosef("Device started")
if entryDev != nil {
err = bringUpDevice(entryDev, entrySettings, logger)
if err != nil {
dev.Close()
return errBadWgConfig
}
}

var i int32
for i = 0; i < math.MaxInt32; i++ {
Expand All @@ -147,135 +160,83 @@ func wgTurnOnMultihopInner(tun tun.Device, exitSettings *C.char, entrySettings *
}
}
if i == math.MaxInt32 {
tun.Close()
dev.Close()
return errDeviceLimitHit
}
tunnelHandles[i] = tunnelHandle{exitDev, entryDev, logger, nil}
tunnelHandles[i] = tunnelHandle{dev, entryDev, logger, virtualNet}
return i
}

//export wgTurnOnMultihop
func wgTurnOnMultihop(exitSettings *C.char, entrySettings *C.char, privateIp *C.char, tunFd int32) int32 {
//export wgTurnOn
func wgTurnOn(settings *C.char, tunFd int32) int32 {
logger := &device.Logger{
Verbosef: CLogger(0).Printf,
Errorf: CLogger(1).Printf,
}

dupTunFd, err := unix.Dup(int(tunFd))
if err != nil {
logger.Errorf("Unable to dup tun fd: %v", err)
return errDup
tun, errCode := openTUNFromSocket(tunFd, logger)
if tun == nil {
return errCode
}

err = unix.SetNonblock(dupTunFd, true)
if err != nil {
logger.Errorf("Unable to set tun fd as non blocking: %v", err)
unix.Close(dupTunFd)
return errSetNonblock
}
tun, err := tun.CreateTUNFromFile(os.NewFile(uintptr(dupTunFd), "/dev/tun"), 0)
logger.Verbosef("Attaching to interface")
dev := device.NewDevice(tun, conn.NewStdNetBind(), logger)

return addTunnelFromDevice(dev, nil, C.GoString(settings), "", nil, logger)
}

func wgTurnOnMultihopInner(tun tun.Device, exitSettings *C.char, entrySettings *C.char, privateIp *C.char, exitMtu int, logger *device.Logger) int32 {
ip, err := netip.ParseAddr(C.GoString(privateIp))
if err != nil {
logger.Errorf("Unable to create new tun device from fd: %v", err)
unix.Close(dupTunFd)
return errCreateTun
logger.Errorf("Failed to parse private IP: %v", err)
tun.Close()
return errBadIPString
}

exitMtu, err := tun.MTU()
if err != nil {
exitConfigString := C.GoString(exitSettings)
entryConfigString := C.GoString(entrySettings)
exitEndpoint := parseEndpointFromGoConfig(exitConfigString)
if exitEndpoint == nil {
tun.Close()
return errGetMtu
return errNoEndpointInConfig
}

return wgTurnOnMultihopInner(tun, exitSettings, entrySettings, privateIp, exitMtu, logger)
singletun := multihoptun.NewMultihopTun(ip, exitEndpoint.Addr(), exitEndpoint.Port(), exitMtu+80)

exitDev := device.NewDevice(tun, singletun.Binder(), logger)
entryDev := device.NewDevice(&singletun, conn.NewStdNetBind(), logger)

return addTunnelFromDevice(exitDev, entryDev, exitConfigString, entryConfigString, nil, logger)
}

//export wgTurnOn
func wgTurnOn(settings *C.char, tunFd int32) int32 {
//export wgTurnOnMultihop
func wgTurnOnMultihop(exitSettings *C.char, entrySettings *C.char, privateIp *C.char, tunFd int32) int32 {
logger := &device.Logger{
Verbosef: CLogger(0).Printf,
Errorf: CLogger(1).Printf,
}
dupTunFd, err := unix.Dup(int(tunFd))
if err != nil {
logger.Errorf("Unable to dup tun fd: %v", err)
return -1
}

err = unix.SetNonblock(dupTunFd, true)
if err != nil {
logger.Errorf("Unable to set tun fd as non blocking: %v", err)
unix.Close(dupTunFd)
return -1
}
tun, err := tun.CreateTUNFromFile(os.NewFile(uintptr(dupTunFd), "/dev/tun"), 0)
if err != nil {
logger.Errorf("Unable to create new tun device from fd: %v", err)
unix.Close(dupTunFd)
return -1
tun, errCode := openTUNFromSocket(tunFd, logger)
if tun == nil {
return errCode
}
logger.Verbosef("Attaching to interface")
dev := device.NewDevice(tun, conn.NewStdNetBind(), logger)

err = dev.IpcSet(C.GoString(settings))
exitMtu, err := tun.MTU()
if err != nil {
logger.Errorf("Unable to set IPC settings: %v", err)
unix.Close(dupTunFd)
return -1
tun.Close()
return errGetMtu
}

dev.Up()
logger.Verbosef("Device started")

var i int32
for i = 1; i < math.MaxInt32; i++ {
if _, exists := tunnelHandles[i]; !exists {
break
}
}
if i == math.MaxInt32 {
unix.Close(dupTunFd)
return -1
}
tunnelHandles[i] = tunnelHandle{dev, nil, logger, nil}
return i
return wgTurnOnMultihopInner(tun, exitSettings, entrySettings, privateIp, exitMtu, logger)
}

//export wgTurnOnIAN
func wgTurnOnIAN(settings *C.char, tunFd int32, privateIP *C.char) int32 {
func wgTurnOnIANFromExistingTunnel(tun tun.Device, settings string, privateAddr netip.Addr) int32 {
logger := &device.Logger{
Verbosef: CLogger(0).Printf,
Errorf: CLogger(1).Printf,
}

privateAddrStr := C.GoString(privateIP)
privateAddr, err := netip.ParseAddr(privateAddrStr)
if err != nil {
logger.Errorf("Invalid address: %s", privateAddrStr)
return errBadIPString
}

dupTunFd, err := unix.Dup(int(tunFd))
if err != nil {
logger.Errorf("Unable to dup tun fd: %v", err)
return errDup
}

err = unix.SetNonblock(dupTunFd, true)
if err != nil {
logger.Errorf("Unable to set tun fd as non blocking: %v", err)
unix.Close(dupTunFd)
return errSetNonblock
}
tun, err := tun.CreateTUNFromFile(os.NewFile(uintptr(dupTunFd), "/dev/tun"), 0)
if err != nil {
logger.Errorf("Unable to create new tun device from fd: %v", err)
unix.Close(dupTunFd)
return errCreateTun
}
/// assign the same private IPs associated with your key
vtun, virtualNet, err := netstack.CreateNetTUN([]netip.Addr{privateAddr}, []netip.Addr{}, 1280)

if err != nil {
logger.Errorf("Failed to initialize virtual tunnel device: %v", err)
tun.Close()
Expand All @@ -292,29 +253,29 @@ func wgTurnOnIAN(settings *C.char, tunFd int32, privateIP *C.char) int32 {
logger.Verbosef("Attaching to interface")
dev := device.NewDevice(&wrapper, conn.NewStdNetBind(), logger)

err = dev.IpcSet(C.GoString(settings))
if err != nil {
logger.Errorf("Unable to set IPC settings: %v", err)
dev.Close()
return errBadWgConfig
}
return addTunnelFromDevice(dev, nil, settings, "", virtualNet, logger)
}

dev.Up()
logger.Verbosef("Device started")
//export wgTurnOnIAN
func wgTurnOnIAN(settings *C.char, tunFd int32, privateIP *C.char) int32 {
logger := &device.Logger{
Verbosef: CLogger(0).Printf,
Errorf: CLogger(1).Printf,
}

var i int32
for i = 0; i < math.MaxInt32; i++ {
if _, exists := tunnelHandles[i]; !exists {
break
}
privateAddrStr := C.GoString(privateIP)
privateAddr, err := netip.ParseAddr(privateAddrStr)
if err != nil {
logger.Errorf("Invalid address: %s", privateAddrStr)
return errBadIPString
}
if i == math.MaxInt32 {
dev.Close()
return errDeviceLimitHit

tun, errCode := openTUNFromSocket(tunFd, logger)
if tun == nil {
return errCode
}
tunnelHandles[i] = tunnelHandle{dev, nil, logger, virtualNet}
// TODO: add a tunnel handle, or otherwise make sure we can create connections in the tunnel
return i

return wgTurnOnIANFromExistingTunnel(tun, C.GoString(settings), privateAddr)
}

//export wgTurnOff
Expand Down