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 * config.c - configuration settings 17a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 18a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 19a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <string.h> 20a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <stdlib.h> 21a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <arpa/inet.h> 22a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <stdio.h> 23a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <limits.h> 24a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <errno.h> 25a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <unistd.h> 26a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 27a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <cutils/config_utils.h> 282596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti#include <netutils/ifc.h> 29a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 30a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include "config.h" 31a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include "dns64.h" 32a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include "logging.h" 33a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include "getaddr.h" 34a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include "clatd.h" 359808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti#include "checksum.h" 36a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 37a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownstruct clat_config Global_Clatd_Config; 38a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 39a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function: config_item_str 40a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * locates the config item and returns the pointer to a string, or NULL on failure. Caller frees pointer 41a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * root - parsed configuration 42a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * item_name - name of config item to locate 43a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * defaultvar - value to use if config item isn't present 44a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 45a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownchar *config_item_str(cnode *root, const char *item_name, const char *defaultvar) { 46a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown const char *tmp; 47a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 48a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!(tmp = config_str(root, item_name, defaultvar))) { 49a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"%s config item needed",item_name); 50a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return NULL; 51a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 52a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return strdup(tmp); 53a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown} 54a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 55a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function: config_item_int16_t 56a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * locates the config item, parses the integer, and returns the pointer ret_val_ptr, or NULL on failure 57a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * root - parsed configuration 58a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * item_name - name of config item to locate 59a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * defaultvar - value to use if config item isn't present 60a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * ret_val_ptr - pointer for return value storage 61a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 62a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownint16_t *config_item_int16_t(cnode *root, const char *item_name, const char *defaultvar, int16_t *ret_val_ptr) { 63a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown const char *tmp; 64a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown char *endptr; 65a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown long int conf_int; 66a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 67a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!(tmp = config_str(root, item_name, defaultvar))) { 68a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"%s config item needed",item_name); 69a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return NULL; 70a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 71a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 72a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown errno = 0; 73a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown conf_int = strtol(tmp,&endptr,10); 74a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(errno > 0) { 75a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"%s config item is not numeric: %s (error=%s)",item_name,tmp,strerror(errno)); 76a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return NULL; 77a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 78a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(endptr == tmp || *tmp == '\0') { 79a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"%s config item is not numeric: %s",item_name,tmp); 80a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return NULL; 81a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 82a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(*endptr != '\0') { 83a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"%s config item contains non-numeric characters: %s",item_name,endptr); 84a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return NULL; 85a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 86a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(conf_int > INT16_MAX || conf_int < INT16_MIN) { 87a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"%s config item is too big/small: %d",item_name,conf_int); 88a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return NULL; 89a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 90a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown *ret_val_ptr = conf_int; 91a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return ret_val_ptr; 92a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown} 93a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 94a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function: config_item_ip 95a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * locates the config item, parses the ipv4 address, and returns the pointer ret_val_ptr, or NULL on failure 96a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * root - parsed configuration 97a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * item_name - name of config item to locate 98a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * defaultvar - value to use if config item isn't present 99a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * ret_val_ptr - pointer for return value storage 100a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 101a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownstruct in_addr *config_item_ip(cnode *root, const char *item_name, const char *defaultvar, struct in_addr *ret_val_ptr) { 102a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown const char *tmp; 103a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown int status; 104a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 105a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!(tmp = config_str(root, item_name, defaultvar))) { 106a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"%s config item needed",item_name); 107a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return NULL; 108a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 109a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 110a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown status = inet_pton(AF_INET, tmp, ret_val_ptr); 111a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(status <= 0) { 112a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"invalid IPv4 address specified for %s: %s", item_name, tmp); 113a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return NULL; 114a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 115a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 116a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return ret_val_ptr; 117a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown} 118a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 119a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function: config_item_ip6 120a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * locates the config item, parses the ipv6 address, and returns the pointer ret_val_ptr, or NULL on failure 121a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * root - parsed configuration 122a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * item_name - name of config item to locate 123a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * defaultvar - value to use if config item isn't present 124a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * ret_val_ptr - pointer for return value storage 125a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 126a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownstruct in6_addr *config_item_ip6(cnode *root, const char *item_name, const char *defaultvar, struct in6_addr *ret_val_ptr) { 127a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown const char *tmp; 128a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown int status; 129a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 130a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!(tmp = config_str(root, item_name, defaultvar))) { 131a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"%s config item needed",item_name); 132a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return NULL; 133a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 134a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 135a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown status = inet_pton(AF_INET6, tmp, ret_val_ptr); 136a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(status <= 0) { 137a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"invalid IPv6 address specified for %s: %s", item_name, tmp); 138a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return NULL; 139a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 140a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 141a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return ret_val_ptr; 142a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown} 143a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 144a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function: free_config 145a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * frees the memory used by the global config variable 146a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 147a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownvoid free_config() { 148a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(Global_Clatd_Config.plat_from_dns64_hostname) { 149a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown free(Global_Clatd_Config.plat_from_dns64_hostname); 150a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown Global_Clatd_Config.plat_from_dns64_hostname = NULL; 151a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 152a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown} 153a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 1549808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti/* function: ipv6_prefix_equal 1559808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti * compares the prefixes two ipv6 addresses. assumes the prefix lengths are both /64. 1569808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti * a1 - first address 1579808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti * a2 - second address 1589808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti * returns: 0 if the subnets are different, 1 if they are the same. 1599808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti */ 1609808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colittiint ipv6_prefix_equal(struct in6_addr *a1, struct in6_addr *a2) { 1619808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti return !memcmp(a1, a2, 8); 1629808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti} 1639808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti 164a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function: dns64_detection 165a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * does dns lookups to set the plat subnet or exits on failure, waits forever for a dns response with a query backoff timer 166a1c871c8efad6c0b69e27d3b85e82a27e282b8bePaul Jensen * net_id - (optional) netId to use, NETID_UNSET indicates use of default network 167a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 168a1c871c8efad6c0b69e27d3b85e82a27e282b8bePaul Jensenvoid dns64_detection(unsigned net_id) { 169a33592bd08a20c6a521b8508975b7a74ecdf4f03Bernhard Rosenkränzer int backoff_sleep, status; 170a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown struct in6_addr tmp_ptr; 171a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 172a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown backoff_sleep = 1; 173a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 174a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown while(1) { 175a1c871c8efad6c0b69e27d3b85e82a27e282b8bePaul Jensen status = plat_prefix(Global_Clatd_Config.plat_from_dns64_hostname,net_id,&tmp_ptr); 176a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(status > 0) { 177a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown memcpy(&Global_Clatd_Config.plat_subnet, &tmp_ptr, sizeof(struct in6_addr)); 178a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return; 179a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 1800ec5dfa1da6a97532dc8cca825bae4edfb7d3dceErik Kline logmsg(ANDROID_LOG_WARN, "dns64_detection -- error, sleeping for %d seconds", backoff_sleep); 181a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown sleep(backoff_sleep); 1820ec5dfa1da6a97532dc8cca825bae4edfb7d3dceErik Kline backoff_sleep *= 2; 183a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(backoff_sleep >= 120) { 184a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown backoff_sleep = 120; 185a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 186a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 187a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown} 188a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 189798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti/* function: gen_random_iid 190798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti * picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix 191798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti * myaddr - IPv6 address to write to 192798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti * ipv4_local_subnet - clat IPv4 address 193798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti * plat_subnet - NAT64 prefix 194798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti */ 1959808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colittivoid gen_random_iid(struct in6_addr *myaddr, struct in_addr *ipv4_local_subnet, 1969808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti struct in6_addr *plat_subnet) { 1979808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti // Fill last 8 bytes of IPv6 address with random bits. 1989808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti arc4random_buf(&myaddr->s6_addr[8], 8); 1999808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti 2009808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti // Make the IID checksum-neutral. That is, make it so that: 2019808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti // checksum(Local IPv4 | Remote IPv4) = checksum(Local IPv6 | Remote IPv6) 2029808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti // in other words (because remote IPv6 = NAT64 prefix | Remote IPv4): 2039808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti // checksum(Local IPv4) = checksum(Local IPv6 | NAT64 prefix) 2049808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti // Do this by adjusting the two bytes in the middle of the IID. 2059808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti 2069808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti uint16_t middlebytes = (myaddr->s6_addr[11] << 8) + myaddr->s6_addr[12]; 2079808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti 2089808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti uint32_t c1 = ip_checksum_add(0, ipv4_local_subnet, sizeof(*ipv4_local_subnet)); 2099808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti uint32_t c2 = ip_checksum_add(0, plat_subnet, sizeof(*plat_subnet)) + 2109808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti ip_checksum_add(0, myaddr, sizeof(*myaddr)); 2119808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti 2129808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti uint16_t delta = ip_checksum_adjust(middlebytes, c1, c2); 2139808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti myaddr->s6_addr[11] = delta >> 8; 2149808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti myaddr->s6_addr[12] = delta & 0xff; 2159808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti} 2169808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti 217798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti// Factored out to a separate function for testability. 218798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiint connect_is_ipv4_address_free(in_addr_t addr) { 219798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti int s = socket(AF_INET, SOCK_DGRAM, 0); 220798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti if (s == -1) { 221798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti return 0; 222798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti } 223798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti 224798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti // Attempt to connect to the address. If the connection succeeds and getsockname returns the same 225798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti // the address then the address is already assigned to the system and we can't use it. 226798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti struct sockaddr_in sin = { .sin_family = AF_INET, .sin_addr = { addr }, .sin_port = 53 }; 227798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti socklen_t len = sizeof(sin); 228798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti int inuse = connect(s, (struct sockaddr *) &sin, sizeof(sin)) == 0 && 229798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti getsockname(s, (struct sockaddr *) &sin, &len) == 0 && 230798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti (size_t) len >= sizeof(sin) && 231798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti sin.sin_addr.s_addr == addr; 232798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti 233798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti close(s); 234798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti return !inuse; 235798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti} 236798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti 237798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiaddr_free_func config_is_ipv4_address_free = connect_is_ipv4_address_free; 238798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti 239798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti/* function: config_select_ipv4_address 240798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti * picks a free IPv4 address, starting from ip and trying all addresses in the prefix in order 241798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti * ip - the IP address from the configuration file 242798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti * prefixlen - the length of the prefix from which addresses may be selected. 243798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti * returns: the IPv4 address, or INADDR_NONE if no addresses were available 244798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti */ 245798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colittiin_addr_t config_select_ipv4_address(const struct in_addr *ip, int16_t prefixlen) { 246798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti in_addr_t chosen = INADDR_NONE; 247798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti 248798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti // Don't accept prefixes that are too large because we scan addresses one by one. 249798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti if (prefixlen < 16 || prefixlen > 32) { 250798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti return chosen; 251798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti } 252798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti 253798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti // All these are in host byte order. 254798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti in_addr_t mask = 0xffffffff >> (32 - prefixlen) << (32 - prefixlen); 255798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti in_addr_t ipv4 = ntohl(ip->s_addr); 256798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti in_addr_t first_ipv4 = ipv4; 257798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti in_addr_t prefix = ipv4 & mask; 258798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti 259798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti // Pick the first IPv4 address in the pool, wrapping around if necessary. 260798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti // So, for example, 192.0.0.4 -> 192.0.0.5 -> 192.0.0.6 -> 192.0.0.7 -> 192.0.0.0. 261798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti do { 262798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti if (config_is_ipv4_address_free(htonl(ipv4))) { 263798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti chosen = htonl(ipv4); 264798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti break; 265798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti } 266798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti ipv4 = prefix | ((ipv4 + 1) & ~mask); 267798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti } while (ipv4 != first_ipv4); 268798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti 269798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti return chosen; 270798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti} 271798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti 272a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function: config_generate_local_ipv6_subnet 273a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * generates the local ipv6 subnet when given the interface ip 274a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * requires config.ipv6_host_id 275a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * interface_ip - in: interface ip, out: local ipv6 host address 276a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 277a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownvoid config_generate_local_ipv6_subnet(struct in6_addr *interface_ip) { 278a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown int i; 279a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 2802596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti if (Global_Clatd_Config.use_dynamic_iid) { 2819808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti /* Generate a random interface ID. */ 2829808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti gen_random_iid(interface_ip, 2839808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti &Global_Clatd_Config.ipv4_local_subnet, 2849808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti &Global_Clatd_Config.plat_subnet); 2859808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti } else { 2869808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti /* Use the specified interface ID. */ 2879808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti for(i = 2; i < 4; i++) { 2889808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti interface_ip->s6_addr32[i] = Global_Clatd_Config.ipv6_host_id.s6_addr32[i]; 2899808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti } 290a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 291a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown} 292a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 293a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function: read_config 294a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * reads the config file and parses it into the global variable Global_Clatd_Config. returns 0 on failure, 1 on success 295a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * file - filename to parse 296a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * uplink_interface - interface to use to reach the internet and supplier of address space 297a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * plat_prefix - (optional) plat prefix to use, otherwise follow config file 298a1c871c8efad6c0b69e27d3b85e82a27e282b8bePaul Jensen * net_id - (optional) netId to use, NETID_UNSET indicates use of default network 299a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 300a1c871c8efad6c0b69e27d3b85e82a27e282b8bePaul Jensenint read_config(const char *file, const char *uplink_interface, const char *plat_prefix, 301a1c871c8efad6c0b69e27d3b85e82a27e282b8bePaul Jensen unsigned net_id) { 302a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown cnode *root = config_node("", ""); 303a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown void *tmp_ptr = NULL; 3042596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti unsigned flags; 305a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 306a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!root) { 307a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"out of memory"); 308a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return 0; 309a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 310a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 311a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown memset(&Global_Clatd_Config, '\0', sizeof(Global_Clatd_Config)); 312a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 313a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown config_load_file(root, file); 314a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(root->first_child == NULL) { 315a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"Could not read config file %s", file); 316a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown goto failed; 317a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 318a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 3191352a3a26c4d7c32b38b7fadb837799a23014aa6Lorenzo Colitti Global_Clatd_Config.default_pdp_interface = strdup(uplink_interface); 3201352a3a26c4d7c32b38b7fadb837799a23014aa6Lorenzo Colitti if (!Global_Clatd_Config.default_pdp_interface) 3211352a3a26c4d7c32b38b7fadb837799a23014aa6Lorenzo Colitti goto failed; 322a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 323a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!config_item_int16_t(root, "mtu", "-1", &Global_Clatd_Config.mtu)) 324a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown goto failed; 325a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 326a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!config_item_int16_t(root, "ipv4mtu", "-1", &Global_Clatd_Config.ipv4mtu)) 327a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown goto failed; 328a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 329798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti if(!config_item_ip(root, "ipv4_local_subnet", DEFAULT_IPV4_LOCAL_SUBNET, 330798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti &Global_Clatd_Config.ipv4_local_subnet)) 331798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti goto failed; 332798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti 333798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti if(!config_item_int16_t(root, "ipv4_local_prefixlen", DEFAULT_IPV4_LOCAL_PREFIXLEN, 334798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti &Global_Clatd_Config.ipv4_local_prefixlen)) 335a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown goto failed; 336a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 337a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(plat_prefix) { // plat subnet is coming from the command line 338a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(inet_pton(AF_INET6, plat_prefix, &Global_Clatd_Config.plat_subnet) <= 0) { 339a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL,"invalid IPv6 address specified for plat prefix: %s", plat_prefix); 340a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown goto failed; 341a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 342a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } else { 343a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown tmp_ptr = (void *)config_item_str(root, "plat_from_dns64", "yes"); 344a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!tmp_ptr || strcmp(tmp_ptr, "no") == 0) { 345a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown free(tmp_ptr); 346a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 347a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!config_item_ip6(root, "plat_subnet", NULL, &Global_Clatd_Config.plat_subnet)) { 348a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_FATAL, "plat_from_dns64 disabled, but no plat_subnet specified"); 349a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown goto failed; 350a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 351a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } else { 352a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown free(tmp_ptr); 353a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 354a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown if(!(Global_Clatd_Config.plat_from_dns64_hostname = config_item_str(root, "plat_from_dns64_hostname", DEFAULT_DNS64_DETECTION_HOSTNAME))) 355a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown goto failed; 356a1c871c8efad6c0b69e27d3b85e82a27e282b8bePaul Jensen dns64_detection(net_id); 357a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 358a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown } 359a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 3601352a3a26c4d7c32b38b7fadb837799a23014aa6Lorenzo Colitti if (!config_item_ip6(root, "ipv6_host_id", "::", &Global_Clatd_Config.ipv6_host_id)) 3619808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti goto failed; 3629808952bdf2fa6ce4cbd790d1967691bb95bf327Lorenzo Colitti 3632596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti /* In order to prevent multiple devices attempting to use the same clat address, never use a 3642596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti statically-configured interface ID on a broadcast interface such as wifi. */ 3652596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti if (!IN6_IS_ADDR_UNSPECIFIED(&Global_Clatd_Config.ipv6_host_id)) { 3662596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti ifc_init(); 3672596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti ifc_get_info(Global_Clatd_Config.default_pdp_interface, NULL, NULL, &flags); 3682596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti ifc_close(); 3692596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti Global_Clatd_Config.use_dynamic_iid = (flags & IFF_BROADCAST) != 0; 3702596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti } else { 3712596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti Global_Clatd_Config.use_dynamic_iid = 1; 3722596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti } 3732596f42a4f4c42bfb96ccbfc2700dbf70502ec75Lorenzo Colitti 374a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return 1; 375a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 376a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownfailed: 377a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown free(root); 378a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown free_config(); 379a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown return 0; 380a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown} 381a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 382a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function; dump_config 383a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * prints the current config 384a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */ 385a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownvoid dump_config() { 386a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown char charbuffer[INET6_ADDRSTRLEN]; 387a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown 388a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_DEBUG,"mtu = %d",Global_Clatd_Config.mtu); 389a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_DEBUG,"ipv4mtu = %d",Global_Clatd_Config.ipv4mtu); 390a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_DEBUG,"ipv6_local_subnet = %s",inet_ntop(AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, charbuffer, sizeof(charbuffer))); 391a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_DEBUG,"ipv4_local_subnet = %s",inet_ntop(AF_INET, &Global_Clatd_Config.ipv4_local_subnet, charbuffer, sizeof(charbuffer))); 392798f9934fca523dfb57136bd185cf6e9460323adLorenzo Colitti logmsg(ANDROID_LOG_DEBUG,"ipv4_local_prefixlen = %d", Global_Clatd_Config.ipv4_local_prefixlen); 393a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_DEBUG,"plat_subnet = %s",inet_ntop(AF_INET6, &Global_Clatd_Config.plat_subnet, charbuffer, sizeof(charbuffer))); 394a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown logmsg(ANDROID_LOG_DEBUG,"default_pdp_interface = %s",Global_Clatd_Config.default_pdp_interface); 395a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown} 396