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 foroptval
. Forsetsockopt()
, 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);