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  }