sysctl(), sysctlbyname()

Updated: April 19, 2023

Get or set information about the socket manager

Synopsis:

#include <sys/param.h>
#include <sys/sysctl.h>

int sysctl( const int *name,
            u_int namelen,
            void *oldp,
            size_t *oldlenp,
            const void *newp,
            size_t newlen );

int sysctlbyname( const char *sname,
                  void *oldp,
                  size_t *oldlenp,
                  void * newp,
                  size_t newlen );

Arguments:

name
(sysctl() only) An array of integers that specifies the Management Information Base–style name of the item that you want to set or get; see below. The minimum number of entries in this array is two; the maximum is CTL_MAXNAME.
namelen
(sysctl() only) The length of the name.
sname
(sysctlbyname() only) A string that specifies the MIB-style name of the item that you want to set or get; see below.
oldp
NULL, or a pointer to a buffer where the function can store the old value.
oldlenp
NULL, or a pointer to a location that initially specifies the size of the oldp buffer. The function changes the value in this location to be the size of the old information stored in the oldp buffer.
newp
NULL, or a pointer to a buffer that holds the new value.
newlen
The size of the new value.

Library:

libsocket

Use the -l socket option to qcc to link against this library.

Description:

The sysctl() function retrieves information about the socket manager and allows processes with appropriate privileges to set this information. The sysctlbyname() function is similar, but you specify the name of the variable as a string instead of as an array of integers.

The data available from these functions consists of integers and tables. You can also get or set data using the sysctl utility at the command line.

The state is described using a Management Information Base (MIB) style name, specified in name as a namelen length array of integers, or in sname as a string, depending on which function you call.

Note: For descriptions of the most commonly used variables, see the entry for sysctl in the Utilities Reference.

The sysctl() or sysctlbyname() function copies the information for the specified variable into the buffer specified by oldp. The size of the buffer is given by the location specified by oldlenp before the call, and that location gives the amount of data copied after a successful call. If the amount of data available is greater than the size of the buffer supplied, the call delivers as much data as fits in the buffer provided and returns with the error code ENOMEM. If you don't need the old value, you can set oldp and oldlenp to NULL.

You can determine the size of the available data by calling sysctl() or sysctlbyname() with a NULL parameter for oldp. The function stores the size of the available data in the location pointed to by oldlenp. For some operations, the amount of space may change often. For these operations, the system attempts to round up, so that the returned size is large enough for a call to return the data shortly thereafter.

To specify a new value, set newp to point to a buffer of length newlen from which the requested value is to be taken. If you're not setting a new value, set newp to NULL and newlen to 0.

The top-level names are defined with a CTL_ prefix in <sys/sysctl.h>. The next and subsequent levels down are found in the following header files:

This header file: Contains definitions for:
<sys/sysctl.h> Top-level identifiers
<sys/socket.h> Second-level network identifiers
<netinet/in.h> Third-level Internet identifiers and fourth-level IP identifiers
<netinet/icmp_var.h> Fourth-level ICMP identifiers
<netinet/tcp_var.h> Fourth-level TCP identifiers
<netinet/udp_var.h> Fourth-level UDP identifiers

The <sys/sysctl.h> file defines the top-level identifiers like this:

#define	CTL_UNSPEC	0		/* unused */
#define	CTL_KERN	1		/* "high kernel": proc, limits */
#define	CTL_VM		2		/* virtual memory */
#define	CTL_VFS		3		/* file system, mount type is next */
#define	CTL_NET		4		/* network, see socket.h */
#define	CTL_DEBUG	5		/* debugging parameters */
#define	CTL_HW		6		/* generic cpu/io */
#define	CTL_MACHDEP	7		/* machine dependent */
#define	CTL_USER	8		/* user-level */
#define	CTL_DDB		9		/* in-kernel debugger */
#define	CTL_PROC	10		/* per-proc attr */
#define	CTL_VENDOR	11		/* vendor-specific data */
#define	CTL_EMUL	12		/* emulation-specific data */
#define	CTL_MAXID	13		/* number of valid top-level ids */

#define	CTL_NAMES { \
	{ 0, 0 }, \
	{ "kern", CTLTYPE_NODE }, \
	{ "vm", CTLTYPE_NODE }, \
	{ "vfs", CTLTYPE_NODE }, \
	{ "net", CTLTYPE_NODE }, \
	{ "debug", CTLTYPE_NODE }, \
	{ "hw", CTLTYPE_NODE }, \
	{ "machdep", CTLTYPE_NODE }, \
	{ "user", CTLTYPE_NODE }, \
	{ "ddb", CTLTYPE_NODE }, \
	{ "proc", CTLTYPE_NODE }, \
	{ "vendor", CTLTYPE_NODE }, \
	{ "emul", CTLTYPE_NODE }, \
}

Note how the CTL_* definitions correspond to the strings defined below. Let's look at how you'd build the array of integers from a few strings:

kern.clockrate
The top-level name (kern) corresponds to CTL_KERN, as shown above. The second-level name (clockrate) is also defined in <sys/sysctl.h>. The entries in the name array that you'd pass to sysctl() would be as follows:
Entry Value See:
0 CTL_KERN <sys/sysctl.h>
1 KERN_CLOCKRATE <sys/sysctl.h>
kern.mbuf.mblowat
Once again, the top-level name corresponds to CTL_KERN. The second-level name is defined in <sys/sysctl.h>, but you need to look in <sys/mbuf.h> for the third-level name. The entries in the name array would be as follows:
Entry Value See:
0 CTL_KERN <sys/sysctl.h>
1 KERN_MBUF <sys/sysctl.h>
2 MBUF_MBLOWAT <sys/mbuf.h>
net.inet.tcp.mssdflt
The first-level name (net) corresponds to CTL_NET, as shown above. The second-level name (inet) is for information about Internet protocols, and is defined as one of the address families in <sys/socket>. The third-level name (tcp) is defined as one of the protocols in <netinet/in.h>, and the fourth-level name (mssdflt) is defined in <netinet/in_offload.h>.

The entries in the name array would be as follows:

Entry Value See:
0 CTL_NET <sys/sysctl.h>
1 AF_INET <sys/socket.h>
2 IPPROTO_TCP <netinet/in.h>
3 TCPCTL_MSSDFLT <netinet/in_offload.h>

Returns:

0
Success.
-1
An error occurred (errno is set).

Errors:

EFAULT
One of the buffers name, oldp, newp, or the length pointer oldlenp contains an invalid address.
EINVAL
The name array is less than two or greater than CTL_MAXNAME entries long, or a non-NULL newp was given, and its specified length in newlen is too large or too small.
ENOMEM
The length pointed to by oldlenp is too short to hold the requested value.
ENOTDIR
The name array specifies an intermediate rather than terminal name.
EOPNOTSUPP
The name array specifies an unknown value.
EPERM
An attempt was made to set a read-only value, or a process without the appropriate privilege attempted to set or change a value protected by the current system security level.

Examples:

The following code fragment checks whether the UDP packets checksum is enabled:

int mib[5], val;
size_t len;

mib[0] = CTL_NET;
mib[1] = AF_INET;
mib[2] = IPPROTO_UDP;
mib[3] = UDPCTL_CHECKSUM;
len = sizeof(val);
sysctl(mib, 4, &val, &len, NULL, 0);

Classification:

Unix

Safety:  
Cancellation point Yes
Interrupt handler No
Signal handler No
Thread Yes