From 9d77e4f49dd02404009d762d165b61377a0a6434 Mon Sep 17 00:00:00 2001 From: "jiasheng.yu" Date: Mon, 13 Jan 2025 15:26:59 +0800 Subject: [PATCH] fix: Fix the ARP packet parsing code to adapt to the scenario where the switch adds extra padding bytes to ARP packets to meet the 64-byte minimum frame size. Signed-off-by: jiasheng.yu --- protocol/arp.go | 10 ++++++++++ protocol/arp_test.go | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 protocol/arp_test.go diff --git a/protocol/arp.go b/protocol/arp.go index 59f1d61..a4e1374 100755 --- a/protocol/arp.go +++ b/protocol/arp.go @@ -21,6 +21,9 @@ type ARP struct { IPSrc net.IP HWDst net.HardwareAddr IPDst net.IP + // The actual test shows that ARP reply packets sent by the H3C switch include an additional 14 bytes. + // This is done by the switch to meet the minimum frame length requirement of 64 bytes. + Padding []byte } func NewARP(opt int) (*ARP, error) { @@ -43,6 +46,8 @@ func NewARP(opt int) (*ARP, error) { func (a *ARP) Len() (n uint16) { n = 8 n += uint16(a.HWLength*2 + a.ProtoLength*2) + // Including the padding bytes, an inaccurate length can cause a panic in PacketIn2PropPacket.UnmarshalBinary. + n += uint16(len(a.Padding)) return } @@ -91,5 +96,10 @@ func (a *ARP) UnmarshalBinary(data []byte) error { n += int(a.HWLength) a.IPDst = make([]byte, a.ProtoLength) copy(a.IPDst, data[n:n+int(a.ProtoLength)]) + n += int(a.ProtoLength) + if len(data[n:]) > 0 { + a.Padding = make([]byte, len(data[n:])) + copy(a.Padding, data[n:]) + } return nil } diff --git a/protocol/arp_test.go b/protocol/arp_test.go new file mode 100644 index 0000000..924fb20 --- /dev/null +++ b/protocol/arp_test.go @@ -0,0 +1,18 @@ +package protocol + +import ( + "encoding/hex" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_ARPUnmarshalBinary(t *testing.T) { + data, err := hex.DecodeString("00010800060400027057bf301a03c0a8ac01525400ec4b98c0a8accc0000000000000000000000000000") + assert.Nil(t, err) + arp := new(ARP) + err = arp.UnmarshalBinary(data) + assert.Nil(t, err) + assert.Equal(t, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, arp.Padding) + assert.Equal(t, 42, arp.Len()) +}