resyfer |
03-26-2024 02:07 AM |
Can't send UDP IPv4 packets in loadable module
Hi!
I've been trying to send UDP packets to the broadcast address of my network interface from a loadable kernel module.
I've been receiving a -EFAULT error for sending it (I've highlighted in the logs).
socat is able to send it without any issue using the same network interface and port.
Logs:
[ 4462.150380] onekfs: Interface: enp0s3, Broadcast Address: x.x.x.x
[ 4462.150395] onekfs: Broadcast of UDP packets at port 39529
[ 4462.150402] onekfs: UDP Packet Send failed: -14
Code:
Code:
#define ONEKFS_PORT 39529
static struct socket *sd_brdcst_sock = NULL;
static struct sockaddr_in sd_brdcst_sin;
__be32 onekfs_brdcst_addr = 0;
/*
... Here there is code that retrieves the broadcast address in __be32 format (for onekfs_brdcst_addr).
/*
/* Setting up socket */
{
int sd_err = 0;
int enable_brodcast = 1;
sockptr_t enable_brdcst;
/* Get socket */
sd_err = sock_create_kern(&init_net, AF_INET, SOCK_DGRAM, 0, &sd_brdcst_sock);
if (sd_err < 0) {
printk(KERN_ERR "onekfs: Failed to create broadcast socket: %d\n", sd_err);
goto errout;
}
/* Enable broadcast */
enable_brdcst.is_kernel = 1;
enable_brdcst.kernel = &enable_brodcast;
sd_err = sock_setsockopt(sd_brdcst_sock, SOL_SOCKET,
SO_BROADCAST, enable_brdcst,
sizeof(enable_brdcst));
if (sd_err < 0) {
printk(KERN_ERR "onekfs: Could not set up broadcast: %d\n", sd_err);
goto errout_with_socket;
}
/* Bind to port */
memset(&sd_brdcst_sin, 0, sizeof(struct sockaddr_in));
sd_brdcst_sin.sin_family = AF_INET;
sd_brdcst_sin.sin_port = htons(ONEKFS_PORT);
printk(KERN_INFO "onekfs: ADD: %pI4", &onekfs_brdcst_addr);
sd_brdcst_sin.sin_addr.s_addr = onekfs_brdcst_addr;
sd_err = sd_brdcst_sock->ops->bind(sd_brdcst_sock,
(struct sockaddr *)&sd_brdcst_sin,
sizeof(struct sockaddr_in));
if (sd_err < 0) {
printk(KERN_ERR "onekfs: Failed to bind broadcast socket: %d\n", sd_err);
goto errout_with_socket;
}
/* We're live */
printk(KERN_INFO "onekfs: Broadcast of UDP packets at port %d\n",
ONEKFS_PORT);
return 0;
errout_with_socket:
sock_release(sd_listener_sock);
errout:
return sd_err;
}
int broadcast_msg(char *data, ssize_t data_len)
{
/* Generate Msg */
struct msghdr msg;
struct iovec iov[1];
int ret = 0;
memset(&msg, 0, sizeof(struct msghdr));
memset(&iov, 0, sizeof(struct kvec));
iov[0].iov_base = data;
iov[0].iov_len = data_len;
msg.msg_name = (void *) &sd_brdcst_sin;
msg.msg_namelen = sizeof(struct sockaddr_in);
iov_iter_init(&msg.msg_iter, WRITE, iov, 1, iov[0].iov_len);
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
/* Broadcast */
ret = sock_sendmsg(sd_brdcst_sock, &msg);
if (ret < 0) {
/* THIS IS THE PLACE OF THE PROBLEM */
printk(KERN_INFO "onekfs: UDP Packet Send failed: %d\n", ret);
/* Temporary */
sock_release(sd_brdcst_sock);
sock_release(sd_listener_sock);
}
return ret < 0;
}
|