Robb1
Robb1

Reputation: 5025

Bad address received from recvfrom: why?

I'm writing a function that is supposed to do some operations and then return (using its arguments) the address of the device that is interacting with (i.e. that used sendto) the recvfrom inside the function.

Here's how I call the function, instantiating cliaddr before.

struct sockaddr_in cliaddr;
memset((void *) &cliaddr, 0, sizeof(cliaddr));
rcv_string(sockfd, &return_string, &cliaddr);
// Here I'll need to use cliaddr, that's why I need it outside too

Here's the implementation of the function:

int rcv_string(int sockfd, char **return_string, struct sockaddr_in *sndaddr) {
    // ...
    char buff[PACKETSZ + 2];
    memset(&buff, 0, sizeof(buff)); // Clean buffer
    socklen_t *plen = malloc(sizeof(struct sockaddr *));
    if ((recvfrom(sockfd, buff, sizeof(buff), 0, (struct sockaddr *) sndaddr, plen)) < 0) {
            perror("recvfrom");
            return -1;
    }
    char *snd_ip = malloc(INET_ADDRSTRLEN * sizeof(char));
    if (inet_ntop(AF_INET, &((*sndaddr).sin_addr.s_addr), snd_ip, INET_ADDRSTRLEN * sizeof(char)) == NULL) {
            perror("inet_ntop");
            return -1;
    }
    printf("Received '%s' from '%s'.\n", buff, snd_ip);
    // ...
}

Now, even if the ip address of the sending device is 192.168.1.251 I get the following output:

Received '0packetx' from '0.0.0.0'.

The received buffer is formatted correctly, but the address is evidently wrong. Why? Does it have to do with the definition of the address variable outside the function?

EDIT

If after the memset of cliaddr I add also those 3 lines:

cliaddr.sin_family = AF_INET;
cliaddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliaddr.sin_port = htons(SERV_PORT);

I get a random behavior. Sometimes I get 0.0.0.0, sometimes 127.0.0.1 and sometimes the correct address (192.168.1.251).

Upvotes: 2

Views: 2367

Answers (2)

Snohdo
Snohdo

Reputation: 156

It should work if you fill plen with valid sizeof data.

*plen = sizeof(struct sockaddr_in);

You can put that right before the recvfrom call.

Upvotes: -3

pm100
pm100

Reputation: 50190

you are passing the wrong length to recvfrom

  socklen_t *plen = malloc(sizeof(struct sockaddr *));
    if ((recvfrom(sockfd, buff, sizeof(buff), 0, (struct sockaddr *) sndaddr, plen))

Why you malloc is a mystery, but you need

socklen_t *plen = malloc(sizeof(socklen_t));
*plen = sizeof(struct sockaddr_in );

much simpler is

      socklen_t plen = sizeof(struct sockaddr_in);
   if ((recvfrom(sockfd, buff, sizeof(buff), 0, (struct sockaddr *) sndaddr, &plen))

Upvotes: 4

Related Questions