mirror of
				https://github.com/yggdrasil-network/water.git
				synced 2025-10-31 09:15:09 +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
	
	 Song Gao
						Song Gao