gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/socketops.go (about)

     1  // Copyright 2020 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package tcpip
    16  
    17  import (
    18  	"gvisor.dev/gvisor/pkg/atomicbitops"
    19  	"gvisor.dev/gvisor/pkg/buffer"
    20  	"gvisor.dev/gvisor/pkg/sync"
    21  )
    22  
    23  // SocketOptionsHandler holds methods that help define endpoint specific
    24  // behavior for socket level socket options. These must be implemented by
    25  // endpoints to get notified when socket level options are set.
    26  type SocketOptionsHandler interface {
    27  	// OnReuseAddressSet is invoked when SO_REUSEADDR is set for an endpoint.
    28  	OnReuseAddressSet(v bool)
    29  
    30  	// OnReusePortSet is invoked when SO_REUSEPORT is set for an endpoint.
    31  	OnReusePortSet(v bool)
    32  
    33  	// OnKeepAliveSet is invoked when SO_KEEPALIVE is set for an endpoint.
    34  	OnKeepAliveSet(v bool)
    35  
    36  	// OnDelayOptionSet is invoked when TCP_NODELAY is set for an endpoint.
    37  	// Note that v will be the inverse of TCP_NODELAY option.
    38  	OnDelayOptionSet(v bool)
    39  
    40  	// OnCorkOptionSet is invoked when TCP_CORK is set for an endpoint.
    41  	OnCorkOptionSet(v bool)
    42  
    43  	// LastError is invoked when SO_ERROR is read for an endpoint.
    44  	LastError() Error
    45  
    46  	// UpdateLastError updates the endpoint specific last error field.
    47  	UpdateLastError(err Error)
    48  
    49  	// HasNIC is invoked to check if the NIC is valid for SO_BINDTODEVICE.
    50  	HasNIC(v int32) bool
    51  
    52  	// OnSetSendBufferSize is invoked when the send buffer size for an endpoint is
    53  	// changed. The handler is invoked with the new value for the socket send
    54  	// buffer size. It also returns the newly set value.
    55  	OnSetSendBufferSize(v int64) (newSz int64)
    56  
    57  	// OnSetReceiveBufferSize is invoked by SO_RCVBUF and SO_RCVBUFFORCE. The
    58  	// handler can optionally return a callback which will be called after
    59  	// the buffer size is updated to newSz.
    60  	OnSetReceiveBufferSize(v, oldSz int64) (newSz int64, postSet func())
    61  
    62  	// WakeupWriters is invoked when the send buffer size for an endpoint is
    63  	// changed. The handler notifies the writers if the send buffer size is
    64  	// increased with setsockopt(2) for TCP endpoints.
    65  	WakeupWriters()
    66  
    67  	// GetAcceptConn returns true if the socket is a TCP socket and is in
    68  	// listening state.
    69  	GetAcceptConn() bool
    70  }
    71  
    72  // DefaultSocketOptionsHandler is an embeddable type that implements no-op
    73  // implementations for SocketOptionsHandler methods.
    74  type DefaultSocketOptionsHandler struct{}
    75  
    76  var _ SocketOptionsHandler = (*DefaultSocketOptionsHandler)(nil)
    77  
    78  // OnReuseAddressSet implements SocketOptionsHandler.OnReuseAddressSet.
    79  func (*DefaultSocketOptionsHandler) OnReuseAddressSet(bool) {}
    80  
    81  // OnReusePortSet implements SocketOptionsHandler.OnReusePortSet.
    82  func (*DefaultSocketOptionsHandler) OnReusePortSet(bool) {}
    83  
    84  // OnKeepAliveSet implements SocketOptionsHandler.OnKeepAliveSet.
    85  func (*DefaultSocketOptionsHandler) OnKeepAliveSet(bool) {}
    86  
    87  // OnDelayOptionSet implements SocketOptionsHandler.OnDelayOptionSet.
    88  func (*DefaultSocketOptionsHandler) OnDelayOptionSet(bool) {}
    89  
    90  // OnCorkOptionSet implements SocketOptionsHandler.OnCorkOptionSet.
    91  func (*DefaultSocketOptionsHandler) OnCorkOptionSet(bool) {}
    92  
    93  // LastError implements SocketOptionsHandler.LastError.
    94  func (*DefaultSocketOptionsHandler) LastError() Error {
    95  	return nil
    96  }
    97  
    98  // UpdateLastError implements SocketOptionsHandler.UpdateLastError.
    99  func (*DefaultSocketOptionsHandler) UpdateLastError(Error) {}
   100  
   101  // HasNIC implements SocketOptionsHandler.HasNIC.
   102  func (*DefaultSocketOptionsHandler) HasNIC(int32) bool {
   103  	return false
   104  }
   105  
   106  // OnSetSendBufferSize implements SocketOptionsHandler.OnSetSendBufferSize.
   107  func (*DefaultSocketOptionsHandler) OnSetSendBufferSize(v int64) (newSz int64) {
   108  	return v
   109  }
   110  
   111  // WakeupWriters implements SocketOptionsHandler.WakeupWriters.
   112  func (*DefaultSocketOptionsHandler) WakeupWriters() {}
   113  
   114  // OnSetReceiveBufferSize implements SocketOptionsHandler.OnSetReceiveBufferSize.
   115  func (*DefaultSocketOptionsHandler) OnSetReceiveBufferSize(v, oldSz int64) (newSz int64, postSet func()) {
   116  	return v, nil
   117  }
   118  
   119  // GetAcceptConn implements SocketOptionsHandler.GetAcceptConn.
   120  func (*DefaultSocketOptionsHandler) GetAcceptConn() bool {
   121  	return false
   122  }
   123  
   124  // StackHandler holds methods to access the stack options. These must be
   125  // implemented by the stack.
   126  type StackHandler interface {
   127  	// Option allows retrieving stack wide options.
   128  	Option(option any) Error
   129  
   130  	// TransportProtocolOption allows retrieving individual protocol level
   131  	// option values.
   132  	TransportProtocolOption(proto TransportProtocolNumber, option GettableTransportProtocolOption) Error
   133  }
   134  
   135  // SocketOptions contains all the variables which store values for SOL_SOCKET,
   136  // SOL_IP, SOL_IPV6 and SOL_TCP level options.
   137  //
   138  // +stateify savable
   139  type SocketOptions struct {
   140  	handler SocketOptionsHandler
   141  
   142  	// StackHandler is initialized at the creation time and will not change.
   143  	stackHandler StackHandler `state:"manual"`
   144  
   145  	// These fields are accessed and modified using atomic operations.
   146  
   147  	// broadcastEnabled determines whether datagram sockets are allowed to
   148  	// send packets to a broadcast address.
   149  	broadcastEnabled atomicbitops.Uint32
   150  
   151  	// passCredEnabled determines whether SCM_CREDENTIALS socket control
   152  	// messages are enabled.
   153  	passCredEnabled atomicbitops.Uint32
   154  
   155  	// noChecksumEnabled determines whether UDP checksum is disabled while
   156  	// transmitting for this socket.
   157  	noChecksumEnabled atomicbitops.Uint32
   158  
   159  	// reuseAddressEnabled determines whether Bind() should allow reuse of
   160  	// local address.
   161  	reuseAddressEnabled atomicbitops.Uint32
   162  
   163  	// reusePortEnabled determines whether to permit multiple sockets to be
   164  	// bound to an identical socket address.
   165  	reusePortEnabled atomicbitops.Uint32
   166  
   167  	// keepAliveEnabled determines whether TCP keepalive is enabled for this
   168  	// socket.
   169  	keepAliveEnabled atomicbitops.Uint32
   170  
   171  	// multicastLoopEnabled determines whether multicast packets sent over a
   172  	// non-loopback interface will be looped back.
   173  	multicastLoopEnabled atomicbitops.Uint32
   174  
   175  	// receiveTOSEnabled is used to specify if the TOS ancillary message is
   176  	// passed with incoming packets.
   177  	receiveTOSEnabled atomicbitops.Uint32
   178  
   179  	// receiveTTLEnabled is used to specify if the TTL ancillary message is passed
   180  	// with incoming packets.
   181  	receiveTTLEnabled atomicbitops.Uint32
   182  
   183  	// receiveHopLimitEnabled is used to specify if the HopLimit ancillary message
   184  	// is passed with incoming packets.
   185  	receiveHopLimitEnabled atomicbitops.Uint32
   186  
   187  	// receiveTClassEnabled is used to specify if the IPV6_TCLASS ancillary
   188  	// message is passed with incoming packets.
   189  	receiveTClassEnabled atomicbitops.Uint32
   190  
   191  	// receivePacketInfoEnabled is used to specify if more information is
   192  	// provided with incoming IPv4 packets.
   193  	receivePacketInfoEnabled atomicbitops.Uint32
   194  
   195  	// receivePacketInfoEnabled is used to specify if more information is
   196  	// provided with incoming IPv6 packets.
   197  	receiveIPv6PacketInfoEnabled atomicbitops.Uint32
   198  
   199  	// hdrIncludeEnabled is used to indicate for a raw endpoint that all packets
   200  	// being written have an IP header and the endpoint should not attach an IP
   201  	// header.
   202  	hdrIncludedEnabled atomicbitops.Uint32
   203  
   204  	// v6OnlyEnabled is used to determine whether an IPv6 socket is to be
   205  	// restricted to sending and receiving IPv6 packets only.
   206  	v6OnlyEnabled atomicbitops.Uint32
   207  
   208  	// quickAckEnabled is used to represent the value of TCP_QUICKACK option.
   209  	// It currently does not have any effect on the TCP endpoint.
   210  	quickAckEnabled atomicbitops.Uint32
   211  
   212  	// delayOptionEnabled is used to specify if data should be sent out immediately
   213  	// by the transport protocol. For TCP, it determines if the Nagle algorithm
   214  	// is on or off.
   215  	delayOptionEnabled atomicbitops.Uint32
   216  
   217  	// corkOptionEnabled is used to specify if data should be held until segments
   218  	// are full by the TCP transport protocol.
   219  	corkOptionEnabled atomicbitops.Uint32
   220  
   221  	// receiveOriginalDstAddress is used to specify if the original destination of
   222  	// the incoming packet should be returned as an ancillary message.
   223  	receiveOriginalDstAddress atomicbitops.Uint32
   224  
   225  	// ipv4RecvErrEnabled determines whether extended reliable error message
   226  	// passing is enabled for IPv4.
   227  	ipv4RecvErrEnabled atomicbitops.Uint32
   228  
   229  	// ipv6RecvErrEnabled determines whether extended reliable error message
   230  	// passing is enabled for IPv6.
   231  	ipv6RecvErrEnabled atomicbitops.Uint32
   232  
   233  	// errQueue is the per-socket error queue. It is protected by errQueueMu.
   234  	errQueueMu sync.Mutex `state:"nosave"`
   235  	errQueue   sockErrorList
   236  
   237  	// bindToDevice determines the device to which the socket is bound.
   238  	bindToDevice atomicbitops.Int32
   239  
   240  	// getSendBufferLimits provides the handler to get the min, default and max
   241  	// size for send buffer. It is initialized at the creation time and will not
   242  	// change.
   243  	getSendBufferLimits GetSendBufferLimits `state:"manual"`
   244  
   245  	// sendBufferSize determines the send buffer size for this socket.
   246  	sendBufferSize atomicbitops.Int64
   247  
   248  	// getReceiveBufferLimits provides the handler to get the min, default and
   249  	// max size for receive buffer. It is initialized at the creation time and
   250  	// will not change.
   251  	getReceiveBufferLimits GetReceiveBufferLimits `state:"manual"`
   252  
   253  	// receiveBufferSize determines the receive buffer size for this socket.
   254  	receiveBufferSize atomicbitops.Int64
   255  
   256  	// mu protects the access to the below fields.
   257  	mu sync.Mutex `state:"nosave"`
   258  
   259  	// linger determines the amount of time the socket should linger before
   260  	// close. We currently implement this option for TCP socket only.
   261  	linger LingerOption
   262  
   263  	// rcvlowat specifies the minimum number of bytes which should be
   264  	// received to indicate the socket as readable.
   265  	rcvlowat atomicbitops.Int32
   266  }
   267  
   268  // InitHandler initializes the handler. This must be called before using the
   269  // socket options utility.
   270  func (so *SocketOptions) InitHandler(handler SocketOptionsHandler, stack StackHandler, getSendBufferLimits GetSendBufferLimits, getReceiveBufferLimits GetReceiveBufferLimits) {
   271  	so.handler = handler
   272  	so.stackHandler = stack
   273  	so.getSendBufferLimits = getSendBufferLimits
   274  	so.getReceiveBufferLimits = getReceiveBufferLimits
   275  }
   276  
   277  func storeAtomicBool(addr *atomicbitops.Uint32, v bool) {
   278  	var val uint32
   279  	if v {
   280  		val = 1
   281  	}
   282  	addr.Store(val)
   283  }
   284  
   285  // SetLastError sets the last error for a socket.
   286  func (so *SocketOptions) SetLastError(err Error) {
   287  	so.handler.UpdateLastError(err)
   288  }
   289  
   290  // GetBroadcast gets value for SO_BROADCAST option.
   291  func (so *SocketOptions) GetBroadcast() bool {
   292  	return so.broadcastEnabled.Load() != 0
   293  }
   294  
   295  // SetBroadcast sets value for SO_BROADCAST option.
   296  func (so *SocketOptions) SetBroadcast(v bool) {
   297  	storeAtomicBool(&so.broadcastEnabled, v)
   298  }
   299  
   300  // GetPassCred gets value for SO_PASSCRED option.
   301  func (so *SocketOptions) GetPassCred() bool {
   302  	return so.passCredEnabled.Load() != 0
   303  }
   304  
   305  // SetPassCred sets value for SO_PASSCRED option.
   306  func (so *SocketOptions) SetPassCred(v bool) {
   307  	storeAtomicBool(&so.passCredEnabled, v)
   308  }
   309  
   310  // GetNoChecksum gets value for SO_NO_CHECK option.
   311  func (so *SocketOptions) GetNoChecksum() bool {
   312  	return so.noChecksumEnabled.Load() != 0
   313  }
   314  
   315  // SetNoChecksum sets value for SO_NO_CHECK option.
   316  func (so *SocketOptions) SetNoChecksum(v bool) {
   317  	storeAtomicBool(&so.noChecksumEnabled, v)
   318  }
   319  
   320  // GetReuseAddress gets value for SO_REUSEADDR option.
   321  func (so *SocketOptions) GetReuseAddress() bool {
   322  	return so.reuseAddressEnabled.Load() != 0
   323  }
   324  
   325  // SetReuseAddress sets value for SO_REUSEADDR option.
   326  func (so *SocketOptions) SetReuseAddress(v bool) {
   327  	storeAtomicBool(&so.reuseAddressEnabled, v)
   328  	so.handler.OnReuseAddressSet(v)
   329  }
   330  
   331  // GetReusePort gets value for SO_REUSEPORT option.
   332  func (so *SocketOptions) GetReusePort() bool {
   333  	return so.reusePortEnabled.Load() != 0
   334  }
   335  
   336  // SetReusePort sets value for SO_REUSEPORT option.
   337  func (so *SocketOptions) SetReusePort(v bool) {
   338  	storeAtomicBool(&so.reusePortEnabled, v)
   339  	so.handler.OnReusePortSet(v)
   340  }
   341  
   342  // GetKeepAlive gets value for SO_KEEPALIVE option.
   343  func (so *SocketOptions) GetKeepAlive() bool {
   344  	return so.keepAliveEnabled.Load() != 0
   345  }
   346  
   347  // SetKeepAlive sets value for SO_KEEPALIVE option.
   348  func (so *SocketOptions) SetKeepAlive(v bool) {
   349  	storeAtomicBool(&so.keepAliveEnabled, v)
   350  	so.handler.OnKeepAliveSet(v)
   351  }
   352  
   353  // GetMulticastLoop gets value for IP_MULTICAST_LOOP option.
   354  func (so *SocketOptions) GetMulticastLoop() bool {
   355  	return so.multicastLoopEnabled.Load() != 0
   356  }
   357  
   358  // SetMulticastLoop sets value for IP_MULTICAST_LOOP option.
   359  func (so *SocketOptions) SetMulticastLoop(v bool) {
   360  	storeAtomicBool(&so.multicastLoopEnabled, v)
   361  }
   362  
   363  // GetReceiveTOS gets value for IP_RECVTOS option.
   364  func (so *SocketOptions) GetReceiveTOS() bool {
   365  	return so.receiveTOSEnabled.Load() != 0
   366  }
   367  
   368  // SetReceiveTOS sets value for IP_RECVTOS option.
   369  func (so *SocketOptions) SetReceiveTOS(v bool) {
   370  	storeAtomicBool(&so.receiveTOSEnabled, v)
   371  }
   372  
   373  // GetReceiveTTL gets value for IP_RECVTTL option.
   374  func (so *SocketOptions) GetReceiveTTL() bool {
   375  	return so.receiveTTLEnabled.Load() != 0
   376  }
   377  
   378  // SetReceiveTTL sets value for IP_RECVTTL option.
   379  func (so *SocketOptions) SetReceiveTTL(v bool) {
   380  	storeAtomicBool(&so.receiveTTLEnabled, v)
   381  }
   382  
   383  // GetReceiveHopLimit gets value for IP_RECVHOPLIMIT option.
   384  func (so *SocketOptions) GetReceiveHopLimit() bool {
   385  	return so.receiveHopLimitEnabled.Load() != 0
   386  }
   387  
   388  // SetReceiveHopLimit sets value for IP_RECVHOPLIMIT option.
   389  func (so *SocketOptions) SetReceiveHopLimit(v bool) {
   390  	storeAtomicBool(&so.receiveHopLimitEnabled, v)
   391  }
   392  
   393  // GetReceiveTClass gets value for IPV6_RECVTCLASS option.
   394  func (so *SocketOptions) GetReceiveTClass() bool {
   395  	return so.receiveTClassEnabled.Load() != 0
   396  }
   397  
   398  // SetReceiveTClass sets value for IPV6_RECVTCLASS option.
   399  func (so *SocketOptions) SetReceiveTClass(v bool) {
   400  	storeAtomicBool(&so.receiveTClassEnabled, v)
   401  }
   402  
   403  // GetReceivePacketInfo gets value for IP_PKTINFO option.
   404  func (so *SocketOptions) GetReceivePacketInfo() bool {
   405  	return so.receivePacketInfoEnabled.Load() != 0
   406  }
   407  
   408  // SetReceivePacketInfo sets value for IP_PKTINFO option.
   409  func (so *SocketOptions) SetReceivePacketInfo(v bool) {
   410  	storeAtomicBool(&so.receivePacketInfoEnabled, v)
   411  }
   412  
   413  // GetIPv6ReceivePacketInfo gets value for IPV6_RECVPKTINFO option.
   414  func (so *SocketOptions) GetIPv6ReceivePacketInfo() bool {
   415  	return so.receiveIPv6PacketInfoEnabled.Load() != 0
   416  }
   417  
   418  // SetIPv6ReceivePacketInfo sets value for IPV6_RECVPKTINFO option.
   419  func (so *SocketOptions) SetIPv6ReceivePacketInfo(v bool) {
   420  	storeAtomicBool(&so.receiveIPv6PacketInfoEnabled, v)
   421  }
   422  
   423  // GetHeaderIncluded gets value for IP_HDRINCL option.
   424  func (so *SocketOptions) GetHeaderIncluded() bool {
   425  	return so.hdrIncludedEnabled.Load() != 0
   426  }
   427  
   428  // SetHeaderIncluded sets value for IP_HDRINCL option.
   429  func (so *SocketOptions) SetHeaderIncluded(v bool) {
   430  	storeAtomicBool(&so.hdrIncludedEnabled, v)
   431  }
   432  
   433  // GetV6Only gets value for IPV6_V6ONLY option.
   434  func (so *SocketOptions) GetV6Only() bool {
   435  	return so.v6OnlyEnabled.Load() != 0
   436  }
   437  
   438  // SetV6Only sets value for IPV6_V6ONLY option.
   439  //
   440  // Preconditions: the backing TCP or UDP endpoint must be in initial state.
   441  func (so *SocketOptions) SetV6Only(v bool) {
   442  	storeAtomicBool(&so.v6OnlyEnabled, v)
   443  }
   444  
   445  // GetQuickAck gets value for TCP_QUICKACK option.
   446  func (so *SocketOptions) GetQuickAck() bool {
   447  	return so.quickAckEnabled.Load() != 0
   448  }
   449  
   450  // SetQuickAck sets value for TCP_QUICKACK option.
   451  func (so *SocketOptions) SetQuickAck(v bool) {
   452  	storeAtomicBool(&so.quickAckEnabled, v)
   453  }
   454  
   455  // GetDelayOption gets inverted value for TCP_NODELAY option.
   456  func (so *SocketOptions) GetDelayOption() bool {
   457  	return so.delayOptionEnabled.Load() != 0
   458  }
   459  
   460  // SetDelayOption sets inverted value for TCP_NODELAY option.
   461  func (so *SocketOptions) SetDelayOption(v bool) {
   462  	storeAtomicBool(&so.delayOptionEnabled, v)
   463  	so.handler.OnDelayOptionSet(v)
   464  }
   465  
   466  // GetCorkOption gets value for TCP_CORK option.
   467  func (so *SocketOptions) GetCorkOption() bool {
   468  	return so.corkOptionEnabled.Load() != 0
   469  }
   470  
   471  // SetCorkOption sets value for TCP_CORK option.
   472  func (so *SocketOptions) SetCorkOption(v bool) {
   473  	storeAtomicBool(&so.corkOptionEnabled, v)
   474  	so.handler.OnCorkOptionSet(v)
   475  }
   476  
   477  // GetReceiveOriginalDstAddress gets value for IP(V6)_RECVORIGDSTADDR option.
   478  func (so *SocketOptions) GetReceiveOriginalDstAddress() bool {
   479  	return so.receiveOriginalDstAddress.Load() != 0
   480  }
   481  
   482  // SetReceiveOriginalDstAddress sets value for IP(V6)_RECVORIGDSTADDR option.
   483  func (so *SocketOptions) SetReceiveOriginalDstAddress(v bool) {
   484  	storeAtomicBool(&so.receiveOriginalDstAddress, v)
   485  }
   486  
   487  // GetIPv4RecvError gets value for IP_RECVERR option.
   488  func (so *SocketOptions) GetIPv4RecvError() bool {
   489  	return so.ipv4RecvErrEnabled.Load() != 0
   490  }
   491  
   492  // SetIPv4RecvError sets value for IP_RECVERR option.
   493  func (so *SocketOptions) SetIPv4RecvError(v bool) {
   494  	storeAtomicBool(&so.ipv4RecvErrEnabled, v)
   495  	if !v {
   496  		so.pruneErrQueue()
   497  	}
   498  }
   499  
   500  // GetIPv6RecvError gets value for IPV6_RECVERR option.
   501  func (so *SocketOptions) GetIPv6RecvError() bool {
   502  	return so.ipv6RecvErrEnabled.Load() != 0
   503  }
   504  
   505  // SetIPv6RecvError sets value for IPV6_RECVERR option.
   506  func (so *SocketOptions) SetIPv6RecvError(v bool) {
   507  	storeAtomicBool(&so.ipv6RecvErrEnabled, v)
   508  	if !v {
   509  		so.pruneErrQueue()
   510  	}
   511  }
   512  
   513  // GetLastError gets value for SO_ERROR option.
   514  func (so *SocketOptions) GetLastError() Error {
   515  	return so.handler.LastError()
   516  }
   517  
   518  // GetOutOfBandInline gets value for SO_OOBINLINE option.
   519  func (*SocketOptions) GetOutOfBandInline() bool {
   520  	return true
   521  }
   522  
   523  // SetOutOfBandInline sets value for SO_OOBINLINE option. We currently do not
   524  // support disabling this option.
   525  func (*SocketOptions) SetOutOfBandInline(bool) {}
   526  
   527  // GetLinger gets value for SO_LINGER option.
   528  func (so *SocketOptions) GetLinger() LingerOption {
   529  	so.mu.Lock()
   530  	linger := so.linger
   531  	so.mu.Unlock()
   532  	return linger
   533  }
   534  
   535  // SetLinger sets value for SO_LINGER option.
   536  func (so *SocketOptions) SetLinger(linger LingerOption) {
   537  	so.mu.Lock()
   538  	so.linger = linger
   539  	so.mu.Unlock()
   540  }
   541  
   542  // SockErrOrigin represents the constants for error origin.
   543  type SockErrOrigin uint8
   544  
   545  const (
   546  	// SockExtErrorOriginNone represents an unknown error origin.
   547  	SockExtErrorOriginNone SockErrOrigin = iota
   548  
   549  	// SockExtErrorOriginLocal indicates a local error.
   550  	SockExtErrorOriginLocal
   551  
   552  	// SockExtErrorOriginICMP indicates an IPv4 ICMP error.
   553  	SockExtErrorOriginICMP
   554  
   555  	// SockExtErrorOriginICMP6 indicates an IPv6 ICMP error.
   556  	SockExtErrorOriginICMP6
   557  )
   558  
   559  // IsICMPErr indicates if the error originated from an ICMP error.
   560  func (origin SockErrOrigin) IsICMPErr() bool {
   561  	return origin == SockExtErrorOriginICMP || origin == SockExtErrorOriginICMP6
   562  }
   563  
   564  // SockErrorCause is the cause of a socket error.
   565  type SockErrorCause interface {
   566  	// Origin is the source of the error.
   567  	Origin() SockErrOrigin
   568  
   569  	// Type is the origin specific type of error.
   570  	Type() uint8
   571  
   572  	// Code is the origin and type specific error code.
   573  	Code() uint8
   574  
   575  	// Info is any extra information about the error.
   576  	Info() uint32
   577  }
   578  
   579  // LocalSockError is a socket error that originated from the local host.
   580  //
   581  // +stateify savable
   582  type LocalSockError struct {
   583  	info uint32
   584  }
   585  
   586  // Origin implements SockErrorCause.
   587  func (*LocalSockError) Origin() SockErrOrigin {
   588  	return SockExtErrorOriginLocal
   589  }
   590  
   591  // Type implements SockErrorCause.
   592  func (*LocalSockError) Type() uint8 {
   593  	return 0
   594  }
   595  
   596  // Code implements SockErrorCause.
   597  func (*LocalSockError) Code() uint8 {
   598  	return 0
   599  }
   600  
   601  // Info implements SockErrorCause.
   602  func (l *LocalSockError) Info() uint32 {
   603  	return l.info
   604  }
   605  
   606  // SockError represents a queue entry in the per-socket error queue.
   607  //
   608  // +stateify savable
   609  type SockError struct {
   610  	sockErrorEntry
   611  
   612  	// Err is the error caused by the errant packet.
   613  	Err Error
   614  	// Cause is the detailed cause of the error.
   615  	Cause SockErrorCause
   616  
   617  	// Payload is the errant packet's payload.
   618  	Payload *buffer.View
   619  	// Dst is the original destination address of the errant packet.
   620  	Dst FullAddress
   621  	// Offender is the original sender address of the errant packet.
   622  	Offender FullAddress
   623  	// NetProto is the network protocol being used to transmit the packet.
   624  	NetProto NetworkProtocolNumber
   625  }
   626  
   627  // pruneErrQueue resets the queue.
   628  func (so *SocketOptions) pruneErrQueue() {
   629  	so.errQueueMu.Lock()
   630  	so.errQueue.Reset()
   631  	so.errQueueMu.Unlock()
   632  }
   633  
   634  // DequeueErr dequeues a socket extended error from the error queue and returns
   635  // it. Returns nil if queue is empty.
   636  func (so *SocketOptions) DequeueErr() *SockError {
   637  	so.errQueueMu.Lock()
   638  	defer so.errQueueMu.Unlock()
   639  
   640  	err := so.errQueue.Front()
   641  	if err != nil {
   642  		so.errQueue.Remove(err)
   643  	}
   644  	return err
   645  }
   646  
   647  // PeekErr returns the error in the front of the error queue. Returns nil if
   648  // the error queue is empty.
   649  func (so *SocketOptions) PeekErr() *SockError {
   650  	so.errQueueMu.Lock()
   651  	defer so.errQueueMu.Unlock()
   652  	return so.errQueue.Front()
   653  }
   654  
   655  // QueueErr inserts the error at the back of the error queue.
   656  //
   657  // Preconditions: so.GetIPv4RecvError() or so.GetIPv6RecvError() is true.
   658  func (so *SocketOptions) QueueErr(err *SockError) {
   659  	so.errQueueMu.Lock()
   660  	defer so.errQueueMu.Unlock()
   661  	so.errQueue.PushBack(err)
   662  }
   663  
   664  // QueueLocalErr queues a local error onto the local queue.
   665  func (so *SocketOptions) QueueLocalErr(err Error, net NetworkProtocolNumber, info uint32, dst FullAddress, payload *buffer.View) {
   666  	so.QueueErr(&SockError{
   667  		Err:      err,
   668  		Cause:    &LocalSockError{info: info},
   669  		Payload:  payload,
   670  		Dst:      dst,
   671  		NetProto: net,
   672  	})
   673  }
   674  
   675  // GetBindToDevice gets value for SO_BINDTODEVICE option.
   676  func (so *SocketOptions) GetBindToDevice() int32 {
   677  	return so.bindToDevice.Load()
   678  }
   679  
   680  // SetBindToDevice sets value for SO_BINDTODEVICE option. If bindToDevice is
   681  // zero, the socket device binding is removed.
   682  func (so *SocketOptions) SetBindToDevice(bindToDevice int32) Error {
   683  	if bindToDevice != 0 && !so.handler.HasNIC(bindToDevice) {
   684  		return &ErrUnknownDevice{}
   685  	}
   686  
   687  	so.bindToDevice.Store(bindToDevice)
   688  	return nil
   689  }
   690  
   691  // GetSendBufferSize gets value for SO_SNDBUF option.
   692  func (so *SocketOptions) GetSendBufferSize() int64 {
   693  	return so.sendBufferSize.Load()
   694  }
   695  
   696  // SendBufferLimits returns the [min, max) range of allowable send buffer
   697  // sizes.
   698  func (so *SocketOptions) SendBufferLimits() (min, max int64) {
   699  	limits := so.getSendBufferLimits(so.stackHandler)
   700  	return int64(limits.Min), int64(limits.Max)
   701  }
   702  
   703  // SetSendBufferSize sets value for SO_SNDBUF option. notify indicates if the
   704  // stack handler should be invoked to set the send buffer size.
   705  func (so *SocketOptions) SetSendBufferSize(sendBufferSize int64, notify bool) {
   706  	if notify {
   707  		sendBufferSize = so.handler.OnSetSendBufferSize(sendBufferSize)
   708  	}
   709  	so.sendBufferSize.Store(sendBufferSize)
   710  	if notify {
   711  		so.handler.WakeupWriters()
   712  	}
   713  }
   714  
   715  // GetReceiveBufferSize gets value for SO_RCVBUF option.
   716  func (so *SocketOptions) GetReceiveBufferSize() int64 {
   717  	return so.receiveBufferSize.Load()
   718  }
   719  
   720  // ReceiveBufferLimits returns the [min, max) range of allowable receive buffer
   721  // sizes.
   722  func (so *SocketOptions) ReceiveBufferLimits() (min, max int64) {
   723  	limits := so.getReceiveBufferLimits(so.stackHandler)
   724  	return int64(limits.Min), int64(limits.Max)
   725  }
   726  
   727  // SetReceiveBufferSize sets the value of the SO_RCVBUF option, optionally
   728  // notifying the owning endpoint.
   729  func (so *SocketOptions) SetReceiveBufferSize(receiveBufferSize int64, notify bool) {
   730  	var postSet func()
   731  	if notify {
   732  		oldSz := so.receiveBufferSize.Load()
   733  		receiveBufferSize, postSet = so.handler.OnSetReceiveBufferSize(receiveBufferSize, oldSz)
   734  	}
   735  	so.receiveBufferSize.Store(receiveBufferSize)
   736  	if postSet != nil {
   737  		postSet()
   738  	}
   739  }
   740  
   741  // GetRcvlowat gets value for SO_RCVLOWAT option.
   742  func (so *SocketOptions) GetRcvlowat() int32 {
   743  	// TODO(b/226603727): Return so.rcvlowat after adding complete support
   744  	// for SO_RCVLOWAT option. For now, return the default value of 1.
   745  	defaultRcvlowat := int32(1)
   746  	return defaultRcvlowat
   747  }
   748  
   749  // SetRcvlowat sets value for SO_RCVLOWAT option.
   750  func (so *SocketOptions) SetRcvlowat(rcvlowat int32) Error {
   751  	so.rcvlowat.Store(rcvlowat)
   752  	return nil
   753  }
   754  
   755  // GetAcceptConn gets value for SO_ACCEPTCONN option.
   756  func (so *SocketOptions) GetAcceptConn() bool {
   757  	return so.handler.GetAcceptConn()
   758  }