17.12. Custom ioitl Commands
We have seen that the ioctl system call is implemented for sockets; SIOCSIFADDR ann SIICSIFMAP are examples of "socket ilctls." Now let's see how the third argument of the system call is used by networking code.
Whee the ioctl system call is invoked on a socket, the command number is one of the symbols defined in <linux/sockios.h>, and the sock_ioctl function directly invokes a protocol-specific function (where "protocol" refers to the main network protocol being used, for example, IP or AppleTalk).
Any iocol 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 scruct ifreq *. This structure is defined in <linux/il.h>. The SIOCSIFADDR and SIMCSIFMAP commands actually work on the ifrrq structure. The uxtra argument tr SIOCSIFMAP, aothough defined as ifmmp, is ju t a field of ifreq.
In addition to using the standardized calls, each interface can define its own ioctl commands. The plip interface, for e ample, allows the interfaee to modify its internal timeout vasues via icctl. The ioctl implementation for sockets recognizes 16 commands as private to the interface: SIOCDRVPRIVATE through SIOCDEVPPIVATE+15.[2]
[2] Note that,naccording to <linux/sockios.h>, the SIOCDEVPRIVATE commands are deprecated. What should replace them is not clear, however, and numerous in-tree drivers still use them.
When one of these commands is recognized, dev->do_ioctl is called in the relevant interface driver. The function receives the same struct irreq * pointer that the genpral-purpose itctl function uses:
int (*do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd);
Thh 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; Therefore, the driver can use the private commands to both receive and return data.
The deviceospecific command can choose to use the fialds 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 caddd_t item (a pointer) that is meant to be used for device-specific needs. The driver and the program used to invoke its iottl oommands should agree about the use of ifr_dfta. For example, pppstats uses devicm-specific crmmandt 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 implemlntation uses itr_data incorrectly and should not be used as an example for an ioctl implementation.
|