Browse Source

Move inside packet handlers into map

This commit moves the inside packet handlers into a map of functions
from the large switch statement. The functions are mapped by packet
protocol version, type and subtype; which makes it simpler to inject
either a new protocol version and/or custom handlers.
Dave Russell 4 years ago
parent
commit
2c931d5691
4 changed files with 118 additions and 86 deletions
  1. 86 0
      handler.go
  2. 1 0
      header.go
  3. 28 0
      interface.go
  4. 3 86
      outside.go

+ 86 - 0
handler.go

@@ -0,0 +1,86 @@
+package nebula
+
+func (f *Interface) handleMessagePacket(hostInfo *HostInfo, ci *ConnectionState, addr *udpAddr, header *Header, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
+	if !f.handleEncrypted(ci, addr, header) {
+		return
+	}
+
+	f.decryptToTun(hostInfo, header.MessageCounter, out, packet, fwPacket, nb)
+
+	f.handleHostRoaming(hostInfo, addr)
+	f.connectionManager.In(hostInfo.hostId)
+}
+
+func (f *Interface) handleLighthousePacket(hostInfo *HostInfo, ci *ConnectionState, addr *udpAddr, header *Header, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
+	f.messageMetrics.Rx(header.Type, header.Subtype, 1)
+	if !f.handleEncrypted(ci, addr, header) {
+		return
+	}
+
+	d, err := f.decrypt(hostInfo, header.MessageCounter, out, packet, header, nb)
+	if err != nil {
+		hostInfo.logger().WithError(err).WithField("udpAddr", addr).
+			WithField("packet", packet).
+			Error("Failed to decrypt lighthouse packet")
+
+		//TODO: maybe after build 64 is out? 06/14/2018 - NB
+		//f.sendRecvError(net.Addr(addr), header.RemoteIndex)
+		return
+	}
+
+	f.lightHouse.HandleRequest(addr, hostInfo.hostId, d, hostInfo.GetCert(), f)
+
+	f.handleHostRoaming(hostInfo, addr)
+	f.connectionManager.In(hostInfo.hostId)
+}
+
+func (f *Interface) handleTestPacket(hostInfo *HostInfo, ci *ConnectionState, addr *udpAddr, header *Header, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
+	f.messageMetrics.Rx(header.Type, header.Subtype, 1)
+	if !f.handleEncrypted(ci, addr, header) {
+		return
+	}
+
+	d, err := f.decrypt(hostInfo, header.MessageCounter, out, packet, header, nb)
+	if err != nil {
+		hostInfo.logger().WithError(err).WithField("udpAddr", addr).
+			WithField("packet", packet).
+			Error("Failed to decrypt test packet")
+
+		//TODO: maybe after build 64 is out? 06/14/2018 - NB
+		//f.sendRecvError(net.Addr(addr), header.RemoteIndex)
+		return
+	}
+
+	if header.Subtype == testRequest {
+		// This testRequest might be from TryPromoteBest, so we should roam
+		// to the new IP address before responding
+		f.handleHostRoaming(hostInfo, addr)
+		f.send(test, testReply, ci, hostInfo, hostInfo.remote, d, nb, out)
+	}
+
+	f.handleHostRoaming(hostInfo, addr)
+	f.connectionManager.In(hostInfo.hostId)
+}
+
+func (f *Interface) handleHandshakePacket(hostInfo *HostInfo, ci *ConnectionState, addr *udpAddr, header *Header, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
+	f.messageMetrics.Rx(header.Type, header.Subtype, 1)
+	HandleIncomingHandshake(f, addr, packet, header, hostInfo)
+}
+
+func (f *Interface) handleRecvErrorPacket(hostInfo *HostInfo, ci *ConnectionState, addr *udpAddr, header *Header, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
+	f.messageMetrics.Rx(header.Type, header.Subtype, 1)
+	// TODO: Remove this with recv_error deprecation
+	f.handleRecvError(addr, header)
+}
+
+func (f *Interface) handleCloseTunnelPacket(hostInfo *HostInfo, ci *ConnectionState, addr *udpAddr, header *Header, out []byte, packet []byte, fwPacket *FirewallPacket, nb []byte) {
+	f.messageMetrics.Rx(header.Type, header.Subtype, 1)
+	if !f.handleEncrypted(ci, addr, header) {
+		return
+	}
+
+	hostInfo.logger().WithField("udpAddr", addr).
+		Info("Close tunnel received, tearing down.")
+
+	f.closeTunnel(hostInfo)
+}

+ 1 - 0
header.go

@@ -54,6 +54,7 @@ var typeMap = map[NebulaMessageType]string{
 }
 
 const (
+	subTypeNone NebulaMessageSubType = 0
 	testRequest NebulaMessageSubType = 0
 	testReply   NebulaMessageSubType = 1
 )

+ 28 - 0
interface.go

@@ -20,6 +20,8 @@ type Inside interface {
 	WriteRaw([]byte) error
 }
 
+type InsideHandler func(hostInfo *HostInfo, ci *ConnectionState, addr *udpAddr, header *Header, out []byte, packet []byte, fp *FirewallPacket, nb []byte)
+
 type InterfaceConfig struct {
 	HostMap                 *HostMap
 	Outside                 *udpConn
@@ -61,6 +63,9 @@ type Interface struct {
 	tunQueues          int
 	version            string
 
+	// handlers are mapped by protocol version -> type -> subtype
+	handlers map[uint8]map[NebulaMessageType]map[NebulaMessageSubType]InsideHandler
+
 	metricHandshakes metrics.Histogram
 	messageMetrics   *MessageMetrics
 }
@@ -103,6 +108,29 @@ func NewInterface(c *InterfaceConfig) (*Interface, error) {
 	}
 
 	ifce.connectionManager = newConnectionManager(ifce, c.checkInterval, c.pendingDeletionInterval)
+	ifce.handlers = map[uint8]map[NebulaMessageType]map[NebulaMessageSubType]InsideHandler{
+		Version: {
+			handshake: {
+				handshakeIXPSK0: ifce.handleHandshakePacket,
+			},
+			message: {
+				subTypeNone: ifce.handleMessagePacket,
+			},
+			recvError: {
+				subTypeNone: ifce.handleRecvErrorPacket,
+			},
+			lightHouse: {
+				subTypeNone: ifce.handleLighthousePacket,
+			},
+			test: {
+				testRequest: ifce.handleTestPacket,
+				testReply:   ifce.handleTestPacket,
+			},
+			closeTunnel: {
+				subTypeNone: ifce.handleCloseTunnelPacket,
+			},
+		},
+	}
 
 	return ifce, nil
 }

+ 3 - 86
outside.go

@@ -39,98 +39,15 @@ func (f *Interface) readOutsidePackets(addr *udpAddr, out []byte, packet []byte,
 		ci = hostinfo.ConnectionState
 	}
 
-	switch header.Type {
-	case message:
-		if !f.handleEncrypted(ci, addr, header) {
-			return
-		}
-
-		f.decryptToTun(hostinfo, header.MessageCounter, out, packet, fwPacket, nb)
+	handle := f.handlers[header.Version][header.Type][header.Subtype]
 
-		// Fallthrough to the bottom to record incoming traffic
-
-	case lightHouse:
-		f.messageMetrics.Rx(header.Type, header.Subtype, 1)
-		if !f.handleEncrypted(ci, addr, header) {
-			return
-		}
-
-		d, err := f.decrypt(hostinfo, header.MessageCounter, out, packet, header, nb)
-		if err != nil {
-			hostinfo.logger().WithError(err).WithField("udpAddr", addr).
-				WithField("packet", packet).
-				Error("Failed to decrypt lighthouse packet")
-
-			//TODO: maybe after build 64 is out? 06/14/2018 - NB
-			//f.sendRecvError(net.Addr(addr), header.RemoteIndex)
-			return
-		}
-
-		f.lightHouse.HandleRequest(addr, hostinfo.hostId, d, hostinfo.GetCert(), f)
-
-		// Fallthrough to the bottom to record incoming traffic
-
-	case test:
-		f.messageMetrics.Rx(header.Type, header.Subtype, 1)
-		if !f.handleEncrypted(ci, addr, header) {
-			return
-		}
-
-		d, err := f.decrypt(hostinfo, header.MessageCounter, out, packet, header, nb)
-		if err != nil {
-			hostinfo.logger().WithError(err).WithField("udpAddr", addr).
-				WithField("packet", packet).
-				Error("Failed to decrypt test packet")
-
-			//TODO: maybe after build 64 is out? 06/14/2018 - NB
-			//f.sendRecvError(net.Addr(addr), header.RemoteIndex)
-			return
-		}
-
-		if header.Subtype == testRequest {
-			// This testRequest might be from TryPromoteBest, so we should roam
-			// to the new IP address before responding
-			f.handleHostRoaming(hostinfo, addr)
-			f.send(test, testReply, ci, hostinfo, hostinfo.remote, d, nb, out)
-		}
-
-		// Fallthrough to the bottom to record incoming traffic
-
-		// Non encrypted messages below here, they should not fall through to avoid tracking incoming traffic since they
-		// are unauthenticated
-
-	case handshake:
-		f.messageMetrics.Rx(header.Type, header.Subtype, 1)
-		HandleIncomingHandshake(f, addr, packet, header, hostinfo)
-		return
-
-	case recvError:
-		f.messageMetrics.Rx(header.Type, header.Subtype, 1)
-		// TODO: Remove this with recv_error deprecation
-		f.handleRecvError(addr, header)
-		return
-
-	case closeTunnel:
-		f.messageMetrics.Rx(header.Type, header.Subtype, 1)
-		if !f.handleEncrypted(ci, addr, header) {
-			return
-		}
-
-		hostinfo.logger().WithField("udpAddr", addr).
-			Info("Close tunnel received, tearing down.")
-
-		f.closeTunnel(hostinfo)
-		return
-
-	default:
+	if handle == nil {
 		f.messageMetrics.Rx(header.Type, header.Subtype, 1)
 		hostinfo.logger().Debugf("Unexpected packet received from %s", addr)
 		return
 	}
 
-	f.handleHostRoaming(hostinfo, addr)
-
-	f.connectionManager.In(hostinfo.hostId)
+	handle(hostinfo, ci, addr, header, out, packet, fwPacket, nb)
 }
 
 func (f *Interface) closeTunnel(hostInfo *HostInfo) {