mirror of
https://github.com/soypat/lneto.git
synced 2026-08-20 06:29:03 +00:00
Tcp rst handling (#40)
* claude suggests a way forward * add timing to capture printer * add pcap.Flags * fix ICMP CRC calculation and add test * bugfix: still send data on half-close state(close-wait) * fix pcap test
This commit is contained in:
+21
-14
@@ -603,10 +603,21 @@ type FrameField struct {
|
||||
FrameBitOffset int
|
||||
BitLength int
|
||||
SubFields []FrameField
|
||||
RightAligned bool
|
||||
Legacy bool
|
||||
|
||||
Flags Flags
|
||||
}
|
||||
|
||||
// Flags stores frame field interpretation bits.
|
||||
type Flags uint32
|
||||
|
||||
const (
|
||||
FlagRightAligned Flags = 1 << iota
|
||||
FlagLegacy
|
||||
)
|
||||
|
||||
func (ff Flags) IsLegacy() bool { return ff&FlagLegacy != 0 }
|
||||
func (ff Flags) IsRightAligned() bool { return ff&FlagRightAligned != 0 }
|
||||
|
||||
type Frame struct {
|
||||
Protocol any
|
||||
Fields []FrameField
|
||||
@@ -653,7 +664,7 @@ func (frm Frame) FieldAsUint(fieldIdx int, pkt []byte) (uint64, error) {
|
||||
return badUint64, errors.New("invalid field index")
|
||||
}
|
||||
field := frm.Fields[fieldIdx]
|
||||
return fieldAsUint(pkt, frm.PacketBitOffset+field.FrameBitOffset, field.BitLength, field.RightAligned)
|
||||
return fieldAsUint(pkt, frm.PacketBitOffset+field.FrameBitOffset, field.BitLength, field.Flags.IsRightAligned())
|
||||
}
|
||||
|
||||
// AppendField appends the binary on-the-wire representation of the field and aligns the field so it starts at the first bit of appended data.
|
||||
@@ -662,7 +673,7 @@ func (frm Frame) AppendField(dst []byte, fieldIdx int, pkt []byte) ([]byte, erro
|
||||
return dst, errors.New("invalid field index")
|
||||
}
|
||||
field := frm.Fields[fieldIdx]
|
||||
return appendField(dst, pkt, frm.PacketBitOffset+field.FrameBitOffset, field.BitLength, field.RightAligned)
|
||||
return appendField(dst, pkt, frm.PacketBitOffset+field.FrameBitOffset, field.BitLength, field.Flags.IsRightAligned())
|
||||
}
|
||||
|
||||
func fieldAsUint(pkt []byte, fieldBitStart, bitlen int, rightAligned bool) (uint64, error) {
|
||||
@@ -860,14 +871,14 @@ var baseIPv6Fields = [...]FrameField{
|
||||
Class: FieldClassFlags,
|
||||
FrameBitOffset: 4,
|
||||
BitLength: 1 * octet,
|
||||
RightAligned: true,
|
||||
Flags: FlagRightAligned,
|
||||
},
|
||||
{
|
||||
Name: "Flow Label",
|
||||
Class: FieldClassID,
|
||||
FrameBitOffset: 12,
|
||||
BitLength: 20,
|
||||
RightAligned: true,
|
||||
Flags: FlagRightAligned,
|
||||
},
|
||||
{
|
||||
Name: "Total Length",
|
||||
@@ -928,11 +939,6 @@ var baseIPv4Fields = [...]FrameField{
|
||||
FrameBitOffset: 4 * octet,
|
||||
BitLength: 2 * octet,
|
||||
},
|
||||
{
|
||||
Class: FieldClassID,
|
||||
FrameBitOffset: 4 * octet,
|
||||
BitLength: 2 * octet,
|
||||
},
|
||||
{
|
||||
Class: FieldClassFlags,
|
||||
FrameBitOffset: 6 * octet,
|
||||
@@ -1000,7 +1006,7 @@ var baseTCPFields = [...]FrameField{
|
||||
Class: FieldClassFlags,
|
||||
FrameBitOffset: 12*octet + 4,
|
||||
BitLength: 12,
|
||||
RightAligned: true,
|
||||
Flags: FlagRightAligned,
|
||||
},
|
||||
{
|
||||
Name: "Window",
|
||||
@@ -1018,6 +1024,7 @@ var baseTCPFields = [...]FrameField{
|
||||
Class: 0,
|
||||
FrameBitOffset: 18 * octet,
|
||||
BitLength: 2 * octet,
|
||||
Flags: FlagLegacy,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1199,14 +1206,14 @@ var baseDHCPv4Fields = [...]FrameField{
|
||||
Class: FieldClassBinaryText,
|
||||
FrameBitOffset: (28 + 6) * octet, // Part of Client Hardware Address(16 bytes) but unused.
|
||||
BitLength: 10 * octet,
|
||||
Legacy: true,
|
||||
Flags: FlagLegacy,
|
||||
},
|
||||
{
|
||||
Name: "BOOTP",
|
||||
Class: FieldClassBinaryText,
|
||||
FrameBitOffset: (28 + 16) * octet,
|
||||
BitLength: (dhcpv4.OptionsOffset - (28 + 16)) * octet,
|
||||
Legacy: true,
|
||||
Flags: FlagLegacy,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -474,15 +474,15 @@ func ExampleFormatter_dhcp() {
|
||||
fmt.Println(string(out))
|
||||
// Output:
|
||||
// Ethernet len=14; destination=ff:ff:ff:ff:ff:ff; source=de:ad:be:ef:ca:fe; protocol=0x0800
|
||||
// IPv4 len=20; version=0x04; (Header Length)=5; (Type of Service)=0x00; (Total Length)=312; identification=0x6043; identification=0x6043; flags=0x4000; (Time to live)=0x40; protocol=0x11; checksum=0xd972; source=0.0.0.0; destination=255.255.255.255
|
||||
// IPv4 len=20; version=0x04; (Header Length)=5; (Type of Service)=0x00; (Total Length)=312; identification=0x6043; flags=0x4000; (Time to live)=0x40; protocol=0x11; checksum=0xd972; source=0.0.0.0; destination=255.255.255.255
|
||||
// UDP [RFC768] len=8; (Source port)=68; (Destination port)=67; size=292; checksum=0x0000
|
||||
// DHCPv4 len=240; op=1; (Hardware Address Type)=0x01; (Hardware Address Length)=6; Hops=0x00; (Transaction ID)=0xdeadbeef; (Start Time)=0x0001; Flags=0x0000; (Client Address)=0.0.0.0; (Offered Address)=0.0.0.0; (Server Next Address)=255.255.255.255; (Relay Agent Address)=0.0.0.0; (Client Hardware Address)=de:ad:be:ef:ca:fe; options
|
||||
// (DHCP message type.)=1
|
||||
// (Parameter request list)=0x0102031a1c060f2a
|
||||
// (DHCP maximum message size)=558
|
||||
// (Requested IP address)=192.168.1.100
|
||||
// (Client identifier)="lneto-test"
|
||||
// (Hostname string)="myhost"
|
||||
// (DHCP message type.)=1
|
||||
// (Parameter request list)=0x0102031a1c060f2a
|
||||
// (DHCP maximum message size)=558
|
||||
// (Requested IP address)=192.168.1.100
|
||||
// (Client identifier)="lneto-test"
|
||||
// (Hostname string)="myhost"
|
||||
}
|
||||
func writeOpt(dst []byte, opt dhcpv4.OptNum, data ...byte) int {
|
||||
dst[0] = byte(opt)
|
||||
|
||||
@@ -68,7 +68,7 @@ func (f *Formatter) FormatFrame(dst []byte, frm Frame, pkt []byte) (_ []byte, er
|
||||
if field.Class == FieldClassFlags && frm.Protocol == lneto.IPProtoTCP {
|
||||
// TCP flags pretty print special case.
|
||||
dst = append(dst, "flags="...)
|
||||
v, err := fieldAsUint(pkt, frm.PacketBitOffset+field.FrameBitOffset, field.BitLength, field.RightAligned)
|
||||
v, err := fieldAsUint(pkt, frm.PacketBitOffset+field.FrameBitOffset, field.BitLength, field.Flags.IsRightAligned())
|
||||
if err != nil {
|
||||
return dst, err
|
||||
}
|
||||
@@ -95,7 +95,7 @@ func (f *Formatter) FormatFrame(dst []byte, frm Frame, pkt []byte) (_ []byte, er
|
||||
|
||||
func (f *Formatter) filterField(field FrameField) bool {
|
||||
return f.FilterClasses != nil && !slices.Contains(f.FilterClasses, field.Class) ||
|
||||
(field.Legacy && !f.DisableLegacyFilter)
|
||||
(field.Flags.IsLegacy() && !f.DisableLegacyFilter)
|
||||
}
|
||||
|
||||
func (f *Formatter) FormatField(dst []byte, pktStartOff int, field FrameField, pkt []byte) (_ []byte, err error) {
|
||||
@@ -133,7 +133,7 @@ func (f *Formatter) formatField(dst []byte, pktStartOff int, field FrameField, p
|
||||
dst = append(dst, '=')
|
||||
f.mubuf.Lock()
|
||||
defer f.mubuf.Unlock()
|
||||
f.buf, err = appendField(f.buf[:0], pkt, field.FrameBitOffset+pktStartOff, field.BitLength, field.RightAligned)
|
||||
f.buf, err = appendField(f.buf[:0], pkt, field.FrameBitOffset+pktStartOff, field.BitLength, field.Flags.IsRightAligned())
|
||||
if err != nil {
|
||||
return dst, err
|
||||
}
|
||||
@@ -158,7 +158,7 @@ func (f *Formatter) formatField(dst []byte, pktStartOff int, field FrameField, p
|
||||
case FieldClassDst, FieldClassSrc, FieldClassSize, FieldClassAddress, FieldClassOperation:
|
||||
// IP, MAC addresses and ports.
|
||||
if field.BitLength <= 16 {
|
||||
v, err := fieldAsUint(pkt, fieldBitStart, field.BitLength, field.RightAligned)
|
||||
v, err := fieldAsUint(pkt, fieldBitStart, field.BitLength, field.Flags.IsRightAligned())
|
||||
if err != nil {
|
||||
return dst, err
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ func (sb *StackIP) Demux(carrierData []byte, offset int) error {
|
||||
totalLen := ifrm.TotalLength()
|
||||
proto := ifrm.Protocol()
|
||||
if proto == lneto.IPProtoICMP {
|
||||
return sb.recvicmp(ifrm.RawData(), ifrm.HeaderLength())
|
||||
return sb.recvicmp(ifrm.Payload())
|
||||
}
|
||||
node := sb.handlers.nodeByProto(uint16(proto))
|
||||
// nodeIdx := getNodeByProto(sb.handlers, uint16(proto))
|
||||
@@ -205,10 +205,9 @@ func (sb *StackIP) Register(h StackNode) error {
|
||||
return sb.handlers.registerByPortProto(nodeFromStackNode(h, h.LocalPort(), proto, nil))
|
||||
}
|
||||
|
||||
func (sb *StackIP) recvicmp(carrierData []byte, offset int) error {
|
||||
frameData := carrierData[offset:]
|
||||
func (sb *StackIP) recvicmp(icmpData []byte) error {
|
||||
var crc lneto.CRC791
|
||||
if crc.PayloadSum16(frameData) != 0 {
|
||||
if crc.PayloadSum16(icmpData) != 0 {
|
||||
return errors.New("ICMP CRC mismatch")
|
||||
}
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user