0

I'm trying to send a multicast message via a socket, then receive responses from devices on the network that respond.

The message sends successfully, and I can see the responses targeting the source IP address on wireshark, but attempting to call recvfrom just results in timeouts.

I have tried many combinations of socket options, bindings, but I've been unable to get past a timeout on recvfrom.

My current code (sending and receiving):

// Ethernet/IP Encapsulation Header
struct __attribute__((__packed__)) EnipEncapHeader
{
    uint16_t command;
    uint16_t length;
    uint32_t session_handle;
    uint32_t status;
    uint64_t ctx_64;
    uint32_t options;
};

int main() {
    // initialize winsock
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);

    // create a udp socket
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        printf("ERROR opening socket");
        return 1;
    }

    // set the broadcast flag
    int broadcastEnable = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcastEnable, sizeof(broadcastEnable));

    // Construct the message
    struct EnipEncapHeader header;
    header.command = 0x63;
    header.length = 0x0000;
    header.session_handle = 0x00000000;
    header.status = 0x0000;
    header.ctx_64 = (uint64_t)0;
    header.options = 0x0000;

    // send to 255.255.255.255 on port 44818
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr("255.255.255.255");
    servaddr.sin_port = htons(44818);
    
    // send the packet
    int rc = sendto(sockfd, (const char*)&header, sizeof(header), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
    if (rc < 0) {
        printf("ERROR sending packet, %d, %d", rc, WSAGetLastError());
        return 1;
    }

    // clear the broadcast flag
    broadcastEnable = 0;
    setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcastEnable, sizeof(broadcastEnable));

    // set the timeout to 5 seconds
    struct timeval tv;
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);

    // bind the socket to any address
    struct sockaddr_in myaddr;
    memset(&myaddr, 0, sizeof(myaddr));
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    myaddr.sin_port = htons(0);
    bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr));

    // recieve from any address on the socket
    struct sockaddr_in from;
    int fromlen = sizeof(from);
    char buf[1024];
    rc = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
    if (rc < 0) {
        printf("ERROR recieving packet, %d, %d", rc, WSAGetLastError());
        return 1;
    }
    else {
        printf("Received %d bytes from %s:%d", rc, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
    }


    return 0;
}

This code results in the following:

ERROR recieving packet, -1, 10060

Winsock Error 10060: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.

lcs
  • 4,227
  • 17
  • 36
  • Your title says "multicast" but you're using "broadcast". You probably want true multicast. A multicast address (e.g. 239.x.x.x IP range) https://en.wikipedia.org/wiki/Multicast_address With IPv6, _every_ IPv6 unicast address has a corresponding multicast address. And you need to join a multicast group. Multicast uses the IGMP protocol. You need to bind to the address. And, you need `setsockopt` calls with `IP_ADD_MEMBERSHIP` and `IP_DROP_MEMBERSHIP`: https://docs.oracle.com/cd/E19683-01/816-5042/sockets-5/index.htmlhttps://docs.oracle.com/cd/E19683-01/816-5042/sockets-5/index.html – Craig Estey Nov 03 '22 at 18:19
  • Ah, I’ve updated the title thanks. Basing this off an existing tool that successfully implements this, it’s using broadcast. – lcs Nov 03 '22 at 18:24
  • A web search on: `"receiving" broadcast message TCP/IP` produces: https://stackoverflow.com/questions/22878625/receiving-broadcast-packets-in-python – Craig Estey Nov 03 '22 at 18:40
  • What **port number** are the return messages using, and what port number did the socket bind to? – user3386109 Nov 03 '22 at 18:46
  • Replies are also on port 44818, I’ve tried that and htons(0) – lcs Nov 03 '22 at 18:50

0 Answers0