mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-06 05:17:38 +03:00
Refactor socksaddr
This commit is contained in:
parent
9378ae739c
commit
b35c53ca8f
54 changed files with 1191 additions and 666 deletions
171
common/tun/tun_linux.go
Normal file
171
common/tun/tun_linux.go
Normal file
|
@ -0,0 +1,171 @@
|
|||
package tun
|
||||
|
||||
/*
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const ifReqSize = unix.IFNAMSIZ + 64
|
||||
|
||||
func (t *Interface) Name() (string, error) {
|
||||
if t.tunName != "" {
|
||||
return t.tunName, nil
|
||||
}
|
||||
var ifr [ifReqSize]byte
|
||||
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(t.tunFd), uintptr(unix.TUNGETIFF), uintptr(unsafe.Pointer(&ifr[0])))
|
||||
if errno != 0 {
|
||||
return "", errno
|
||||
}
|
||||
name := ifr[:]
|
||||
if i := bytes.IndexByte(name, 0); i != -1 {
|
||||
name = name[:i]
|
||||
}
|
||||
t.tunName = string(name)
|
||||
return t.tunName, nil
|
||||
}
|
||||
|
||||
func (t *Interface) MTU() (int, error) {
|
||||
name, err := t.Name()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
fd, err := unix.Socket(
|
||||
unix.AF_INET,
|
||||
unix.SOCK_DGRAM,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer unix.Close(fd)
|
||||
var ifr [ifReqSize]byte
|
||||
copy(ifr[:], name)
|
||||
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.SIOCGIFMTU), uintptr(unsafe.Pointer(&ifr[0])))
|
||||
if errno != 0 {
|
||||
return 0, errno
|
||||
}
|
||||
return int(*(*int32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ]))), nil
|
||||
}
|
||||
|
||||
func (t *Interface) SetMTU(mtu int) error {
|
||||
name, err := t.Name()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fd, err := unix.Socket(
|
||||
unix.AF_INET,
|
||||
unix.SOCK_DGRAM,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer unix.Close(fd)
|
||||
var ifr [ifReqSize]byte
|
||||
copy(ifr[:], name)
|
||||
*(*uint32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = uint32(mtu)
|
||||
_, _, errno := unix.Syscall(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(fd),
|
||||
uintptr(unix.SIOCSIFMTU),
|
||||
uintptr(unsafe.Pointer(&ifr[0])),
|
||||
)
|
||||
if errno != 0 {
|
||||
return errno
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Interface) SetAddress() error {
|
||||
name, err := t.Name()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fd, err := unix.Socket(
|
||||
unix.AF_INET,
|
||||
unix.SOCK_DGRAM,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer unix.Close(fd)
|
||||
ifreq, err := unix.NewIfreq(name)
|
||||
if err != nil {
|
||||
return E.Cause(err, "failed to create ifreq for name ", name)
|
||||
}
|
||||
|
||||
ifreq.SetInet4Addr(t.inetAddress.Addr().AsSlice())
|
||||
err = unix.IoctlIfreq(fd, syscall.SIOCSIFADDR, ifreq)
|
||||
if err == nil {
|
||||
ifreq, _ = unix.NewIfreq(name)
|
||||
ifreq.SetInet4Addr(net.CIDRMask(t.inetAddress.Bits(), 32))
|
||||
err = unix.IoctlIfreq(fd, syscall.SIOCSIFNETMASK, ifreq)
|
||||
}
|
||||
if err != nil {
|
||||
return E.Cause(err, "failed to set ipv4 address on ", name)
|
||||
}
|
||||
if t.inet6Address.IsValid() {
|
||||
ifreq, _ = unix.NewIfreq(name)
|
||||
err = unix.IoctlIfreq(fd, syscall.SIOCGIFINDEX, ifreq)
|
||||
if err != nil {
|
||||
return E.Cause(err, "failed to get interface index for ", name)
|
||||
}
|
||||
|
||||
ifreq6 := in6_ifreq{
|
||||
ifr6_addr: in6_addr{
|
||||
addr: t.inet6Address.Addr().As16(),
|
||||
},
|
||||
ifr6_prefixlen: uint32(t.inet6Address.Bits()),
|
||||
ifr6_ifindex: ifreq.Uint32(),
|
||||
}
|
||||
|
||||
fd6, err := unix.Socket(
|
||||
unix.AF_INET6,
|
||||
unix.SOCK_DGRAM,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer unix.Close(fd6)
|
||||
|
||||
if _, _, errno := syscall.Syscall(
|
||||
syscall.SYS_IOCTL,
|
||||
uintptr(fd6),
|
||||
uintptr(syscall.SIOCSIFADDR),
|
||||
uintptr(unsafe.Pointer(&ifreq6)),
|
||||
); errno != 0 {
|
||||
return E.Cause(errno, "failed to set ipv6 address on ", name)
|
||||
}
|
||||
}
|
||||
|
||||
ifreq, _ = unix.NewIfreq(name)
|
||||
err = unix.IoctlIfreq(fd, syscall.SIOCGIFFLAGS, ifreq)
|
||||
if err == nil {
|
||||
ifreq.SetUint16(ifreq.Uint16() | syscall.IFF_UP | syscall.IFF_RUNNING)
|
||||
err = unix.IoctlIfreq(fd, syscall.SIOCSIFFLAGS, ifreq)
|
||||
}
|
||||
if err != nil {
|
||||
return E.Cause(err, "failed to bring tun device up")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type in6_addr struct {
|
||||
addr [16]byte
|
||||
}
|
||||
|
||||
type in6_ifreq struct {
|
||||
ifr6_addr in6_addr
|
||||
ifr6_prefixlen uint32
|
||||
ifr6_ifindex uint32
|
||||
}
|
||||
*/
|
Loading…
Add table
Add a link
Reference in a new issue