initial: ZeroTier-like P2P mesh VPN server with multi-tenant Web UI
This commit is contained in:
24
internal/tap/tap.go
Normal file
24
internal/tap/tap.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package tap
|
||||
|
||||
type Interface struct {
|
||||
Name string
|
||||
MTU int
|
||||
fd int
|
||||
}
|
||||
|
||||
// Open creates a TAP interface on Linux. On other platforms it returns an error.
|
||||
func Open(name string, mtu int) (*Interface, error) {
|
||||
return openTap(name, mtu)
|
||||
}
|
||||
|
||||
func (t *Interface) Read(buf []byte) (int, error) {
|
||||
return readBuf(t.fd, buf)
|
||||
}
|
||||
|
||||
func (t *Interface) Write(buf []byte) (int, error) {
|
||||
return writeBuf(t.fd, buf)
|
||||
}
|
||||
|
||||
func (t *Interface) Close() error {
|
||||
return closeFD(t.fd)
|
||||
}
|
||||
71
internal/tap/tap_linux.go
Normal file
71
internal/tap/tap_linux.go
Normal file
@@ -0,0 +1,71 @@
|
||||
//go:build linux
|
||||
|
||||
package tap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
cIFF_TAP = 0x0002
|
||||
cIFF_NO_PI = 0x1000
|
||||
cTUNSETIFF = 0x400454ca
|
||||
cSIOCSIFMTU = 0x8922
|
||||
)
|
||||
|
||||
func openTap(name string, mtu int) (*Interface, error) {
|
||||
fd, err := syscall.Open("/dev/net/tun", syscall.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open /dev/net/tun: %w (is TUN/TAP supported?)", err)
|
||||
}
|
||||
|
||||
ifr := make([]byte, 40)
|
||||
copy(ifr, []byte(name))
|
||||
*(*uint16)(unsafe.Pointer(&ifr[16])) = uint16(cIFF_TAP | cIFF_NO_PI)
|
||||
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), cTUNSETIFF, uintptr(unsafe.Pointer(&ifr[0])))
|
||||
if errno != 0 {
|
||||
syscall.Close(fd)
|
||||
return nil, fmt.Errorf("ioctl TUNSETIFF: %w", errno)
|
||||
}
|
||||
|
||||
if mtu > 0 {
|
||||
mtuIfr := make([]byte, 40)
|
||||
copy(mtuIfr, ifr[:16])
|
||||
*(*int32)(unsafe.Pointer(&mtuIfr[16])) = int32(mtu)
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), cSIOCSIFMTU, uintptr(unsafe.Pointer(&mtuIfr[0])))
|
||||
if errno != 0 {
|
||||
syscall.Close(fd)
|
||||
return nil, fmt.Errorf("ioctl SIOCSIFMTU: %w", errno)
|
||||
}
|
||||
}
|
||||
|
||||
return &Interface{
|
||||
Name: name,
|
||||
MTU: mtu,
|
||||
fd: fd,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func readBuf(fd int, buf []byte) (int, error) {
|
||||
n, err := syscall.Read(fd, buf)
|
||||
if err != nil {
|
||||
return 0, os.NewSyscallError("read", err)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func writeBuf(fd int, buf []byte) (int, error) {
|
||||
n, err := syscall.Write(fd, buf)
|
||||
if err != nil {
|
||||
return 0, os.NewSyscallError("write", err)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func closeFD(fd int) error {
|
||||
return syscall.Close(fd)
|
||||
}
|
||||
21
internal/tap/tap_stub.go
Normal file
21
internal/tap/tap_stub.go
Normal file
@@ -0,0 +1,21 @@
|
||||
//go:build !linux
|
||||
|
||||
package tap
|
||||
|
||||
import "fmt"
|
||||
|
||||
func openTap(_ string, _ int) (*Interface, error) {
|
||||
return nil, fmt.Errorf("TAP devices are only supported on Linux")
|
||||
}
|
||||
|
||||
func readBuf(_ int, _ []byte) (int, error) {
|
||||
return 0, fmt.Errorf("not supported")
|
||||
}
|
||||
|
||||
func writeBuf(_ int, _ []byte) (int, error) {
|
||||
return 0, fmt.Errorf("not supported")
|
||||
}
|
||||
|
||||
func closeFD(_ int) error {
|
||||
return fmt.Errorf("not supported")
|
||||
}
|
||||
Reference in New Issue
Block a user