X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fnetwork.c;h=bff0e7e2d44c760132267ee7040c683e0c4da16f;hb=5f5b3609c4f9884954623d7e6bf2ae1ae7096637;hp=058495df65a899ba17b1b3ea31ba5c003cbc4d75;hpb=b2425856d9b2f3d23b35fa4bcf06e1f1f2986365;p=framework%2Fconnectivity%2Fconnman.git diff --git a/src/network.c b/src/network.c index 058495d..bff0e7e 100644 --- a/src/network.c +++ b/src/network.c @@ -45,6 +45,7 @@ struct connman_network { char *group; char *path; int index; + int router_solicit_count; struct connman_network_driver *driver; void *driver_data; @@ -767,7 +768,8 @@ void connman_network_clear_error(struct connman_network *network) __connman_service_clear_error(service); } -static void set_configuration(struct connman_network *network) +static void set_configuration(struct connman_network *network, + enum connman_ipconfig_type type) { struct connman_service *service; @@ -783,7 +785,7 @@ static void set_configuration(struct connman_network *network) service = __connman_service_lookup_from_network(network); __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_CONFIGURATION, - CONNMAN_IPCONFIG_TYPE_IPV4); + type); } static void dhcp_success(struct connman_network *network) @@ -852,7 +854,7 @@ static int set_connected_fixed(struct connman_network *network) ipconfig_ipv4 = __connman_service_get_ip4config(service); - set_configuration(network); + set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4); network->connecting = FALSE; @@ -890,7 +892,7 @@ static void set_connected_manual(struct connman_network *network) if (__connman_ipconfig_get_local(ipconfig) == NULL) __connman_service_read_ip4config(service); - set_configuration(network); + set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4); err = __connman_ipconfig_address_add(ipconfig); if (err < 0) @@ -918,7 +920,7 @@ static int set_connected_dhcp(struct connman_network *network) DBG("network %p", network); - set_configuration(network); + set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4); err = __connman_dhcp_start(network, dhcp_callback); if (err < 0) { @@ -967,17 +969,161 @@ static int manual_ipv6_set(struct connman_network *network, return 0; } +static void stop_dhcpv6(struct connman_network *network) +{ + __connman_dhcpv6_stop(network); +} + +static void dhcpv6_info_callback(struct connman_network *network, + connman_bool_t success) +{ + DBG("success %d", success); + + stop_dhcpv6(network); +} + +static gboolean dhcpv6_set_addresses(struct connman_network *network) +{ + struct connman_service *service; + struct connman_ipconfig *ipconfig_ipv6; + int err = -EINVAL; + + service = __connman_service_lookup_from_network(network); + if (service == NULL) + goto err; + + connman_network_set_associating(network, FALSE); + + network->connecting = FALSE; + + ipconfig_ipv6 = __connman_service_get_ip6config(service); + err = __connman_ipconfig_address_add(ipconfig_ipv6); + if (err < 0) + goto err; + + err = __connman_ipconfig_gateway_add(ipconfig_ipv6); + if (err < 0) + goto err; + + return 0; + +err: + connman_network_set_error(network, + CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); + return err; +} + +static void autoconf_ipv6_set(struct connman_network *network); +static void dhcpv6_callback(struct connman_network *network, + connman_bool_t success); + +/* + * Have a separate callback for renew so that we do not do autoconf + * in wrong phase as the dhcpv6_callback() is also called when doing + * DHCPv6 solicitation. + */ +static void dhcpv6_renew_callback(struct connman_network *network, + connman_bool_t success) +{ + if (success == TRUE) + dhcpv6_callback(network, success); + else { + stop_dhcpv6(network); + + /* restart and do solicit again. */ + autoconf_ipv6_set(network); + } +} + +static void dhcpv6_callback(struct connman_network *network, + connman_bool_t success) +{ + DBG("success %d", success); + + /* Start the renew process if necessary */ + if (success == TRUE) { + + if (dhcpv6_set_addresses(network) < 0) { + stop_dhcpv6(network); + return; + } + + if (__connman_dhcpv6_start_renew(network, + dhcpv6_renew_callback) == -ETIMEDOUT) + dhcpv6_renew_callback(network, FALSE); + } else + stop_dhcpv6(network); +} + +static void check_dhcpv6(struct nd_router_advert *reply, + unsigned int length, void *user_data) +{ + struct connman_network *network = user_data; + GSList *prefixes; + + DBG("reply %p", reply); + + if (reply == NULL) { + /* + * Router solicitation message seem to get lost easily so + * try to send it again. + */ + if (network->router_solicit_count > 0) { + DBG("re-send router solicitation %d", + network->router_solicit_count); + network->router_solicit_count--; + __connman_inet_ipv6_send_rs(network->index, 1, + check_dhcpv6, network); + return; + } + connman_network_unref(network); + return; + } + + network->router_solicit_count = 0; + + prefixes = __connman_inet_ipv6_get_prefixes(reply, length); + + /* + * We do stateful/stateless DHCPv6 if router advertisement says so. + */ + if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) + __connman_dhcpv6_start(network, prefixes, dhcpv6_callback); + else if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) + __connman_dhcpv6_start_info(network, dhcpv6_info_callback); + + connman_network_unref(network); +} + static void autoconf_ipv6_set(struct connman_network *network) { + struct connman_service *service; + struct connman_ipconfig *ipconfig; + int index; + DBG("network %p", network); __connman_device_set_network(network->device, network); connman_device_set_disconnected(network->device, FALSE); - /* XXX: Append IPv6 nameservers here */ - network->connecting = FALSE; + + service = __connman_service_lookup_from_network(network); + if (service == NULL) + return; + + ipconfig = __connman_service_get_ip6config(service); + if (ipconfig == NULL) + return; + + index = connman_ipconfig_get_index(ipconfig); + + connman_network_ref(network); + + /* Try to get stateless DHCPv6 information, RFC 3736 */ + network->router_solicit_count = 3; + __connman_inet_ipv6_send_rs(index, 1, check_dhcpv6, network); } static gboolean set_connected(gpointer user_data) @@ -1008,6 +1154,7 @@ static gboolean set_connected(gpointer user_data) case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: break; + case CONNMAN_IPCONFIG_METHOD_DHCP: case CONNMAN_IPCONFIG_METHOD_AUTO: autoconf_ipv6_set(network); break; @@ -1020,8 +1167,6 @@ static gboolean set_connected(gpointer user_data) return FALSE; } break; - case CONNMAN_IPCONFIG_METHOD_DHCP: - break; } switch (ipv4_method) { @@ -1050,8 +1195,26 @@ static gboolean set_connected(gpointer user_data) } else { enum connman_service_state state; + /* + * Resetting solicit count here will prevent the RS resend loop + * from sending packets in check_dhcpv6() + */ + network->router_solicit_count = 0; + __connman_device_set_network(network->device, NULL); + switch (ipv6_method) { + case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + case CONNMAN_IPCONFIG_METHOD_OFF: + case CONNMAN_IPCONFIG_METHOD_FIXED: + case CONNMAN_IPCONFIG_METHOD_MANUAL: + break; + case CONNMAN_IPCONFIG_METHOD_DHCP: + case CONNMAN_IPCONFIG_METHOD_AUTO: + stop_dhcpv6(network); + break; + } + switch (ipv4_method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: @@ -1169,6 +1332,26 @@ connman_bool_t connman_network_get_associating(struct connman_network *network) return network->associating; } +int connman_network_connect_hidden(struct connman_network *network, + char *identity, char* passphrase) +{ + struct connman_service *service; + + DBG(""); + + service = __connman_service_lookup_from_network(network); + if (service == NULL) + return -EINVAL; + + if (identity != NULL) + __connman_service_set_agent_identity(service, identity); + + if (passphrase != NULL) + __connman_service_add_passphrase(service, passphrase); + + return __connman_service_connect(service); +} + /** * __connman_network_connect: * @network: network structure @@ -1392,7 +1575,7 @@ int connman_network_set_nameservers(struct connman_network *network, const char *nameservers) { struct connman_service *service; - char **nameservers_array = NULL; + char **nameservers_array; int i; DBG("network %p nameservers %s", network, nameservers); @@ -1403,12 +1586,14 @@ int connman_network_set_nameservers(struct connman_network *network, __connman_service_nameserver_clear(service); - if (nameservers != NULL) - nameservers_array = g_strsplit(nameservers, " ", 0); + if (nameservers == NULL) + return 0; + + nameservers_array = g_strsplit(nameservers, " ", 0); for (i = 0; nameservers_array[i] != NULL; i++) { __connman_service_nameserver_append(service, - nameservers_array[i]); + nameservers_array[i], FALSE); } g_strfreev(nameservers_array); @@ -1504,23 +1689,6 @@ connman_uint16_t connman_network_get_wifi_channel(struct connman_network *networ } /** - * connman_network_set_roaming: - * @network: network structure - * @roaming: roaming state - * - * Set roaming state for network - */ -int connman_network_set_roaming(struct connman_network *network, - connman_bool_t roaming) -{ - DBG("network %p roaming %d", network, roaming); - - network->roaming = roaming; - - return 0; -} - -/** * connman_network_set_string: * @network: network structure * @key: unique identifier @@ -1650,7 +1818,7 @@ int connman_network_set_bool(struct connman_network *network, DBG("network %p key %s value %d", network, key, value); if (g_strcmp0(key, "Roaming") == 0) - return connman_network_set_roaming(network, value); + network->roaming = value; else if (g_strcmp0(key, "WiFi.WPS") == 0) network->wifi.wps = value; else if (g_strcmp0(key, "WiFi.UseWPS") == 0)