As an optimization, the following code checks the size of the message for reuse:
mp->b_cont->b_datap->db_lim - mp->b_cont->b_datap->db_base >= sizeof (struct options) |
Note - Hardening Information. After message reuse, make sure to retain the relation:
db_base <= b_rptr <= b_wptr <= db_lim |
A new linked message is allocated to hold the option request. When using the transparent ioctl(2) M_COPYOUT command, data contained in the linked message is passed to the stream head. The stream head will copy the data to the user's address space and issue an M_IOCDATA in response to the M_COPYOUT message, which the module must acknowledge in an M_IOCACK message.
/* hypothetical routine */ xx_get_options(mp->b_cont); if (transparent) { mp->b_datap->db_type = M_COPYOUT; mp->b_wptr = mp->b_rptr + sizeof(struct copyreq); } else { mp->b_datap->db_type = M_IOCACK; iocbp->ioc_count = sizeof(struct options); } |
If the message is not transparent (is issued through an I_STR ioctl(2)), the data is sent with the M_IOCACK acknowledgement message and copied into the buffer specified by the strioctl data structure. ioc_error, ioc_count, and ioc_rval are cleared to prevent any stale data from being passed back to the stream head.
/* reuse M_IOCDATA for ack */ mp->b_datap->db_type = M_IOCACK; mp->b_wptr = mp->b_rptr + sizeof(struct iocblk); /* can have been overwritten */ iocbp->ioc_error = 0; iocbp->ioc_count = 0; iocbp->ioc_rval = 0; qreply(q, mp); break; |
Bidirectional Data Transfer Example
Example 8-11 illustrates bidirectional data transfer between the kernel and application during transparent ioctl(2) processing. It also shows how to use more complex state information.
The user wants to send and receive data from user buffers as part of a transparent ioctl(2) call of the form:
ioctl(fd, XX_IOCTL, (caddr_t) &addr_xxdata) |
Example 8-11 Bidirectional Data Transfer
Three pairs of messages are required following the M_IOCTL message:
case GETSTRUCT copies the structure into the message buffer.
case GETINDATA copies the user buffer into the message buffer.
case PUTOUTDATA copies the second message buffer into the user buffer.