github.com/slackhq/nebula@v1.9.0/overlay/tun_disabled.go (about)

     1  package overlay
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net"
     7  	"strings"
     8  
     9  	"github.com/rcrowley/go-metrics"
    10  	"github.com/sirupsen/logrus"
    11  	"github.com/slackhq/nebula/iputil"
    12  )
    13  
    14  type disabledTun struct {
    15  	read chan []byte
    16  	cidr *net.IPNet
    17  
    18  	// Track these metrics since we don't have the tun device to do it for us
    19  	tx metrics.Counter
    20  	rx metrics.Counter
    21  	l  *logrus.Logger
    22  }
    23  
    24  func newDisabledTun(cidr *net.IPNet, queueLen int, metricsEnabled bool, l *logrus.Logger) *disabledTun {
    25  	tun := &disabledTun{
    26  		cidr: cidr,
    27  		read: make(chan []byte, queueLen),
    28  		l:    l,
    29  	}
    30  
    31  	if metricsEnabled {
    32  		tun.tx = metrics.GetOrRegisterCounter("messages.tx.message", nil)
    33  		tun.rx = metrics.GetOrRegisterCounter("messages.rx.message", nil)
    34  	} else {
    35  		tun.tx = &metrics.NilCounter{}
    36  		tun.rx = &metrics.NilCounter{}
    37  	}
    38  
    39  	return tun
    40  }
    41  
    42  func (*disabledTun) Activate() error {
    43  	return nil
    44  }
    45  
    46  func (*disabledTun) RouteFor(iputil.VpnIp) iputil.VpnIp {
    47  	return 0
    48  }
    49  
    50  func (t *disabledTun) Cidr() *net.IPNet {
    51  	return t.cidr
    52  }
    53  
    54  func (*disabledTun) Name() string {
    55  	return "disabled"
    56  }
    57  
    58  func (t *disabledTun) Read(b []byte) (int, error) {
    59  	r, ok := <-t.read
    60  	if !ok {
    61  		return 0, io.EOF
    62  	}
    63  
    64  	if len(r) > len(b) {
    65  		return 0, fmt.Errorf("packet larger than mtu: %d > %d bytes", len(r), len(b))
    66  	}
    67  
    68  	t.tx.Inc(1)
    69  	if t.l.Level >= logrus.DebugLevel {
    70  		t.l.WithField("raw", prettyPacket(r)).Debugf("Write payload")
    71  	}
    72  
    73  	return copy(b, r), nil
    74  }
    75  
    76  func (t *disabledTun) handleICMPEchoRequest(b []byte) bool {
    77  	out := make([]byte, len(b))
    78  	out = iputil.CreateICMPEchoResponse(b, out)
    79  	if out == nil {
    80  		return false
    81  	}
    82  
    83  	// attempt to write it, but don't block
    84  	select {
    85  	case t.read <- out:
    86  	default:
    87  		t.l.Debugf("tun_disabled: dropped ICMP Echo Reply response")
    88  	}
    89  
    90  	return true
    91  }
    92  
    93  func (t *disabledTun) Write(b []byte) (int, error) {
    94  	t.rx.Inc(1)
    95  
    96  	// Check for ICMP Echo Request before spending time doing the full parsing
    97  	if t.handleICMPEchoRequest(b) {
    98  		if t.l.Level >= logrus.DebugLevel {
    99  			t.l.WithField("raw", prettyPacket(b)).Debugf("Disabled tun responded to ICMP Echo Request")
   100  		}
   101  	} else if t.l.Level >= logrus.DebugLevel {
   102  		t.l.WithField("raw", prettyPacket(b)).Debugf("Disabled tun received unexpected payload")
   103  	}
   104  	return len(b), nil
   105  }
   106  
   107  func (t *disabledTun) NewMultiQueueReader() (io.ReadWriteCloser, error) {
   108  	return t, nil
   109  }
   110  
   111  func (t *disabledTun) Close() error {
   112  	if t.read != nil {
   113  		close(t.read)
   114  		t.read = nil
   115  	}
   116  	return nil
   117  }
   118  
   119  type prettyPacket []byte
   120  
   121  func (p prettyPacket) String() string {
   122  	var s strings.Builder
   123  
   124  	for i, b := range p {
   125  		if i > 0 && i%8 == 0 {
   126  			s.WriteString(" ")
   127  		}
   128  		s.WriteString(fmt.Sprintf("%02x ", b))
   129  	}
   130  
   131  	return s.String()
   132  }