github.com/slackhq/nebula@v1.9.0/overlay/tun_android.go (about) 1 //go:build !e2e_testing 2 // +build !e2e_testing 3 4 package overlay 5 6 import ( 7 "fmt" 8 "io" 9 "net" 10 "os" 11 "sync/atomic" 12 13 "github.com/sirupsen/logrus" 14 "github.com/slackhq/nebula/cidr" 15 "github.com/slackhq/nebula/config" 16 "github.com/slackhq/nebula/iputil" 17 "github.com/slackhq/nebula/util" 18 ) 19 20 type tun struct { 21 io.ReadWriteCloser 22 fd int 23 cidr *net.IPNet 24 Routes atomic.Pointer[[]Route] 25 routeTree atomic.Pointer[cidr.Tree4[iputil.VpnIp]] 26 l *logrus.Logger 27 } 28 29 func newTunFromFd(c *config.C, l *logrus.Logger, deviceFd int, cidr *net.IPNet) (*tun, error) { 30 // XXX Android returns an fd in non-blocking mode which is necessary for shutdown to work properly. 31 // Be sure not to call file.Fd() as it will set the fd to blocking mode. 32 file := os.NewFile(uintptr(deviceFd), "/dev/net/tun") 33 34 t := &tun{ 35 ReadWriteCloser: file, 36 fd: deviceFd, 37 cidr: cidr, 38 l: l, 39 } 40 41 err := t.reload(c, true) 42 if err != nil { 43 return nil, err 44 } 45 46 c.RegisterReloadCallback(func(c *config.C) { 47 err := t.reload(c, false) 48 if err != nil { 49 util.LogWithContextIfNeeded("failed to reload tun device", err, t.l) 50 } 51 }) 52 53 return t, nil 54 } 55 56 func newTun(_ *config.C, _ *logrus.Logger, _ *net.IPNet, _ bool) (*tun, error) { 57 return nil, fmt.Errorf("newTun not supported in Android") 58 } 59 60 func (t *tun) RouteFor(ip iputil.VpnIp) iputil.VpnIp { 61 _, r := t.routeTree.Load().MostSpecificContains(ip) 62 return r 63 } 64 65 func (t tun) Activate() error { 66 return nil 67 } 68 69 func (t *tun) reload(c *config.C, initial bool) error { 70 change, routes, err := getAllRoutesFromConfig(c, t.cidr, initial) 71 if err != nil { 72 return err 73 } 74 75 if !initial && !change { 76 return nil 77 } 78 79 routeTree, err := makeRouteTree(t.l, routes, false) 80 if err != nil { 81 return err 82 } 83 84 // Teach nebula how to handle the routes 85 t.Routes.Store(&routes) 86 t.routeTree.Store(routeTree) 87 return nil 88 } 89 90 func (t *tun) Cidr() *net.IPNet { 91 return t.cidr 92 } 93 94 func (t *tun) Name() string { 95 return "android" 96 } 97 98 func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) { 99 return nil, fmt.Errorf("TODO: multiqueue not implemented for android") 100 }