/* function: subnet_from_interface * finds the ipv6 subnet configured on the specified interface * root - parsed configuration * interface - network interface name */ int subnet_from_interface(cnode *root, const char *interface) { union anyip *interface_ip; if(!config_item_ip6(root, "ipv6_host_id", "::200:5E10:0:0", &Global_Clatd_Config.ipv6_host_id)) return 0; interface_ip = getinterface_ip(interface, AF_INET6); if(!interface_ip) { logmsg(ANDROID_LOG_FATAL,"unable to find an ipv6 ip on interface %s",interface); return 0; } memcpy(&Global_Clatd_Config.ipv6_local_subnet, &interface_ip->ip6, sizeof(struct in6_addr)); free(interface_ip); config_generate_local_ipv6_subnet(&Global_Clatd_Config.ipv6_local_subnet); return 1; }
/* function: subnet_from_interface * finds the ipv6 subnet configured on the specified interface * root - parsed configuration * interface - network interface name */ int subnet_from_interface(cnode *root, const char *interface) { union anyip *interface_ip; char prop_name[PROPERTY_KEY_MAX]; char prop_value[PROPERTY_VALUE_MAX]; int cnt = 10; if(!config_item_ip6(root, "ipv6_host_id", "::200:5E10:0:0", &Global_Clatd_Config.ipv6_host_id)) return 0; logmsg(ANDROID_LOG_INFO, "before get net.ipv6.prefix"); snprintf(prop_name, sizeof(prop_name), "net.ipv6.%s.prefix", interface); while(cnt-->0) { property_get(prop_name, prop_value, NULL); if (strcmp(prop_value, "")) { break; } sleep(1); } logmsg(ANDROID_LOG_INFO, "after get net.ipv6.prefix"); interface_ip = getinterface_ip(interface, AF_INET6); if(!interface_ip) { logmsg(ANDROID_LOG_FATAL,"unable to find an ipv6 ip on interface %s",interface); return 0; } memcpy(&Global_Clatd_Config.ipv6_local_subnet, &interface_ip->ip6, sizeof(struct in6_addr)); free(interface_ip); config_generate_local_ipv6_subnet(&Global_Clatd_Config.ipv6_local_subnet); return 1; }
/* function: read_config * reads the config file and parses it into the global variable Global_Clatd_Config. returns 0 on failure, 1 on success * file - filename to parse * uplink_interface - interface to use to reach the internet and supplier of address space * plat_prefix - (optional) plat prefix to use, otherwise follow config file */ int read_config(const char *file, const char *uplink_interface, const char *plat_prefix) { cnode *root = config_node("", ""); void *tmp_ptr = NULL; if(!root) { logmsg(ANDROID_LOG_FATAL,"out of memory"); return 0; } memset(&Global_Clatd_Config, '\0', sizeof(Global_Clatd_Config)); config_load_file(root, file); if(root->first_child == NULL) { logmsg(ANDROID_LOG_FATAL,"Could not read config file %s", file); goto failed; } strncpy(Global_Clatd_Config.default_pdp_interface, uplink_interface, sizeof(Global_Clatd_Config.default_pdp_interface)); if(!subnet_from_interface(root,Global_Clatd_Config.default_pdp_interface)) goto failed; if(!config_item_int16_t(root, "mtu", "-1", &Global_Clatd_Config.mtu)) goto failed; if(!config_item_int16_t(root, "ipv4mtu", "-1", &Global_Clatd_Config.ipv4mtu)) goto failed; if(!config_item_ip(root, "ipv4_local_subnet", DEFAULT_IPV4_LOCAL_SUBNET, &Global_Clatd_Config.ipv4_local_subnet)) goto failed; if(!config_item_ip6(root, "ipv6_local_address", DEFAULT_IPV6_LOCAL_ADDRESS, &Global_Clatd_Config.ipv6_local_address)) goto failed; if(plat_prefix) { // plat subnet is coming from the command line if(inet_pton(AF_INET6, plat_prefix, &Global_Clatd_Config.plat_subnet) <= 0) { logmsg(ANDROID_LOG_FATAL,"invalid IPv6 address specified for plat prefix: %s", plat_prefix); goto failed; } } else { tmp_ptr = (void *)config_item_str(root, "plat_from_dns64", "yes"); if(!tmp_ptr || strcmp(tmp_ptr, "no") == 0) { free(tmp_ptr); if(!config_item_ip6(root, "plat_subnet", NULL, &Global_Clatd_Config.plat_subnet)) { logmsg(ANDROID_LOG_FATAL, "plat_from_dns64 disabled, but no plat_subnet specified"); goto failed; } } else { free(tmp_ptr); if(!(Global_Clatd_Config.plat_from_dns64_hostname = config_item_str(root, "plat_from_dns64_hostname", DEFAULT_DNS64_DETECTION_HOSTNAME))) goto failed; dns64_detection(); } } return 1; failed: free(root); free_config(); return 0; }