mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
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:
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user