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 }