1a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* 2a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * Copyright 2011 Daniel Drown 3a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * 4a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * Licensed under the Apache License, Version 2.0 (the "License"); 5a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * you may not use this file except in compliance with the License. 6a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * You may obtain a copy of the License at 7a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * 8a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * http://www.apache.org/licenses/LICENSE-2.0 9a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * 10a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * Unless required by applicable law or agreed to in writing, software 11a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * distributed under the License is distributed on an "AS IS" BASIS, 12a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * See the License for the specific language governing permissions and 14a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * limitations under the License. 15a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * 16a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * dns64.c - find the nat64 prefix with a dns64 lookup 17a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 18a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 19a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <sys/socket.h> 20a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <netinet/in.h> 21a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <arpa/inet.h> 22a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <netdb.h> 23a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <strings.h> 24a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <stdio.h> 25a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <stdlib.h> 26a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <unistd.h> 27a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 28a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include "dns64.h" 29a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include "logging.h" 30a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 31a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function: plat_prefix 32a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * looks up an ipv4-only hostname and looks for a nat64 /96 prefix, returns 1 on success, 0 on temporary failure, -1 on permanent failure 33a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * ipv4_name - name to lookup 34a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * prefix - the plat /96 prefix 35a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 36a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownint plat_prefix(const char *ipv4_name, struct in6_addr *prefix) { 37a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown struct addrinfo hints, *result, *p; 38a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown int status, plat_addr_set, ipv4_records, ipv6_records; 39a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown struct in6_addr plat_addr, this_plat_addr; 40a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown struct sockaddr_in6 *this_addr; 41baf62997b598ac38a99fd30419ccf7c109ffb3bcLorenzo Colitti char plat_addr_str[INET6_ADDRSTRLEN]; 42baf62997b598ac38a99fd30419ccf7c109ffb3bcLorenzo Colitti 43baf62997b598ac38a99fd30419ccf7c109ffb3bcLorenzo Colitti logmsg(ANDROID_LOG_INFO, "Detecting NAT64 prefix from DNS..."); 44a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 45a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown result = NULL; 46a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown plat_addr_set = 0; 47a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown ipv4_records = ipv6_records = 0; 48a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 49a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown bzero(&hints, sizeof(hints)); 50a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown hints.ai_family = AF_UNSPEC; 51a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown status = getaddrinfo(ipv4_name, NULL, &hints, &result); 52a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(status != 0) { 53a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_ERROR,"plat_prefix/dns(%s) status = %d/%s\n", ipv4_name, status, gai_strerror(status)); 54a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return 0; 55a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 56a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 57a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown for(p = result; p; p = p->ai_next) { 58a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(p->ai_family == AF_INET) { 59a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown ipv4_records++; 60a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown continue; 61a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 62a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(p->ai_family != AF_INET6) { 63a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_WARN,"plat_prefix/unexpected address family: %d\n", p->ai_family); 64a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown continue; 65a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 66a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown ipv6_records++; 67a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown this_addr = (struct sockaddr_in6 *)p->ai_addr; 68a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown this_plat_addr = this_addr->sin6_addr; 69a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown this_plat_addr.s6_addr32[3] = 0; 70a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 71a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!plat_addr_set) { 72a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown plat_addr = this_plat_addr; 73a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown plat_addr_set = 1; 74a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown continue; 75a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 76a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 77baf62997b598ac38a99fd30419ccf7c109ffb3bcLorenzo Colitti inet_ntop(AF_INET6, &plat_addr, plat_addr_str, sizeof(plat_addr_str)); 78a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!IN6_ARE_ADDR_EQUAL(&plat_addr, &this_plat_addr)) { 79baf62997b598ac38a99fd30419ccf7c109ffb3bcLorenzo Colitti char this_plat_addr_str[INET6_ADDRSTRLEN]; 80baf62997b598ac38a99fd30419ccf7c109ffb3bcLorenzo Colitti inet_ntop(AF_INET6, &this_plat_addr, this_plat_addr_str, sizeof(this_plat_addr_str)); 81a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_ERROR,"plat_prefix/two different plat addrs = %s,%s", 82baf62997b598ac38a99fd30419ccf7c109ffb3bcLorenzo Colitti plat_addr_str,this_plat_addr_str); 83a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 84a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 85a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(result != NULL) { 86a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown freeaddrinfo(result); 87a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 88a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(ipv4_records > 0 && ipv6_records == 0) { 89a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_WARN,"plat_prefix/no dns64 detected\n"); 90a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return -1; 91a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 92baf62997b598ac38a99fd30419ccf7c109ffb3bcLorenzo Colitti 93baf62997b598ac38a99fd30419ccf7c109ffb3bcLorenzo Colitti logmsg(ANDROID_LOG_INFO, "Detected NAT64 prefix %s/96", plat_addr_str); 94a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown *prefix = plat_addr; 95a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return 1; 96a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown} 97