mirror of
https://github.com/yggdrasil-network/water.git
synced 2025-05-19 16:35:10 +03:00
add darwin support for point-to-point TUN and update doc
This commit is contained in:
parent
f87d2289c2
commit
a7802d4a18
5 changed files with 230 additions and 51 deletions
123
syscalls_darwin.go
Normal file
123
syscalls_darwin.go
Normal file
|
@ -0,0 +1,123 @@
|
|||
// +build darwin
|
||||
|
||||
package water
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const appleUTUNCtl = "com.apple.net.utun_control"
|
||||
|
||||
/*
|
||||
* From ioctl.h:
|
||||
* #define IOCPARM_MASK 0x1fff // parameter length, at most 13 bits
|
||||
* ...
|
||||
* #define IOC_OUT 0x40000000 // copy out parameters
|
||||
* #define IOC_IN 0x80000000 // copy in parameters
|
||||
* #define IOC_INOUT (IOC_IN|IOC_OUT)
|
||||
* ...
|
||||
* #define _IOC(inout,group,num,len) \
|
||||
* (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))
|
||||
* ...
|
||||
* #define _IOWR(g,n,t) _IOC(IOC_INOUT, (g), (n), sizeof(t))
|
||||
*
|
||||
* From kern_control.h:
|
||||
* #define CTLIOCGINFO _IOWR('N', 3, struct ctl_info) // get id from name
|
||||
*
|
||||
*/
|
||||
|
||||
const appleCTLIOCGINFO = (0x40000000 | 0x80000000) | ((100 & 0x1fff) << 16) | uint32(byte('N'))<<8 | 3
|
||||
|
||||
/*
|
||||
* #define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t))
|
||||
* #define TUNSIFMODE _IOW('t', 94, int)
|
||||
*/
|
||||
const appleTUNSIFMODE = (0x80000000) | ((4 & 0x1fff) << 16) | uint32(byte('t'))<<8 | 94
|
||||
|
||||
/*
|
||||
* struct sockaddr_ctl {
|
||||
* u_char sc_len; // depends on size of bundle ID string
|
||||
* u_char sc_family; // AF_SYSTEM
|
||||
* u_int16_t ss_sysaddr; // AF_SYS_KERNCONTROL
|
||||
* u_int32_t sc_id; // Controller unique identifier
|
||||
* u_int32_t sc_unit; // Developer private unit number
|
||||
* u_int32_t sc_reserved[5];
|
||||
* };
|
||||
*/
|
||||
type sockaddrCtl struct {
|
||||
scLen uint8
|
||||
scFamily uint8
|
||||
ssSysaddr uint16
|
||||
scID uint32
|
||||
scUnit uint32
|
||||
scReserved [5]uint32
|
||||
}
|
||||
|
||||
var sockaddrCtlSize uintptr = 32
|
||||
|
||||
func newTUN(string) (ifce *Interface, err error) {
|
||||
var fd int
|
||||
// Supposed to be socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), but ...
|
||||
//
|
||||
// In sys/socket.h:
|
||||
// #define PF_SYSTEM AF_SYSTEM
|
||||
//
|
||||
// In sys/sys_domain.h:
|
||||
// #define SYSPROTO_CONTROL 2 /* kernel control protocol */
|
||||
if fd, err = syscall.Socket(syscall.AF_SYSTEM, syscall.SOCK_DGRAM, 2); err != nil {
|
||||
return nil, fmt.Errorf("error in syscall.Socket: %v", err)
|
||||
}
|
||||
|
||||
var ctlInfo = &struct {
|
||||
ctlID uint32
|
||||
ctlName [96]byte
|
||||
}{}
|
||||
copy(ctlInfo.ctlName[:], []byte(appleUTUNCtl))
|
||||
|
||||
if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(appleCTLIOCGINFO), uintptr(unsafe.Pointer(ctlInfo))); errno != 0 {
|
||||
err = errno
|
||||
return nil, fmt.Errorf("error in syscall.Syscall(syscall.SYS_IOTL, ...): %v", err)
|
||||
}
|
||||
|
||||
addrP := unsafe.Pointer(&sockaddrCtl{
|
||||
scLen: uint8(sockaddrCtlSize),
|
||||
scFamily: syscall.AF_SYSTEM,
|
||||
|
||||
/* #define AF_SYS_CONTROL 2 */
|
||||
ssSysaddr: 2,
|
||||
|
||||
scID: ctlInfo.ctlID,
|
||||
scUnit: 0,
|
||||
})
|
||||
if _, _, errno := syscall.RawSyscall(syscall.SYS_CONNECT, uintptr(fd), uintptr(addrP), uintptr(sockaddrCtlSize)); errno != 0 {
|
||||
err = errno
|
||||
return nil, fmt.Errorf("error in syscall.RawSyscall(syscall.SYS_CONNECT, ...): %v", err)
|
||||
}
|
||||
|
||||
var ifName struct {
|
||||
name [16]byte
|
||||
}
|
||||
ifNameSize := uintptr(16)
|
||||
if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd),
|
||||
2, /* #define SYSPROTO_CONTROL 2 */
|
||||
2, /* #define UTUN_OPT_IFNAME 2 */
|
||||
uintptr(unsafe.Pointer(&ifName)),
|
||||
uintptr(unsafe.Pointer(&ifNameSize)), 0); errno != 0 {
|
||||
err = errno
|
||||
return nil, fmt.Errorf("error in syscall.Syscall6(syscall.SYS_GETSOCKOPT, ...): %v", err)
|
||||
}
|
||||
|
||||
return &Interface{
|
||||
isTAP: false,
|
||||
name: string(ifName.name[:ifNameSize-1 /* -1 is for \0 */]),
|
||||
ReadWriteCloser: os.NewFile(uintptr(fd), string(ifName.name[:])),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newTAP(ifName string) (ifce *Interface, err error) {
|
||||
return nil, errors.New("tap interface not implemented on this platform")
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue