GETSOCKOPT(2)

πŸ’– GETSOCKOPT(2) πŸ’– β€” System Calls Manual, bestie edition

okay so. this is the page for getsockopt and setsockopt, and it lives in section 2 (system calls) of the manual. yes the header says GETSOCKOPT(2) on both sides, that's just how manpages flex. sit down, hydrate, we're doing socket options 🫢


✨ NAME ✨

getsockopt, setsockopt β€” get and set options on sockets

πŸ“š LIBRARY πŸ“š

Standard C Library (libc, -lc)

🌸 SYNOPSIS 🌸

#include <sys/types.h>
#include <sys/socket.h>

int
getsockopt(int s, int level, int optname, void * restrict optval,
    socklen_t * restrict optlen);

int
setsockopt(int s, int level, int optname, const void *optval,
    socklen_t optlen);

πŸ‘‘ DESCRIPTION πŸ‘‘

So getsockopt() and setsockopt() are the two system calls that mess with the options attached to a socket. and the way that options can exist at multiple protocol levels, like it's giving layered cake πŸŽ‚ β€” but they're always present at the topmost "socket" level. always. no cap.

When you're manipulating socket options you gotta specify two things: the level the option lives at, and the name of the option. To do it at the socket level, you set level to SOL_SOCKET. To do it at literally any other level, you pass the protocol number of whatever protocol controls that option. Like β€” say you want TCP to interpret the option? Then level should be the protocol number of TCP. see getprotoent(3). slay.

The optval and optlen arguments are how you actually get at the option values for setsockopt(). For getsockopt() they instead point at a buffer where the value(s) for the option(s) you asked for get returned. and for getsockopt(), optlen is a value-result argument β€” it starts out holding the size of the buffer that optval points to, and then on return it gets modified to show the actual size of the value that came back. iconic behavior honestly. If there's no option value being supplied or returned, optval can just be NULL.

The optname argument and any options you specify get passed uninterpreted to the appropriate protocol module to be interpreted. The include file <sys/socket.h> has the definitions for the socket level options, which are all listed below. Options at other protocol levels? different formats, different names β€” go consult the appropriate entries in section 4 of the manual. iykyk.

Most socket-level options use an int argument for optval. For setsockopt(), that argument should be non-zero to enable a boolean option, or zero if you're disabling it. SO_LINGER is the exception, it uses a struct linger argument defined in <sys/socket.h>, which specifies the desired state of the option and the linger interval (more on that below). SO_SNDTIMEO and SO_RCVTIMEO use a struct timeval argument, defined in <sys/time.h>.

The following options are recognized at the socket level. For protocol-specific options, go look at the protocol manual pages, e.g. ip(4) or tcp(4). Except where noted, each one can be examined with getsockopt() and set with setsockopt().

  • SO_DEBUG β€” enables recording of debugging information
  • SO_REUSEADDR β€” enables local address reuse
  • SO_REUSEPORT β€” enables duplicate address and port bindings
  • SO_REUSEPORT_LB β€” enables duplicate address and port bindings with load balancing
  • SO_KEEPALIVE β€” enables keep connections alive
  • SO_DONTROUTE β€” enables routing bypass for outgoing messages
  • SO_LINGER β€” linger on close if data present
  • SO_BROADCAST β€” enables permission to transmit broadcast messages
  • SO_OOBINLINE β€” enables reception of out-of-band data in band
  • SO_SNDBUF β€” set buffer size for output
  • SO_RCVBUF β€” set buffer size for input
  • SO_SNDLOWAT β€” set minimum count for output
  • SO_RCVLOWAT β€” set minimum count for input
  • SO_SNDTIMEO β€” set timeout value for output
  • SO_RCVTIMEO β€” set timeout value for input
  • SO_ACCEPTFILTER β€” set accept filter on listening socket
  • SO_NOSIGPIPE β€” controls generation of SIGPIPE for the socket
  • SO_TIMESTAMP β€” enables reception of a timestamp with datagrams
  • SO_BINTIME β€” enables reception of a timestamp with datagrams
  • SO_ACCEPTCONN β€” get listening status of the socket (get only)
  • SO_DOMAIN β€” get the domain of the socket (get only)
  • SO_TYPE β€” get the type of the socket (get only)
  • SO_PROTOCOL β€” get the protocol number for the socket (get only)
  • SO_PROTOTYPE β€” SunOS alias for the Linux SO_PROTOCOL (get only)
  • SO_ERROR β€” get and clear error on the socket (get only)
  • SO_SETFIB β€” set the associated FIB (routing table) for the socket (set only)

The following options are recognized in FreeBSD:

  • SO_LABEL β€” get MAC label of the socket (get only)
  • SO_PEERLABEL β€” get socket's peer's MAC label (get only)
  • SO_LISTENQLIMIT β€” get backlog limit of the socket (get only)
  • SO_LISTENQLEN β€” get complete queue length of the socket (get only)
  • SO_LISTENINCQLEN β€” get incomplete queue length of the socket (get only)
  • SO_USER_COOKIE β€” set the 'so_user_cookie' value for the socket (uint32_t, set only)
  • SO_TS_CLOCK β€” set specific format of timestamp returned by SO_TIMESTAMP
  • SO_MAX_PACING_RATE β€” set the maximum transmit rate in bytes per second for the socket
  • SO_NO_OFFLOAD β€” disables protocol offloads
  • SO_NO_DDP β€” disables direct data placement offload

SO_DEBUG enables debugging in the underlying protocol modules. πŸ’…

SO_REUSEADDR says that the rules used for validating addresses supplied in a bind(2) system call should allow reuse of local addresses.

SO_REUSEPORT allows completely duplicate bindings by multiple processes β€” but only if they all set SO_REUSEPORT before binding the port. This option lets multiple instances of a program each receive UDP/IP multicast or broadcast datagrams destined for the bound port. team effort fr fr.

SO_REUSEPORT_LB also allows completely duplicate bindings by multiple processes, again only if they all set SO_REUSEPORT_LB before binding the port. Incoming TCP and UDP connections get distributed among the sharing processes based on a hash function of local port number, foreign IP address and port number. A maximum of 256 processes can share one socket. that's the limit bestie, no more.

SO_KEEPALIVE enables the periodic transmission of messages on a connected socket. If the connected party fails to respond to these messages, the connection is considered broken and processes using the socket get notified via a SIGPIPE signal when they attempt to send data. πŸ’€

SO_DONTROUTE says outgoing messages should bypass the standard routing facilities. Instead, messages get directed to the appropriate network interface according to the network portion of the destination address. main character routing energy.

SO_LINGER controls what happens when unsent messages are queued on the socket and a close(2) is performed. If the socket promises reliable delivery of data and SO_LINGER is set, the system will block the process on the close(2) attempt until it's able to transmit the data, or until it decides it's unable to deliver the info. (the timeout period, called the linger interval, is specified in seconds in the setsockopt() system call when SO_LINGER is requested.) If SO_LINGER is disabled and a close(2) is issued, the system processes the close in a manner that lets the process continue as quickly as possible. bye bye speedrun πŸƒβ€β™€οΈ

The option SO_BROADCAST requests permission to send broadcast datagrams on the socket. fun fact: broadcast was a privileged operation in earlier versions of the system. glow-up.

With protocols that support out-of-band data, the SO_OOBINLINE option requests that out-of-band data be placed in the normal data input queue as it's received; it's then accessible with recv(2) or read(2) calls without the MSG_OOB flag. Some protocols always behave as if this option is set. they're just like that.

SO_SNDBUF and SO_RCVBUF are options to adjust the normal buffer sizes allocated for output and input buffers, respectively. You can increase the buffer size for high-volume connections, or decrease it to limit the possible backlog of incoming data. The system places an absolute maximum on these values, which is accessible through the sysctl(3) MIB variable "kern.ipc.maxsockbuf". don't try to fight the max, you won't win.

SO_SNDLOWAT is an option to set the minimum count for output operations. Most output operations process all of the data supplied by the call, delivering data to the protocol for transmission and blocking as necessary for flow control. Nonblocking output operations will process as much data as permitted subject to flow control without blocking, but will process no data if flow control doesn't allow the smaller of the low water mark value or the entire request to be processed. A select(2) operation testing the ability to write to a socket returns true only if the low water mark amount could be processed. The default value for SO_SNDLOWAT is set to a convenient size for network efficiency, often 1024.

SO_RCVLOWAT is an option to set the minimum count for input operations. In general, receive calls block until any (non-zero) amount of data is received, then return with the smaller of the amount available or the amount requested. The default value for SO_RCVLOWAT is 1. If SO_RCVLOWAT is set to a larger value, blocking receive calls normally wait until they've received the smaller of the low water mark value or the requested amount. Receive calls may still return less than the low water mark if an error occurs, a signal is caught, or the type of data next in the receive queue is different from that which was returned. rude but true.

SO_SNDTIMEO is an option to set a timeout value for output operations. It accepts a struct timeval argument with the number of seconds and microseconds used to limit waits for output operations to complete. If a send operation has blocked for this much time, it returns with a partial count or with the error EWOULDBLOCK if no data were sent. In the current implementation, this timer is restarted each time additional data are delivered to the protocol β€” meaning the limit applies to output portions ranging in size from the low water mark to the high water mark for output.

SO_RCVTIMEO is an option to set a timeout value for input operations. It accepts a struct timeval argument with the number of seconds and microseconds used to limit waits for input operations to complete. In the current implementation, this timer is restarted each time additional data are received by the protocol, so the limit is in effect an inactivity timer. If a receive operation has been blocked for this much time without receiving additional data, it returns with a short count or with the error EWOULDBLOCK if no data were received.


okay and that's where part 1 wraps, but we're SO not done β€” more of this page is coming, don't go anywhere πŸ¦‹

okay bestie we're back πŸ’– and we're picking up right where we left off, mid-glow-up, mid-DESCRIPTION, no recap, let's GO πŸƒβ€β™€οΈβœ¨


  • SO_SETFIB β€” lets you over-ride the default FIB (that's the routing table, iykyk πŸ—ΊοΈ) for the socket you're holding. The value has to be from 0 to one less than whatever sysctl net.fibs hands back. No cap.
  • SO_USER_COOKIE β€” sets the uint32_t so_user_cookie field inside the socket. The value is a uint32_t, and kernel code that messes with traffic related to that socket can use it. The default for this field is 0. Fr example, you can use the value as the skipto target or as a pipe number in ipfw/dummynet. She's useful πŸ’…
  • SO_ACCEPTFILTER β€” places an accept_filter(9) on the socket, which filters incoming connections on a listening stream socket before they get presented to accept(2). And once more for the people in the back: you must call listen(2) on the socket before you try to install the filter, or else setsockopt() will just fail on you. Tragic but true 😭
struct  accept_filter_arg {
        char    af_name[16];
        char    af_arg[256-16];
};

The optval argument should point to a struct accept_filter_arg that selects and configures the accept_filter(9). Fill af_name with the name of the accept filter your app wants to place on the listening socket. The optional af_arg gets passed along to the filter named in af_name, so you can hand over extra config options at attach time. And if you pass an optval of NULL? Bye bye filter, it's removed 🫢

  • SO_NOSIGPIPE β€” controls generation of the SIGPIPE signal. You know the one, it's normally sent when you write to a connected socket whose other end has been closed, and the write comes back with the EPIPE error. This option says "not today" ✨
  • SO_TIMESTAMP / SO_BINTIME β€” if either is enabled on a SOCK_DGRAM socket, the recvmsg(2) call may return a timestamp for when the datagram was received. May. Not will. Sometimes there's a resource shortage and it just doesn't, okay πŸ™ˆ The msg_control field in the msghdr structure points to a buffer holding a cmsghdr structure followed by a struct timeval for SO_TIMESTAMP and a struct bintime for SO_BINTIME. Here's what the cmsghdr fields look like for TIMESTAMP by default:
cmsg_len = CMSG_LEN(sizeof(struct timeval));
cmsg_level = SOL_SOCKET;
cmsg_type = SCM_TIMESTAMP;

and for SO_BINTIME:

cmsg_len = CMSG_LEN(sizeof(struct bintime));
cmsg_level = SOL_SOCKET;
cmsg_type = SCM_BINTIME;

More timestamp types? Obsessed. You get them by following SO_TIMESTAMP with SO_TS_CLOCK, which requests a specific timestamp format to come back instead of SCM_TIMESTAMP when SO_TIMESTAMP is enabled. These SO_TS_CLOCK values are recognized in FreeBSD 🌸

  • SO_TS_REALTIME_MICRO β€” realtime (SCM_TIMESTAMP, struct timeval), the default πŸ‘‘
  • SO_TS_BINTIME β€” realtime (SCM_BINTIME, struct bintime)
  • SO_TS_REALTIME β€” realtime (SCM_REALTIME, struct timespec)
  • SO_TS_MONOTONIC β€” monotonic time (SCM_MONOTONIC, struct timespec)

SO_ACCEPTCONN, SO_TYPE, SO_PROTOCOL (and its alias SO_PROTOTYPE) and SO_ERROR are the read-only girlies β€” options used only with getsockopt(). Let's break it down:

  • SO_ACCEPTCONN β€” returns whether the socket is currently accepting connections, aka whether or not listen(2) was ever invoked on it.
  • SO_TYPE β€” returns the type of the socket, like SOCK_STREAM. Super handy for servers that inherit sockets on startup 🧚
  • SO_PROTOCOL β€” returns the protocol number for the socket, for AF_INET and AF_INET6 address families.
  • SO_ERROR β€” returns any pending error on the socket and clears the error status. Use it to check for asynchronous errors on connected datagram sockets, or for other asynchronous errors. Note that clearing part, bestie, it's giving "look but also it's gone now" πŸ’€
  • SO_LABEL β€” returns the MAC label of the socket.
  • SO_PEERLABEL β€” returns the MAC label of the socket's peer. Heads up: your kernel must be compiled with MAC support. See mac(3) for the details.
  • SO_LISTENQLIMIT β€” returns the maximal number of queued connections, as set by listen(2).
  • SO_LISTENQLEN β€” returns the number of unaccepted complete connections.
  • SO_LISTENINCQLEN β€” returns the number of unaccepted incomplete connections.
  • SO_MAX_PACING_RATE β€” instructs the socket and the underlying network adapter layers to limit the transfer rate to the given unsigned 32-bit value, in bytes per second. Slow it down, queen 🐌
  • SO_NO_OFFLOAD β€” disables support for protocol offloads. At present, this stops TCP sockets from using TCP offload engines.
  • SO_NO_DDP β€” disables support for one specific TCP offload known as direct data placement (DDP). DDP is an offload supported by Chelsio network adapters that lets reassembled TCP data streams be received via zero-copy into user-supplied buffers using aio_read(2). Fancy ✨

πŸ’« RETURN VALUES πŸ’«

Upon successful completion, the value 0 is returned. Otherwise the value -1 is returned and the global variable errno is set to indicate the error. That's it, that's the whole vibe check πŸŽ€


🚨 ERRORS 🚨

The getsockopt() and setsockopt() system calls succeed unless:

  • [EBADF] β€” the argument s is not a valid descriptor.
  • [ENOTSOCK] β€” the argument s is a file, not a socket. (girl what 😭)
  • [ENOPROTOOPT] β€” the option is unknown at the level indicated.
  • [EFAULT] β€” the address pointed to by optval is not in a valid part of the process address space. For getsockopt(), this error may also be returned if optlen is not in a valid part of the process address space.
  • [EINVAL] β€” installing an accept_filter(9) on a non-listening socket was attempted. (we told you to listen(2) first!! πŸ™ˆ)
  • [ENOMEM] β€” a memory allocation failed that was required to service the request.

The setsockopt() system call may also return this one:

  • [ENOBUFS] β€” insufficient resources were available in the system to perform the operation.

πŸ‘€ SEE ALSO πŸ‘€

ioctl(2), listen(2), recvmsg(2), socket(2), getprotoent(3), mac(3), sysctl(3), ip(4), ip6(4), sctp(4), tcp(4), protocols(5), sysctl(8), accept_filter(9), bintime(9)

Go read them, bestie, they're all part of the lore πŸ“šπŸ’œ


πŸ¦‹ HISTORY πŸ¦‹

The getsockopt() and setsockopt() system calls appeared in 4.2BSD. Ancient. Iconic. Still running the world 🌍


πŸ’€ BUGS πŸ’€

Several of the socket options should be handled at lower levels of the system. That's it, that's the bug. Not me exposing the whole architecture πŸ’…


and that's the whole page, bestie!! 🫢 this one comes to you from the Debian crew, dated June 03, 2020, and it's GETSOCKOPT(2) β€” part 2 of 2, completed, slayed, no notes β­πŸ’–βœ¨

πŸ“¦ where this page comes from