static void update_ipconfig(struct connman_service *service, struct connman_ipconfig *ipconfig) { if (service == NULL || service != __connman_service_get_default()) return; if (ipconfig != __connman_service_get_ip6config(service)) return; if (__connman_ipconfig_ipv6_is_enabled(ipconfig) == FALSE) { if (default_interface != NULL) { int ifindex; ifindex = connman_inet_ifindex(default_interface); __connman_dhcpv6_stop_pd(ifindex); g_free(default_interface); default_interface = NULL; } DBG("No IPv6 support for interface %s", __connman_ipconfig_get_ifname(ipconfig)); return; } /* * Did we had PD activated already? If not, then start it. */ if (default_interface == NULL) { DBG("IPv6 ipconfig %p changed for interface %s", ipconfig, __connman_ipconfig_get_ifname(ipconfig)); setup_prefix_delegation(service); } }
static int setup_prefix_delegation(struct connman_service *service) { struct connman_ipconfig *ipconfig; char *interface; int err = 0, ifindex; if (service == NULL) { /* * We do not have uplink connection. We just wait until * default interface is updated. */ return -EINPROGRESS; } interface = connman_service_get_interface(service); DBG("interface %s bridge_index %d", interface, bridge_index); if (default_interface != NULL) { stop_ra(bridge_index); ifindex = connman_inet_ifindex(default_interface); __connman_dhcpv6_stop_pd(ifindex); } g_free(default_interface); ipconfig = __connman_service_get_ip6config(service); if (__connman_ipconfig_ipv6_is_enabled(ipconfig) == FALSE) { g_free(interface); default_interface = NULL; return -EPFNOSUPPORT; } default_interface = interface; if (default_interface != NULL) { ifindex = connman_inet_ifindex(default_interface); /* * Try to get a IPv6 prefix so we can start to advertise it. */ err = __connman_dhcpv6_start_pd(ifindex, prefixes, dhcpv6_callback); if (err < 0) DBG("prefix delegation %d/%s", err, strerror(-err)); } return err; }
void connman_network_set_ipv6_method(struct connman_network *network, enum connman_ipconfig_method method) { struct connman_service *service; struct connman_ipconfig *ipconfig; service = __connman_service_lookup_from_network(network); if (service == NULL) return; ipconfig = __connman_service_get_ip6config(service); if (ipconfig == NULL) return; connman_ipconfig_set_method(ipconfig, method); }
static void append_ipconfig_ipv6(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6; if (!service) return; if (!__connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV6)) return; ipconfig_ipv4 = __connman_service_get_ip4config(service); ipconfig_ipv6 = __connman_service_get_ip6config(service); if (!ipconfig_ipv6) return; __connman_ipconfig_append_ipv6(ipconfig_ipv6, iter, ipconfig_ipv4); }
static int set_addresses(GDHCPClient *dhcp_client, struct connman_dhcpv6 *dhcp) { struct connman_service *service; struct connman_ipconfig *ipconfig; int entries, i; GList *option, *list; char **nameservers, **timeservers; const char *c_address; char *address = NULL; service = connman_service_lookup_from_network(dhcp->network); if (service == NULL) { connman_error("Can not lookup service"); return -EINVAL; } ipconfig = __connman_service_get_ip6config(service); if (ipconfig == NULL) { connman_error("Could not lookup ip6config"); return -EINVAL; } option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_DNS_SERVERS); entries = g_list_length(option); nameservers = g_try_new0(char *, entries + 1); if (nameservers != NULL) { for (i = 0, list = option; list; list = list->next, i++) nameservers[i] = g_strdup(list->data); } if (compare_string_arrays(nameservers, dhcp->nameservers) == FALSE) { if (dhcp->nameservers != NULL) { for (i = 0; dhcp->nameservers[i] != NULL; i++) __connman_service_nameserver_remove(service, dhcp->nameservers[i], FALSE); g_strfreev(dhcp->nameservers); } dhcp->nameservers = nameservers; for (i = 0; dhcp->nameservers != NULL && dhcp->nameservers[i] != NULL; i++) __connman_service_nameserver_append(service, dhcp->nameservers[i], FALSE); } else g_strfreev(nameservers); option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_SNTP_SERVERS); entries = g_list_length(option); timeservers = g_try_new0(char *, entries + 1); if (timeservers != NULL) { for (i = 0, list = option; list; list = list->next, i++) timeservers[i] = g_strdup(list->data); } if (compare_string_arrays(timeservers, dhcp->timeservers) == FALSE) { if (dhcp->timeservers != NULL) { for (i = 0; dhcp->timeservers[i] != NULL; i++) __connman_service_timeserver_remove(service, dhcp->timeservers[i]); g_strfreev(dhcp->timeservers); } dhcp->timeservers = timeservers; for (i = 0; dhcp->timeservers != NULL && dhcp->timeservers[i] != NULL; i++) __connman_service_timeserver_append(service, dhcp->timeservers[i]); } else g_strfreev(timeservers); option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_IA_NA); if (option != NULL) address = g_strdup(option->data); else { option = g_dhcp_client_get_option(dhcp_client, G_DHCPV6_IA_TA); if (option != NULL) address = g_strdup(option->data); } c_address = __connman_ipconfig_get_local(ipconfig); if (address != NULL && ((c_address != NULL && g_strcmp0(address, c_address) != 0) || (c_address == NULL))) { int prefix_len; /* Is this prefix part of the subnet we are suppose to use? */ prefix_len = check_ipv6_addr_prefix(dhcp->prefixes, address); __connman_ipconfig_set_local(ipconfig, address); __connman_ipconfig_set_prefixlen(ipconfig, prefix_len); DBG("new address %s/%d", address, prefix_len); } return 0; }
static int dhcpv6_solicitation(struct connman_dhcpv6 *dhcp) { struct connman_service *service; struct connman_ipconfig *ipconfig_ipv6; GDHCPClient *dhcp_client; GDHCPClientError error; int index, ret; DBG("dhcp %p", dhcp); index = connman_network_get_index(dhcp->network); dhcp_client = g_dhcp_client_new(G_DHCP_IPV6, index, &error); if (error != G_DHCP_CLIENT_ERROR_NONE) { clear_timer(dhcp); return -EINVAL; } if (getenv("CONNMAN_DHCPV6_DEBUG")) g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6"); service = connman_service_lookup_from_network(dhcp->network); if (service == NULL) { clear_timer(dhcp); g_dhcp_client_unref(dhcp_client); return -EINVAL; } ret = set_duid(service, dhcp->network, dhcp_client, index); if (ret < 0) { clear_timer(dhcp); g_dhcp_client_unref(dhcp_client); return ret; } g_dhcp_client_set_request(dhcp_client, G_DHCPV6_CLIENTID); g_dhcp_client_set_request(dhcp_client, G_DHCPV6_RAPID_COMMIT); g_dhcp_client_set_request(dhcp_client, G_DHCPV6_DNS_SERVERS); g_dhcp_client_set_request(dhcp_client, G_DHCPV6_SNTP_SERVERS); g_dhcpv6_client_set_oro(dhcp_client, 2, G_DHCPV6_DNS_SERVERS, G_DHCPV6_SNTP_SERVERS); ipconfig_ipv6 = __connman_service_get_ip6config(service); dhcp->use_ta = __connman_ipconfig_ipv6_privacy_enabled(ipconfig_ipv6); g_dhcpv6_client_set_ia(dhcp_client, index, dhcp->use_ta == TRUE ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, NULL, NULL, FALSE); clear_callbacks(dhcp_client); g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_SOLICITATION, solicitation_cb, dhcp); g_dhcp_client_register_event(dhcp_client, G_DHCP_CLIENT_EVENT_ADVERTISE, advertise_cb, dhcp); dhcp->dhcp_client = dhcp_client; return g_dhcp_client_start(dhcp_client, NULL); }
static void set_vpn_routes(struct gateway_data *new_gateway, struct connman_service *service, const char *gateway, enum connman_ipconfig_type type, const char *peer, struct gateway_data *active_gateway) { struct gateway_config *config; struct connman_ipconfig *ipconfig; char *dest; DBG("new %p service %p gw %s type %d peer %s active %p", new_gateway, service, gateway, type, peer, active_gateway); if (type == CONNMAN_IPCONFIG_TYPE_IPV4) { ipconfig = __connman_service_get_ip4config(service); config = new_gateway->ipv4_gateway; } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) { ipconfig = __connman_service_get_ip6config(service); config = new_gateway->ipv6_gateway; } else return; if (config) { int index = __connman_ipconfig_get_index(ipconfig); struct get_gateway_params *params; config->vpn = true; if (peer) config->vpn_ip = g_strdup(peer); else if (gateway) config->vpn_ip = g_strdup(gateway); params = g_try_malloc(sizeof(struct get_gateway_params)); if (!params) return; params->vpn_index = index; params->vpn_gateway = g_strdup(gateway); /* * Find the gateway that is serving the VPN link */ __connman_inet_get_route(gateway, get_gateway_cb, params); } if (!active_gateway) return; if (type == CONNMAN_IPCONFIG_TYPE_IPV4) { /* * Special route to VPN server via gateway. This * is needed so that we can access hosts behind * the VPN. The route might already exist depending * on network topology. */ if (!active_gateway->ipv4_gateway) return; DBG("active gw %s", active_gateway->ipv4_gateway->gateway); if (g_strcmp0(active_gateway->ipv4_gateway->gateway, "0.0.0.0") != 0) dest = active_gateway->ipv4_gateway->gateway; else dest = NULL; connman_inet_add_host_route(active_gateway->index, gateway, dest); } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) { if (!active_gateway->ipv6_gateway) return; DBG("active gw %s", active_gateway->ipv6_gateway->gateway); if (g_strcmp0(active_gateway->ipv6_gateway->gateway, "::") != 0) dest = active_gateway->ipv6_gateway->gateway; else dest = NULL; connman_inet_add_ipv6_host_route(active_gateway->index, gateway, dest); } }
static gboolean set_connected(gpointer user_data) { struct connman_network *network = user_data; struct connman_service *service; struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6; enum connman_ipconfig_method ipv4_method, ipv6_method; service = __connman_service_lookup_from_network(network); ipconfig_ipv4 = __connman_service_get_ip4config(service); ipconfig_ipv6 = __connman_service_get_ip6config(service); DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4, ipconfig_ipv6); ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4); ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6); DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method); DBG("network connected %d", network->connected); if (network->connected == TRUE) { int ret; switch (ipv6_method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: break; case CONNMAN_IPCONFIG_METHOD_AUTO: autoconf_ipv6_set(network); break; case CONNMAN_IPCONFIG_METHOD_FIXED: case CONNMAN_IPCONFIG_METHOD_MANUAL: ret = manual_ipv6_set(network, ipconfig_ipv6); if (ret != 0) { connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); return FALSE; } break; case CONNMAN_IPCONFIG_METHOD_DHCP: break; } switch (ipv4_method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: case CONNMAN_IPCONFIG_METHOD_AUTO: return FALSE; case CONNMAN_IPCONFIG_METHOD_FIXED: if (set_connected_fixed(network) < 0) { connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); return FALSE; } return TRUE; case CONNMAN_IPCONFIG_METHOD_MANUAL: set_connected_manual(network); return TRUE; case CONNMAN_IPCONFIG_METHOD_DHCP: if (set_connected_dhcp(network) < 0) { connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); return FALSE; } } } else { enum connman_service_state state; __connman_device_set_network(network->device, NULL); switch (ipv4_method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: case CONNMAN_IPCONFIG_METHOD_AUTO: case CONNMAN_IPCONFIG_METHOD_FIXED: case CONNMAN_IPCONFIG_METHOD_MANUAL: break; case CONNMAN_IPCONFIG_METHOD_DHCP: __connman_dhcp_stop(network); break; } /* * We only set the disconnect state if we were not in idle * or in failure. It does not make sense to go to disconnect * state if we were not connected. */ state = __connman_service_ipconfig_get_state(service, CONNMAN_IPCONFIG_TYPE_IPV4); if (state != CONNMAN_SERVICE_STATE_IDLE && state != CONNMAN_SERVICE_STATE_FAILURE) __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_DISCONNECT, CONNMAN_IPCONFIG_TYPE_IPV4); state = __connman_service_ipconfig_get_state(service, CONNMAN_IPCONFIG_TYPE_IPV6); if (state != CONNMAN_SERVICE_STATE_IDLE && state != CONNMAN_SERVICE_STATE_FAILURE) __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_DISCONNECT, CONNMAN_IPCONFIG_TYPE_IPV6); __connman_connection_gateway_remove(service, CONNMAN_IPCONFIG_TYPE_ALL); __connman_ipconfig_address_unset(ipconfig_ipv4); __connman_ipconfig_address_unset(ipconfig_ipv6); /* * Special handling for IPv6 autoconfigured address. * The simplest way to remove autoconfigured routes is to * disable IPv6 temporarily so that kernel will do the cleanup * automagically. */ if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) { __connman_ipconfig_disable_ipv6(ipconfig_ipv6); __connman_ipconfig_enable_ipv6(ipconfig_ipv6); } #if defined TIZEN_EXT if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_CELLULAR) { network->connecting = FALSE; connman_network_set_associating(network, FALSE); } #endif __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV4); __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV6); #if defined TIZEN_EXT if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_CELLULAR) return FALSE; #endif } network->connecting = FALSE; connman_network_set_associating(network, FALSE); return FALSE; }