mirror of
https://github.com/soypat/lneto.git
synced 2026-08-29 10:59:03 +00:00
Checksum fixes (#24)
* Checksum 0x0000 is returned as 0xFFFF (mandatory for UDP, common for TCP) * Both checksum zero values (0x0000 and 0xFFFF) are accepted when receiving * Rename parameter in VerifySum16 to expectedSum16 --------- Co-authored-by: Pat Whittingslow <graded.sp@gmail.com>
This commit is contained in:
@@ -68,8 +68,7 @@ func (c *CRC791) AddUint8(value uint8) {
|
|||||||
c.needPad = !c.needPad
|
c.needPad = !c.needPad
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sum16 calculates the checksum with the data written to c thus far.
|
func (c *CRC791) sum16() uint16 {
|
||||||
func (c *CRC791) Sum16() uint16 {
|
|
||||||
sum := c.sum
|
sum := c.sum
|
||||||
if c.needPad {
|
if c.needPad {
|
||||||
sum += uint32(c.excedent) << 8
|
sum += uint32(c.excedent) << 8
|
||||||
@@ -80,5 +79,26 @@ func (c *CRC791) Sum16() uint16 {
|
|||||||
return uint16(^sum)
|
return uint16(^sum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sum16 calculates the checksum with the data written to c thus far.
|
||||||
|
func (c *CRC791) Sum16() uint16 {
|
||||||
|
sum16 := c.sum16()
|
||||||
|
if sum16 == 0 {
|
||||||
|
// The zero value is always transmitted as 0xFFFF, as required by UDP (RFC 768), and still valid for TCP and IP.
|
||||||
|
sum16 = 0xffff
|
||||||
|
}
|
||||||
|
return sum16
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifySum16 verifies that the given checksum matches the data written to c thus far.
|
||||||
|
func (c *CRC791) VerifySum16(expectedSum16 uint16) bool {
|
||||||
|
// as recommended by RFC 1624, this implementation supports both 0x0000 and 0xFFFF as zero value for the checksum
|
||||||
|
cc := *c
|
||||||
|
if cc.needPad {
|
||||||
|
cc.AddUint8(0)
|
||||||
|
}
|
||||||
|
cc.AddUint16(expectedSum16)
|
||||||
|
return cc.sum16() == 0
|
||||||
|
}
|
||||||
|
|
||||||
// Reset zeros out the CRC791, resetting it to the initial state.
|
// Reset zeros out the CRC791, resetting it to the initial state.
|
||||||
func (c *CRC791) Reset() { *c = CRC791{} }
|
func (c *CRC791) Reset() { *c = CRC791{} }
|
||||||
|
|||||||
+11
-9
@@ -90,11 +90,12 @@ func (sb *StackIP) Demux(carrierData []byte, offset int) error {
|
|||||||
sb.handlers.error("ip:Demux.validate")
|
sb.handlers.error("ip:Demux.validate")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gotCRC := ifrm.CRC()
|
|
||||||
wantCRC := ifrm.CalculateHeaderCRC()
|
// Incoming CRC Validation of common IP Protocols.
|
||||||
if gotCRC != wantCRC {
|
var crc lneto.CRC791
|
||||||
sb.handlers.error("StackIP:Demux:crc-mismatch", slog.Uint64("want", uint64(wantCRC)), slog.Uint64("got", uint64(gotCRC)))
|
ifrm.CRCWriteHeader(&crc)
|
||||||
return lneto.ErrBadCRC
|
if !crc.VerifySum16(ifrm.CRC()) {
|
||||||
|
sb.handlers.error("ip:demux.crc")
|
||||||
}
|
}
|
||||||
off := ifrm.HeaderLength()
|
off := ifrm.HeaderLength()
|
||||||
totalLen := ifrm.TotalLength()
|
totalLen := ifrm.TotalLength()
|
||||||
@@ -110,7 +111,7 @@ func (sb *StackIP) Demux(carrierData []byte, offset int) error {
|
|||||||
return lneto.ErrPacketDrop
|
return lneto.ErrPacketDrop
|
||||||
}
|
}
|
||||||
// Incoming CRC Validation of common IP Protocols.
|
// Incoming CRC Validation of common IP Protocols.
|
||||||
var crc lneto.CRC791
|
crc.Reset()
|
||||||
switch proto {
|
switch proto {
|
||||||
case lneto.IPProtoTCP:
|
case lneto.IPProtoTCP:
|
||||||
ifrm.CRCWriteTCPPseudo(&crc)
|
ifrm.CRCWriteTCPPseudo(&crc)
|
||||||
@@ -119,7 +120,7 @@ func (sb *StackIP) Demux(carrierData []byte, offset int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tfrm.CRCWrite(&crc)
|
tfrm.CRCWrite(&crc)
|
||||||
if crc.Sum16() != tfrm.CRC() {
|
if !crc.VerifySum16(tfrm.CRC()) {
|
||||||
sb.handlers.error("ip:demux.tcpcrc")
|
sb.handlers.error("ip:demux.tcpcrc")
|
||||||
return lneto.ErrBadCRC
|
return lneto.ErrBadCRC
|
||||||
}
|
}
|
||||||
@@ -130,7 +131,8 @@ func (sb *StackIP) Demux(carrierData []byte, offset int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ufrm.CRCWriteIPv4(&crc)
|
ufrm.CRCWriteIPv4(&crc)
|
||||||
if crc.Sum16() != ufrm.CRC() {
|
// checksums are optional in UDP: the field is set to zero in this case
|
||||||
|
if gotCrc := ufrm.CRC(); gotCrc != 0 && !crc.VerifySum16(gotCrc) {
|
||||||
sb.handlers.error("ip:demux.udpcrc")
|
sb.handlers.error("ip:demux.udpcrc")
|
||||||
return lneto.ErrBadCRC
|
return lneto.ErrBadCRC
|
||||||
}
|
}
|
||||||
@@ -210,7 +212,7 @@ func (sb *StackIP) recvicmp(carrierData []byte, offset int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cfrm.CRCWrite(&crc)
|
cfrm.CRCWrite(&crc)
|
||||||
if crc.Sum16() != cfrm.CRC() {
|
if !crc.VerifySum16(cfrm.CRC()) {
|
||||||
return errors.New("ICMP CRC mismatch")
|
return errors.New("ICMP CRC mismatch")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+5
-1
@@ -131,9 +131,13 @@ func (ifrm Frame) SetCRC(cs uint16) {
|
|||||||
// CalculateHeaderCRC calculates the CRC for this IPv4 frame.
|
// CalculateHeaderCRC calculates the CRC for this IPv4 frame.
|
||||||
func (ifrm Frame) CalculateHeaderCRC() uint16 {
|
func (ifrm Frame) CalculateHeaderCRC() uint16 {
|
||||||
var crc lneto.CRC791
|
var crc lneto.CRC791
|
||||||
|
ifrm.CRCWriteHeader(&crc)
|
||||||
|
return crc.Sum16()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ifrm Frame) CRCWriteHeader(crc *lneto.CRC791) {
|
||||||
crc.Write(ifrm.buf[0:10])
|
crc.Write(ifrm.buf[0:10])
|
||||||
crc.Write(ifrm.buf[12:20])
|
crc.Write(ifrm.buf[12:20])
|
||||||
return crc.Sum16()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ifrm Frame) CRCWriteTCPPseudo(crc *lneto.CRC791) {
|
func (ifrm Frame) CRCWriteTCPPseudo(crc *lneto.CRC791) {
|
||||||
|
|||||||
Reference in New Issue
Block a user