Files
cunicu/pkg/device/device_user.go
Steffen Vogel 5dca738b0f device: do not delete TUN device on shutdown
Signed-off-by: Steffen Vogel <post@steffenvogel.de>
2022-08-25 18:55:53 +02:00

132 lines
2.5 KiB
Go

package device
import (
"errors"
"fmt"
"net"
"os"
"sync"
"go.uber.org/zap"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun"
"riasc.eu/wice/pkg/wg"
)
var (
userDevices = map[string]*UserDevice{}
userDevicesLock sync.Mutex
)
type UserDevice struct {
Device
device *device.Device
api net.Listener
Bind *wg.UserBind
logger *zap.Logger
}
func NewUserDevice(name string) (*UserDevice, error) {
var err error
logger := zap.L().Named("device").With(
zap.String("dev", name),
zap.String("type", "user"),
)
wgLogger := logger.Named("wg").Sugar()
wgDeviceLogger := &device.Logger{
Verbosef: wgLogger.Debugf,
Errorf: wgLogger.Errorf,
}
dev := &UserDevice{
Bind: wg.NewUserBind(),
logger: logger,
}
// Create TUN device
tunDev, err := tun.CreateTUN(name, device.DefaultMTU)
if err != nil {
return nil, fmt.Errorf("failed to create TUN device: %w", err)
}
// Fix TUN device name
realName, err := tunDev.Name()
if err == nil && realName != name {
logger.Debug("using real tun device name", zap.String("real", realName))
name = realName
}
// Open UAPI socket
if dev.api, err = ListenUAPI(name); err != nil {
return nil, err
}
// Handle UApi requests
go dev.handleUserAPI()
// Create new device
dev.device = device.NewDevice(tunDev, dev.Bind, wgDeviceLogger)
if dev.Device, err = FindKernelDevice(name); err != nil {
return nil, err
}
logger.Info("Started in-process wireguard-go interface")
// Register user device
userDevicesLock.Lock()
defer userDevicesLock.Unlock()
userDevices[name] = dev
return dev, nil
}
func (d *UserDevice) Close() error {
d.device.Close()
if err := d.api.Close(); err != nil {
return err
}
// TODO: Check for stale TUN device and cleanup?
return nil
}
func (d *UserDevice) handleUserAPI() {
for {
conn, err := d.api.Accept()
if err != nil {
if errors.Is(err, net.ErrClosed) {
return
} else {
d.logger.Error("Failed to accept new user api connection", zap.Error(err))
continue
}
} else if d.device == nil {
d.logger.Warn("Dropping user api connection as device is not ready yet")
continue
}
d.logger.Debug("Handle new IPC connection", zap.String("socket", conn.LocalAddr().String()))
go d.device.IpcHandle(conn)
}
}
func FindUserDevice(name string) (Device, error) {
// Register user device
userDevicesLock.Lock()
defer userDevicesLock.Unlock()
if dev, ok := userDevices[name]; ok {
return dev, nil
}
return nil, os.ErrNotExist
}