summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/transport/udp
diff options
context:
space:
mode:
authorBrian Geffon <bgeffon@google.com>2018-08-07 07:56:08 -0700
committerShentubot <shentubot@google.com>2018-08-07 07:57:20 -0700
commitd839dc13c689f853fd87c495c26208048a540919 (patch)
tree4776c32bdcef43e3a02d6d1a75d6d4457a6d697e /pkg/tcpip/transport/udp
parent9752174a7f211328c0ff59f8ed6c51325a6fc23d (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.go15
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