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