How to retrieve the value of synthesized ipv6 address

As described in Use System APIs to Synthesize IPv6 Addresses, starting with iOS 9.2 and OS X 10.11.2 you can use

getaddrinfo
to synthesise an IPv6 address from an IPv4 address. Can anybody please tell how to retrieve the exact synthesized IPv6 address in string format.

First up, I’m assuming you have

getaddrinfo_compat
from this post. Follow the link to find out why that’s important.

Second, pasted in below there’s some code I wrote for dealing with this sort of thing. It breaks down as follows:

  • +addressesForIPv4DottedDecimal:port:
    returns an array of NSData objects that hold the addresses in
    struct sockaddr
    format
  • +stringForAddress:
    takes one of those addresses and returns a string for it; this includes the port number, which may or may not be what you want
  • +URLBySettingAddress:inURL:
    modifies a URL to connect to the supplied address

WARNING

getaddrinfo
as used by
+addressesForIPv4DottedDecimal:port:
, can hit the network, making it a synchronous blocking networking call. Do not do this on the main thread. See QA1693 Synchronous Networking On The Main Thread for an explanation of why.

Note The reason why

getaddrinfo
can hit the network in this case is that it may need to look up
ipv4only.arpa.
. RFC 7050 explains why.

Share and Enjoy

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

let myEmail = "eskimo" + "1" + "@apple.com"
+ (nullable NSArray<NSData *> *)addressesForIPv4DottedDecimal:(NSString *)ipv4Addr port:(NSInteger)port {
    NSMutableArray *    result;
    NSString *          portStr;
    struct addrinfo *  addrList;
    int                err;
    static const struct addrinfo    hints = {
        .ai_family = AF_UNSPEC,
        .ai_socktype = SOCK_STREAM,
        .ai_flags = AI_DEFAULT
    };

    NSParameterAssert( ! [NSThread isMainThread] );

    result = nil;

    portStr = [NSString stringWithFormat:@"%zd", port];
    err = getaddrinfo_compat(ipv4Addr.UTF8String, portStr.UTF8String, &hints, &addrList);
    if (err == 0) {
        struct addrinfo *  addr;

        result = [[NSMutableArray alloc] init];

        for (addr = addrList; addr != NULL; addr = addr->ai_next) {
            [result addObject:[NSData dataWithBytes:addr->ai_addr length:addr->ai_addrlen]];
        }
        freeaddrinfo(addrList);
    }

    return result;
}

+ (nullable NSString *)stringForAddress:(NSData *)address {
    NSString *          result;
    char                host[NI_MAXHOST];
    char                service[NI_MAXSERV];
    int                err;

    result = nil;

    err = getnameinfo(address.bytes, (socklen_t) address.length, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV);
    if (err == 0) {
        result = [NSString stringWithFormat:@"%s:%s", host, service];
    }

    return result;
}

+ (nullable NSURL *)URLBySettingAddress:(NSData *)address inURL:(NSURL *)url {
    NSURL *            result;
    NSURLComponents *  components;
    char                host[NI_MAXHOST];
    char                service[NI_MAXSERV];
    int                err;

    result = nil;
    components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:YES];
    if (components != nil) {
        err = getnameinfo(address.bytes, (socklen_t) address.length, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV);
        if (err == 0) {
            NSString *      hostStr = @(host);
            if ([hostStr containsString:@":"]) {
                hostStr = [NSString stringWithFormat:@"[%@]", hostStr];
            }
            components.host = hostStr;
            components.port = @(atoi(service));

            result = components.URL;
        }
    }
    return result;
}
How to retrieve the value of synthesized ipv6 address
 
 
Q