diff options
author | Arthur Sfez <asfez@google.com> | 2020-10-28 18:16:16 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-10-28 18:18:18 -0700 |
commit | 906f912b7c9484fd0028224a24055b887d4f84d2 (patch) | |
tree | a0dfa3cc965c7da0599f3a3185903c83f9be83b6 | |
parent | b4b42a5fce4cdd134d7d28d96ae7d4862791d911 (diff) |
Add the payload directly to the ICMPv4 type
This makes handling inbound fragmented packets easier, because a fragmented
packet might not have an actual ICMP header but only a payload. After this
change, the ICMPv4 is the last layer you can get because the payload is
embedded in it.
Note that this makes it consistent with the ICMPv6 implementation.
While I'm here, I've also added the Ident and Sequence fields on the ICMPv4
type. Defaults are still zero.
PiperOrigin-RevId: 339577094
-rw-r--r-- | test/packetimpact/testbench/layers.go | 40 | ||||
-rw-r--r-- | test/packetimpact/tests/tcp_network_unreachable_test.go | 4 |
2 files changed, 35 insertions, 9 deletions
diff --git a/test/packetimpact/testbench/layers.go b/test/packetimpact/testbench/layers.go index a35562ca8..af7a2ba4e 100644 --- a/test/packetimpact/testbench/layers.go +++ b/test/packetimpact/testbench/layers.go @@ -879,6 +879,9 @@ type ICMPv4 struct { Type *header.ICMPv4Type Code *header.ICMPv4Code Checksum *uint16 + Ident *uint16 + Sequence *uint16 + Payload []byte } func (l *ICMPv4) String() string { @@ -887,7 +890,7 @@ func (l *ICMPv4) String() string { // ToBytes implements Layer.ToBytes. func (l *ICMPv4) ToBytes() ([]byte, error) { - b := make([]byte, header.ICMPv4MinimumSize) + b := make([]byte, header.ICMPv4MinimumSize+len(l.Payload)) h := header.ICMPv4(b) if l.Type != nil { h.SetType(*l.Type) @@ -895,15 +898,33 @@ func (l *ICMPv4) ToBytes() ([]byte, error) { if l.Code != nil { h.SetCode(*l.Code) } + if copied := copy(h.Payload(), l.Payload); copied != len(l.Payload) { + panic(fmt.Sprintf("wrong number of bytes copied into h.Payload(): got = %d, want = %d", len(h.Payload()), len(l.Payload))) + } + if l.Ident != nil { + h.SetIdent(*l.Ident) + } + if l.Sequence != nil { + h.SetSequence(*l.Sequence) + } + + // The checksum must be handled last because the ICMPv4 header fields are + // included in the computation. if l.Checksum != nil { h.SetChecksum(*l.Checksum) - return h, nil - } - payload, err := payload(l) - if err != nil { - return nil, err + } else { + // Compute the checksum based on the ICMPv4.Payload and also the subsequent + // layers. + payload, err := payload(l) + if err != nil { + return nil, err + } + var vv buffer.VectorisedView + vv.AppendView(buffer.View(l.Payload)) + vv.Append(payload) + h.SetChecksum(header.ICMPv4Checksum(h, vv)) } - h.SetChecksum(header.ICMPv4Checksum(h, payload)) + return h, nil } @@ -915,8 +936,11 @@ func parseICMPv4(b []byte) (Layer, layerParser) { Type: ICMPv4Type(h.Type()), Code: ICMPv4Code(h.Code()), Checksum: Uint16(h.Checksum()), + Ident: Uint16(h.Ident()), + Sequence: Uint16(h.Sequence()), + Payload: h.Payload(), } - return &icmpv4, parsePayload + return &icmpv4, nil } func (l *ICMPv4) match(other Layer) bool { diff --git a/test/packetimpact/tests/tcp_network_unreachable_test.go b/test/packetimpact/tests/tcp_network_unreachable_test.go index 2f57dff19..8a1fe1279 100644 --- a/test/packetimpact/tests/tcp_network_unreachable_test.go +++ b/test/packetimpact/tests/tcp_network_unreachable_test.go @@ -74,7 +74,9 @@ func TestTCPSynSentUnreachable(t *testing.T) { } var icmpv4 testbench.ICMPv4 = testbench.ICMPv4{ Type: testbench.ICMPv4Type(header.ICMPv4DstUnreachable), - Code: testbench.ICMPv4Code(header.ICMPv4HostUnreachable)} + Code: testbench.ICMPv4Code(header.ICMPv4HostUnreachable), + } + layers = append(layers, &icmpv4, ip, tcp) rawConn.SendFrameStateless(t, layers) |