add EthernetPacket, network.HandleEthernetPacket

Change-Id: I9b9f471c8fcc49ea16d732fe3ce06d5be4ff1125
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2024-07-27 11:53:50 -07:00
parent 013ea64e94
commit c860129eb0

View File

@ -291,6 +291,15 @@ var (
fakeControlplaneIP = netip.AddrFrom4([4]byte{52, 52, 0, 1}) fakeControlplaneIP = netip.AddrFrom4([4]byte{52, 52, 0, 1})
) )
type EthernetPacket struct {
le *layers.Ethernet
gp gopacket.Packet
}
func (ep EthernetPacket) SrcMAC() MAC {
return MAC(ep.le.SrcMAC)
}
type MAC [6]byte type MAC [6]byte
func macOf(hwa net.HardwareAddr) (_ MAC, ok bool) { func macOf(hwa net.HardwareAddr) (_ MAC, ok bool) {
@ -425,11 +434,13 @@ func (s *Server) serveConn(uc net.Conn) {
packetRaw := buf[4 : 4+n] // raw ethernet frame packetRaw := buf[4 : 4+n] // raw ethernet frame
packet := gopacket.NewPacket(packetRaw, layers.LayerTypeEthernet, gopacket.Lazy) packet := gopacket.NewPacket(packetRaw, layers.LayerTypeEthernet, gopacket.Lazy)
ll, ok := packet.LinkLayer().(*layers.Ethernet) le, ok := packet.LinkLayer().(*layers.Ethernet)
if !ok { if !ok || len(le.SrcMAC) != 6 || len(le.DstMAC) != 6 {
continue continue
} }
srcMAC := MAC(ll.SrcMAC) ep := EthernetPacket{le, packet}
srcMAC := ep.SrcMAC()
if srcNode == nil { if srcNode == nil {
srcNode, ok = s.nodes[srcMAC] srcNode, ok = s.nodes[srcMAC]
if !ok { if !ok {
@ -446,47 +457,68 @@ func (s *Server) serveConn(uc net.Conn) {
continue continue
} }
} }
netw.HandleEthernetPacket(ep)
}
}
if ll.EthernetType == layers.EthernetTypeARP { func (n *network) writeEth(res []byte) {
res, err := netw.createARPResponse(packet) if len(res) < 6 {
return
}
dstMAC := MAC(res[0:6])
if writeFunc, ok := n.writeFunc.Load(dstMAC); ok {
writeFunc(res)
}
}
func (n *network) HandleEthernetPacket(ep EthernetPacket) {
packet := ep.gp
s := n.s
writePkt := n.writeEth
switch ep.le.EthernetType {
default:
log.Printf("Dropping non-IP packet: %v", ep.le.EthernetType)
return
case layers.EthernetTypeARP:
res, err := n.createARPResponse(packet)
if err != nil { if err != nil {
log.Printf("createARPResponse: %v", err) log.Printf("createARPResponse: %v", err)
} else { } else {
writePkt(res) writePkt(res)
} }
continue return
} case layers.EthernetTypeIPv6:
// One day. Low value for now. IPv4 NAT modes is the main thing
if ll.EthernetType != layers.EthernetTypeIPv4 { // this project wants to test.
if ll.EthernetType != layers.EthernetTypeIPv6 { return
log.Printf("Dropping non-IP packet: %v", ll.EthernetType) case layers.EthernetTypeIPv4:
} // Below
continue
} }
if isDHCPRequest(packet) { if isDHCPRequest(packet) {
res, err := s.createDHCPResponse(packet) res, err := s.createDHCPResponse(packet)
if err != nil { if err != nil {
log.Printf("createDHCPResponse: %v", err) log.Printf("createDHCPResponse: %v", err)
continue return
} }
writePkt(res) writePkt(res)
continue return
} }
if isMDNSQuery(packet) || isIGMP(packet) { if isMDNSQuery(packet) || isIGMP(packet) {
// Don't log. Spammy for now. // Don't log. Spammy for now.
continue return
} }
if isDNSRequest(packet) { if isDNSRequest(packet) {
res, err := s.createDNSResponse(packet) res, err := s.createDNSResponse(packet)
if err != nil { if err != nil {
log.Printf("createDNSResponse: %v", err) log.Printf("createDNSResponse: %v", err)
continue return
} }
writePkt(res) writePkt(res)
continue return
} }
if isSTUNRequest(packet) { if isSTUNRequest(packet) {
@ -494,10 +526,10 @@ func (s *Server) serveConn(uc net.Conn) {
res, err := s.createSTUNResponse(packet) res, err := s.createSTUNResponse(packet)
if err != nil { if err != nil {
log.Printf("createSTUNResponse: %v", err) log.Printf("createSTUNResponse: %v", err)
continue return
} }
writePkt(res) writePkt(res)
continue return
} }
if shouldInterceptTCP(packet) { if shouldInterceptTCP(packet) {
@ -508,7 +540,7 @@ func (s *Server) serveConn(uc net.Conn) {
packetBuf := stack.NewPacketBuffer(stack.PacketBufferOptions{ packetBuf := stack.NewPacketBuffer(stack.PacketBufferOptions{
Payload: buffer.MakeWithData(pktCopy), Payload: buffer.MakeWithData(pktCopy),
}) })
netw.linkEP.InjectInbound(header.IPv4ProtocolNumber, packetBuf) n.linkEP.InjectInbound(header.IPv4ProtocolNumber, packetBuf)
// var list stack.PacketBufferList // var list stack.PacketBufferList
// list.PushBack(packetBuf) // list.PushBack(packetBuf)
@ -516,11 +548,10 @@ func (s *Server) serveConn(uc net.Conn) {
// log.Printf("Injected: %v, %v", n, err) // log.Printf("Injected: %v, %v", n, err)
packetBuf.DecRef() packetBuf.DecRef()
continue return
} }
log.Printf("Got packet: %v", packet) log.Printf("Got packet: %v", packet)
}
} }
func (s *Server) createDHCPResponse(request gopacket.Packet) ([]byte, error) { func (s *Server) createDHCPResponse(request gopacket.Packet) ([]byte, error) {