Sockets UDP: Using Sender Info from Recvfrom() in Sendto() Fails

34,458

You shouldn't use a struct sockaddr to store the source address in the recvfrom call, it might not be able to represent an IP socket address.

You're supposed to use a struct sockaddr_in for an IPv4 address or a struct sockaddr_in6 for an IPv6 address, or better yet, a struct sockaddr_storage to cope with either.

struct sockaddr_storage sender;
socklen_t sendsize = sizeof(sender);
bzero(&sender, sizeof(sender));

recvfrom(sock, message, sizeof(message), 0, (struct sockaddr*)&sender, &sendsize);
Share:
34,458
Oblivious Sage
Author by

Oblivious Sage

This space accidentally left blank.

Updated on July 09, 2022

Comments

  • Oblivious Sage
    Oblivious Sage almost 2 years

    I'm trying to write a server that that receives a query via UDP and sends a response via UDP. The problem I'm running into is that when I try to send my response, I get a "101 Network is unreachable" error.

    Based on the question here I tried to resolve this by taking out the hints.ai_flags = AI_PASSIVE; line, but then the server never successfully gets the message. I looked at the man page for addrinfo and it sounds like if the AI_PASSIVE flag is set, the socket can only recvfrom(), while if it's not set, the socket can only sendto(). I've seen a bunch of examples online with people doing both from a single socket, though; what am I missing?

    Relevant code:

    struct addrinfo hints;
    struct addrinfo *serverinfo;
    memset(&hints,0,sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = AI_PASSIVE;
    
    int status = getaddrinfo(NULL, port, &hints, &serverinfo);
    int sock = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol);
    status = bind(sock, serverinfo->ai_addr, serverinfo->ai_addrlen);
    freeaddrinfo(serverinfo);
    
    // poll until there's an incoming packet
    
    struct sockaddr sender;
    socklen_t sendsize = sizeof(sender);
    bzero(&sender, sizeof(sender));
    
    recvfrom(sock, message, sizeof(message), 0, &sender, &sendsize);
    
    // message processing
    
    sendto(sock, response, sizeof(response), 0, (struct sockaddr *)&sender, sendsize);
    

    Yes, I have error checking for all those calls (that's how I found the problem); it's simply been left out here for brevity's sake.