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