diff options
author | Julian Elischer <jrelis@google.com> | 2020-10-05 20:41:50 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-10-05 20:43:55 -0700 |
commit | 798cc6b04dc1206538b2cedb1af427e0d5468b46 (patch) | |
tree | c45c33e2bd35ccf9001a4b127af58cabf11c1228 /pkg/tcpip/checker | |
parent | a1df7f2ed1be5cb170218c3e127a9b5f51a314fd (diff) |
Fix IPv4 ICMP echo handler to copy options
The IPv4 RFCs are specific (though obtuse) that an echo response
packet needs to contain all the options from the echo request,
much as if it been routed back to the sender, though apparently
with a new TTL. They suggest copying the incoming packet header
to achieve this so that is what this patch does.
PiperOrigin-RevId: 335559176
Diffstat (limited to 'pkg/tcpip/checker')
-rw-r--r-- | pkg/tcpip/checker/checker.go | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/pkg/tcpip/checker/checker.go b/pkg/tcpip/checker/checker.go index 71b2f1bda..d4d785cca 100644 --- a/pkg/tcpip/checker/checker.go +++ b/pkg/tcpip/checker/checker.go @@ -178,12 +178,32 @@ func PayloadLen(payloadLength int) NetworkChecker { } } +// IPv4Options returns a checker that checks the options in an IPv4 packet. +func IPv4Options(want []byte) NetworkChecker { + return func(t *testing.T, h []header.Network) { + t.Helper() + + ip, ok := h[0].(header.IPv4) + if !ok { + t.Fatalf("unexpected network header passed to checker, got = %T, want = header.IPv4", h[0]) + } + options := ip.Options() + // cmp.Diff does not consider nil slices equal to empty slices, but we do. + if len(want) == 0 && len(options) == 0 { + return + } + if diff := cmp.Diff(want, options); diff != "" { + t.Errorf("options mismatch (-want +got):\n%s", diff) + } + } +} + // FragmentOffset creates a checker that checks the FragmentOffset field. func FragmentOffset(offset uint16) NetworkChecker { return func(t *testing.T, h []header.Network) { t.Helper() - // We only do this of IPv4 for now. + // We only do this for IPv4 for now. switch ip := h[0].(type) { case header.IPv4: if v := ip.FragmentOffset(); v != offset { @@ -198,7 +218,7 @@ func FragmentFlags(flags uint8) NetworkChecker { return func(t *testing.T, h []header.Network) { t.Helper() - // We only do this of IPv4 for now. + // We only do this for IPv4 for now. switch ip := h[0].(type) { case header.IPv4: if v := ip.Flags(); v != flags { @@ -664,8 +684,8 @@ func TCPTimestampChecker(wantTS bool, wantTSVal uint32, wantTSEcr uint32) Transp } } -// TCPNoSACKBlockChecker creates a checker that verifies that the segment does not -// contain any SACK blocks in the TCP options. +// TCPNoSACKBlockChecker creates a checker that verifies that the segment does +// not contain any SACK blocks in the TCP options. func TCPNoSACKBlockChecker() TransportChecker { return TCPSACKBlockChecker(nil) } @@ -739,8 +759,8 @@ func Payload(want []byte) TransportChecker { } } -// ICMPv4 creates a checker that checks that the transport protocol is ICMPv4 and -// potentially additional ICMPv4 header fields. +// ICMPv4 creates a checker that checks that the transport protocol is ICMPv4 +// and potentially additional ICMPv4 header fields. func ICMPv4(checkers ...TransportChecker) NetworkChecker { return func(t *testing.T, h []header.Network) { t.Helper() @@ -851,8 +871,8 @@ func ICMPv4Payload(want []byte) TransportChecker { t.Fatalf("unexpected transport header passed to checker, got = %T, want = header.ICMPv4", h) } payload := icmpv4.Payload() - if diff := cmp.Diff(payload, want); diff != "" { - t.Errorf("got ICMP payload mismatch (-want +got):\n%s", diff) + if diff := cmp.Diff(want, payload); diff != "" { + t.Errorf("ICMP payload mismatch (-want +got):\n%s", diff) } } } |