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