github.com/slackhq/nebula@v1.9.0/udp/udp_generic.go (about)

     1  //go:build (!linux || android) && !e2e_testing
     2  // +build !linux android
     3  // +build !e2e_testing
     4  
     5  // udp_generic implements the nebula UDP interface in pure Go stdlib. This
     6  // means it can be used on platforms like Darwin and Windows.
     7  
     8  package udp
     9  
    10  import (
    11  	"context"
    12  	"fmt"
    13  	"net"
    14  
    15  	"github.com/sirupsen/logrus"
    16  	"github.com/slackhq/nebula/config"
    17  	"github.com/slackhq/nebula/firewall"
    18  	"github.com/slackhq/nebula/header"
    19  )
    20  
    21  type GenericConn struct {
    22  	*net.UDPConn
    23  	l *logrus.Logger
    24  }
    25  
    26  var _ Conn = &GenericConn{}
    27  
    28  func NewGenericListener(l *logrus.Logger, ip net.IP, port int, multi bool, batch int) (Conn, error) {
    29  	lc := NewListenConfig(multi)
    30  	pc, err := lc.ListenPacket(context.TODO(), "udp", net.JoinHostPort(ip.String(), fmt.Sprintf("%v", port)))
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  	if uc, ok := pc.(*net.UDPConn); ok {
    35  		return &GenericConn{UDPConn: uc, l: l}, nil
    36  	}
    37  	return nil, fmt.Errorf("Unexpected PacketConn: %T %#v", pc, pc)
    38  }
    39  
    40  func (u *GenericConn) WriteTo(b []byte, addr *Addr) error {
    41  	_, err := u.UDPConn.WriteToUDP(b, &net.UDPAddr{IP: addr.IP, Port: int(addr.Port)})
    42  	return err
    43  }
    44  
    45  func (u *GenericConn) LocalAddr() (*Addr, error) {
    46  	a := u.UDPConn.LocalAddr()
    47  
    48  	switch v := a.(type) {
    49  	case *net.UDPAddr:
    50  		addr := &Addr{IP: make([]byte, len(v.IP))}
    51  		copy(addr.IP, v.IP)
    52  		addr.Port = uint16(v.Port)
    53  		return addr, nil
    54  
    55  	default:
    56  		return nil, fmt.Errorf("LocalAddr returned: %#v", a)
    57  	}
    58  }
    59  
    60  func (u *GenericConn) ReloadConfig(c *config.C) {
    61  	// TODO
    62  }
    63  
    64  func NewUDPStatsEmitter(udpConns []Conn) func() {
    65  	// No UDP stats for non-linux
    66  	return func() {}
    67  }
    68  
    69  type rawMessage struct {
    70  	Len uint32
    71  }
    72  
    73  func (u *GenericConn) ListenOut(r EncReader, lhf LightHouseHandlerFunc, cache *firewall.ConntrackCacheTicker, q int) {
    74  	plaintext := make([]byte, MTU)
    75  	buffer := make([]byte, MTU)
    76  	h := &header.H{}
    77  	fwPacket := &firewall.Packet{}
    78  	udpAddr := &Addr{IP: make([]byte, 16)}
    79  	nb := make([]byte, 12, 12)
    80  
    81  	for {
    82  		// Just read one packet at a time
    83  		n, rua, err := u.ReadFromUDP(buffer)
    84  		if err != nil {
    85  			u.l.WithError(err).Debug("udp socket is closed, exiting read loop")
    86  			return
    87  		}
    88  
    89  		udpAddr.IP = rua.IP
    90  		udpAddr.Port = uint16(rua.Port)
    91  		r(udpAddr, plaintext[:0], buffer[:n], h, fwPacket, lhf, nb, q, cache.Get(u.l))
    92  	}
    93  }