Checksum the header and refuse sequence numbers the sender never sent

This commit is contained in:
flamingcow
2026-08-04 20:41:16 -07:00
parent 703039587b
commit 1d54a1a1f6
9 changed files with 241 additions and 35 deletions
+42 -6
View File
@@ -13,6 +13,8 @@ const (
hdrMagic = 0x43424c54
minFrame = ethHdrLen + hdrLen
maxFrame = 9216
hdrCheckOff = 18
)
var crcTable = crc32.MakeTable(crc32.Castagnoli)
@@ -113,6 +115,26 @@ func (f *frameSpec) expectedCRC(patIdx, payLen int) (uint32, bool) {
return crc, ok
}
// A one's complement sum over the header, skipping the two bytes it is written
// into. The payload checksum covers the payload alone, so without this the
// sequence number is the one field on the wire that nothing checks, and a bit
// flipped in it arrives looking exactly like a legitimate frame from far in the
// future. Every single bit error changes the folded sum, which is the error a
// cable going marginal actually produces.
func headerCheck(h []byte) uint16 {
var sum uint32
for i := 0; i+1 < hdrLen; i += 2 {
if i == hdrCheckOff {
continue
}
sum += uint32(binary.BigEndian.Uint16(h[i:]))
}
for sum>>16 != 0 {
sum = sum&0xffff + sum>>16
}
return ^uint16(sum)
}
func putHeader(buf []byte, patIdx int, stream uint16, seq uint64, payLen int) {
h := buf[ethHdrLen:]
binary.BigEndian.PutUint32(h[0:4], hdrMagic)
@@ -121,7 +143,7 @@ func putHeader(buf []byte, patIdx int, stream uint16, seq uint64, payLen int) {
binary.BigEndian.PutUint16(h[6:8], stream)
binary.BigEndian.PutUint64(h[8:16], seq)
binary.BigEndian.PutUint16(h[16:18], uint16(payLen))
binary.BigEndian.PutUint16(h[18:20], 0)
binary.BigEndian.PutUint16(h[hdrCheckOff:], headerCheck(h))
}
type parsed struct {
@@ -131,21 +153,35 @@ type parsed struct {
payLen int
}
func parseHeader(buf []byte) (parsed, bool) {
// Why a frame was turned away. A header that is not ours and a header of ours
// that arrived damaged are different things to report: the first is somebody
// else on the wire, the second is the fault being tested for.
type hdrStatus int
const (
hdrOK hdrStatus = iota
hdrForeign
hdrDamaged
)
func parseHeader(buf []byte) (parsed, hdrStatus) {
var p parsed
if len(buf) < minFrame {
return p, false
return p, hdrForeign
}
h := buf[ethHdrLen:]
if binary.BigEndian.Uint32(h[0:4]) != hdrMagic {
return p, false
return p, hdrForeign
}
if binary.BigEndian.Uint16(h[hdrCheckOff:]) != headerCheck(h) {
return p, hdrDamaged
}
p.patIdx = int(h[5])
p.stream = binary.BigEndian.Uint16(h[6:8])
p.seq = binary.BigEndian.Uint64(h[8:16])
p.payLen = int(binary.BigEndian.Uint16(h[16:18]))
if minFrame+p.payLen > len(buf) {
return p, false
return p, hdrDamaged
}
return p, true
return p, hdrOK
}