StackPorts: set MAC destination when node has MAC

This commit is contained in:
Patricio Whittingslow
2025-12-19 01:04:18 -03:00
parent 1554b89a08
commit 5e631a1b3d
5 changed files with 47 additions and 15 deletions
+3 -3
View File
@@ -359,7 +359,7 @@ func (s *Stack) StartLookupIP(host string) error {
var u internet.StackUDPPort var u internet.StackUDPPort
dns4 := dnsSrvs.As4() dns4 := dnsSrvs.As4()
u.SetStackNode(&s.dns, dns4[:], dns.ServerPort) u.SetStackNode(&s.dns, dns4[:], dns.ServerPort)
err = s.udps.Register(&u) err = s.udps.Register(&u, nil)
if err != nil { if err != nil {
return err return err
} }
@@ -405,7 +405,7 @@ func (s *Stack) BeginDHCPRequest(request [4]byte) error {
} }
var u internet.StackUDPPort var u internet.StackUDPPort
u.SetStackNode(&s.dhcp, nil, dhcpv4.DefaultServerPort) u.SetStackNode(&s.dhcp, nil, dhcpv4.DefaultServerPort)
err = s.udps.Register(&u) err = s.udps.Register(&u, nil)
if err != nil { if err != nil {
return err return err
} }
@@ -417,7 +417,7 @@ func (s *Stack) StartNTP(addr netip.Addr) error {
var u internet.StackUDPPort var u internet.StackUDPPort
addr4 := addr.As4() addr4 := addr.As4()
u.SetStackNode(&s.ntp, addr4[:], ntp.ServerPort) u.SetStackNode(&s.ntp, addr4[:], ntp.ServerPort)
err := s.udps.Register(&u) err := s.udps.Register(&u, nil)
return err return err
} }
+2 -2
View File
@@ -239,7 +239,7 @@ func (stack *Stack) OpenTCPListener(port uint16) (*internet.NodeTCPListener, err
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = stack.tcpports.Register(&listener) err = stack.tcpports.Register(&listener, nil) // Passive TCP requires no MAC setting.
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -261,7 +261,7 @@ func (stack *Stack) OpenPassiveTCP(port uint16, iss tcp.Value) (*tcp.Conn, error
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = stack.tcpports.Register(conn) err = stack.tcpports.Register(conn, nil) // Passive MAC with no listening.
if err != nil { if err != nil {
return nil, err return nil, err
} }
+11 -2
View File
@@ -174,7 +174,7 @@ func (h *handlers) demuxByPort(buf []byte, offset int, port uint16) (*node, erro
func (h *handlers) encapsulateAny(buf []byte, offsetIP, offsetThisFrame int) (_ *node, n int, err error) { func (h *handlers) encapsulateAny(buf []byte, offsetIP, offsetThisFrame int) (_ *node, n int, err error) {
for i := range h.nodes { for i := range h.nodes {
node := &h.nodes[i] node := &h.nodes[i]
if node.IsInvalid() { if node.IsInvalid() || (len(node.remoteAddr) > 0 && isAllZeros(node.remoteAddr)) {
continue continue
} }
n, err = node.encapsulate(buf, offsetIP, offsetThisFrame) n, err = node.encapsulate(buf, offsetIP, offsetThisFrame)
@@ -191,6 +191,15 @@ func (h *handlers) encapsulateAny(buf []byte, offsetIP, offsetThisFrame int) (_
return nil, 0, err // Return last written error. return nil, 0, err // Return last written error.
} }
func isAllZeros(b []byte) bool {
for i := range b {
if b[i] != 0 {
return false
}
}
return true
}
var ( var (
errZeroMaxNodesArg = errors.New("zero max nodes arg") errZeroMaxNodesArg = errors.New("zero max nodes arg")
errZeroPort = errors.New("port must be greater than zero") errZeroPort = errors.New("port must be greater than zero")
@@ -224,7 +233,7 @@ func nodeFromStackNode(s StackNode, port uint16, protocol uint64, remoteAddr []b
encapsulate: s.Encapsulate, encapsulate: s.Encapsulate,
proto: uint16(protocol), proto: uint16(protocol),
port: port, port: port,
remoteAddr: append([]byte{}, remoteAddr...), remoteAddr: remoteAddr, // SHARED MEMORY- used to signal.
} }
} }
+14 -3
View File
@@ -2,11 +2,13 @@ package internet
import ( import (
"encoding/binary" "encoding/binary"
"errors"
"io" "io"
"math" "math"
"strconv" "strconv"
"github.com/soypat/lneto" "github.com/soypat/lneto"
"github.com/soypat/lneto/ethernet"
) )
type StackPorts struct { type StackPorts struct {
@@ -50,7 +52,12 @@ func (ps *StackPorts) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame
if int(ps.dstPortOff)+offsetToFrame+2 > len(carrierData) { if int(ps.dstPortOff)+offsetToFrame+2 > len(carrierData) {
return 0, io.ErrShortBuffer return 0, io.ErrShortBuffer
} }
_, n, err = ps.handlers.encapsulateAny(carrierData, offsetToIP, offsetToFrame) var node *node
node, n, err = ps.handlers.encapsulateAny(carrierData, offsetToIP, offsetToFrame)
if n > 0 && len(node.remoteAddr) == 6 && offsetToIP >= 14 {
efrm, _ := ethernet.NewFrame(carrierData[offsetToIP-14:])
*efrm.DestinationHardwareAddr() = [6]byte(node.remoteAddr)
}
return n, err return n, err
} }
@@ -63,13 +70,17 @@ func (ps *StackPorts) Demux(b []byte, offset int) (err error) {
return err return err
} }
func (ps *StackPorts) Register(h StackNode) error { // Register registers a port StackNode on StackPorts.
// If dstMAC is set to non-nil, length six buffer then
func (ps *StackPorts) Register(h StackNode, dstMAC []byte) error {
port := h.LocalPort() port := h.LocalPort()
proto := h.Protocol() proto := h.Protocol()
if port <= 0 { if port <= 0 {
return errZeroPort return errZeroPort
} else if proto != uint64(ps.protocol) { } else if proto != uint64(ps.protocol) {
return errInvalidProto return errInvalidProto
} else if dstMAC != nil && len(dstMAC) != 6 {
return errors.New("invalid MAC")
} }
return ps.handlers.registerByPortProto(nodeFromStackNode(h, port, proto, nil)) return ps.handlers.registerByPortProto(nodeFromStackNode(h, port, proto, dstMAC))
} }
+17 -5
View File
@@ -234,11 +234,23 @@ func (s *StackAsync) Gateway6() [6]byte {
func (s *StackAsync) DialTCP(conn *tcp.Conn, localPort uint16, addrp netip.AddrPort) (err error) { func (s *StackAsync) DialTCP(conn *tcp.Conn, localPort uint16, addrp netip.AddrPort) (err error) {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
var mac []byte
if s.dhcpResults.Subnet.Contains(addrp.Addr()) {
mac = make([]byte, 6)
ip := addrp.Addr().As4()
// StartQuery starts an ARP query for addresses in this network.
// On finishing query MAC is set and thus the StackPort will allow encapsulating
// data on that connection.
err = s.arp.StartQuery(mac, ip[:])
if err != nil {
return err
}
}
err = conn.OpenActive(localPort, addrp, tcp.Value(s.Prand32())) err = conn.OpenActive(localPort, addrp, tcp.Value(s.Prand32()))
if err != nil { if err != nil {
return err return err
} }
err = s.tcps.Register(conn) err = s.tcps.Register(conn, mac) // MAC is set later on by ARP response arriving to our network.
if err != nil { if err != nil {
conn.Abort() conn.Abort()
return err return err
@@ -253,7 +265,7 @@ func (s *StackAsync) ListenTCP(conn *tcp.Conn, localPort uint16) (err error) {
if err != nil { if err != nil {
return err return err
} }
err = s.tcps.Register(conn) err = s.tcps.Register(conn, nil)
if err != nil { if err != nil {
conn.Abort() conn.Abort()
return err return err
@@ -294,7 +306,7 @@ func (s *StackAsync) StartLookupIP(host string) error {
} }
dns4 := s.dnssv.As4() dns4 := s.dnssv.As4()
s.dnsUDP.SetStackNode(&s.dns, dns4[:], dns.ServerPort) s.dnsUDP.SetStackNode(&s.dns, dns4[:], dns.ServerPort)
err = s.udps.Register(&s.dnsUDP) err = s.udps.Register(&s.dnsUDP, nil)
return err return err
} }
@@ -341,7 +353,7 @@ func (s *StackAsync) StartDHCPv4Request(request [4]byte) error {
} }
s.dhcpUDP.SetStackNode(&s.dhcp, nil, dhcpv4.DefaultServerPort) s.dhcpUDP.SetStackNode(&s.dhcp, nil, dhcpv4.DefaultServerPort)
err = s.udps.Register(&s.dhcpUDP) err = s.udps.Register(&s.dhcpUDP, nil)
if err != nil { if err != nil {
return err return err
} }
@@ -355,7 +367,7 @@ func (s *StackAsync) StartNTP(addr netip.Addr) error {
addr4 := addr.As4() addr4 := addr.As4()
s.ntpUDP.SetStackNode(&s.ntp, addr4[:], ntp.ServerPort) s.ntpUDP.SetStackNode(&s.ntp, addr4[:], ntp.ServerPort)
err := s.udps.Register(&s.ntpUDP) err := s.udps.Register(&s.ntpUDP, nil)
return err return err
} }