| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 | // +build iospackage nebulaimport (	"errors"	"fmt"	"io"	"net"	"os"	"sync"	"syscall")type Tun struct {	io.ReadWriteCloser	Device string	Cidr   *net.IPNet}func newTun(deviceName string, cidr *net.IPNet, defaultMTU int, routes []route, unsafeRoutes []route, txQueueLen int) (ifce *Tun, err error) {	return nil, fmt.Errorf("newTun not supported in iOS")}func newTunFromFd(deviceFd int, cidr *net.IPNet, defaultMTU int, routes []route, unsafeRoutes []route, txQueueLen int) (ifce *Tun, err error) {	if len(routes) > 0 {		return nil, fmt.Errorf("route MTU not supported in Darwin")	}	file := os.NewFile(uintptr(deviceFd), "/dev/tun")	ifce = &Tun{		Cidr:            cidr,		Device:          "iOS",		ReadWriteCloser: &tunReadCloser{f: file},	}	return}func (c *Tun) Activate() error {	return nil}func (c *Tun) WriteRaw(b []byte) error {	_, err := c.Write(b)	return err}// The following is hoisted up from water, we do this so we can inject our own fd on iOStype tunReadCloser struct {	f io.ReadWriteCloser	rMu  sync.Mutex	rBuf []byte	wMu  sync.Mutex	wBuf []byte}func (t *tunReadCloser) Read(to []byte) (int, error) {	t.rMu.Lock()	defer t.rMu.Unlock()	if cap(t.rBuf) < len(to)+4 {		t.rBuf = make([]byte, len(to)+4)	}	t.rBuf = t.rBuf[:len(to)+4]	n, err := t.f.Read(t.rBuf)	copy(to, t.rBuf[4:])	return n - 4, err}func (t *tunReadCloser) Write(from []byte) (int, error) {	if len(from) == 0 {		return 0, syscall.EIO	}	t.wMu.Lock()	defer t.wMu.Unlock()	if cap(t.wBuf) < len(from)+4 {		t.wBuf = make([]byte, len(from)+4)	}	t.wBuf = t.wBuf[:len(from)+4]	// Determine the IP Family for the NULL L2 Header	ipVer := from[0] >> 4	if ipVer == 4 {		t.wBuf[3] = syscall.AF_INET	} else if ipVer == 6 {		t.wBuf[3] = syscall.AF_INET6	} else {		return 0, errors.New("unable to determine IP version from packet")	}	copy(t.wBuf[4:], from)	n, err := t.f.Write(t.wBuf)	return n - 4, err}func (t *tunReadCloser) Close() error {	return t.f.Close()}func (c *Tun) CidrNet() *net.IPNet {	return c.Cidr}func (c *Tun) DeviceName() string {	return c.Device}
 |