Checksum the header and refuse sequence numbers the sender never sent
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user