예제 #1
0
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);
	}
}
예제 #2
0
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);
}
예제 #4
0
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);
}
예제 #5
0
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;
}
예제 #6
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);
}
예제 #7
0
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;
}