LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Networking (https://www.linuxquestions.org/questions/linux-networking-3/)
-   -   Can't send UDP IPv4 packets in loadable module (https://www.linuxquestions.org/questions/linux-networking-3/cant-send-udp-ipv4-packets-in-loadable-module-4175735321/)

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;
}


nini09 03-28-2024 02:51 PM

> sd_brdcst_sin.sin_addr.s_addr = onekfs_brdcst_addr;
The above line is wrong, should be
sd_brdcst_sin.sin_addr.s_addr = INADDR_BROADCAST;

resyfer 04-06-2024 12:36 PM

Quote:

Originally Posted by nini09 (Post 6492579)
> should be
sd_brdcst_sin.sin_addr.s_addr = INADDR_BROADCAST;

Hi,

I had received the broadcast address for the desired address, and INADDR_BROADCAST only seemed to send this to listeners connected to my `lo` interface.

resyfer 04-06-2024 12:37 PM

I figured out the problem, `sock_sendmsg` needs to be replaced with `kernel_sendmsg` with the required fields, though I have yet to verify _why_ this works.


All times are GMT -5. The time now is 08:29 PM.