Daniel Olaya
Daniel Olaya

Reputation: 21

Why inet_ntop() and inet_ntoa() gives different result?

I am creating a UDP server-client program. Client requests a file and the server sends to client if found. Based on Beej's Guide to Networking,

  • inet_ntoa() returns the dots-and-numbers string in a static buffer that is overwritten with each call to the function.
  • inet_ntop() returns the dst parameter on success, or NULL on failure (and errno is set).

The guide mentions ntoa is deprecated so ntop is recommended since it supports IPv4 and IPv6.

On my code I am getting different results when I use function or the other and my understanding is that they should throw the same result. Anything I am missing? Any help would be greatly appreciated.

Code:

    //UDP Client
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>

    #define MAXBUFLEN 1024
    #define SER_IP "176.180.226.0" 
    #define SER_PORT "1212"

    // Get port, IPv4 or IPv6:
    in_port_t get_in_port(struct sockaddr *sa){
        if (sa->sa_family == AF_INET) {
            return (((struct sockaddr_in*)sa)->sin_port);
        }
        return (((struct sockaddr_in6*)sa)->sin6_port);
    }

    int main(int argc, char *argv[]){
        int sock, rv, numbytes;
        struct addrinfo hints, *servinfo, *p;
        char buffer[MAXBUFLEN];

        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_DGRAM;

        rv = getaddrinfo(NULL, SER_PORT, &hints, &servinfo);
        if (rv != 0){
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
            exit(1);
        }

        // Printing IP, should provide same result
        for(p = servinfo; p != NULL; p = p->ai_next) {
            char str1[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, &p->ai_addr, str1, INET_ADDRSTRLEN); 
            printf("ntop:%s\n", str1) ;
            printf("inet_ntoa:%s \n", inet_ntoa(((struct sockaddr_in *)p->ai_addr)->sin_addr));
            printf("\n");
        }

        exit(1);
    }

Current output:

ntop:64.80.142.0
inet_ntoa:0.0.0.0 

ntop:160.80.142.0
inet_ntoa:127.0.0.1 

Upvotes: 2

Views: 10717

Answers (1)

user8549610
user8549610

Reputation:

As per the man page, in the case of AF_INET the argument src must point to a struct in_addr (network byte order).

In your struct addrinfo you have a pointer to struct sockaddr which is basically

sa_family_t sa_family;
char        sa_data[];

However, struct sockaddr_in is

sa_family_t    sin_family;
in_port_t      sin_port;
struct in_addr sin_addr;

So, you need to replace

inet_ntop(AF_INET, &p->ai_addr, str1, INET_ADDRSTRLEN);

by either

inet_ntop(AF_INET, &p->ai_addr->sa_data[2], str1, INET_ADDRSTRLEN);

(the src argument may be &p->ai_addr->sa_data[1 << 1] to avoid the "magic number" 2 - the offset which counts for the port number storage)

or

inet_ntop(AF_INET, &((struct sockaddr_in *)p->ai_addr)->sin_addr, str1, INET_ADDRSTRLEN);

Then it will produce correct output.

Upvotes: 6

Related Questions