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 }