mirror of
https://github.com/soypat/lneto.git
synced 2026-08-09 09:23:40 +00:00
be949d960c
* tcp: mss honoring; accept syn with ECE/CWR flags; add RSTQueue type * tcp: move option logic to own file * remove prints in pcap * add MSS send threshold inspired by linux/freebsd/lwip thresh
64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
package tcp
|
|
|
|
import "github.com/soypat/lneto/internal"
|
|
|
|
// RSTQueue is a small fixed-size queue of pending stateless RST responses.
|
|
// It is not safe for concurrent use; callers must synchronize access.
|
|
type RSTQueue struct {
|
|
buf [4]rstEntry
|
|
len uint8
|
|
}
|
|
|
|
type rstEntry struct {
|
|
remoteAddr [4]byte
|
|
remotePort uint16
|
|
localPort uint16
|
|
seq Value
|
|
ack Value
|
|
flags Flags
|
|
}
|
|
|
|
// Queue enqueues a RST response. Silently drops if srcaddr is not IPv4 or queue is full.
|
|
func (q *RSTQueue) Queue(srcaddr []byte, remotePort, localPort uint16, seq, ack Value, flags Flags) {
|
|
if len(srcaddr) == 4 && q.len < uint8(len(q.buf)) {
|
|
entry := &q.buf[q.len]
|
|
copy(entry.remoteAddr[:], srcaddr)
|
|
entry.remotePort = remotePort
|
|
entry.localPort = localPort
|
|
entry.seq = seq
|
|
entry.ack = ack
|
|
entry.flags = flags
|
|
q.len++
|
|
}
|
|
}
|
|
|
|
// Pending returns the number of queued RST entries.
|
|
func (q *RSTQueue) Pending() int { return int(q.len) }
|
|
|
|
// Drain writes one pending RST to the carrier buffer and returns the TCP frame length written.
|
|
// Returns (0, nil) if the queue is empty or offsetToIP < 0.
|
|
func (q *RSTQueue) Drain(carrierData []byte, offsetToIP, offsetToFrame int) (int, error) {
|
|
if q.len == 0 || offsetToIP < 0 {
|
|
return 0, nil
|
|
}
|
|
q.len--
|
|
entry := &q.buf[q.len]
|
|
tfrm, err := NewFrame(carrierData[offsetToFrame:])
|
|
if err != nil {
|
|
return 0, nil
|
|
}
|
|
tfrm.SetSourcePort(entry.localPort)
|
|
tfrm.SetDestinationPort(entry.remotePort)
|
|
tfrm.SetSegment(Segment{
|
|
SEQ: entry.seq,
|
|
ACK: entry.ack,
|
|
Flags: entry.flags,
|
|
}, 5)
|
|
tfrm.SetUrgentPtr(0)
|
|
err = internal.SetIPAddrs(carrierData[offsetToIP:offsetToFrame], 0, nil, entry.remoteAddr[:])
|
|
if err != nil {
|
|
return 0, nil
|
|
}
|
|
return sizeHeaderTCP, nil
|
|
}
|