You call inet_ntop() with incorrect parameters. The second parameter should be &(((struct sockaddr_in *)curr->ai_addr)->sin_addr) for IPv4, and &(((struct sockaddr_in6 *)curr->ai_addr)->sin6_addr) for IPv6. The pointer you use happens to point to the port number for IPv4 (which is zero as no service was specified), and that's why you get that particular string as output. Also, the last parameter should be just sizeof addrstr.
There are several other issues in your code. For example, you only output the first result, not all of them. Consider the following program, which takes the host name(s) as command-line parameters, and prints the usage if no parameters are specified:
Code:
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
int main(int argc, char *argv[])
{
struct addrinfo hints, *list, *curr;
int arg, errcode;
if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s HOSTNAME ...\n", argv[0]);
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
for (arg = 1; arg < argc; arg++) {
memset(&hints, 0, sizeof (hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
errcode = getaddrinfo(argv[arg], NULL, &hints, &list);
if (errcode) {
fprintf(stderr, "%s: %s.\n", argv[arg], gai_strerror(errcode));
return EXIT_FAILURE;
}
for (curr = list; curr != NULL; curr = curr->ai_next) {
if (curr->ai_family == AF_INET) {
char addrbuf[INET_ADDRSTRLEN + 1];
const char *addr;
addr = inet_ntop(AF_INET, &(((struct sockaddr_in *)curr->ai_addr)->sin_addr), addrbuf, sizeof addrbuf);
if (addr == NULL) {
fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno));
return EXIT_FAILURE;
}
printf("%s: IPv4 = %s\n", argv[arg], addr);
} else
if (curr->ai_family == AF_INET6) {
char addrbuf[INET6_ADDRSTRLEN + 1];
const char *addr;
addr = inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)curr->ai_addr)->sin6_addr), addrbuf, sizeof addrbuf);
if (addr == NULL) {
fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno));
return EXIT_FAILURE;
}
printf("%s: IPv6 = %s\n", argv[arg], addr);
}
}
freeaddrinfo(list);
}
return EXIT_SUCCESS;
}
Please compare the above code to yours, to see how you're supposed to use e.g. the getaddrinfo() and inet_ntop() interfaces. It should not be too long or complicated to understand, I hope.
I recommend compiling this using gcc -Wall -Wextra -O2 example.c -o example (i.e. enabling all warnings). When I run ./example www.google.com, the output is
www.google.com: IPv4 = 74.125.133.106
www.google.com: IPv4 = 74.125.133.105
www.google.com: IPv4 = 74.125.133.103
www.google.com: IPv4 = 74.125.133.147
www.google.com: IPv4 = 74.125.133.99
www.google.com: IPv4 = 74.125.133.104
www.google.com: IPv6 = 2a00:1450:400c:c07::93
which shows all the addresses matching the name. (A good application should try them in order, not just fail if the first one fails. That's what the client example in the getaddrinfo(3) man page does.)
Questions?