AliyunOSSSDK/OSSIPv6/OSSIPv6PrefixResolver.m (168 lines of code) (raw):
//
// OSSIPv6PrefixResolver.m
//
// Created by lingkun on 16/5/16.
// Edit by zhouzhuo on 2016/5/22
// Copyright © 2016 Ali. All rights reserved.
#import "OSSIPv6PrefixResolver.h"
#import "OSSLog.h"
#import <Foundation/Foundation.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
static const __uint8_t NS_PREFIX_32[4] = {0x20, 0x01, 0x0d, 0xb8};
static const __uint8_t NS_PREFIX_40[5] = {0x20, 0x01, 0x0d, 0xb8, 0x01};
static const __uint8_t NS_PREFIX_48[6] = {0x20, 0x01, 0x0d, 0xb8, 0x01, 0x22};
static const __uint8_t NS_PREFIX_56[7] = {0x20, 0x01, 0x0d, 0xb8, 0x01, 0x22, 0x03};
static const __uint8_t NS_PREFIX_64[8] = {0x20, 0x01, 0x0d, 0xb8, 0x01, 0x22, 0x03, 0x44};
static const __uint8_t NS_PREFIX_96[12] = {0x20, 0x01, 0x0d, 0xb8, 0x01, 0x22, 0x03, 0x44, 0x00, 0x00, 0x00, 0x00};
static const __uint8_t WK_PREFIX_96[12] = {0x00, 0x64, 0xff, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const __uint8_t* V6_PREFIX_CONTENT_TABLE[7] = {
WK_PREFIX_96,
NS_PREFIX_32,
NS_PREFIX_40,
NS_PREFIX_48,
NS_PREFIX_56,
NS_PREFIX_64,
NS_PREFIX_96};
static const __uint8_t V6_PREFIX_SIZE_TABLE[7] = {
sizeof(WK_PREFIX_96)/sizeof(__uint8_t),
sizeof(NS_PREFIX_32)/sizeof(__uint8_t),
sizeof(NS_PREFIX_40)/sizeof(__uint8_t),
sizeof(NS_PREFIX_48)/sizeof(__uint8_t),
sizeof(NS_PREFIX_56)/sizeof(__uint8_t),
sizeof(NS_PREFIX_64)/sizeof(__uint8_t),
sizeof(NS_PREFIX_96)/sizeof(__uint8_t)};
static const __uint8_t V6_PREFIX_TABLE_SIZE = 7;
typedef enum {
IPv6PrefixUnResolved = 0,
IPv6PrefixResolving,
IPv6PrefixResolved
} IPv6PrefixResolveStatus;
@implementation OSSIPv6PrefixResolver {
IPv6PrefixResolveStatus ipv6PrefixResolveStatus;
__uint8_t *ipv6Prefix;
int prefixLen;
}
- (instancetype)init {
if (self = [super init]) {
ipv6PrefixResolveStatus = IPv6PrefixUnResolved;
ipv6Prefix = (__uint8_t *)V6_PREFIX_CONTENT_TABLE[0];
prefixLen = V6_PREFIX_SIZE_TABLE[0];
}
return self;
}
+ (instancetype)getInstance {
static id singletonInstance = nil;
static dispatch_once_t once_token;
dispatch_once(&once_token, ^{
if (!singletonInstance) {
singletonInstance = [[super allocWithZone:NULL] init];
}
});
return singletonInstance;
}
/**
* @brief Updates IPv6 Prefix
*/
- (void)updateIPv6Prefix {
@synchronized(self) {
ipv6PrefixResolveStatus = IPv6PrefixUnResolved;
[self resolveIPv6Prefix:ipv6Prefix];
}
}
- (BOOL)isIPv6Prefix:(__uint8_t *)v6Prefix
withPrefixLen:(int)pLen
withIP:(__uint8_t *)ip
withIPLen:(int)ipLen {
for (int i = 0; i < pLen && i < ipLen; i++) {
if (*(v6Prefix + i) != *(ip + i)) {
return NO;
}
}
return YES;
}
- (__uint8_t)resolveIPv6Prefix:(__uint8_t *)prefix {
if ( !prefix ) {
return 0;
}
__uint8_t len = prefixLen;
memcpy(prefix, ipv6Prefix, prefixLen);
@synchronized(self) {
if (ipv6PrefixResolveStatus==IPv6PrefixUnResolved ) {
ipv6PrefixResolveStatus = IPv6PrefixResolving;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
struct addrinfo hints, *addr;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_DEFAULT;
if (0 != getaddrinfo("ipv4only.arpa", "http", &hints, &addr)) {
ipv6PrefixResolveStatus = IPv6PrefixUnResolved;
return;
}
if (addr && AF_INET6 == addr->ai_addr->sa_family) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)(addr->ai_addr);
if ( !addr6 ) {
ipv6PrefixResolveStatus = IPv6PrefixUnResolved;
return;
}
__uint8_t* u8 = addr6->sin6_addr.__u6_addr.__u6_addr8;
for (__uint8_t i=0; i < V6_PREFIX_TABLE_SIZE; i++) {
if ([self isIPv6Prefix:(__uint8_t *)V6_PREFIX_CONTENT_TABLE[i]
withPrefixLen:V6_PREFIX_SIZE_TABLE[i]
withIP:u8
withIPLen:16]) {
ipv6Prefix = (__uint8_t *)V6_PREFIX_CONTENT_TABLE[i];
prefixLen = V6_PREFIX_SIZE_TABLE[i];
ipv6PrefixResolveStatus = IPv6PrefixResolved;
break;
}
}
ipv6PrefixResolveStatus = IPv6PrefixUnResolved;
}
});
}
}
return len;
}
- (NSString *)convertIPv4toIPv6:(NSString *)ipv4 {
if ([ipv4 length] <= 0) {
return nil;
}
__uint8_t ipv6[16] = {0x00};
__uint8_t length = [self resolveIPv6Prefix:ipv6];
if (length <= 0) {
return nil;
}
in_addr_t addr_v4 = inet_addr([ipv4 UTF8String]);
// 按length的不同情况进行处理
if (length==4 || length==12) { //32 bits or 96 bits
ipv6[length+0] |= (__uint8_t)(addr_v4>>0 & 0xff);
ipv6[length+1] |= (__uint8_t)(addr_v4>>8 & 0xff);
ipv6[length+2] |= (__uint8_t)(addr_v4>>16 & 0xff);
ipv6[length+3] |= (__uint8_t)(addr_v4>>24 & 0xff);
}
else if (length == 5) { //40 bits :a.b.c.0.d
ipv6[length+0] |= (__uint8_t)(addr_v4>>0 & 0xff);
ipv6[length+1] |= (__uint8_t)(addr_v4>>8 & 0xff);
ipv6[length+2] |= (__uint8_t)(addr_v4>>16 & 0xff);
ipv6[length+4] |= (__uint8_t)(addr_v4>>24 & 0xff);
}
else if (length == 6) { //48 bits :a.b.0.c.d
ipv6[length+0] |= (__uint8_t)(addr_v4>>0 & 0xff);
ipv6[length+1] |= (__uint8_t)(addr_v4>>8 & 0xff);
ipv6[length+3] |= (__uint8_t)(addr_v4>>16 & 0xff);
ipv6[length+4] |= (__uint8_t)(addr_v4>>24 & 0xff);
}
else if (length == 7) { //56 bits :a.0.b.c.d
ipv6[length+0] |= (__uint8_t)(addr_v4>>0 & 0xff);
ipv6[length+2] |= (__uint8_t)(addr_v4>>8 & 0xff);
ipv6[length+3] |= (__uint8_t)(addr_v4>>16 & 0xff);
ipv6[length+4] |= (__uint8_t)(addr_v4>>24 & 0xff);
}
else if (length == 8) { //64 bits :0.a.b.c.d
ipv6[length+1] |= (__uint8_t)(addr_v4>>0 & 0xff);
ipv6[length+2] |= (__uint8_t)(addr_v4>>8 & 0xff);
ipv6[length+3] |= (__uint8_t)(addr_v4>>16 & 0xff);
ipv6[length+4] |= (__uint8_t)(addr_v4>>24 & 0xff);
}
// constructs the IPv6 structure
char addr_text[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
if(inet_ntop(AF_INET6, ipv6, addr_text, INET6_ADDRSTRLEN)) {
NSString *ret = [NSString stringWithUTF8String:addr_text];
return ret;
}
return nil;
}
@end