From 5e631a1b3dd313c866ec7cc514fe567acef9af94 Mon Sep 17 00:00:00 2001 From: Patricio Whittingslow Date: Fri, 19 Dec 2025 01:04:18 -0300 Subject: [PATCH] StackPorts: set MAC destination when node has MAC --- examples/bridge/main.go | 6 +++--- examples/stack/main.go | 4 ++-- internet/definitions.go | 13 +++++++++++-- internet/stack-ports.go | 17 ++++++++++++++--- x/xnet/stack-async.go | 22 +++++++++++++++++----- 5 files changed, 47 insertions(+), 15 deletions(-) diff --git a/examples/bridge/main.go b/examples/bridge/main.go index 8a423d1..b8ed5d2 100644 --- a/examples/bridge/main.go +++ b/examples/bridge/main.go @@ -359,7 +359,7 @@ func (s *Stack) StartLookupIP(host string) error { var u internet.StackUDPPort dns4 := dnsSrvs.As4() u.SetStackNode(&s.dns, dns4[:], dns.ServerPort) - err = s.udps.Register(&u) + err = s.udps.Register(&u, nil) if err != nil { return err } @@ -405,7 +405,7 @@ func (s *Stack) BeginDHCPRequest(request [4]byte) error { } var u internet.StackUDPPort u.SetStackNode(&s.dhcp, nil, dhcpv4.DefaultServerPort) - err = s.udps.Register(&u) + err = s.udps.Register(&u, nil) if err != nil { return err } @@ -417,7 +417,7 @@ func (s *Stack) StartNTP(addr netip.Addr) error { var u internet.StackUDPPort addr4 := addr.As4() u.SetStackNode(&s.ntp, addr4[:], ntp.ServerPort) - err := s.udps.Register(&u) + err := s.udps.Register(&u, nil) return err } diff --git a/examples/stack/main.go b/examples/stack/main.go index f81c4c2..b248202 100644 --- a/examples/stack/main.go +++ b/examples/stack/main.go @@ -239,7 +239,7 @@ func (stack *Stack) OpenTCPListener(port uint16) (*internet.NodeTCPListener, err if err != nil { return nil, err } - err = stack.tcpports.Register(&listener) + err = stack.tcpports.Register(&listener, nil) // Passive TCP requires no MAC setting. if err != nil { return nil, err } @@ -261,7 +261,7 @@ func (stack *Stack) OpenPassiveTCP(port uint16, iss tcp.Value) (*tcp.Conn, error if err != nil { return nil, err } - err = stack.tcpports.Register(conn) + err = stack.tcpports.Register(conn, nil) // Passive MAC with no listening. if err != nil { return nil, err } diff --git a/internet/definitions.go b/internet/definitions.go index 5b47ee0..47e0ee1 100644 --- a/internet/definitions.go +++ b/internet/definitions.go @@ -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) { for i := range h.nodes { node := &h.nodes[i] - if node.IsInvalid() { + if node.IsInvalid() || (len(node.remoteAddr) > 0 && isAllZeros(node.remoteAddr)) { continue } 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. } +func isAllZeros(b []byte) bool { + for i := range b { + if b[i] != 0 { + return false + } + } + return true +} + var ( errZeroMaxNodesArg = errors.New("zero max nodes arg") 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, proto: uint16(protocol), port: port, - remoteAddr: append([]byte{}, remoteAddr...), + remoteAddr: remoteAddr, // SHARED MEMORY- used to signal. } } diff --git a/internet/stack-ports.go b/internet/stack-ports.go index dd5e304..d98faa6 100644 --- a/internet/stack-ports.go +++ b/internet/stack-ports.go @@ -2,11 +2,13 @@ package internet import ( "encoding/binary" + "errors" "io" "math" "strconv" "github.com/soypat/lneto" + "github.com/soypat/lneto/ethernet" ) type StackPorts struct { @@ -50,7 +52,12 @@ func (ps *StackPorts) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame if int(ps.dstPortOff)+offsetToFrame+2 > len(carrierData) { 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 } @@ -63,13 +70,17 @@ func (ps *StackPorts) Demux(b []byte, offset int) (err error) { 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() proto := h.Protocol() if port <= 0 { return errZeroPort } else if proto != uint64(ps.protocol) { 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)) } diff --git a/x/xnet/stack-async.go b/x/xnet/stack-async.go index 7946153..13e604e 100644 --- a/x/xnet/stack-async.go +++ b/x/xnet/stack-async.go @@ -234,11 +234,23 @@ func (s *StackAsync) Gateway6() [6]byte { func (s *StackAsync) DialTCP(conn *tcp.Conn, localPort uint16, addrp netip.AddrPort) (err error) { s.mu.Lock() 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())) if err != nil { 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 { conn.Abort() return err @@ -253,7 +265,7 @@ func (s *StackAsync) ListenTCP(conn *tcp.Conn, localPort uint16) (err error) { if err != nil { return err } - err = s.tcps.Register(conn) + err = s.tcps.Register(conn, nil) if err != nil { conn.Abort() return err @@ -294,7 +306,7 @@ func (s *StackAsync) StartLookupIP(host string) error { } dns4 := s.dnssv.As4() s.dnsUDP.SetStackNode(&s.dns, dns4[:], dns.ServerPort) - err = s.udps.Register(&s.dnsUDP) + err = s.udps.Register(&s.dnsUDP, nil) return err } @@ -341,7 +353,7 @@ func (s *StackAsync) StartDHCPv4Request(request [4]byte) error { } s.dhcpUDP.SetStackNode(&s.dhcp, nil, dhcpv4.DefaultServerPort) - err = s.udps.Register(&s.dhcpUDP) + err = s.udps.Register(&s.dhcpUDP, nil) if err != nil { return err } @@ -355,7 +367,7 @@ func (s *StackAsync) StartNTP(addr netip.Addr) error { addr4 := addr.As4() s.ntpUDP.SetStackNode(&s.ntp, addr4[:], ntp.ServerPort) - err := s.udps.Register(&s.ntpUDP) + err := s.udps.Register(&s.ntpUDP, nil) return err }