mirror of
https://github.com/qdm12/gluetun.git
synced 2026-08-05 03:43:24 +02:00
54 lines
1.7 KiB
Go
54 lines
1.7 KiB
Go
package wireguard
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"golang.org/x/sys/unix"
|
|
"golang.zx2c4.com/wireguard/tun"
|
|
)
|
|
|
|
// createTUN creates a TUN device. When gso is false, IFF_VNET_HDR is
|
|
// omitted so wireguard-go's initFromFlags sees no vnet header support and
|
|
// keeps tun.vnetHdr=false, falling back to simple single-packet writes instead
|
|
// of the GRO/GSO batch path that causes EINVAL on some vendor kernels.
|
|
func createTUN(name string, mtu int, gso bool) (tun.Device, error) { //nolint:ireturn
|
|
if gso {
|
|
return tun.CreateTUN(name, mtu)
|
|
}
|
|
tunFile, err := OpenTUNFile(name)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("creating tun fd file: %w", err)
|
|
}
|
|
tunDevice, err := tun.CreateTUNFromFile(tunFile, mtu)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("creating TUN device from file: %w", err)
|
|
}
|
|
return tunDevice, nil
|
|
}
|
|
|
|
// OpenTUNFile opens /dev/net/tun with IFF_TUN|IFF_NO_PI but without
|
|
// IFF_VNET_HDR. It is exported so that the amneziawg package can use the same
|
|
// file with amneziatun.CreateTUNFromFile.
|
|
func OpenTUNFile(name string) (*os.File, error) {
|
|
tunFD, err := unix.Open("/dev/net/tun", unix.O_RDWR|unix.O_CLOEXEC, 0)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("opening /dev/net/tun: %w", err)
|
|
}
|
|
ifr, err := unix.NewIfreq(name)
|
|
if err != nil {
|
|
unix.Close(tunFD)
|
|
return nil, fmt.Errorf("creating ifreq: %w", err)
|
|
}
|
|
ifr.SetUint16(unix.IFF_TUN | unix.IFF_NO_PI) // intentionally omit IFF_VNET_HDR
|
|
if err := unix.IoctlIfreq(tunFD, unix.TUNSETIFF, ifr); err != nil {
|
|
unix.Close(tunFD)
|
|
return nil, fmt.Errorf("setting TUN flags: %w", err)
|
|
}
|
|
if err := unix.SetNonblock(tunFD, true); err != nil {
|
|
unix.Close(tunFD)
|
|
return nil, fmt.Errorf("setting nonblock: %w", err)
|
|
}
|
|
return os.NewFile(uintptr(tunFD), "/dev/net/tun"), nil
|
|
}
|