struct addrinfo hints, *res, *ressave;
bzero(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_IP;
官网:
https://developer.apple.com/library/mac/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html#//apple_ref/doc/uid/TP40010220-CH213-SW1
Check Source Code for IPv6 DNS64/NAT64 Incompatibilities
Check for and eliminate IPv4-specific APIs, such as:
-
inet_addr()
-
inet_aton()
-
inet_lnaof()
-
inet_makeaddr()
-
inet_netof()
-
inet_network()
-
inet_ntoa()
-
inet_ntoa_r()
-
bindresvport()
-
getipv4sourcefilter()
-
setipv4sourcefilter()
If your code handles IPv4 types, make sure the IPv6 equivalents are handled too.
IPv4 | IPv6 |
---|---|
| |
| |
| |
| |
| |
Use System APIs to Synthesize IPv6 Addresses
If your app needs to connect to an IPv4-only server without a DNS hostname, use getaddrinfo
to resolve the IPv4 address literal. If the current network interface doesn’t support IPv4, but supports IPv6, NAT64, and DNS64, performing this task will result in a synthesized IPv6 address.
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.
getaddrinfo
to resolve an IPv4 address literal
#include <sys/socket.h> |
#include <netdb.h> |
#include <arpa/inet.h> |
#include <err.h> |
|
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); |
if (error) { |
errx(1, "%s", gai_strerror(error)); |
/*NOTREACHED*/ |
} |
s = -1; |
for (res = res0; res; res = res->ai_next) { |
s = socket(res->ai_family, res->ai_socktype, |
res->ai_protocol); |
if (s < 0) { |
cause = "socket"; |
continue; |
} |
|
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { |
cause = "connect"; |
close(s); |
s = -1; |
continue; |
} |
|
break; /* okay we got one */ |
} |
if (s < 0) { |
err(1, "%s", cause); |
/*NOTREACHED*/ |
} |
freeaddrinfo(res0); |
Note: The ability to synthesize IPv6 addresses was added to getaddrinfo
in iOS 9.2 and OS X 10.11.2. However, leveraging it does not break compatibility with older system versions. See getaddrinfo(3) Mac OS X Developer Tools Manual Page
.