diff options
author | Brian Geffon <bgeffon@google.com> | 2018-08-07 07:56:08 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-08-07 07:57:20 -0700 |
commit | d839dc13c689f853fd87c495c26208048a540919 (patch) | |
tree | 4776c32bdcef43e3a02d6d1a75d6d4457a6d697e /pkg/tcpip/transport/udp | |
parent | 9752174a7f211328c0ff59f8ed6c51325a6fc23d (diff) |
Netstack doesn't handle sending after SHUT_WR correctly.
PiperOrigin-RevId: 207715032
Change-Id: I7b6690074c5be283145192895d706a92e921b22c
Diffstat (limited to 'pkg/tcpip/transport/udp')
-rw-r--r-- | pkg/tcpip/transport/udp/endpoint.go | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/pkg/tcpip/transport/udp/endpoint.go b/pkg/tcpip/transport/udp/endpoint.go index 03fb76f92..b2d7f9779 100644 --- a/pkg/tcpip/transport/udp/endpoint.go +++ b/pkg/tcpip/transport/udp/endpoint.go @@ -80,6 +80,9 @@ type endpoint struct { dstPort uint16 v6only bool + // shutdownFlags represent the current shutdown state of the endpoint. + shutdownFlags tcpip.ShutdownFlags + // effectiveNetProtos contains the network protocols actually in use. In // most cases it will only contain "netProto", but in cases like IPv6 // endpoints with v6only set to false, this could include multiple @@ -124,6 +127,7 @@ func NewConnectedEndpoint(stack *stack.Stack, r *stack.Route, id stack.Transport // associated with it. func (e *endpoint) Close() { e.mu.Lock() + e.shutdownFlags = tcpip.ShutdownRead | tcpip.ShutdownWrite switch e.state { case stateBound, stateConnected: @@ -236,6 +240,11 @@ func (e *endpoint) Write(p tcpip.Payload, opts tcpip.WriteOptions) (uintptr, *tc e.mu.RLock() defer e.mu.RUnlock() + // If we've shutdown with SHUT_WR we are in an invalid state for sending. + if e.shutdownFlags&tcpip.ShutdownWrite != 0 { + return 0, tcpip.ErrClosedForSend + } + // Prepare for write. for { retry, err := e.prepareForWrite(to) @@ -562,13 +571,15 @@ func (*endpoint) ConnectEndpoint(tcpip.Endpoint) *tcpip.Error { // Shutdown closes the read and/or write end of the endpoint connection // to its peer. func (e *endpoint) Shutdown(flags tcpip.ShutdownFlags) *tcpip.Error { - e.mu.RLock() - defer e.mu.RUnlock() + e.mu.Lock() + defer e.mu.Unlock() if e.state != stateConnected { return tcpip.ErrNotConnected } + e.shutdownFlags |= flags + if flags&tcpip.ShutdownRead != 0 { e.rcvMu.Lock() wasClosed := e.rcvClosed |