[ Team LiB ] Previous Section Next Section

18.4 sysctl Operations

Our main interest in routing sockets is the use of the sysctl function to examine both the routing table and interface list. Whereas the creation of a routing socket (a raw socket in the AF_ROUTE domain) requires superuser privileges, any process can examine the routing table and interface list using sysctl.

#include <sys/param.h>

#include <sys/sysctl.h>

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

Returns: 0 if OK, -1 on error

This function uses names that look like SNMP management information base (MIB) names. Chapter 25 of TCPv1 talks about SNMP and its MIB in detail. These names are hierarchical.

The name argument is an array of integers specifying the name, and namelen specifies the number of elements in the array. The first element in the array specifies which subsystem of the kernel the request is directed to. The second element specifies some part of that subsystem, and so on. Figure 18.11 shows the hierarchical arrangement, with some of the constants used at the first three levels.

Figure 18.11. Hierarchical arrangement of sysctl names.

graphics/18fig11.gif

To fetch a value, oldp points to a buffer into which the kernel stores the value. oldlenp is a value-result argument: When the function is called, the value pointed to by oldlenp specifies the size of this buffer, and on return, the value contains the amount of data stored in the buffer by the kernel. If the buffer is not large enough, ENOMEM is returned. As a special case, oldp can be a null pointer and oldlenp a non-null pointer, and the kernel can determine how much data the call would have returned and returns this size through oldlenp.

To set a new value, newp points to a buffer of size newlen. If a new value is not being specified, newp should be a null pointer and newlen should be 0.

The sysctl man page details all the various system information that can be obtained with this function: information on the filesystems, virtual memory, kernel limits, hardware, and so on. Our interest is in the networking subsystem, designated by the first element of the name array being set to CTL_NET. (The CTL_xxx constants are defined by including the <sys/sysctl.h> header.) The second element can then be as follows:

  • AF_INET—Get or set variables affecting the Internet protocols. The next level specifies the protocol using one of the IPPROTO_xxx constants. FreeBSD 5.0 provides about 75 variables at this level, controlling features such as whether the kernel should generate an ICMP redirect, whether TCP should use the RFC 1323 options, whether UDP checksums should be sent, and so on. We will show an example of this use of sysctl at the end of this section.

  • AF_LINK—Get or set link-layer information such as the number of PPP interfaces.

  • AF_ROUTE—Return information on either the routing table or interface list. We will describe this information shortly.

  • AF_UNSPEC—Get or set some socket-layer variables such as the maximum size of a socket send or receive buffer.

When the second element of the name array is AF_ROUTE, the third element (a protocol number) is always 0 (since there are no protocols within the AF_ROUTE family, as there are within the AF_INET family, for example), the fourth element is an address family, and the fifth and sixth levels specify what to do. We will summarize this in Figure 18.12.

Figure 18.12. sysctl information returned for route domain.

graphics/18fig12.gif

Three operations are supported, specified by name [4]. (The NET_RT_xxx constants are defined by including the <sys/socket.h> header.) The information returned by these four operations is returned through the oldp pointer in the call to sysctl. This buffer contains a variable number of RTM_xxx messages (Figure 18.2).

  1. NET_RT_DUMP returns the routing table for the address family specified by name [3]. If this address family is 0, the routing tables for all address families are returned.

    The routing table is returned as a variable number of RTM_GET messages, with each message followed by up to four socket address structures: the destination, gateway, network mask, and cloning mask of the routing table entry. We showed one of these messages on the right side of Figure 18.5 and our code in Figure 18.7 parsed one of these messages. All that changes with this sysctl operation is that one or more of these messages are returned by the kernel.

  2. NET_RT_FLAGS returns the routing table for the address family specified by name [3], but only the routing table entries with an RTF_xxx flag value that contains the flag specified by name [5]. All ARP cache entries in the routing table have the RTF_LLINFO flag bit set.

    The information is returned in the same format as the previous item.

  3. NET_RT_IFLIST returns information on all configured interfaces. If name [5] is nonzero, it is an interface index number, and only information on that interface is returned. (We will say more about interface indexes in Section 18.6.) All the addresses assigned to each interface are also returned, and if name [3] is nonzero, only addresses for that address family are returned.

    For each interface, one RTM_IFINFO message is returned, followed by one RTM_NEWADDR message for each address assigned to the interface. The RTM_IFINFO message is followed by one datalink socket address structure, and each RTM_NEWADDR message is followed by up to three socket address structures: the interface address, the network mask, and the broadcast address. These two messages are shown in Figure 18.14.

Example: Determine if UDP Checksums Are Enabled

We now provide a simple example of sysctl with the Internet protocols to check whether UDP checksums are enabled. Some UDP applications (e.g., BIND) check whether UDP checksums are enabled when they start, and if not, they try to enable them. Naturally, it takes superuser privileges to enable a feature such as this, but all we do now is check whether the feature is enabled or not. Figure 18.13 is our program.

Figure 18.13 Check whether UDP checksums are enabled.

route/checkudpsum.c

 1 #include     "unproute.h"
 2 #include     <netinet/udp.h>
 3 #include     <netinet/ip_var.h>
 4 #include     <netinet/udp_var.h> /* for UDPCTL_xxx constants */
 5 int
 6 main(int argc, char **argv)
 7 {
 8     int     mib[4], val;
 9     size_t  len;

10    mib[0] = CTL_NET;
11    mib[1] = AF_INET;
12    mib[2] = IPPROTO_UDP;
13    mib[3] = UDPCTL_CHECKSUM;

14    len = sizeof(val);
15    Sysctl(mib, 4, &val, &len, NULL, 0);
16    printf("udp checksum flag: %d\n", val);

17    exit(0) ;
18 }
Figure 18.14. Information returned for sysctl, CTL_NET, NET_RT_IFLIST command.

graphics/18fig14.gif

Include system headers

2–4 We must include the <netinet/udp_var.h> header to obtain the definition of the UDP sysctl constants. The two other headers are required for this header.

Call sysctl

10–16 We allocate an integer array with four elements and store the constants that correspond to the hierarchy shown in Figure 18.11. Since we are only fetching a variable and not setting a new value, we specify a null pointer for the newp argument to sysctl and a value of 0 for the newlen argument. oldp points to an integer variable of ours into which the result is stored and oldlenp points to a value-result variable for the size of this integer. The flag that we print will be either 0 (disabled) or 1 (enabled).

    [ Team LiB ] Previous Section Next Section