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.
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鈥擥et 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鈥擥et or set link-layer
information such as the number of PPP interfaces.
-
AF_ROUTE鈥擱eturn information on either
the routing table or interface list. We will describe this
information shortly.
-
AF_UNSPEC鈥擥et 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.
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).
-
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.
-
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.
-
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 }
Include system headers
2鈥? 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鈥?6
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).
|