We have seen that the ioctl system call is
implemented for sockets; SIOCSIFADDR
and
SIOCSIFMAP
are examples of ``socket
ioctls.'' Now let’s see how the third
argument of the system call is used by networking code.
When the ioctl system call is invoked on a socket, the
command number is one of the symbols defined in
<linux/sockios.h>
, and the function sock_ioctl
directly invokes a protocol-specific function (where ``protocol'' refers
to the main network protocol being used; for example, IP or AppleTalk).
Any ioctl command that is not recognized by the protocol
layer is passed to the device layer. These device-related ioctl
commands accept a third argument from user space,
a struct ifreq *
; this structure
is defined in <linux/if.h>
. The SIOCSIFADDR
and
SIOCSIFMAP
commands actually work on the ifreq
structure.
The extra argument to SIOCSIFMAP
, although defined as ifmap
,
is just a field of ifreq
.
In addition to using the standardized calls,
each interface can define its own ioctl commands. The plip
interface, for example, allows the interface to modify its internal
timeout values via ioctl. The ioctl implementation for
sockets recognizes 16 commands as private to the interface:
SIOCDEVPRIVATE
through SIOCDEVPRIVATE+15
.
When one of these commands is recognized, dev->do_ioctl
is called in the relevant interface driver. The function
receives the same struct ifreq *
pointer that
the general-purpose ioctl function uses:
int (*do_ioctl)(struct device *dev, struct ifreq *ifr, int cmd);
The ifr
pointer points to a kernel-space address that holds
a copy of the structure passed by the user. After do_ioctl
returns, the structure is copied back to user space; the driver can
thus use the private commands to both receive and return data.
The device-specific commands can choose to use the fields in
struct ifreq
, but they already convey a standardized
meaning, and it’s unlikely that the driver can adapt the structure to
its needs. The field ifr_data
is a caddr_t
item (a pointer) that is meant to be used for device-specific
needs. The driver and the program used to invoke its
ioctl commands should agree about the use of
ifr_data
. For example, pppstats uses
device-specific commands to retrieve information from the
ppp interface driver.
It’s not worth showing an implementation of
do_ioctl here, but with the information in this
chapter and the kernel examples, you should be able to write one when
you need it. Note, however, that the plip
implementation uses ifr_data
incorrectly and should not be
used as an example for an ioctl implementation.
3.145.74.54