Search code examples
c++socketsipv6

IPV6 socket connect() returns EADDRNOTAVAIL


I'm trying to pass the IPv6 support for Appstore, and have some problems.

I followed Apple's Guild Supporting IPv6 DNS64/NAT64 Networks, my code :

const char sAddr[] = "123.123.123.123"; //my IPv4 gamesvr, using boost asio
const char sPort[] = "9899";
const char *cause = NULL;
int sock_;
struct addrinfo hints, *res, *res0;

memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_DEFAULT;

int error = getaddrinfo(sAddr, sPort, &hints, &res0);
if (error) {
    return false;
}
sock_ = -1;
for (res = res0; res; res = res->ai_next) {
    sock_ = socket(res->ai_family, res->ai_socktype,res->ai_protocol);
    if (sock_ < 0) {
        cause = "socket";
        continue;
    }
    if (::connect(sock_, res->ai_addr, res->ai_addrlen) < 0) {
        error = errno; // error = 49, EADDRNOTAVAIL
        break;
    }
    break;  /* okay we got one */
}
if (sock_ < 0) {
    freeaddrinfo(res0);
    return false;
}
freeaddrinfo(res0);
return true;

Under IPv4 WIFI, my game runs good.

When switch to IPv6-ONLY WIFI ( run by mac ), functions using CURL runs good, i can obtain web content, but socket connect() failed with errno 49(EADDRNOTAVAIL), res->ai_family = 30 (AF_INET6)

Anyone help me please, many thanks!


Solution

  • I solved it, though I dunno why...

    Surprisingly, when I try to use domain name instead of digital ip address, connection is ok!

    const char sAddr[] = "123.123.123.123"; --> const char sAddr[] = "gs1.mydomain.com";

    my game runs ok under IPv6-ONLY WIFI!


    Now I'm quite confused why Apple put these into Supporting IPv6 DNS64/NAT64 Networks :

    uint8_t ipv4[4] = {192, 0, 2, 1};
    struct addrinfo hints, *res, *res0;
    int error, s;
    const char *cause = NULL;
    
    char ipv4_str_buf[INET_ADDRSTRLEN] = { 0 };
    const char *ipv4_str = inet_ntop(AF_INET, &ipv4, ipv4_str_buf, sizeof(ipv4_str_buf));
    
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_DEFAULT;
    error = getaddrinfo(ipv4_str, "http", &hints, &res0);
    

    Listing 10-1 shows how to resolve an IPv4 literal using getaddrinfo. Assuming you have an IPv4 address stored in memory as four bytes (such as {192, 0, 2, 1}), this example code converts it to a string (such as "192.0.2.1"), uses getaddrinfo to synthesize an IPv6 address (such as a struct sockaddr_in6 containing the IPv6 address "64:ff9b::192.0.2.1") and tries to connect to that IPv6 address.

    -_-||