Return error when handshake fails.

performHandshake should return the last error in case
the handshake fails.

PiperOrigin-RevId: 443721651
This commit is contained in:
Bhasker Hariharan
2022-04-22 11:54:52 -07:00
committed by gVisor bot
parent 6d77aa52b8
commit 96c9cf74f5
3 changed files with 71 additions and 0 deletions
+6
View File
@@ -324,6 +324,12 @@ func (l *listenContext) performHandshake(s *segment, opts header.TCPSynOptions,
ep.Close()
ep.notifyAborted()
ep.drainClosingSegmentQueue()
err := ep.LastError()
if err == nil {
// If err was nil then return the best error we can to indicate
// a connection failure.
err = &tcpip.ErrConnectionAborted{}
}
return nil, err
}
+2
View File
@@ -77,7 +77,9 @@ go_test(
"//pkg/refs",
"//pkg/refsvfs2",
"//pkg/tcpip",
"//pkg/tcpip/checker",
"//pkg/tcpip/header",
"//pkg/tcpip/seqnum",
"//pkg/tcpip/transport/tcp",
"//pkg/tcpip/transport/tcp/testing/context",
],
@@ -22,7 +22,9 @@ import (
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/refsvfs2"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/checker"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/seqnum"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp/test/e2e"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp/testing/context"
@@ -106,6 +108,67 @@ func TestForwarderDoesNotRejectECNFlags(t *testing.T) {
}
}
func TestForwarderFailedConnect(t *testing.T) {
const mtu = 1200
c := context.New(t, mtu)
defer c.Cleanup()
s := c.Stack()
ch := make(chan tcpip.Error, 1)
f := tcp.NewForwarder(s, 65536, 10, func(r *tcp.ForwarderRequest) {
var err tcpip.Error
c.EP, err = r.CreateEndpoint(&c.WQ)
ch <- err
close(ch)
r.Complete(false)
})
s.SetTransportProtocolHandler(tcp.ProtocolNumber, f.HandlePacket)
// Initiate a connection that will be forwarded by the Forwarder.
// Send a SYN request.
iss := seqnum.Value(context.TestInitialSequenceNumber)
c.SendPacket(nil, &context.Headers{
SrcPort: context.TestPort,
DstPort: context.StackPort,
Flags: header.TCPFlagSyn,
SeqNum: iss,
RcvWnd: 30000,
})
// Receive the SYN-ACK reply. Make sure MSS and other expected options
// are present.
b := c.GetPacket()
tcp := header.TCP(header.IPv4(b).Payload())
c.IRS = seqnum.Value(tcp.SequenceNumber())
tcpCheckers := []checker.TransportChecker{
checker.SrcPort(context.StackPort),
checker.DstPort(context.TestPort),
checker.TCPFlags(header.TCPFlagAck | header.TCPFlagSyn),
checker.TCPAckNum(uint32(iss) + 1),
}
checker.IPv4(t, b, checker.TCP(tcpCheckers...))
// Now send an active RST to abort the handshake.
c.SendPacket(nil, &context.Headers{
SrcPort: context.TestPort,
DstPort: context.StackPort,
Flags: header.TCPFlagRst,
SeqNum: iss + 1,
RcvWnd: 0,
})
// Wait for connect to fail.
select {
case err := <-ch:
if err == nil {
t.Fatalf("endpoint creation should have failed")
}
case <-time.After(2 * time.Second):
t.Fatalf("Timed out waiting for connection to fail")
}
}
func TestMain(m *testing.M) {
refs.SetLeakMode(refs.LeaksPanic)
code := m.Run()