Issue
I am trying to send a UDP packet from a driver using sock_sendmsg().
There are several guides on how to use sock_sendmsg() and msghdr to fill out at a UDP packet and transmit it, but they are all for older kernel versions. Sometime between 3.13 and 4.8, the struct msghdr changed from:
struct msghdr {
void * msg_name; /* Socket name */
int msg_namelen; /* Length of name */
struct iovec * msg_iov; /* Data blocks */
__kernel_size_t msg_iovlen; /* Number of blocks */
void * msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
__kernel_size_t msg_controllen; /* Length of cmsg list */
unsigned int msg_flags;
};
To:
struct msghdr {
void *msg_name; /* ptr to socket address structure */
int msg_namelen; /* size of socket address structure */
struct iov_iter msg_iter; /* data */
void *msg_control; /* ancillary data */
__kernel_size_t msg_controllen; /* ancillary data buffer length */
unsigned int msg_flags; /* flags on received message */
struct kiocb *msg_iocb; /* ptr to iocb for async requests */
};
Instead of setting msg_iov to point to an iovec with the data:
struct msghdr msg = {};
struct iovec iov = {};
iov.iov_base = data;
iov.iov_len = dataLen;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
There is now an iov_iter structure:
struct iov_iter {
int type;
size_t iov_offset;
size_t count;
union {
const struct iovec *iov;
const struct kvec *kvec;
const struct bio_vec *bvec;
struct pipe_inode_info *pipe;
};
union {
unsigned long nr_segs;
struct {
int idx;
int start_idx;
};
};
};
How do I fill out the iov_iter structure inside of msghdr with data so that I can pass it to sock_sendmsg?
Solution
After some playing around and reading the guide posted by Ctx (lwn.net/Articles/625077), I figured it out.
unsigned long nr_segments = 1;
size_t count = 1;
struct msghdr msg = {};
struct iovec iov = {};
iov.iov_base = data;
iov.iov_len = dataLen;
iov_iter_init(&msg.msg_iter, READ, &iov, nr_segments, count);
Answered By - charlesw Answer Checked By - Marie Seifert (WPSolving Admin)