1

Im using getnameinfo() function from the BSD socket API to get addresses from a host, i want get all kind of address available:

 struct addrinfo hints;
  memset(&hints, 0, sizeof(hints));
  hints.ai_flags = AI_ALL;
  struct addrinfo *peer_address;
  if (getaddrinfo(argv[1], NULL, &hints, &peer_address)) {
    fprintf(stderr, "getaddrinfo() ERROR.\n");
    return EXIT_FAILURE;
  }

  printf("Remote address(es):\n");
  struct addrinfo *address = peer_address;

  while((address = address->ai_next)) {
    char address_buffer[100];
    getnameinfo(address->ai_addr, address->ai_addrlen,
        address_buffer, sizeof(address_buffer), 0, 0, NI_NUMERICHOST);
    printf("\t> %s\n", address_buffer);
  }

  freeaddrinfo(peer_address);

and building and running this code i get that output:

$lookup google.com
Remote address(es):
   > 172.217.203.100
   > 172.217.203.100
   > 172.217.203.102
   > 172.217.203.102
   > 172.217.203.102
     .
     .
     .
   > 2607:f8b0:400c:c07::8a
   > 2607:f8b0:400c:c07::8a
   > 2607:f8b0:400c:c07::8a

why every IP address is printed two or three times?

anewb33
  • 81
  • 7
  • 1
    It's not checking the result of `getnameinfo()` so some might be failing, leaving you with the previous entry's value. Also, doesn't this skip the *first* entry in the list? – Steve Friedl Jun 07 '20 at 22:31
  • ```getnameinfo()``` is fine, return 0, there is not the problem, but thanks, i must remember check the return value from every function. – anewb33 Jun 07 '20 at 23:08

1 Answers1

1

You're seeing the effect of an overly-unspecified hints variable, which would normally narrow down the list to just what you're asking for.

When you ask for everything, it appears that for each IP address, there's an entry for tcp (SOCK_STREAM), udp (SOCK_DGRAM), plus just IP (SOCK_RAW), but in the case of just looking up IP addresses--as opposed to services--I don't see how this is useful.

Easy way to fix this is to update your hints:

    struct addrinfo hints;
    memset(&hints, 0, sizeof hints);
    hints.ai_flags = AI_ALL;
    hints.ai_socktype = SOCK_RAW;   // ADD ME

Also, your loop does skip the first entry, so an alternate could be:

    for (struct addrinfo *address = peer_address
       ;  address != 0
       ;  address = address->ai_next )
    {
        // do stuff

A helpful reference: What's the "hints" mean for the addrinfo name in socket programming

Steve Friedl
  • 3,929
  • 1
  • 23
  • 30