diff options
-rw-r--r-- | pkg/sentry/socket/netstack/netstack.go | 23 | ||||
-rw-r--r-- | pkg/sentry/socket/unix/transport/connectioned.go | 27 | ||||
-rw-r--r-- | pkg/sentry/socket/unix/transport/connectionless.go | 1 | ||||
-rw-r--r-- | pkg/sentry/socket/unix/transport/transport_state_autogen.go | 23 | ||||
-rw-r--r-- | pkg/sentry/socket/unix/transport/unix.go | 8 | ||||
-rw-r--r-- | pkg/tcpip/socketops.go | 61 | ||||
-rw-r--r-- | pkg/tcpip/tcpip.go | 8 | ||||
-rw-r--r-- | pkg/tcpip/tcpip_state_autogen.go | 21 | ||||
-rw-r--r-- | pkg/tcpip/transport/icmp/endpoint.go | 7 | ||||
-rw-r--r-- | pkg/tcpip/transport/icmp/icmp_state_autogen.go | 59 | ||||
-rw-r--r-- | pkg/tcpip/transport/packet/endpoint.go | 3 | ||||
-rw-r--r-- | pkg/tcpip/transport/packet/packet_state_autogen.go | 63 | ||||
-rw-r--r-- | pkg/tcpip/transport/raw/endpoint.go | 3 | ||||
-rw-r--r-- | pkg/tcpip/transport/raw/raw_state_autogen.go | 63 | ||||
-rw-r--r-- | pkg/tcpip/transport/tcp/endpoint.go | 40 | ||||
-rw-r--r-- | pkg/tcpip/transport/tcp/tcp_state_autogen.go | 259 | ||||
-rw-r--r-- | pkg/tcpip/transport/udp/endpoint.go | 40 | ||||
-rw-r--r-- | pkg/tcpip/transport/udp/udp_state_autogen.go | 131 |
18 files changed, 452 insertions, 388 deletions
diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go index d48b92c66..bf6d8c5dc 100644 --- a/pkg/sentry/socket/netstack/netstack.go +++ b/pkg/sentry/socket/netstack/netstack.go @@ -1112,25 +1112,16 @@ func getSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, fam return nil, syserr.ErrInvalidArgument } - v, err := ep.GetSockOptBool(tcpip.ReuseAddressOption) - if err != nil { - return nil, syserr.TranslateNetstackError(err) - } - vP := primitive.Int32(boolToInt32(v)) - return &vP, nil + v := primitive.Int32(boolToInt32(ep.SocketOptions().GetReuseAddress())) + return &v, nil case linux.SO_REUSEPORT: if outLen < sizeOfInt32 { return nil, syserr.ErrInvalidArgument } - v, err := ep.GetSockOptBool(tcpip.ReusePortOption) - if err != nil { - return nil, syserr.TranslateNetstackError(err) - } - - vP := primitive.Int32(boolToInt32(v)) - return &vP, nil + v := primitive.Int32(boolToInt32(ep.SocketOptions().GetReusePort())) + return &v, nil case linux.SO_BINDTODEVICE: var v tcpip.BindToDeviceOption @@ -1869,7 +1860,8 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam } v := usermem.ByteOrder.Uint32(optVal) - return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.ReuseAddressOption, v != 0)) + ep.SocketOptions().SetReuseAddress(v != 0) + return nil case linux.SO_REUSEPORT: if len(optVal) < sizeOfInt32 { @@ -1877,7 +1869,8 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam } v := usermem.ByteOrder.Uint32(optVal) - return syserr.TranslateNetstackError(ep.SetSockOptBool(tcpip.ReusePortOption, v != 0)) + ep.SocketOptions().SetReusePort(v != 0) + return nil case linux.SO_BINDTODEVICE: n := bytes.IndexByte(optVal, 0) diff --git a/pkg/sentry/socket/unix/transport/connectioned.go b/pkg/sentry/socket/unix/transport/connectioned.go index 6d9e502bd..9f7aca305 100644 --- a/pkg/sentry/socket/unix/transport/connectioned.go +++ b/pkg/sentry/socket/unix/transport/connectioned.go @@ -118,28 +118,24 @@ var ( // NewConnectioned creates a new unbound connectionedEndpoint. func NewConnectioned(ctx context.Context, stype linux.SockType, uid UniqueIDProvider) Endpoint { - return &connectionedEndpoint{ + return newConnectioned(ctx, stype, uid) +} + +func newConnectioned(ctx context.Context, stype linux.SockType, uid UniqueIDProvider) *connectionedEndpoint { + ep := &connectionedEndpoint{ baseEndpoint: baseEndpoint{Queue: &waiter.Queue{}}, id: uid.UniqueID(), idGenerator: uid, stype: stype, } + ep.ops.InitHandler(ep) + return ep } // NewPair allocates a new pair of connected unix-domain connectionedEndpoints. func NewPair(ctx context.Context, stype linux.SockType, uid UniqueIDProvider) (Endpoint, Endpoint) { - a := &connectionedEndpoint{ - baseEndpoint: baseEndpoint{Queue: &waiter.Queue{}}, - id: uid.UniqueID(), - idGenerator: uid, - stype: stype, - } - b := &connectionedEndpoint{ - baseEndpoint: baseEndpoint{Queue: &waiter.Queue{}}, - id: uid.UniqueID(), - idGenerator: uid, - stype: stype, - } + a := newConnectioned(ctx, stype, uid) + b := newConnectioned(ctx, stype, uid) q1 := &queue{ReaderQueue: a.Queue, WriterQueue: b.Queue, limit: initialLimit} q1.InitRefs() @@ -171,12 +167,14 @@ func NewPair(ctx context.Context, stype linux.SockType, uid UniqueIDProvider) (E // NewExternal creates a new externally backed Endpoint. It behaves like a // socketpair. func NewExternal(ctx context.Context, stype linux.SockType, uid UniqueIDProvider, queue *waiter.Queue, receiver Receiver, connected ConnectedEndpoint) Endpoint { - return &connectionedEndpoint{ + ep := &connectionedEndpoint{ baseEndpoint: baseEndpoint{Queue: queue, receiver: receiver, connected: connected}, id: uid.UniqueID(), idGenerator: uid, stype: stype, } + ep.ops.InitHandler(ep) + return ep } // ID implements ConnectingEndpoint.ID. @@ -298,6 +296,7 @@ func (e *connectionedEndpoint) BidirectionalConnect(ctx context.Context, ce Conn idGenerator: e.idGenerator, stype: e.stype, } + ne.ops.InitHandler(ne) readQueue := &queue{ReaderQueue: ce.WaiterQueue(), WriterQueue: ne.Queue, limit: initialLimit} readQueue.InitRefs() diff --git a/pkg/sentry/socket/unix/transport/connectionless.go b/pkg/sentry/socket/unix/transport/connectionless.go index 1406971bc..0813ad87d 100644 --- a/pkg/sentry/socket/unix/transport/connectionless.go +++ b/pkg/sentry/socket/unix/transport/connectionless.go @@ -44,6 +44,7 @@ func NewConnectionless(ctx context.Context) Endpoint { q := queue{ReaderQueue: ep.Queue, WriterQueue: &waiter.Queue{}, limit: initialLimit} q.InitRefs() ep.receiver = &queueReceiver{readQueue: &q} + ep.ops.InitHandler(ep) return ep } diff --git a/pkg/sentry/socket/unix/transport/transport_state_autogen.go b/pkg/sentry/socket/unix/transport/transport_state_autogen.go index 4235ff488..06d6e3c21 100644 --- a/pkg/sentry/socket/unix/transport/transport_state_autogen.go +++ b/pkg/sentry/socket/unix/transport/transport_state_autogen.go @@ -329,6 +329,7 @@ func (e *baseEndpoint) StateTypeName() string { func (e *baseEndpoint) StateFields() []string { return []string{ "Queue", + "DefaultSocketOptionsHandler", "receiver", "connected", "path", @@ -342,22 +343,24 @@ func (e *baseEndpoint) beforeSave() {} func (e *baseEndpoint) StateSave(stateSinkObject state.Sink) { e.beforeSave() stateSinkObject.Save(0, &e.Queue) - stateSinkObject.Save(1, &e.receiver) - stateSinkObject.Save(2, &e.connected) - stateSinkObject.Save(3, &e.path) - stateSinkObject.Save(4, &e.linger) - stateSinkObject.Save(5, &e.ops) + stateSinkObject.Save(1, &e.DefaultSocketOptionsHandler) + stateSinkObject.Save(2, &e.receiver) + stateSinkObject.Save(3, &e.connected) + stateSinkObject.Save(4, &e.path) + stateSinkObject.Save(5, &e.linger) + stateSinkObject.Save(6, &e.ops) } func (e *baseEndpoint) afterLoad() {} func (e *baseEndpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &e.Queue) - stateSourceObject.Load(1, &e.receiver) - stateSourceObject.Load(2, &e.connected) - stateSourceObject.Load(3, &e.path) - stateSourceObject.Load(4, &e.linger) - stateSourceObject.Load(5, &e.ops) + stateSourceObject.Load(1, &e.DefaultSocketOptionsHandler) + stateSourceObject.Load(2, &e.receiver) + stateSourceObject.Load(3, &e.connected) + stateSourceObject.Load(4, &e.path) + stateSourceObject.Load(5, &e.linger) + stateSourceObject.Load(6, &e.ops) } func init() { diff --git a/pkg/sentry/socket/unix/transport/unix.go b/pkg/sentry/socket/unix/transport/unix.go index 0324dcd93..8482d1603 100644 --- a/pkg/sentry/socket/unix/transport/unix.go +++ b/pkg/sentry/socket/unix/transport/unix.go @@ -738,6 +738,7 @@ func (e *connectedEndpoint) CloseUnread() { // +stateify savable type baseEndpoint struct { *waiter.Queue + tcpip.DefaultSocketOptionsHandler // Mutex protects the below fields. sync.Mutex `state:"nosave"` @@ -756,6 +757,7 @@ type baseEndpoint struct { // linger is used for SO_LINGER socket option. linger tcpip.LingerOption + // ops is used to get socket level options. ops tcpip.SocketOptions } @@ -856,11 +858,7 @@ func (e *baseEndpoint) SetSockOpt(opt tcpip.SettableSocketOption) *tcpip.Error { } func (e *baseEndpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error { - switch opt { - case tcpip.ReuseAddressOption: - default: - log.Warningf("Unsupported socket option: %d", opt) - } + log.Warningf("Unsupported socket option: %d", opt) return nil } diff --git a/pkg/tcpip/socketops.go b/pkg/tcpip/socketops.go index cc3d59d9d..99c3e9c45 100644 --- a/pkg/tcpip/socketops.go +++ b/pkg/tcpip/socketops.go @@ -18,11 +18,36 @@ import ( "sync/atomic" ) +// SocketOptionsHandler holds methods that help define endpoint specific +// behavior for socket options. These must be implemented by endpoints to get +// notified when socket level options are set. +type SocketOptionsHandler interface { + // OnReuseAddressSet is invoked when SO_REUSEADDR is set for an endpoint. + OnReuseAddressSet(v bool) + + // OnReusePortSet is invoked when SO_REUSEPORT is set for an endpoint. + OnReusePortSet(v bool) +} + +// DefaultSocketOptionsHandler is an embeddable type that implements no-op +// implementations for SocketOptionsHandler methods. +type DefaultSocketOptionsHandler struct{} + +var _ SocketOptionsHandler = (*DefaultSocketOptionsHandler)(nil) + +// OnReuseAddressSet implements SocketOptionsHandler.OnReuseAddressSet. +func (*DefaultSocketOptionsHandler) OnReuseAddressSet(bool) {} + +// OnReusePortSet implements SocketOptionsHandler.OnReusePortSet. +func (*DefaultSocketOptionsHandler) OnReusePortSet(bool) {} + // SocketOptions contains all the variables which store values for SOL_SOCKET // level options. // // +stateify savable type SocketOptions struct { + handler SocketOptionsHandler + // These fields are accessed and modified using atomic operations. // broadcastEnabled determines whether datagram sockets are allowed to send @@ -36,6 +61,20 @@ type SocketOptions struct { // noChecksumEnabled determines whether UDP checksum is disabled while // transmitting for this socket. noChecksumEnabled uint32 + + // reuseAddressEnabled determines whether Bind() should allow reuse of local + // address. + reuseAddressEnabled uint32 + + // reusePortEnabled determines whether to permit multiple sockets to be bound + // to an identical socket address. + reusePortEnabled uint32 +} + +// InitHandler initializes the handler. This must be called before using the +// socket options utility. +func (so *SocketOptions) InitHandler(handler SocketOptionsHandler) { + so.handler = handler } func storeAtomicBool(addr *uint32, v bool) { @@ -75,3 +114,25 @@ func (so *SocketOptions) GetNoChecksum() bool { func (so *SocketOptions) SetNoChecksum(v bool) { storeAtomicBool(&so.noChecksumEnabled, v) } + +// GetReuseAddress gets value for SO_REUSEADDR option. +func (so *SocketOptions) GetReuseAddress() bool { + return atomic.LoadUint32(&so.reuseAddressEnabled) != 0 +} + +// SetReuseAddress sets value for SO_REUSEADDR option. +func (so *SocketOptions) SetReuseAddress(v bool) { + storeAtomicBool(&so.reuseAddressEnabled, v) + so.handler.OnReuseAddressSet(v) +} + +// GetReusePort gets value for SO_REUSEPORT option. +func (so *SocketOptions) GetReusePort() bool { + return atomic.LoadUint32(&so.reusePortEnabled) != 0 +} + +// SetReusePort sets value for SO_REUSEPORT option. +func (so *SocketOptions) SetReusePort(v bool) { + storeAtomicBool(&so.reusePortEnabled, v) + so.handler.OnReusePortSet(v) +} diff --git a/pkg/tcpip/tcpip.go b/pkg/tcpip/tcpip.go index 09361360f..7ae36fde7 100644 --- a/pkg/tcpip/tcpip.go +++ b/pkg/tcpip/tcpip.go @@ -738,14 +738,6 @@ const ( // interface index and address. ReceiveIPPacketInfoOption - // ReuseAddressOption is used by SetSockOptBool/GetSockOptBool to - // specify whether Bind() should allow reuse of local address. - ReuseAddressOption - - // ReusePortOption is used by SetSockOptBool/GetSockOptBool to permit - // multiple sockets to be bound to an identical socket address. - ReusePortOption - // V6OnlyOption is used by SetSockOptBool/GetSockOptBool to specify // whether an IPv6 socket is to be restricted to sending and receiving // IPv6 packets only. diff --git a/pkg/tcpip/tcpip_state_autogen.go b/pkg/tcpip/tcpip_state_autogen.go index a50f49a2f..37300006e 100644 --- a/pkg/tcpip/tcpip_state_autogen.go +++ b/pkg/tcpip/tcpip_state_autogen.go @@ -12,9 +12,12 @@ func (so *SocketOptions) StateTypeName() string { func (so *SocketOptions) StateFields() []string { return []string{ + "handler", "broadcastEnabled", "passCredEnabled", "noChecksumEnabled", + "reuseAddressEnabled", + "reusePortEnabled", } } @@ -22,17 +25,23 @@ func (so *SocketOptions) beforeSave() {} func (so *SocketOptions) StateSave(stateSinkObject state.Sink) { so.beforeSave() - stateSinkObject.Save(0, &so.broadcastEnabled) - stateSinkObject.Save(1, &so.passCredEnabled) - stateSinkObject.Save(2, &so.noChecksumEnabled) + stateSinkObject.Save(0, &so.handler) + stateSinkObject.Save(1, &so.broadcastEnabled) + stateSinkObject.Save(2, &so.passCredEnabled) + stateSinkObject.Save(3, &so.noChecksumEnabled) + stateSinkObject.Save(4, &so.reuseAddressEnabled) + stateSinkObject.Save(5, &so.reusePortEnabled) } func (so *SocketOptions) afterLoad() {} func (so *SocketOptions) StateLoad(stateSourceObject state.Source) { - stateSourceObject.Load(0, &so.broadcastEnabled) - stateSourceObject.Load(1, &so.passCredEnabled) - stateSourceObject.Load(2, &so.noChecksumEnabled) + stateSourceObject.Load(0, &so.handler) + stateSourceObject.Load(1, &so.broadcastEnabled) + stateSourceObject.Load(2, &so.passCredEnabled) + stateSourceObject.Load(3, &so.noChecksumEnabled) + stateSourceObject.Load(4, &so.reuseAddressEnabled) + stateSourceObject.Load(5, &so.reusePortEnabled) } func (f *FullAddress) StateTypeName() string { diff --git a/pkg/tcpip/transport/icmp/endpoint.go b/pkg/tcpip/transport/icmp/endpoint.go index fe6514bcd..39560a9fa 100644 --- a/pkg/tcpip/transport/icmp/endpoint.go +++ b/pkg/tcpip/transport/icmp/endpoint.go @@ -49,6 +49,7 @@ const ( // +stateify savable type endpoint struct { stack.TransportEndpointInfo + tcpip.DefaultSocketOptionsHandler // The following fields are initialized at creation time and are // immutable. @@ -85,7 +86,7 @@ type endpoint struct { } func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProto tcpip.TransportProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { - return &endpoint{ + ep := &endpoint{ stack: s, TransportEndpointInfo: stack.TransportEndpointInfo{ NetProto: netProto, @@ -96,7 +97,9 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProt sndBufSize: 32 * 1024, state: stateInitial, uniqueID: s.UniqueID(), - }, nil + } + ep.ops.InitHandler(ep) + return ep, nil } // UniqueID implements stack.TransportEndpoint.UniqueID. diff --git a/pkg/tcpip/transport/icmp/icmp_state_autogen.go b/pkg/tcpip/transport/icmp/icmp_state_autogen.go index 81d864da0..0fcfe0dd8 100644 --- a/pkg/tcpip/transport/icmp/icmp_state_autogen.go +++ b/pkg/tcpip/transport/icmp/icmp_state_autogen.go @@ -47,6 +47,7 @@ func (e *endpoint) StateTypeName() string { func (e *endpoint) StateFields() []string { return []string{ "TransportEndpointInfo", + "DefaultSocketOptionsHandler", "waiterQueue", "uniqueID", "rcvReady", @@ -67,39 +68,41 @@ func (e *endpoint) StateFields() []string { func (e *endpoint) StateSave(stateSinkObject state.Sink) { e.beforeSave() var rcvBufSizeMaxValue int = e.saveRcvBufSizeMax() - stateSinkObject.SaveValue(5, rcvBufSizeMaxValue) + stateSinkObject.SaveValue(6, rcvBufSizeMaxValue) stateSinkObject.Save(0, &e.TransportEndpointInfo) - stateSinkObject.Save(1, &e.waiterQueue) - stateSinkObject.Save(2, &e.uniqueID) - stateSinkObject.Save(3, &e.rcvReady) - stateSinkObject.Save(4, &e.rcvList) - stateSinkObject.Save(6, &e.rcvBufSize) - stateSinkObject.Save(7, &e.rcvClosed) - stateSinkObject.Save(8, &e.sndBufSize) - stateSinkObject.Save(9, &e.shutdownFlags) - stateSinkObject.Save(10, &e.state) - stateSinkObject.Save(11, &e.ttl) - stateSinkObject.Save(12, &e.linger) - stateSinkObject.Save(13, &e.owner) - stateSinkObject.Save(14, &e.ops) + stateSinkObject.Save(1, &e.DefaultSocketOptionsHandler) + stateSinkObject.Save(2, &e.waiterQueue) + stateSinkObject.Save(3, &e.uniqueID) + stateSinkObject.Save(4, &e.rcvReady) + stateSinkObject.Save(5, &e.rcvList) + stateSinkObject.Save(7, &e.rcvBufSize) + stateSinkObject.Save(8, &e.rcvClosed) + stateSinkObject.Save(9, &e.sndBufSize) + stateSinkObject.Save(10, &e.shutdownFlags) + stateSinkObject.Save(11, &e.state) + stateSinkObject.Save(12, &e.ttl) + stateSinkObject.Save(13, &e.linger) + stateSinkObject.Save(14, &e.owner) + stateSinkObject.Save(15, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &e.TransportEndpointInfo) - stateSourceObject.Load(1, &e.waiterQueue) - stateSourceObject.Load(2, &e.uniqueID) - stateSourceObject.Load(3, &e.rcvReady) - stateSourceObject.Load(4, &e.rcvList) - stateSourceObject.Load(6, &e.rcvBufSize) - stateSourceObject.Load(7, &e.rcvClosed) - stateSourceObject.Load(8, &e.sndBufSize) - stateSourceObject.Load(9, &e.shutdownFlags) - stateSourceObject.Load(10, &e.state) - stateSourceObject.Load(11, &e.ttl) - stateSourceObject.Load(12, &e.linger) - stateSourceObject.Load(13, &e.owner) - stateSourceObject.Load(14, &e.ops) - stateSourceObject.LoadValue(5, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) + stateSourceObject.Load(1, &e.DefaultSocketOptionsHandler) + stateSourceObject.Load(2, &e.waiterQueue) + stateSourceObject.Load(3, &e.uniqueID) + stateSourceObject.Load(4, &e.rcvReady) + stateSourceObject.Load(5, &e.rcvList) + stateSourceObject.Load(7, &e.rcvBufSize) + stateSourceObject.Load(8, &e.rcvClosed) + stateSourceObject.Load(9, &e.sndBufSize) + stateSourceObject.Load(10, &e.shutdownFlags) + stateSourceObject.Load(11, &e.state) + stateSourceObject.Load(12, &e.ttl) + stateSourceObject.Load(13, &e.linger) + stateSourceObject.Load(14, &e.owner) + stateSourceObject.Load(15, &e.ops) + stateSourceObject.LoadValue(6, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) stateSourceObject.AfterLoad(e.afterLoad) } diff --git a/pkg/tcpip/transport/packet/endpoint.go b/pkg/tcpip/transport/packet/endpoint.go index 3bff3755a..35d1be792 100644 --- a/pkg/tcpip/transport/packet/endpoint.go +++ b/pkg/tcpip/transport/packet/endpoint.go @@ -60,6 +60,8 @@ type packet struct { // +stateify savable type endpoint struct { stack.TransportEndpointInfo + tcpip.DefaultSocketOptionsHandler + // The following fields are initialized at creation time and are // immutable. stack *stack.Stack `state:"manual"` @@ -107,6 +109,7 @@ func NewEndpoint(s *stack.Stack, cooked bool, netProto tcpip.NetworkProtocolNumb rcvBufSizeMax: 32 * 1024, sndBufSize: 32 * 1024, } + ep.ops.InitHandler(ep) // Override with stack defaults. var ss stack.SendBufferSizeOption diff --git a/pkg/tcpip/transport/packet/packet_state_autogen.go b/pkg/tcpip/transport/packet/packet_state_autogen.go index 2ce71eb84..42236056b 100644 --- a/pkg/tcpip/transport/packet/packet_state_autogen.go +++ b/pkg/tcpip/transport/packet/packet_state_autogen.go @@ -50,6 +50,7 @@ func (ep *endpoint) StateTypeName() string { func (ep *endpoint) StateFields() []string { return []string{ "TransportEndpointInfo", + "DefaultSocketOptionsHandler", "netProto", "waiterQueue", "cooked", @@ -71,42 +72,44 @@ func (ep *endpoint) StateFields() []string { func (ep *endpoint) StateSave(stateSinkObject state.Sink) { ep.beforeSave() var rcvBufSizeMaxValue int = ep.saveRcvBufSizeMax() - stateSinkObject.SaveValue(5, rcvBufSizeMaxValue) + stateSinkObject.SaveValue(6, rcvBufSizeMaxValue) var lastErrorValue string = ep.saveLastError() - stateSinkObject.SaveValue(14, lastErrorValue) + stateSinkObject.SaveValue(15, lastErrorValue) stateSinkObject.Save(0, &ep.TransportEndpointInfo) - stateSinkObject.Save(1, &ep.netProto) - stateSinkObject.Save(2, &ep.waiterQueue) - stateSinkObject.Save(3, &ep.cooked) - stateSinkObject.Save(4, &ep.rcvList) - stateSinkObject.Save(6, &ep.rcvBufSize) - stateSinkObject.Save(7, &ep.rcvClosed) - stateSinkObject.Save(8, &ep.sndBufSize) - stateSinkObject.Save(9, &ep.sndBufSizeMax) - stateSinkObject.Save(10, &ep.closed) - stateSinkObject.Save(11, &ep.bound) - stateSinkObject.Save(12, &ep.boundNIC) - stateSinkObject.Save(13, &ep.linger) - stateSinkObject.Save(15, &ep.ops) + stateSinkObject.Save(1, &ep.DefaultSocketOptionsHandler) + stateSinkObject.Save(2, &ep.netProto) + stateSinkObject.Save(3, &ep.waiterQueue) + stateSinkObject.Save(4, &ep.cooked) + stateSinkObject.Save(5, &ep.rcvList) + stateSinkObject.Save(7, &ep.rcvBufSize) + stateSinkObject.Save(8, &ep.rcvClosed) + stateSinkObject.Save(9, &ep.sndBufSize) + stateSinkObject.Save(10, &ep.sndBufSizeMax) + stateSinkObject.Save(11, &ep.closed) + stateSinkObject.Save(12, &ep.bound) + stateSinkObject.Save(13, &ep.boundNIC) + stateSinkObject.Save(14, &ep.linger) + stateSinkObject.Save(16, &ep.ops) } func (ep *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &ep.TransportEndpointInfo) - stateSourceObject.Load(1, &ep.netProto) - stateSourceObject.Load(2, &ep.waiterQueue) - stateSourceObject.Load(3, &ep.cooked) - stateSourceObject.Load(4, &ep.rcvList) - stateSourceObject.Load(6, &ep.rcvBufSize) - stateSourceObject.Load(7, &ep.rcvClosed) - stateSourceObject.Load(8, &ep.sndBufSize) - stateSourceObject.Load(9, &ep.sndBufSizeMax) - stateSourceObject.Load(10, &ep.closed) - stateSourceObject.Load(11, &ep.bound) - stateSourceObject.Load(12, &ep.boundNIC) - stateSourceObject.Load(13, &ep.linger) - stateSourceObject.Load(15, &ep.ops) - stateSourceObject.LoadValue(5, new(int), func(y interface{}) { ep.loadRcvBufSizeMax(y.(int)) }) - stateSourceObject.LoadValue(14, new(string), func(y interface{}) { ep.loadLastError(y.(string)) }) + stateSourceObject.Load(1, &ep.DefaultSocketOptionsHandler) + stateSourceObject.Load(2, &ep.netProto) + stateSourceObject.Load(3, &ep.waiterQueue) + stateSourceObject.Load(4, &ep.cooked) + stateSourceObject.Load(5, &ep.rcvList) + stateSourceObject.Load(7, &ep.rcvBufSize) + stateSourceObject.Load(8, &ep.rcvClosed) + stateSourceObject.Load(9, &ep.sndBufSize) + stateSourceObject.Load(10, &ep.sndBufSizeMax) + stateSourceObject.Load(11, &ep.closed) + stateSourceObject.Load(12, &ep.bound) + stateSourceObject.Load(13, &ep.boundNIC) + stateSourceObject.Load(14, &ep.linger) + stateSourceObject.Load(16, &ep.ops) + stateSourceObject.LoadValue(6, new(int), func(y interface{}) { ep.loadRcvBufSizeMax(y.(int)) }) + stateSourceObject.LoadValue(15, new(string), func(y interface{}) { ep.loadLastError(y.(string)) }) stateSourceObject.AfterLoad(ep.afterLoad) } diff --git a/pkg/tcpip/transport/raw/endpoint.go b/pkg/tcpip/transport/raw/endpoint.go index 0a1e1fbb3..e64392f7b 100644 --- a/pkg/tcpip/transport/raw/endpoint.go +++ b/pkg/tcpip/transport/raw/endpoint.go @@ -58,6 +58,8 @@ type rawPacket struct { // +stateify savable type endpoint struct { stack.TransportEndpointInfo + tcpip.DefaultSocketOptionsHandler + // The following fields are initialized at creation time and are // immutable. stack *stack.Stack `state:"manual"` @@ -116,6 +118,7 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProt associated: associated, hdrIncluded: !associated, } + e.ops.InitHandler(e) // Override with stack defaults. var ss stack.SendBufferSizeOption diff --git a/pkg/tcpip/transport/raw/raw_state_autogen.go b/pkg/tcpip/transport/raw/raw_state_autogen.go index 26fc86a27..4874e4636 100644 --- a/pkg/tcpip/transport/raw/raw_state_autogen.go +++ b/pkg/tcpip/transport/raw/raw_state_autogen.go @@ -47,6 +47,7 @@ func (e *endpoint) StateTypeName() string { func (e *endpoint) StateFields() []string { return []string{ "TransportEndpointInfo", + "DefaultSocketOptionsHandler", "waiterQueue", "associated", "hdrIncluded", @@ -68,41 +69,43 @@ func (e *endpoint) StateFields() []string { func (e *endpoint) StateSave(stateSinkObject state.Sink) { e.beforeSave() var rcvBufSizeMaxValue int = e.saveRcvBufSizeMax() - stateSinkObject.SaveValue(6, rcvBufSizeMaxValue) + stateSinkObject.SaveValue(7, rcvBufSizeMaxValue) stateSinkObject.Save(0, &e.TransportEndpointInfo) - stateSinkObject.Save(1, &e.waiterQueue) - stateSinkObject.Save(2, &e.associated) - stateSinkObject.Save(3, &e.hdrIncluded) - stateSinkObject.Save(4, &e.rcvList) - stateSinkObject.Save(5, &e.rcvBufSize) - stateSinkObject.Save(7, &e.rcvClosed) - stateSinkObject.Save(8, &e.sndBufSize) - stateSinkObject.Save(9, &e.sndBufSizeMax) - stateSinkObject.Save(10, &e.closed) - stateSinkObject.Save(11, &e.connected) - stateSinkObject.Save(12, &e.bound) - stateSinkObject.Save(13, &e.linger) - stateSinkObject.Save(14, &e.owner) - stateSinkObject.Save(15, &e.ops) + stateSinkObject.Save(1, &e.DefaultSocketOptionsHandler) + stateSinkObject.Save(2, &e.waiterQueue) + stateSinkObject.Save(3, &e.associated) + stateSinkObject.Save(4, &e.hdrIncluded) + stateSinkObject.Save(5, &e.rcvList) + stateSinkObject.Save(6, &e.rcvBufSize) + stateSinkObject.Save(8, &e.rcvClosed) + stateSinkObject.Save(9, &e.sndBufSize) + stateSinkObject.Save(10, &e.sndBufSizeMax) + stateSinkObject.Save(11, &e.closed) + stateSinkObject.Save(12, &e.connected) + stateSinkObject.Save(13, &e.bound) + stateSinkObject.Save(14, &e.linger) + stateSinkObject.Save(15, &e.owner) + stateSinkObject.Save(16, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &e.TransportEndpointInfo) - stateSourceObject.Load(1, &e.waiterQueue) - stateSourceObject.Load(2, &e.associated) - stateSourceObject.Load(3, &e.hdrIncluded) - stateSourceObject.Load(4, &e.rcvList) - stateSourceObject.Load(5, &e.rcvBufSize) - stateSourceObject.Load(7, &e.rcvClosed) - stateSourceObject.Load(8, &e.sndBufSize) - stateSourceObject.Load(9, &e.sndBufSizeMax) - stateSourceObject.Load(10, &e.closed) - stateSourceObject.Load(11, &e.connected) - stateSourceObject.Load(12, &e.bound) - stateSourceObject.Load(13, &e.linger) - stateSourceObject.Load(14, &e.owner) - stateSourceObject.Load(15, &e.ops) - stateSourceObject.LoadValue(6, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) + stateSourceObject.Load(1, &e.DefaultSocketOptionsHandler) + stateSourceObject.Load(2, &e.waiterQueue) + stateSourceObject.Load(3, &e.associated) + stateSourceObject.Load(4, &e.hdrIncluded) + stateSourceObject.Load(5, &e.rcvList) + stateSourceObject.Load(6, &e.rcvBufSize) + stateSourceObject.Load(8, &e.rcvClosed) + stateSourceObject.Load(9, &e.sndBufSize) + stateSourceObject.Load(10, &e.sndBufSizeMax) + stateSourceObject.Load(11, &e.closed) + stateSourceObject.Load(12, &e.connected) + stateSourceObject.Load(13, &e.bound) + stateSourceObject.Load(14, &e.linger) + stateSourceObject.Load(15, &e.owner) + stateSourceObject.Load(16, &e.ops) + stateSourceObject.LoadValue(7, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) stateSourceObject.AfterLoad(e.afterLoad) } diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go index 36b915510..f893324c2 100644 --- a/pkg/tcpip/transport/tcp/endpoint.go +++ b/pkg/tcpip/transport/tcp/endpoint.go @@ -362,6 +362,7 @@ func (*EndpointInfo) IsEndpointInfo() {} // +stateify savable type endpoint struct { EndpointInfo + tcpip.DefaultSocketOptionsHandler // endpointEntry is used to queue endpoints for processing to the // a given tcp processor goroutine. @@ -884,6 +885,7 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue windowClamp: DefaultReceiveBufferSize, maxSynRetries: DefaultSynRetries, } + e.ops.InitHandler(e) var ss tcpip.TCPSendBufferSizeRangeOption if err := s.TransportProtocolOption(ProtocolNumber, &ss); err == nil { @@ -1627,6 +1629,20 @@ func (e *endpoint) windowCrossedACKThresholdLocked(deltaBefore int) (crossed boo return false, false } +// OnReuseAddressSet implements tcpip.SocketOptionsHandler.OnReuseAddressSet. +func (e *endpoint) OnReuseAddressSet(v bool) { + e.LockUser() + e.portFlags.TupleOnly = v + e.UnlockUser() +} + +// OnReusePortSet implements tcpip.SocketOptionsHandler.OnReusePortSet. +func (e *endpoint) OnReusePortSet(v bool) { + e.LockUser() + e.portFlags.LoadBalanced = v + e.UnlockUser() +} + // SetSockOptBool sets a socket option. func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error { switch opt { @@ -1666,16 +1682,6 @@ func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error { } atomic.StoreUint32(&e.slowAck, o) - case tcpip.ReuseAddressOption: - e.LockUser() - e.portFlags.TupleOnly = v - e.UnlockUser() - - case tcpip.ReusePortOption: - e.LockUser() - e.portFlags.LoadBalanced = v - e.UnlockUser() - case tcpip.V6OnlyOption: // We only recognize this option on v6 endpoints. if e.NetProto != header.IPv6ProtocolNumber { @@ -1995,20 +2001,6 @@ func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) { v := atomic.LoadUint32(&e.slowAck) == 0 return v, nil - case tcpip.ReuseAddressOption: - e.LockUser() - v := e.portFlags.TupleOnly - e.UnlockUser() - - return v, nil - - case tcpip.ReusePortOption: - e.LockUser() - v := e.portFlags.LoadBalanced - e.UnlockUser() - - return v, nil - case tcpip.V6OnlyOption: // We only recognize this option on v6 endpoints. if e.NetProto != header.IPv6ProtocolNumber { diff --git a/pkg/tcpip/transport/tcp/tcp_state_autogen.go b/pkg/tcpip/transport/tcp/tcp_state_autogen.go index 56b58d41d..e9599cb6d 100644 --- a/pkg/tcpip/transport/tcp/tcp_state_autogen.go +++ b/pkg/tcpip/transport/tcp/tcp_state_autogen.go @@ -157,6 +157,7 @@ func (e *endpoint) StateTypeName() string { func (e *endpoint) StateFields() []string { return []string{ "EndpointInfo", + "DefaultSocketOptionsHandler", "waiterQueue", "uniqueID", "hardError", @@ -227,143 +228,145 @@ func (e *endpoint) StateFields() []string { func (e *endpoint) StateSave(stateSinkObject state.Sink) { e.beforeSave() var hardErrorValue string = e.saveHardError() - stateSinkObject.SaveValue(3, hardErrorValue) + stateSinkObject.SaveValue(4, hardErrorValue) var lastErrorValue string = e.saveLastError() - stateSinkObject.SaveValue(4, lastErrorValue) + stateSinkObject.SaveValue(5, lastErrorValue) var stateValue EndpointState = e.saveState() - stateSinkObject.SaveValue(12, stateValue) + stateSinkObject.SaveValue(13, stateValue) var recentTSTimeValue unixTime = e.saveRecentTSTime() - stateSinkObject.SaveValue(26, recentTSTimeValue) + stateSinkObject.SaveValue(27, recentTSTimeValue) var acceptedChanValue []*endpoint = e.saveAcceptedChan() - stateSinkObject.SaveValue(52, acceptedChanValue) + stateSinkObject.SaveValue(53, acceptedChanValue) stateSinkObject.Save(0, &e.EndpointInfo) - stateSinkObject.Save(1, &e.waiterQueue) - stateSinkObject.Save(2, &e.uniqueID) - stateSinkObject.Save(5, &e.rcvList) - stateSinkObject.Save(6, &e.rcvClosed) - stateSinkObject.Save(7, &e.rcvBufSize) - stateSinkObject.Save(8, &e.rcvBufUsed) - stateSinkObject.Save(9, &e.rcvAutoParams) - stateSinkObject.Save(10, &e.rcvMemUsed) - stateSinkObject.Save(11, &e.ownedByUser) - stateSinkObject.Save(13, &e.boundNICID) - stateSinkObject.Save(14, &e.ttl) - stateSinkObject.Save(15, &e.v6only) - stateSinkObject.Save(16, &e.isConnectNotified) - stateSinkObject.Save(17, &e.portFlags) - stateSinkObject.Save(18, &e.boundBindToDevice) - stateSinkObject.Save(19, &e.boundPortFlags) - stateSinkObject.Save(20, &e.boundDest) - stateSinkObject.Save(21, &e.effectiveNetProtos) - stateSinkObject.Save(22, &e.workerRunning) - stateSinkObject.Save(23, &e.workerCleanup) - stateSinkObject.Save(24, &e.sendTSOk) - stateSinkObject.Save(25, &e.recentTS) - stateSinkObject.Save(27, &e.tsOffset) - stateSinkObject.Save(28, &e.shutdownFlags) - stateSinkObject.Save(29, &e.sackPermitted) - stateSinkObject.Save(30, &e.sack) - stateSinkObject.Save(31, &e.bindToDevice) - stateSinkObject.Save(32, &e.delay) - stateSinkObject.Save(33, &e.cork) - stateSinkObject.Save(34, &e.scoreboard) - stateSinkObject.Save(35, &e.slowAck) - stateSinkObject.Save(36, &e.segmentQueue) - stateSinkObject.Save(37, &e.synRcvdCount) - stateSinkObject.Save(38, &e.userMSS) - stateSinkObject.Save(39, &e.maxSynRetries) - stateSinkObject.Save(40, &e.windowClamp) - stateSinkObject.Save(41, &e.sndBufSize) - stateSinkObject.Save(42, &e.sndBufUsed) - stateSinkObject.Save(43, &e.sndClosed) - stateSinkObject.Save(44, &e.sndBufInQueue) - stateSinkObject.Save(45, &e.sndQueue) - stateSinkObject.Save(46, &e.cc) - stateSinkObject.Save(47, &e.packetTooBigCount) - stateSinkObject.Save(48, &e.sndMTU) - stateSinkObject.Save(49, &e.keepalive) - stateSinkObject.Save(50, &e.userTimeout) - stateSinkObject.Save(51, &e.deferAccept) - stateSinkObject.Save(53, &e.rcv) - stateSinkObject.Save(54, &e.snd) - stateSinkObject.Save(55, &e.connectingAddress) - stateSinkObject.Save(56, &e.amss) - stateSinkObject.Save(57, &e.sendTOS) - stateSinkObject.Save(58, &e.gso) - stateSinkObject.Save(59, &e.tcpLingerTimeout) - stateSinkObject.Save(60, &e.closed) - stateSinkObject.Save(61, &e.txHash) - stateSinkObject.Save(62, &e.owner) - stateSinkObject.Save(63, &e.linger) - stateSinkObject.Save(64, &e.ops) + stateSinkObject.Save(1, &e.DefaultSocketOptionsHandler) + stateSinkObject.Save(2, &e.waiterQueue) + stateSinkObject.Save(3, &e.uniqueID) + stateSinkObject.Save(6, &e.rcvList) + stateSinkObject.Save(7, &e.rcvClosed) + stateSinkObject.Save(8, &e.rcvBufSize) + stateSinkObject.Save(9, &e.rcvBufUsed) + stateSinkObject.Save(10, &e.rcvAutoParams) + stateSinkObject.Save(11, &e.rcvMemUsed) + stateSinkObject.Save(12, &e.ownedByUser) + stateSinkObject.Save(14, &e.boundNICID) + stateSinkObject.Save(15, &e.ttl) + stateSinkObject.Save(16, &e.v6only) + stateSinkObject.Save(17, &e.isConnectNotified) + stateSinkObject.Save(18, &e.portFlags) + stateSinkObject.Save(19, &e.boundBindToDevice) + stateSinkObject.Save(20, &e.boundPortFlags) + stateSinkObject.Save(21, &e.boundDest) + stateSinkObject.Save(22, &e.effectiveNetProtos) + stateSinkObject.Save(23, &e.workerRunning) + stateSinkObject.Save(24, &e.workerCleanup) + stateSinkObject.Save(25, &e.sendTSOk) + stateSinkObject.Save(26, &e.recentTS) + stateSinkObject.Save(28, &e.tsOffset) + stateSinkObject.Save(29, &e.shutdownFlags) + stateSinkObject.Save(30, &e.sackPermitted) + stateSinkObject.Save(31, &e.sack) + stateSinkObject.Save(32, &e.bindToDevice) + stateSinkObject.Save(33, &e.delay) + stateSinkObject.Save(34, &e.cork) + stateSinkObject.Save(35, &e.scoreboard) + stateSinkObject.Save(36, &e.slowAck) + stateSinkObject.Save(37, &e.segmentQueue) + stateSinkObject.Save(38, &e.synRcvdCount) + stateSinkObject.Save(39, &e.userMSS) + stateSinkObject.Save(40, &e.maxSynRetries) + stateSinkObject.Save(41, &e.windowClamp) + stateSinkObject.Save(42, &e.sndBufSize) + stateSinkObject.Save(43, &e.sndBufUsed) + stateSinkObject.Save(44, &e.sndClosed) + stateSinkObject.Save(45, &e.sndBufInQueue) + stateSinkObject.Save(46, &e.sndQueue) + stateSinkObject.Save(47, &e.cc) + stateSinkObject.Save(48, &e.packetTooBigCount) + stateSinkObject.Save(49, &e.sndMTU) + stateSinkObject.Save(50, &e.keepalive) + stateSinkObject.Save(51, &e.userTimeout) + stateSinkObject.Save(52, &e.deferAccept) + stateSinkObject.Save(54, &e.rcv) + stateSinkObject.Save(55, &e.snd) + stateSinkObject.Save(56, &e.connectingAddress) + stateSinkObject.Save(57, &e.amss) + stateSinkObject.Save(58, &e.sendTOS) + stateSinkObject.Save(59, &e.gso) + stateSinkObject.Save(60, &e.tcpLingerTimeout) + stateSinkObject.Save(61, &e.closed) + stateSinkObject.Save(62, &e.txHash) + stateSinkObject.Save(63, &e.owner) + stateSinkObject.Save(64, &e.linger) + stateSinkObject.Save(65, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &e.EndpointInfo) - stateSourceObject.LoadWait(1, &e.waiterQueue) - stateSourceObject.Load(2, &e.uniqueID) - stateSourceObject.LoadWait(5, &e.rcvList) - stateSourceObject.Load(6, &e.rcvClosed) - stateSourceObject.Load(7, &e.rcvBufSize) - stateSourceObject.Load(8, &e.rcvBufUsed) - stateSourceObject.Load(9, &e.rcvAutoParams) - stateSourceObject.Load(10, &e.rcvMemUsed) - stateSourceObject.Load(11, &e.ownedByUser) - stateSourceObject.Load(13, &e.boundNICID) - stateSourceObject.Load(14, &e.ttl) - stateSourceObject.Load(15, &e.v6only) - stateSourceObject.Load(16, &e.isConnectNotified) - stateSourceObject.Load(17, &e.portFlags) - stateSourceObject.Load(18, &e.boundBindToDevice) - stateSourceObject.Load(19, &e.boundPortFlags) - stateSourceObject.Load(20, &e.boundDest) - stateSourceObject.Load(21, &e.effectiveNetProtos) - stateSourceObject.Load(22, &e.workerRunning) - stateSourceObject.Load(23, &e.workerCleanup) - stateSourceObject.Load(24, &e.sendTSOk) - stateSourceObject.Load(25, &e.recentTS) - stateSourceObject.Load(27, &e.tsOffset) - stateSourceObject.Load(28, &e.shutdownFlags) - stateSourceObject.Load(29, &e.sackPermitted) - stateSourceObject.Load(30, &e.sack) - stateSourceObject.Load(31, &e.bindToDevice) - stateSourceObject.Load(32, &e.delay) - stateSourceObject.Load(33, &e.cork) - stateSourceObject.Load(34, &e.scoreboard) - stateSourceObject.Load(35, &e.slowAck) - stateSourceObject.LoadWait(36, &e.segmentQueue) - stateSourceObject.Load(37, &e.synRcvdCount) - stateSourceObject.Load(38, &e.userMSS) - stateSourceObject.Load(39, &e.maxSynRetries) - stateSourceObject.Load(40, &e.windowClamp) - stateSourceObject.Load(41, &e.sndBufSize) - stateSourceObject.Load(42, &e.sndBufUsed) - stateSourceObject.Load(43, &e.sndClosed) - stateSourceObject.Load(44, &e.sndBufInQueue) - stateSourceObject.LoadWait(45, &e.sndQueue) - stateSourceObject.Load(46, &e.cc) - stateSourceObject.Load(47, &e.packetTooBigCount) - stateSourceObject.Load(48, &e.sndMTU) - stateSourceObject.Load(49, &e.keepalive) - stateSourceObject.Load(50, &e.userTimeout) - stateSourceObject.Load(51, &e.deferAccept) - stateSourceObject.LoadWait(53, &e.rcv) - stateSourceObject.LoadWait(54, &e.snd) - stateSourceObject.Load(55, &e.connectingAddress) - stateSourceObject.Load(56, &e.amss) - stateSourceObject.Load(57, &e.sendTOS) - stateSourceObject.Load(58, &e.gso) - stateSourceObject.Load(59, &e.tcpLingerTimeout) - stateSourceObject.Load(60, &e.closed) - stateSourceObject.Load(61, &e.txHash) - stateSourceObject.Load(62, &e.owner) - stateSourceObject.Load(63, &e.linger) - stateSourceObject.Load(64, &e.ops) - stateSourceObject.LoadValue(3, new(string), func(y interface{}) { e.loadHardError(y.(string)) }) - stateSourceObject.LoadValue(4, new(string), func(y interface{}) { e.loadLastError(y.(string)) }) - stateSourceObject.LoadValue(12, new(EndpointState), func(y interface{}) { e.loadState(y.(EndpointState)) }) - stateSourceObject.LoadValue(26, new(unixTime), func(y interface{}) { e.loadRecentTSTime(y.(unixTime)) }) - stateSourceObject.LoadValue(52, new([]*endpoint), func(y interface{}) { e.loadAcceptedChan(y.([]*endpoint)) }) + stateSourceObject.Load(1, &e.DefaultSocketOptionsHandler) + stateSourceObject.LoadWait(2, &e.waiterQueue) + stateSourceObject.Load(3, &e.uniqueID) + stateSourceObject.LoadWait(6, &e.rcvList) + stateSourceObject.Load(7, &e.rcvClosed) + stateSourceObject.Load(8, &e.rcvBufSize) + stateSourceObject.Load(9, &e.rcvBufUsed) + stateSourceObject.Load(10, &e.rcvAutoParams) + stateSourceObject.Load(11, &e.rcvMemUsed) + stateSourceObject.Load(12, &e.ownedByUser) + stateSourceObject.Load(14, &e.boundNICID) + stateSourceObject.Load(15, &e.ttl) + stateSourceObject.Load(16, &e.v6only) + stateSourceObject.Load(17, &e.isConnectNotified) + stateSourceObject.Load(18, &e.portFlags) + stateSourceObject.Load(19, &e.boundBindToDevice) + stateSourceObject.Load(20, &e.boundPortFlags) + stateSourceObject.Load(21, &e.boundDest) + stateSourceObject.Load(22, &e.effectiveNetProtos) + stateSourceObject.Load(23, &e.workerRunning) + stateSourceObject.Load(24, &e.workerCleanup) + stateSourceObject.Load(25, &e.sendTSOk) + stateSourceObject.Load(26, &e.recentTS) + stateSourceObject.Load(28, &e.tsOffset) + stateSourceObject.Load(29, &e.shutdownFlags) + stateSourceObject.Load(30, &e.sackPermitted) + stateSourceObject.Load(31, &e.sack) + stateSourceObject.Load(32, &e.bindToDevice) + stateSourceObject.Load(33, &e.delay) + stateSourceObject.Load(34, &e.cork) + stateSourceObject.Load(35, &e.scoreboard) + stateSourceObject.Load(36, &e.slowAck) + stateSourceObject.LoadWait(37, &e.segmentQueue) + stateSourceObject.Load(38, &e.synRcvdCount) + stateSourceObject.Load(39, &e.userMSS) + stateSourceObject.Load(40, &e.maxSynRetries) + stateSourceObject.Load(41, &e.windowClamp) + stateSourceObject.Load(42, &e.sndBufSize) + stateSourceObject.Load(43, &e.sndBufUsed) + stateSourceObject.Load(44, &e.sndClosed) + stateSourceObject.Load(45, &e.sndBufInQueue) + stateSourceObject.LoadWait(46, &e.sndQueue) + stateSourceObject.Load(47, &e.cc) + stateSourceObject.Load(48, &e.packetTooBigCount) + stateSourceObject.Load(49, &e.sndMTU) + stateSourceObject.Load(50, &e.keepalive) + stateSourceObject.Load(51, &e.userTimeout) + stateSourceObject.Load(52, &e.deferAccept) + stateSourceObject.LoadWait(54, &e.rcv) + stateSourceObject.LoadWait(55, &e.snd) + stateSourceObject.Load(56, &e.connectingAddress) + stateSourceObject.Load(57, &e.amss) + stateSourceObject.Load(58, &e.sendTOS) + stateSourceObject.Load(59, &e.gso) + stateSourceObject.Load(60, &e.tcpLingerTimeout) + stateSourceObject.Load(61, &e.closed) + stateSourceObject.Load(62, &e.txHash) + stateSourceObject.Load(63, &e.owner) + stateSourceObject.Load(64, &e.linger) + stateSourceObject.Load(65, &e.ops) + stateSourceObject.LoadValue(4, new(string), func(y interface{}) { e.loadHardError(y.(string)) }) + stateSourceObject.LoadValue(5, new(string), func(y interface{}) { e.loadLastError(y.(string)) }) + stateSourceObject.LoadValue(13, new(EndpointState), func(y interface{}) { e.loadState(y.(EndpointState)) }) + stateSourceObject.LoadValue(27, new(unixTime), func(y interface{}) { e.loadRecentTSTime(y.(unixTime)) }) + stateSourceObject.LoadValue(53, new([]*endpoint), func(y interface{}) { e.loadAcceptedChan(y.([]*endpoint)) }) stateSourceObject.AfterLoad(e.afterLoad) } diff --git a/pkg/tcpip/transport/udp/endpoint.go b/pkg/tcpip/transport/udp/endpoint.go index 5aa16bf35..e57833644 100644 --- a/pkg/tcpip/transport/udp/endpoint.go +++ b/pkg/tcpip/transport/udp/endpoint.go @@ -77,6 +77,7 @@ func (s EndpointState) String() string { // +stateify savable type endpoint struct { stack.TransportEndpointInfo + tcpip.DefaultSocketOptionsHandler // The following fields are initialized at creation time and do not // change throughout the lifetime of the endpoint. @@ -194,6 +195,7 @@ func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQue state: StateInitial, uniqueID: s.UniqueID(), } + e.ops.InitHandler(e) // Override with stack defaults. var ss stack.SendBufferSizeOption @@ -574,6 +576,20 @@ func (e *endpoint) Peek([][]byte) (int64, tcpip.ControlMessages, *tcpip.Error) { return 0, tcpip.ControlMessages{}, nil } +// OnReuseAddressSet implements tcpip.SocketOptionsHandler.OnReuseAddressSet. +func (e *endpoint) OnReuseAddressSet(v bool) { + e.mu.Lock() + e.portFlags.MostRecent = v + e.mu.Unlock() +} + +// OnReusePortSet implements tcpip.SocketOptionsHandler.OnReusePortSet. +func (e *endpoint) OnReusePortSet(v bool) { + e.mu.Lock() + e.portFlags.LoadBalanced = v + e.mu.Unlock() +} + // SetSockOptBool implements tcpip.Endpoint.SetSockOptBool. func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error { switch opt { @@ -602,16 +618,6 @@ func (e *endpoint) SetSockOptBool(opt tcpip.SockOptBool, v bool) *tcpip.Error { e.receiveIPPacketInfo = v e.mu.Unlock() - case tcpip.ReuseAddressOption: - e.mu.Lock() - e.portFlags.MostRecent = v - e.mu.Unlock() - - case tcpip.ReusePortOption: - e.mu.Lock() - e.portFlags.LoadBalanced = v - e.mu.Unlock() - case tcpip.V6OnlyOption: // We only recognize this option on v6 endpoints. if e.NetProto != header.IPv6ProtocolNumber { @@ -875,20 +881,6 @@ func (e *endpoint) GetSockOptBool(opt tcpip.SockOptBool) (bool, *tcpip.Error) { e.mu.RUnlock() return v, nil - case tcpip.ReuseAddressOption: - e.mu.RLock() - v := e.portFlags.MostRecent - e.mu.RUnlock() - - return v, nil - - case tcpip.ReusePortOption: - e.mu.RLock() - v := e.portFlags.LoadBalanced - e.mu.RUnlock() - - return v, nil - case tcpip.V6OnlyOption: // We only recognize this option on v6 endpoints. if e.NetProto != header.IPv6ProtocolNumber { diff --git a/pkg/tcpip/transport/udp/udp_state_autogen.go b/pkg/tcpip/transport/udp/udp_state_autogen.go index 9350a4809..cb05b5cd8 100644 --- a/pkg/tcpip/transport/udp/udp_state_autogen.go +++ b/pkg/tcpip/transport/udp/udp_state_autogen.go @@ -53,6 +53,7 @@ func (e *endpoint) StateTypeName() string { func (e *endpoint) StateFields() []string { return []string{ "TransportEndpointInfo", + "DefaultSocketOptionsHandler", "waiterQueue", "uniqueID", "rcvReady", @@ -91,76 +92,78 @@ func (e *endpoint) StateFields() []string { func (e *endpoint) StateSave(stateSinkObject state.Sink) { e.beforeSave() var rcvBufSizeMaxValue int = e.saveRcvBufSizeMax() - stateSinkObject.SaveValue(5, rcvBufSizeMaxValue) + stateSinkObject.SaveValue(6, rcvBufSizeMaxValue) var lastErrorValue string = e.saveLastError() - stateSinkObject.SaveValue(20, lastErrorValue) + stateSinkObject.SaveValue(21, lastErrorValue) stateSinkObject.Save(0, &e.TransportEndpointInfo) - stateSinkObject.Save(1, &e.waiterQueue) - stateSinkObject.Save(2, &e.uniqueID) - stateSinkObject.Save(3, &e.rcvReady) - stateSinkObject.Save(4, &e.rcvList) - stateSinkObject.Save(6, &e.rcvBufSize) - stateSinkObject.Save(7, &e.rcvClosed) - stateSinkObject.Save(8, &e.sndBufSize) - stateSinkObject.Save(9, &e.sndBufSizeMax) - stateSinkObject.Save(10, &e.state) - stateSinkObject.Save(11, &e.dstPort) - stateSinkObject.Save(12, &e.v6only) - stateSinkObject.Save(13, &e.ttl) - stateSinkObject.Save(14, &e.multicastTTL) - stateSinkObject.Save(15, &e.multicastAddr) - stateSinkObject.Save(16, &e.multicastNICID) - stateSinkObject.Save(17, &e.multicastLoop) - stateSinkObject.Save(18, &e.portFlags) - stateSinkObject.Save(19, &e.bindToDevice) - stateSinkObject.Save(21, &e.boundBindToDevice) - stateSinkObject.Save(22, &e.boundPortFlags) - stateSinkObject.Save(23, &e.sendTOS) - stateSinkObject.Save(24, &e.receiveTOS) - stateSinkObject.Save(25, &e.receiveTClass) - stateSinkObject.Save(26, &e.receiveIPPacketInfo) - stateSinkObject.Save(27, &e.shutdownFlags) - stateSinkObject.Save(28, &e.multicastMemberships) - stateSinkObject.Save(29, &e.effectiveNetProtos) - stateSinkObject.Save(30, &e.owner) - stateSinkObject.Save(31, &e.linger) - stateSinkObject.Save(32, &e.ops) + stateSinkObject.Save(1, &e.DefaultSocketOptionsHandler) + stateSinkObject.Save(2, &e.waiterQueue) + stateSinkObject.Save(3, &e.uniqueID) + stateSinkObject.Save(4, &e.rcvReady) + stateSinkObject.Save(5, &e.rcvList) + stateSinkObject.Save(7, &e.rcvBufSize) + stateSinkObject.Save(8, &e.rcvClosed) + stateSinkObject.Save(9, &e.sndBufSize) + stateSinkObject.Save(10, &e.sndBufSizeMax) + stateSinkObject.Save(11, &e.state) + stateSinkObject.Save(12, &e.dstPort) + stateSinkObject.Save(13, &e.v6only) + stateSinkObject.Save(14, &e.ttl) + stateSinkObject.Save(15, &e.multicastTTL) + stateSinkObject.Save(16, &e.multicastAddr) + stateSinkObject.Save(17, &e.multicastNICID) + stateSinkObject.Save(18, &e.multicastLoop) + stateSinkObject.Save(19, &e.portFlags) + stateSinkObject.Save(20, &e.bindToDevice) + stateSinkObject.Save(22, &e.boundBindToDevice) + stateSinkObject.Save(23, &e.boundPortFlags) + stateSinkObject.Save(24, &e.sendTOS) + stateSinkObject.Save(25, &e.receiveTOS) + stateSinkObject.Save(26, &e.receiveTClass) + stateSinkObject.Save(27, &e.receiveIPPacketInfo) + stateSinkObject.Save(28, &e.shutdownFlags) + stateSinkObject.Save(29, &e.multicastMemberships) + stateSinkObject.Save(30, &e.effectiveNetProtos) + stateSinkObject.Save(31, &e.owner) + stateSinkObject.Save(32, &e.linger) + stateSinkObject.Save(33, &e.ops) } func (e *endpoint) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &e.TransportEndpointInfo) - stateSourceObject.Load(1, &e.waiterQueue) - stateSourceObject.Load(2, &e.uniqueID) - stateSourceObject.Load(3, &e.rcvReady) - stateSourceObject.Load(4, &e.rcvList) - stateSourceObject.Load(6, &e.rcvBufSize) - stateSourceObject.Load(7, &e.rcvClosed) - stateSourceObject.Load(8, &e.sndBufSize) - stateSourceObject.Load(9, &e.sndBufSizeMax) - stateSourceObject.Load(10, &e.state) - stateSourceObject.Load(11, &e.dstPort) - stateSourceObject.Load(12, &e.v6only) - stateSourceObject.Load(13, &e.ttl) - stateSourceObject.Load(14, &e.multicastTTL) - stateSourceObject.Load(15, &e.multicastAddr) - stateSourceObject.Load(16, &e.multicastNICID) - stateSourceObject.Load(17, &e.multicastLoop) - stateSourceObject.Load(18, &e.portFlags) - stateSourceObject.Load(19, &e.bindToDevice) - stateSourceObject.Load(21, &e.boundBindToDevice) - stateSourceObject.Load(22, &e.boundPortFlags) - stateSourceObject.Load(23, &e.sendTOS) - stateSourceObject.Load(24, &e.receiveTOS) - stateSourceObject.Load(25, &e.receiveTClass) - stateSourceObject.Load(26, &e.receiveIPPacketInfo) - stateSourceObject.Load(27, &e.shutdownFlags) - stateSourceObject.Load(28, &e.multicastMemberships) - stateSourceObject.Load(29, &e.effectiveNetProtos) - stateSourceObject.Load(30, &e.owner) - stateSourceObject.Load(31, &e.linger) - stateSourceObject.Load(32, &e.ops) - stateSourceObject.LoadValue(5, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) - stateSourceObject.LoadValue(20, new(string), func(y interface{}) { e.loadLastError(y.(string)) }) + stateSourceObject.Load(1, &e.DefaultSocketOptionsHandler) + stateSourceObject.Load(2, &e.waiterQueue) + stateSourceObject.Load(3, &e.uniqueID) + stateSourceObject.Load(4, &e.rcvReady) + stateSourceObject.Load(5, &e.rcvList) + stateSourceObject.Load(7, &e.rcvBufSize) + stateSourceObject.Load(8, &e.rcvClosed) + stateSourceObject.Load(9, &e.sndBufSize) + stateSourceObject.Load(10, &e.sndBufSizeMax) + stateSourceObject.Load(11, &e.state) + stateSourceObject.Load(12, &e.dstPort) + stateSourceObject.Load(13, &e.v6only) + stateSourceObject.Load(14, &e.ttl) + stateSourceObject.Load(15, &e.multicastTTL) + stateSourceObject.Load(16, &e.multicastAddr) + stateSourceObject.Load(17, &e.multicastNICID) + stateSourceObject.Load(18, &e.multicastLoop) + stateSourceObject.Load(19, &e.portFlags) + stateSourceObject.Load(20, &e.bindToDevice) + stateSourceObject.Load(22, &e.boundBindToDevice) + stateSourceObject.Load(23, &e.boundPortFlags) + stateSourceObject.Load(24, &e.sendTOS) + stateSourceObject.Load(25, &e.receiveTOS) + stateSourceObject.Load(26, &e.receiveTClass) + stateSourceObject.Load(27, &e.receiveIPPacketInfo) + stateSourceObject.Load(28, &e.shutdownFlags) + stateSourceObject.Load(29, &e.multicastMemberships) + stateSourceObject.Load(30, &e.effectiveNetProtos) + stateSourceObject.Load(31, &e.owner) + stateSourceObject.Load(32, &e.linger) + stateSourceObject.Load(33, &e.ops) + stateSourceObject.LoadValue(6, new(int), func(y interface{}) { e.loadRcvBufSizeMax(y.(int)) }) + stateSourceObject.LoadValue(21, new(string), func(y interface{}) { e.loadLastError(y.(string)) }) stateSourceObject.AfterLoad(e.afterLoad) } |