mirror of
https://github.com/soypat/lneto.git
synced 2026-07-26 10:38:47 +00:00
46d4c06b9f
- http/httpraw: cap header slice growth to pre-allocated capacity, fix benchmark to reuse Header across iterations (0 allocs/op) - internal/ring: replace TODO panic comments with invariant explanations - tcp/conn: document truncated-frame offset check - tcp/handler: replace TODO with net.ErrClosed on RST-closed connection - internet/stack-udpport: filter incoming packets by remote IP address when configured via SetStackNode; skip filter for IPv4 multicast destinations (class D) so mDNS and similar protocols work correctly Generated with LLM assistance. Signed-off-by: Marvin Drees <marvin.drees@9elements.com>
101 lines
2.6 KiB
Go
101 lines
2.6 KiB
Go
package internet
|
|
|
|
import (
|
|
"log/slog"
|
|
"net"
|
|
|
|
"github.com/soypat/lneto"
|
|
"github.com/soypat/lneto/internal"
|
|
"github.com/soypat/lneto/udp"
|
|
)
|
|
|
|
type StackUDPPort struct {
|
|
h node
|
|
vld lneto.Validator
|
|
rmport uint16
|
|
raddr []byte
|
|
}
|
|
|
|
func (sudp *StackUDPPort) SetStackNode(node lneto.StackNode, raddr []byte, rmport uint16) {
|
|
sudp.h = nodeFromStackNode(node, node.LocalPort(), node.Protocol(), raddr)
|
|
sudp.rmport = rmport
|
|
sudp.raddr = append(sudp.raddr[:0], raddr...)
|
|
}
|
|
|
|
func (sudp *StackUDPPort) Protocol() uint64 { return uint64(lneto.IPProtoUDP) }
|
|
|
|
func (sudp *StackUDPPort) LocalPort() uint16 { return sudp.h.lport }
|
|
|
|
func (sudp *StackUDPPort) ConnectionID() *uint64 { return sudp.h.connID }
|
|
|
|
func (sudp *StackUDPPort) Demux(carrierData []byte, frameOffset int) error {
|
|
if sudp.h.IsInvalid() {
|
|
sudp.h.destroy()
|
|
return net.ErrClosed
|
|
}
|
|
ufrm, err := udp.NewFrame(carrierData[frameOffset:])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ufrm.ValidateSize(&sudp.vld)
|
|
if sudp.vld.HasError() {
|
|
return sudp.vld.ErrPop()
|
|
}
|
|
dst := ufrm.DestinationPort()
|
|
if dst != sudp.h.lport {
|
|
return lneto.ErrPacketDrop // Not meant for us.
|
|
}
|
|
if len(sudp.raddr) > 0 && !internal.IsMulticastIPAddr(sudp.raddr) {
|
|
srcIP, _, _, _, err := internal.GetIPAddr(carrierData[:frameOffset])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !internal.BytesEqual(srcIP, sudp.raddr) {
|
|
return lneto.ErrPacketDrop
|
|
}
|
|
}
|
|
|
|
src := ufrm.SourcePort()
|
|
if sudp.rmport != 0 && src != sudp.rmport {
|
|
return lneto.ErrPacketDrop // Not from our target remote port.
|
|
}
|
|
err = sudp.h.callbacks.Demux(carrierData, frameOffset+8)
|
|
if err != nil {
|
|
if checkNodeErr(&sudp.h, err) {
|
|
sudp.h.destroy()
|
|
}
|
|
internal.LogAttrs(nil, slog.LevelError, "stackudp:demux", slog.String("err", err.Error()))
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (sudp *StackUDPPort) Encapsulate(carrierData []byte, offsetToIP, offsetToFrame int) (int, error) {
|
|
if sudp.h.IsInvalid() {
|
|
sudp.h.destroy()
|
|
return 0, net.ErrClosed
|
|
}
|
|
ufrm, err := udp.NewFrame(carrierData[offsetToFrame:])
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
ufrm.SetSourcePort(sudp.h.lport)
|
|
ufrm.SetDestinationPort(sudp.rmport)
|
|
if len(sudp.raddr) > 0 && offsetToIP >= 0 {
|
|
err = internal.SetIPAddrs(carrierData[offsetToIP:], 0, nil, sudp.raddr)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
// Child payload starts 8 bytes after UDP header start.
|
|
n, err := sudp.h.callbacks.Encapsulate(carrierData, offsetToIP, offsetToFrame+8)
|
|
if n == 0 {
|
|
if err != nil {
|
|
internal.LogAttrs(nil, slog.LevelError, "stackudp:encapsulate", slog.String("err", err.Error()))
|
|
}
|
|
return 0, err
|
|
}
|
|
// UDP CRC and length left to IP layer.
|
|
length := 8 + n
|
|
return length, err
|
|
}
|