UDP recvfrom (2) bug?

Folks, I’m trying (for tests of third party hardware) to set up a very simple ‘UDP parrot’. It receives a packet, and returns it to the source with a '*' prefixed.

Can’t get it work. The following code works like a charm on FreeBSD, but won’t work on MacOS:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/errno.h>
#include <string.h>

int main(int argc, const char * argv[]) {
    
    struct sockaddr_in myAddr;
    struct sockaddr_in rmtAddr;
    socklen_t rmtAddrLength;
    char buffer [2048];
    char src [256];
    
    printf ("Opening socket…\n");
    int sock;
    
    if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
        printf("Cannot open UDP socket. Bailing!\n");
        return -1;
    }
    
    int opt = 1;
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    
    myAddr.sin_family = AF_INET;
    myAddr.sin_addr.s_addr = INADDR_ANY;
    myAddr.sin_port = htons(5522);
    
    if (bind(sock, (struct sockaddr *) &myAddr, sizeof(myAddr))) {
        printf ("Error binding socket -> %d\n", errno);
        return -1;
    }
    
    printf ("Listening…\n");
    while (1) {
        ssize_t dataLength = recvfrom(sock, buffer + 1, sizeof(buffer) - 1,
                                      0, (struct sockaddr *)& rmtAddr, & rmtAddrLength);
        
        printf ("Received %zd bytes: %s\n", dataLength, buffer);
        printf ("addrLength: %d\n", rmtAddrLength);
        inet_ntop(AF_INET, & rmtAddr.sin_addr, src, sizeof(src));
        printf("From %s port %d\n", src, ntohs (rmtAddr.sin_port));
        if (! strncmp (buffer + 1, "STOP", 4)) {
            sendto (sock, "Terminated\n", 11, 0,
                    (struct sockaddr *)& rmtAddr, sizeof(rmtAddr));
            break;}
        buffer [0] = '*';
        dataLength = sendto(sock, buffer, dataLength + 1, 0,
                            (struct sockaddr *)& rmtAddr, sizeof(rmtAddr));
    }
    return 0;
}

The problem is, the rmtAddr structure, which is supposed to contain the IP address of the remote sender, well, does not. I always get 1.0.0.0 instead. As I said before, I have no such problem with the exact same code on FreeBSD. Also, rmtAddrLength, which is 8 on FreeBSD, is 16 on MacOS apparently.

I've dumped the memory starting at &rmtAddr and did not see a hint of a possible IP address.

Any idea what could be wrong?

Thanks ! V.

Accepted Reply

I think you should set rmtAddrLength to sizeof(rmtAddr) before calling recvfrom, so that recvfrom knows how much space it can use to fill in the address.

Add a Comment

Replies

I think you should set rmtAddrLength to sizeof(rmtAddr) before calling recvfrom, so that recvfrom knows how much space it can use to fill in the address.

Add a Comment

Yeah! Thanks. I had overlooked that in the doc, and did not remember it. The fact that it runs as is on FreeBSD didn’t help scratch my head further… :) Thanks a bunch!