Home > Net >  why am I getting I/O error on a UDP broadcast sendto()?
why am I getting I/O error on a UDP broadcast sendto()?

Time:06-07

I'm attempting a UDP broadcast from an embedded device. Platform is an ESP32; IP stack is from LwIP. I've removed all the error checking, but my calls to socket() and setsockopt() are successful. I get an errno 5 (I/O error) on my sendto() call. Can someone see what I'm doing wrong?

static int iobAnnounce;
const char broadcastEnable = 1;
struct sockaddr_in servaddrAnnounce;
char udp_data[22];
int err;

iobAnnounce = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    
setsockopt(iobAnnounce, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));

memset(&servaddrAnnounce, 0, sizeof(servaddrAnnounce));
servaddrAnnounce.sin_family = AF_INET;
servaddrAnnounce.sin_port = htons(30303);
servaddrAnnounce.sin_addr.s_addr = htonl(INADDR_BROADCAST);

sendto(iobAnnounce,
       udp_data,
       22,
       0,
       (const struct sockaddr *) &servaddrAnnounce,
       sizeof(servaddrAnnounce));

Thanks for any assistance.

EDIT

Per @Barmar's question, I modified my code as follows:

err = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info); // ESP IDF call.
uint32_t subnetBroadcast = ip_info.ip.addr | ~(ip_info.netmask.addr);
servaddrAnnounce.sin_addr.s_addr = (subnetBroadcast);

Unfortunately, this didn't change the behavior. I also tried performing a htonl() on the address returned by tcpip_adapter_get_ip_info(); no difference. The output from the (removed) telltales was:

I (5354) IOB: iob_task(): tcpip_adapter_get_ip_info() returned ip d456a8c0; netmask 00ffffff; gateway 0156a8c0.
I (5364) IOB: iob_task(): subnetBroadcast is ff56a8c0.
I (5374) IOB: iob_task(): servaddrAnnounce.sin_addr.s_addr is c0a856ff.

CodePudding user response:

From setsockopt:

"Most socket-level options utilize an int argument for optval. For setsockopt(), the argument should be nonzero to enable a boolean option, or zero if the option is to be disabled."

... so, changing broadcastEnable from being a char to being an int should do it:

const int broadcastEnable = 1;

CodePudding user response:

In addition to what @TedLyngmo said in his answer, there is another problem with your code. You are not calculating the subnetBroadcast correctly. You need to AND the ip_info.ip.addr with the ip_info.netmask.addr before you OR the inverse of the ip_info.netmask.addr, eg:

// uint32_t subnetBroadcast = ip_info.ip.addr | ~(ip_info.netmask.addr);
uint32_t subnetBroadcast = (ip_info.ip.addr & ip_info.netmask.addr) | ~(ip_info.netmask.addr);
  • Related