getaddrinfo didn't work!

Hi,


Rencently, I try to make my App to support IPv6 network through this guide Supporting IPv6 DNS64/NAT64 Networks. We directly use tcp to comunicate with the server with specific IPv4 address. According to the guide, I use getaddrinfo to do that. But in a NAT64 network, I didn't get the IPv6 address. It's still the IPv4 address. Here is the code:


int main(int argc,char *argv[])
{
    struct addrinfo hints, *res, *aip;
    int sockfd=-1, error;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family   = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_DEFAULT;
    hints.ai_protocol=IPPROTO_TCP;
    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
    error = getaddrinfo("210.5.154.195", "13163", &hints, &res);
    if (error != 0) {
        / handle getaddrinfo error */
    }

    for (aip=res; aip; aip=aip->ai_next) {
        /
        if (getnameinfo(aip->ai_addr, aip->ai_addrlen, hbuf, sizeof(hbuf), sbuf,
                        sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0)
        {
            printf("host=%s, serv=%s\n", hbuf, sbuf);
        }

        sockfd = socket(aip->ai_family,
                        aip->ai_socktype,
                        aip->ai_protocol);

        if (sockfd < 0) {
            switch errno {
            case EAFNOSUPPORT:
            case EPROTONOSUPPORT:
                /
                 *  e.g., skip the errors until
                 *  the last address family,
                 *  see section 4.4.
                 */
                if (aip->ai_next)
                    continue;
                else {
                    / handle unknown protocol errors */
                    break;
                }
            default:
                / handle other socket errors */
                ;
            }
        } else {
            int rlt = connect(sockfd, aip->ai_addr, aip->ai_addrlen);
   
            printf("errno:%d\n",errno);
            if (rlt== 0)
            {
                break;
            }
   
            / handle connect errors */
            close(sockfd);
            sockfd=-1;
        }
    }

    if (sockfd > 0) {
        / socket connected to server address */

        / ... */
        printf("Success\n");
    }
    else
    {
        printf("Failed\n");
    }

    freeaddrinfo(res);
}


Could you tell me how could this happen? What should I do? Thanks very much!


Best wishes,

Jack Gao

Replies

But in a NAT64 network, I didn't get the IPv6 address.

What did it actually return? What was the output of the test code you posted?

Be aware that, when working with BSD Sockets, you have to be able to handle any combination of IPv4 and IPv6 addresses coming back from

getaddrinfo
. This can get complex, as I explain in this post. Life is much easier if you use a connect-by-name API. Later on in the thread I just referenced there’s an example of how to do this while continuing to use BSD Sockets for your core I/O functionality.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you very much! Nice of you.


There is only one IP address I can get in a NAT64 network. It is same to the input address. And the output of the code is:


host=210.5.154.195, serv=0


Same as the IP address I input before. So, failed to get synthesized IPv6 address. It's very weird. BTW, "210.5.154.195" is a internet address. And I also want to know if getaddrinfo works to an intranet address? Becase I found out that it's also failed for an intranet literal address.


Best wishes,

Jack Gao

Presumably you’re running this code on macOS (given that it has a

main
function)? Is that your target platform? Or is the final goạl to get this running on iOS? If it’s the latter, what happens if you put this code into a small iOS test app and run in in the same environment?

Are you using the Internet Sharing-based DNS64/NAT64 test network? If not, please try it there.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for reply!


  1. Yes, the code posted is just for macOS;
  2. iOS is the final target;
  3. I'v test this code on macOS, iPhone hardware, and iPhone simulator, but all failed;
  4. Internet Sharing-based DNS64/NAT64 test network is enabled;
  5. And the server has two IP addresses: one is for internet, and the other is for intranet. I'v tested both of them. But unfortunately, failed;


Now, I'm trying to synthesize the IPv6 address manually according to RFC 7050. That seems works fine. But I still want to know why the code posted is failed. Definately, there is something wrong with it.


BTW, macOS version: 10.12 (16A323); iOS: 10.0.2


Best wishes,

Jack Gao

I’ve no idea why things are failing for you but the following test worked for me:

  1. In Xcode 8, created a new test project from the Single View Application template.

  2. Added a button wired up to the code shown below; this is a tweaked version of the standard

    getaddrinfo
    code that prints the results rather than trying to connect.
  3. Ran it on an iOS 10.0.2 device attached to an Internet Sharing-based DNS64/NAT64 test network.

I saw the following output, which is exactly what you’d expect.

2016-10-21 09:30:19.491066 xxoi[1805:1462654] host=64:ff9b::d205:9ac3, serv=13163

The only oddball thing is that the machine running Internet Sharing is running OS X 10.11.6. I don’t yet have have 10.12 set up on hardware that supports Internet Sharing )-: However, I’d be very surprised if this makes a different; address synthesis is largely a client-side thing.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
- (IBAction)testAction:(id)sender {
    struct addrinfo hints, *res, *aip; 
    int err; 

    memset(&hints, 0, sizeof(hints)); 
    hints.ai_family  = PF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_flags = AI_DEFAULT; 
    hints.ai_protocol=IPPROTO_TCP; 
    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 
    err = getaddrinfo("210.5.154.195", "13163", &hints, &res); 
    if (err != 0) { 
        assert(NO);
    } 

    for (aip=res; aip; aip=aip->ai_next) { 
        err = getnameinfo(
            aip->ai_addr,
            aip->ai_addrlen,
            hbuf, sizeof(hbuf),
            sbuf, sizeof(sbuf),
            NI_NUMERICHOST | NI_NUMERICSERV
        );
        if (err != 0) { 
            assert(NO); 
        }
        NSLog(@"host=%s, serv=%s", hbuf, sbuf); 
    } 

    freeaddrinfo(res); 
}

This code prints out the same IPv4 litteral.


I disabled iPv4 interface, connected to DNS64/NAT64 network. Browser works. IPv6 syntesis doesn't 😠