STREAMS-UX Programmer's Guide (February 2007)

Modules and Drivers
Entry Points
Chapter 4
75
Transparent IOCTL Processing
The transparent IOCTL mechanism offers data transfer capability well beyond what is offered by the I_STR
IOCTL mechanism. The I_STR mechanism only enables IOCTL commands that are defined in streamio (7).
Transparent IOCTL allows user applications and modules to define their own IOCTL commands. The only
requirement is that the handling of the IOCTL command needs to be mutually understood between the user
process that generates the IOCTL and the module that handles the IOCTL. Transparent IOCTL processing
becomes necessary, for example, when the user data to be shared with a stream is scattered across multiple
buffers, or is in complex structures and cannot be linearized into a single data block as required by I_STR
processing. Because the user-defined message buffer can be complex, it is to be expected that transparent
IOCTL commands may take multiple message pairs for complete processing, as opposed to I_STR IOCTLs
which takes only one message pair. Above all, the transparent IOCTL mechanism offers a way to incorporate
the kernel copyin() and copyout() functions for STREAMS modules, which are not directly possible due to
absence of user context for STREAMS modules and drivers in data processing paths. The kernel copyin()
and copyout() functionality is achieved by having the modules and drivers generate M_COPYIN and
M_COPYOUT messages, and send them upstream to the stream head.
Going back to the interface for the ioctl (2) system call, a transparent IOCTL call has following semantics:
int ioctl (fd, ioc_cmd, &ioctl_struct);
Where fd is a STREAMS file descriptor, ioc_cmd is user-specified IOCTL command and ioctl_struct points
to a user buffer in a format mutually agreed upon by the user application and module.
NOTE In this section wherever a module is mentioned it represents a module or driver.
The following steps are generally involved in transparent IOCTL processing:
1. The user application issues an ioctl (2) request with a user-defined IOCTL command.
2. The stream head receives the request, does not recognize the IOCTL command, assumes it is a
transparent IOCTL call and accordingly creates an M_IOCTL message with a special constant
TRANSPARENT set in the ioc_cnt field of the iocblk structure and ioc_cmd field is set to the
user-specified IOCTL command. The special constant TRANSPARENT is used to recognizes the
transparent nature of the M_IOCTL message when received by modules. Also, note that the M_IOCTL
message for transparent processing consists of an M_IOCTL message block followed by one M_DATA
message block containing the four bytes making up the third argument to the ioctl (2) system call. This is
different from I_STR processing where the message may contain zero or more M_DATA blocks.
3. The general rules for M_IOCTL processing apply to transparent processing. The first module to recognize
the IOCTL command (set in ioc_cmd) will process it. This module also recognizes the transparent nature
of the M_IOCTL because of the ioc_cnt attribute.
4. If the module requires user data, it creates an M_COPYIN message and sends it upstream. The M_COPYIN
message contains the address of user data to copy in and number of bytes requested. The stream head
upon receiving the M_COPYIN message, issues a copyin() request to user-space. The response from the
copyin() is sent as a M_IOCDATA message to the module below, with indication of its success/failure
encoded in the M_IOCDATA message.
5. The module receives the M_IOCDATA message and processes it. It may reuse the M_IOCDATA message
contents to request another M_COPYIN from stream head. The module may send as many M_COPYIN
messages to the stream head as necessary to get all the required user data.
6. When all the user data has been received and the IOCTL processed, the module sends a positive
acknowledgment (M_IOCACK) message back to the stream head (or an M_IOCNAK message, in case of error).