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
This commit is contained in:
Arthur Sfez
2020-10-28 18:18:18 -07:00
committed by gVisor bot
parent b4b42a5fce
commit 906f912b7c
2 changed files with 35 additions and 9 deletions
+32 -8
View File
@@ -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
} 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))
}
payload, err := payload(l)
if err != nil {
return nil, err
}
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 {
@@ -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)