clinuxsocketsethernetsendto

How to fix `EPERM` error when trying to use `sendto()` with Ethernet `socket(AF_INET, ..., ...)` (IP output packets) on Linux


Here is a massively reduced code sample, following my code from my eRCaGuy_hello_world repo here as a pattern: socket__geeksforgeeks_udp_client_GS_edit_GREAT.c:

#define SOCKET_TYPE_UDP_IPV4              AF_INET, SOCK_DGRAM, 0

// Create an IPv4 UDP socket to send Ethernet packets out to a connected device
int socket_fd = socket(SOCKET_TYPE_UDP_IPV4);

// Send a packet via `sendto()`
const char msg_to_send[] = "Hello from client.";
ssize_t num_bytes_sent = sendto(socket_fd, msg_to_send, sizeof(msg_to_send), 0,
    (const struct sockaddr *)&addr_server, sizeof(addr_server));
if (num_bytes_sent == -1)
{
    printf("Failed to send to server. errno = %i: %s\n", errno, strerror(errno));
    goto cleanup;
}

sendto() fails, however, with the num_bytes_sent return code set to -1 and errno set to EPERM. EPERM stands for "permissions error: 'E'rror 'PERM'issions". A list of all possible errno errors can be found here: https://man7.org/linux/man-pages/man3/errno.3.html. It shows:

EPERM Operation not permitted (POSIX.1-2001).

However, none of the 3 reference pages I have for the sendto() function show EPERM as a valid or even possible error condition for calling this function! Here are the 3 reference pages I have for sendto(). See the "ERRORS" or "RETURN VALUE" section of each of them:

  1. POSIX Programmer's Manual for sendto(): https://man7.org/linux/man-pages/man3/sendto.3p.html
  2. man7.org "Linux Programmer's Manual" for sendto(): https://man7.org/linux/man-pages/man2/send.2.html
  3. Linux.die.net manual for sendto(): https://linux.die.net/man/2/sendto

So, what's happening and how do I fix it? I'd like sendto() to work so I can send out an Ethernet UDP packet to a connected device. On other machines it works fine, but from my embedded Linux board it fails with EPERM.


Solution

  • How to fix EPERM (permissions error; 'E'rror 'PERM'issions) by disabling the firewall

    After a ton of study, googling, testing on an embedded Linux board, etc, I've determined it's simply because I have a firewall up blocking my outgoing traffic. Do this to disable the firewall, then try again, and the EPERM error will go away:

    # Manually disable the firewall
    iptables -P INPUT ACCEPT
    iptables -P OUTPUT ACCEPT
    iptables -P FORWARD ACCEPT
    iptables -t filter --flush
    

    One source that helped me conclude this was the problem, for instance, was Dmitry V. Krivenok here: UDP socket && sendto && EPERM (emphasis added):

    The program works fine when I poll few hundred of devices, but I get strange error when I poll several thousand of devices:

    sendto returns -1 with errno set to EPERM (Operation not permitted).

    sendto (2) manual page doesn't say anything about EPERM error.

    I searched through the google and found, that sendto may fail with errno == EPERM if local firewall disallows outgoing UDP packets.

    See also:

    1. https://stackoverflow.com/a/73302873/4561887
    2. Google search for "socket EPERM"
    3. Google search for "socket sendto EPERM"