X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fnetwork.c;h=e189955c2ad7931dc6ebbda1db7982e6c289237b;hb=d04bfa0350781ebfb8cbb2e64fabdfb2f36cd302;hp=82c7cd0f965e9d4a4a3c085d61b3830229e9c366;hpb=295fb30ff4057a055d6fe908df8c38b3ee08e27a;p=platform%2Fupstream%2Fconnman.git diff --git a/src/network.c b/src/network.c old mode 100644 new mode 100755 index 82c7cd0..e189955 --- a/src/network.c +++ b/src/network.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -28,17 +28,42 @@ #include "connman.h" +/* + * How many times to send RS with the purpose of + * refreshing RDNSS entries before they actually expire. + * With a value of 1, one RS will be sent, with no retries. + */ +#define RS_REFRESH_COUNT 1 + +/* + * Value in seconds to wait for RA after RS was sent. + * After this time elapsed, we can send another RS. + */ +#define RS_REFRESH_TIMEOUT 3 + +#if defined TIZEN_EXT +#define WIFI_ENCYPTION_MODE_LEN_MAX 6 +#define WIFI_BSSID_LEN_MAX 6 +#endif + +/* + * As per RFC 4861, a host should transmit up to MAX_RTR_SOLICITATIONS(3) + * Router Solicitation messages, each separated by at least + * RTR_SOLICITATION_INTERVAL(4) seconds to obtain RA for IPv6 auto-configuration. + */ +#define RTR_SOLICITATION_INTERVAL 4 + static GSList *network_list = NULL; static GSList *driver_list = NULL; struct connman_network { int refcount; enum connman_network_type type; - connman_bool_t available; - connman_bool_t connected; - connman_bool_t roaming; - connman_uint8_t strength; - connman_uint16_t frequency; + bool available; + bool connected; + bool roaming; + uint8_t strength; + uint16_t frequency; char *identifier; char *name; char *node; @@ -46,12 +71,13 @@ struct connman_network { char *path; int index; int router_solicit_count; + int router_solicit_refresh_count; struct connman_network_driver *driver; void *driver_data; - connman_bool_t connecting; - connman_bool_t associating; + bool connecting; + bool associating; struct connman_device *device; @@ -62,24 +88,47 @@ struct connman_network { unsigned short channel; char *security; char *passphrase; - char *agent_passphrase; char *eap; char *identity; + char *anonymous_identity; char *agent_identity; char *ca_cert_path; + char *subject_match; + char *altsubject_match; + char *domain_suffix_match; + char *domain_match; char *client_cert_path; char *private_key_path; char *private_key_passphrase; char *phase2_auth; - connman_bool_t wps; - connman_bool_t use_wps; + bool wps; + bool use_wps; char *pin_wps; +#if defined TIZEN_EXT + char encryption_mode[WIFI_ENCYPTION_MODE_LEN_MAX]; + unsigned char bssid[WIFI_BSSID_LEN_MAX]; + unsigned int maxrate; + bool isHS20AP; + unsigned int keymgmt; + char *keymgmt_type; + bool rsn_mode; + int disconnect_reason; + int assoc_status_code; + GSList *vsie_list; + /* + * Only for EAP-FAST + */ + char *phase1; + unsigned char country_code[WIFI_COUNTRY_CODE_LEN]; + GSList *bssid_list; +#endif } wifi; - struct { - char *nsp_name; - int nsp_name_len; - } wimax; +#if defined TIZEN_EXT + /* Multiple APN services and a default APN which a user selected */ + bool default_internet; +#endif + }; static const char *type2string(enum connman_network_type type) @@ -90,10 +139,10 @@ static const char *type2string(enum connman_network_type type) break; case CONNMAN_NETWORK_TYPE_ETHERNET: return "ethernet"; + case CONNMAN_NETWORK_TYPE_GADGET: + return "gadget"; case CONNMAN_NETWORK_TYPE_WIFI: return "wifi"; - case CONNMAN_NETWORK_TYPE_WIMAX: - return "wimax"; case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: return "bluetooth"; @@ -104,1204 +153,1418 @@ static const char *type2string(enum connman_network_type type) return NULL; } -connman_bool_t __connman_network_has_driver(struct connman_network *network) -{ - if (network == NULL || network->driver == NULL) - return FALSE; - - return TRUE; -} - -static gboolean match_driver(struct connman_network *network, +static bool match_driver(struct connman_network *network, struct connman_network_driver *driver) { if (network->type == driver->type || driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN) - return TRUE; + return true; - return FALSE; + return false; } -static int network_probe(struct connman_network *network) +static void set_configuration(struct connman_network *network, + enum connman_ipconfig_type type) { - GSList *list; - struct connman_network_driver *driver = NULL; - - DBG("network %p name %s", network, network->name); - - if (network->driver != NULL) - return -EALREADY; - - for (list = driver_list; list; list = list->next) { - driver = list->data; - - if (match_driver(network, driver) == FALSE) - continue; + struct connman_service *service; - DBG("driver %p name %s", driver, driver->name); + DBG("network %p", network); - if (driver->probe(network) == 0) - break; + if (!network->device) + return; - driver = NULL; - } + __connman_device_set_network(network->device, network); - if (driver == NULL) - return -ENODEV; + service = connman_service_lookup_from_network(network); + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_CONFIGURATION, + type); +} - if (network->group == NULL) - return -EINVAL; +static void dhcp_success(struct connman_network *network) +{ + struct connman_service *service; + struct connman_ipconfig *ipconfig_ipv4; + int err; - switch (network->type) { - case CONNMAN_NETWORK_TYPE_UNKNOWN: - case CONNMAN_NETWORK_TYPE_VENDOR: - return 0; - case CONNMAN_NETWORK_TYPE_ETHERNET: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: - case CONNMAN_NETWORK_TYPE_CELLULAR: - case CONNMAN_NETWORK_TYPE_WIFI: - case CONNMAN_NETWORK_TYPE_WIMAX: - network->driver = driver; - if (__connman_service_create_from_network(network) == NULL) { - network->driver = NULL; - return -EINVAL; - } - } + service = connman_service_lookup_from_network(network); + if (!service) + goto err; - return 0; -} + ipconfig_ipv4 = __connman_service_get_ip4config(service); -static void network_remove(struct connman_network *network) -{ - DBG("network %p name %s", network, network->name); + DBG("lease acquired for ipconfig %p", ipconfig_ipv4); - if (network->driver == NULL) + if (!ipconfig_ipv4) return; - connman_network_set_connected(network, FALSE); + err = __connman_ipconfig_address_add(ipconfig_ipv4); + if (err < 0) + goto err; - switch (network->type) { - case CONNMAN_NETWORK_TYPE_UNKNOWN: - case CONNMAN_NETWORK_TYPE_VENDOR: - break; - case CONNMAN_NETWORK_TYPE_ETHERNET: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: - case CONNMAN_NETWORK_TYPE_CELLULAR: - case CONNMAN_NETWORK_TYPE_WIFI: - case CONNMAN_NETWORK_TYPE_WIMAX: - if (network->group != NULL) { - __connman_service_remove_from_network(network); +#if defined TIZEN_EXT + err = __connman_ipconfig_gateway_add(ipconfig_ipv4, service); +#else + err = __connman_ipconfig_gateway_add(ipconfig_ipv4); +#endif + if (err < 0) + goto err; - g_free(network->group); - network->group = NULL; - } - break; - } + __connman_service_save(service); - if (network->driver->remove) - network->driver->remove(network); + return; - network->driver = NULL; +err: + connman_network_set_error(network, + CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); } -static void network_change(struct connman_network *network) +static void dhcp_failure(struct connman_network *network) { - DBG("network %p name %s", network, network->name); + struct connman_service *service; + struct connman_ipconfig *ipconfig_ipv4; - if (network->connected == FALSE) + service = connman_service_lookup_from_network(network); + if (!service) return; - connman_device_set_disconnected(network->device, TRUE); + ipconfig_ipv4 = __connman_service_get_ip4config(service); + + DBG("lease lost for ipconfig %p", ipconfig_ipv4); - if (network->driver && network->driver->disconnect) { - network->driver->disconnect(network); + if (!ipconfig_ipv4) return; - } - network->connected = FALSE; + __connman_ipconfig_address_remove(ipconfig_ipv4); + __connman_ipconfig_gateway_remove(ipconfig_ipv4); } -static void probe_driver(struct connman_network_driver *driver) +static void dhcp_callback(struct connman_ipconfig *ipconfig, + struct connman_network *network, + bool success, gpointer data) { - GSList *list; + network->connecting = false; - DBG("driver %p name %s", driver, driver->name); + if (success) + dhcp_success(network); + else + dhcp_failure(network); +} - for (list = network_list; list != NULL; list = list->next) { - struct connman_network *network = list->data; +static int set_connected_manual(struct connman_network *network) +{ + int err = 0; + struct connman_service *service; + struct connman_ipconfig *ipconfig; - if (network->driver != NULL) - continue; + DBG("network %p", network); - if (driver->type != network->type) - continue; + network->connecting = false; - if (driver->probe(network) < 0) - continue; + service = connman_service_lookup_from_network(network); + ipconfig = __connman_service_get_ip4config(service); + __connman_ipconfig_enable(ipconfig); - network->driver = driver; - } + if (!__connman_ipconfig_get_local(ipconfig)) + __connman_service_read_ip4config(service); + + err = __connman_ipconfig_address_add(ipconfig); + if (err < 0) + goto err; + +#if defined TIZEN_EXT + err = __connman_ipconfig_gateway_add(ipconfig, service); +#else + err = __connman_ipconfig_gateway_add(ipconfig); +#endif + if (err < 0) + goto err; + +err: + return err; } -static void remove_driver(struct connman_network_driver *driver) +static int set_connected_dhcp(struct connman_network *network) { - GSList *list; + struct connman_service *service; + struct connman_ipconfig *ipconfig_ipv4; + int err; - DBG("driver %p name %s", driver, driver->name); + DBG("network %p", network); - for (list = network_list; list != NULL; list = list->next) { - struct connman_network *network = list->data; + service = connman_service_lookup_from_network(network); + ipconfig_ipv4 = __connman_service_get_ip4config(service); + __connman_ipconfig_enable(ipconfig_ipv4); - if (network->driver == driver) - network_remove(network); + err = __connman_dhcp_start(ipconfig_ipv4, network, + dhcp_callback, NULL); + if (err < 0) { + connman_error("Can not request DHCP lease"); + return err; } -} - -static gint compare_priority(gconstpointer a, gconstpointer b) -{ - const struct connman_network_driver *driver1 = a; - const struct connman_network_driver *driver2 = b; - return driver2->priority - driver1->priority; + return 0; } -/** - * connman_network_driver_register: - * @driver: network driver definition - * - * Register a new network driver - * - * Returns: %0 on success - */ -int connman_network_driver_register(struct connman_network_driver *driver) +static int manual_ipv6_set(struct connman_network *network, + struct connman_ipconfig *ipconfig_ipv6) { - GSList *list; + struct connman_service *service; + int err; - DBG("driver %p name %s", driver, driver->name); + DBG("network %p ipv6 %p", network, ipconfig_ipv6); - for (list = driver_list; list; list = list->next) { - struct connman_network_driver *tmp = list->data; + service = connman_service_lookup_from_network(network); + if (!service) + return -EINVAL; - if (tmp->type == driver->type) - return -EALREADY; + if (!__connman_ipconfig_get_local(ipconfig_ipv6)) + __connman_service_read_ip6config(service); + + __connman_ipconfig_enable_ipv6(ipconfig_ipv6); + err = __connman_ipconfig_address_add(ipconfig_ipv6); + if (err < 0) { + connman_network_set_error(network, + CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); + return err; } - driver_list = g_slist_insert_sorted(driver_list, driver, - compare_priority); +#if defined TIZEN_EXT + err = __connman_ipconfig_gateway_add(ipconfig_ipv6, service); +#else + err = __connman_ipconfig_gateway_add(ipconfig_ipv6); +#endif + if (err < 0) + return err; - probe_driver(driver); + __connman_device_set_network(network->device, network); + + connman_network_set_associating(network, false); + + network->connecting = false; return 0; } -/** - * connman_network_driver_unregister: - * @driver: network driver definition - * - * Remove a previously registered network driver - */ -void connman_network_driver_unregister(struct connman_network_driver *driver) +static void stop_dhcpv6(struct connman_network *network) { - DBG("driver %p name %s", driver, driver->name); - - driver_list = g_slist_remove(driver_list, driver); + network->connecting = false; - remove_driver(driver); + __connman_dhcpv6_stop(network); } -static void network_destruct(struct connman_network *network) +static void dhcpv6_release_callback(struct connman_network *network, + enum __connman_dhcpv6_status status, + gpointer data) { - DBG("network %p name %s", network, network->name); + DBG("status %d", status); - g_free(network->wifi.ssid); - g_free(network->wifi.mode); - g_free(network->wifi.security); - g_free(network->wifi.passphrase); - g_free(network->wifi.agent_passphrase); - g_free(network->wifi.eap); - g_free(network->wifi.identity); - g_free(network->wifi.agent_identity); - g_free(network->wifi.ca_cert_path); - g_free(network->wifi.client_cert_path); - g_free(network->wifi.private_key_path); - g_free(network->wifi.private_key_passphrase); - g_free(network->wifi.phase2_auth); - g_free(network->wifi.pin_wps); + stop_dhcpv6(network); +} - g_free(network->path); - g_free(network->group); - g_free(network->node); - g_free(network->name); - g_free(network->identifier); +static void release_dhcpv6(struct connman_network *network) +{ + __connman_dhcpv6_start_release(network, dhcpv6_release_callback); + stop_dhcpv6(network); +} - network->device = NULL; +static void dhcpv6_info_callback(struct connman_network *network, + enum __connman_dhcpv6_status status, + gpointer data) +{ + DBG("status %d", status); - g_free(network); + stop_dhcpv6(network); } -/** - * connman_network_create: - * @identifier: network identifier (for example an unqiue name) - * - * Allocate a new network and assign the #identifier to it. - * - * Returns: a newly-allocated #connman_network structure - */ -struct connman_network *connman_network_create(const char *identifier, - enum connman_network_type type) +static int dhcpv6_set_addresses(struct connman_network *network) { - struct connman_network *network; - char *ident; - - DBG("identifier %s type %d", identifier, type); + struct connman_service *service; + struct connman_ipconfig *ipconfig_ipv6; + int err = -EINVAL; - network = g_try_new0(struct connman_network, 1); - if (network == NULL) - return NULL; + service = connman_service_lookup_from_network(network); + if (!service) + goto err; - DBG("network %p", network); + network->connecting = false; - network->refcount = 1; + ipconfig_ipv6 = __connman_service_get_ip6config(service); + err = __connman_ipconfig_address_add(ipconfig_ipv6); + if (err < 0) + goto err; - ident = g_strdup(identifier); + return 0; - if (ident == NULL) { - g_free(network); - return NULL; - } +err: + connman_network_set_error(network, + CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); + return err; +} - network->type = type; - network->identifier = ident; +static void autoconf_ipv6_set(struct connman_network *network); +static void dhcpv6_callback(struct connman_network *network, + enum __connman_dhcpv6_status status, gpointer data); - network_list = g_slist_append(network_list, network); +/* + * 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, + enum __connman_dhcpv6_status status, + gpointer data) +{ + switch (status) { + case CONNMAN_DHCPV6_STATUS_SUCCEED: + dhcpv6_callback(network, status, data); + break; + case CONNMAN_DHCPV6_STATUS_FAIL: + case CONNMAN_DHCPV6_STATUS_RESTART: + stop_dhcpv6(network); - return network; + /* restart and do solicit again. */ + autoconf_ipv6_set(network); + break; + } } -/** - * connman_network_ref: - * @network: network structure - * - * Increase reference counter of network - */ -struct connman_network *connman_network_ref(struct connman_network *network) +static void dhcpv6_callback(struct connman_network *network, + enum __connman_dhcpv6_status status, gpointer data) { - DBG("network %p name %s refcount %d", network, network->name, - network->refcount + 1); + DBG("status %d", status); - __sync_fetch_and_add(&network->refcount, 1); + /* Start the renew process if necessary */ + if (status == CONNMAN_DHCPV6_STATUS_SUCCEED) { - return network; + if (dhcpv6_set_addresses(network) < 0) { + stop_dhcpv6(network); + return; + } + + if (__connman_dhcpv6_start_renew(network, + dhcpv6_renew_callback) == -ETIMEDOUT) + dhcpv6_renew_callback(network, + CONNMAN_DHCPV6_STATUS_FAIL, + data); + + } else if (status == CONNMAN_DHCPV6_STATUS_RESTART) { + stop_dhcpv6(network); + autoconf_ipv6_set(network); + } else + stop_dhcpv6(network); } -/** - * connman_network_unref: - * @network: network structure - * - * Decrease reference counter of network - */ -void connman_network_unref(struct connman_network *network) +static void check_dhcpv6(struct nd_router_advert *reply, + unsigned int length, void *user_data) { - DBG("network %p name %s refcount %d", network, network->name, - network->refcount - 1); + struct connman_network *network = user_data; + struct connman_service *service; + GSList *prefixes; - if (__sync_fetch_and_sub(&network->refcount, 1) != 1) + DBG("reply %p", reply); + + if (!reply) { + /* + * 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, RTR_SOLICITATION_INTERVAL, + check_dhcpv6, network); + return; + } +#if defined TIZEN_EXT + DBG("RA message is not received from server in reply of RS."); +#endif + connman_network_unref(network); return; + } - network_list = g_slist_remove(network_list, network); + network->router_solicit_count = 0; - network_destruct(network); -} + /* + * If we were disconnected while waiting router advertisement, + * we just quit and do not start DHCPv6 + */ + if (!network->connected) { + connman_network_unref(network); +#if defined TIZEN_EXT + DBG("Network is not connected"); +#endif + return; + } -const char *__connman_network_get_type(struct connman_network *network) -{ - return type2string(network->type); + prefixes = __connman_inet_ipv6_get_prefixes(reply, length); + + /* + * If IPv6 config is missing from service, then create it. + * The ipconfig might be missing if we got a rtnl message + * that disabled IPv6 config and thus removed it. This + * can happen if we are switching from one service to + * another in the same interface. The only way to get IPv6 + * config back is to re-create it here. + */ + service = connman_service_lookup_from_network(network); + if (service) { + connman_service_create_ip6config(service, network->index); + + connman_network_set_associating(network, false); + + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_CONFIGURATION, + CONNMAN_IPCONFIG_TYPE_IPV6); + } + + /* + * We do stateful/stateless DHCPv6 if router advertisement says so. + */ + if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) { +#if defined TIZEN_EXT + DBG("IPv6 ND_RA_FLAG_MANAGED"); +#endif + __connman_dhcpv6_start(network, prefixes, dhcpv6_callback); + } else { + if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) +#if defined TIZEN_EXT + { + DBG("IPv6 ND_RA_FLAG_OTHER"); +#endif + __connman_dhcpv6_start_info(network, + dhcpv6_info_callback); +#if defined TIZEN_EXT + } +#endif + + g_slist_free_full(prefixes, g_free); + network->connecting = false; + } + + connman_network_unref(network); } -/** - * connman_network_get_type: - * @network: network structure - * - * Get type of network - */ -enum connman_network_type connman_network_get_type(struct connman_network *network) +static void receive_refresh_rs_reply(struct nd_router_advert *reply, + unsigned int length, void *user_data) { - return network->type; + struct connman_network *network = user_data; + + DBG("reply %p", reply); + + if (!reply) { + /* + * Router solicitation message seem to get lost easily so + * try to send it again. + */ + if (network->router_solicit_refresh_count > 1) { + network->router_solicit_refresh_count--; + DBG("re-send router solicitation %d", + network->router_solicit_refresh_count); + __connman_inet_ipv6_send_rs(network->index, + RS_REFRESH_TIMEOUT, + receive_refresh_rs_reply, + network); + return; + } + } + + /* RS refresh not in progress anymore */ + network->router_solicit_refresh_count = 0; + + connman_network_unref(network); + return; } -/** - * connman_network_get_identifier: - * @network: network structure - * - * Get identifier of network - */ -const char *connman_network_get_identifier(struct connman_network *network) +int __connman_network_refresh_rs_ipv6(struct connman_network *network, + int index) { - return network->identifier; + int ret = 0; + + DBG("network %p index %d", network, index); + + /* Send only one RS for all RDNSS entries which are about to expire */ + if (network->router_solicit_refresh_count > 0) { + DBG("RS refresh already started"); + return 0; + } + + network->router_solicit_refresh_count = RS_REFRESH_COUNT; + + connman_network_ref(network); + + ret = __connman_inet_ipv6_send_rs(index, RS_REFRESH_TIMEOUT, + receive_refresh_rs_reply, network); + return ret; } -/** - * connman_network_set_index: - * @network: network structure - * @index: index number - * - * Set index number of network - */ -void connman_network_set_index(struct connman_network *network, int index) +static void autoconf_ipv6_set(struct connman_network *network) { struct connman_service *service; struct connman_ipconfig *ipconfig; + int index; - service = __connman_service_lookup_from_network(network); - if (service == NULL) - goto done; + DBG("network %p", network); - ipconfig = __connman_service_get_ip4config(service); + if (network->router_solicit_count > 0) { + /* + * The autoconfiguration is already pending and we have sent + * router solicitation messages and are now waiting answers. + * There is no need to continue any further. + */ + DBG("autoconfiguration already started"); + return; + } - DBG("index %d service %p ip4config %p", network->index, - service, ipconfig); + __connman_device_set_network(network->device, network); - if (network->index < 0 && ipconfig == NULL) { +#if defined TIZEN_EXT + if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR) + return; +#endif - ipconfig = __connman_service_get_ip4config(service); - if (ipconfig == NULL) - /* - * This is needed for plugins that havent set their - * ipconfig layer yet, due to not being able to get - * a network index prior to creating a service. - */ - __connman_service_create_ip4config(service, index); - else - __connman_ipconfig_set_index(ipconfig, index); + service = connman_service_lookup_from_network(network); + if (!service) + return; - } else { - /* If index changed, the index of ipconfig must be reset. */ - if (ipconfig == NULL) - goto done; + ipconfig = __connman_service_get_ip6config(service); + if (!ipconfig) + return; - __connman_ipconfig_set_index(ipconfig, index); - } + __connman_ipconfig_enable(ipconfig); -done: - network->index = index; -} + __connman_ipconfig_enable_ipv6(ipconfig); -/** - * connman_network_get_index: - * @network: network structure - * - * Get index number of network - */ -int connman_network_get_index(struct connman_network *network) -{ - return network->index; + __connman_ipconfig_address_remove(ipconfig); + + 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, RTR_SOLICITATION_INTERVAL, + check_dhcpv6, network); } -/** - * connman_network_set_group: - * @network: network structure - * @group: group name - * - * Set group name for automatic clustering - */ -void connman_network_set_group(struct connman_network *network, - const char *group) +static void set_connected(struct connman_network *network) { - switch (network->type) { - case CONNMAN_NETWORK_TYPE_UNKNOWN: - case CONNMAN_NETWORK_TYPE_VENDOR: - return; - case CONNMAN_NETWORK_TYPE_ETHERNET: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: - case CONNMAN_NETWORK_TYPE_CELLULAR: - case CONNMAN_NETWORK_TYPE_WIFI: - case CONNMAN_NETWORK_TYPE_WIMAX: - break; - } + struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6; + struct connman_service *service; - if (g_strcmp0(network->group, group) == 0) { - if (group != NULL) - __connman_service_update_from_network(network); + if (network->connected) return; - } - if (network->group != NULL) { - __connman_service_remove_from_network(network); + connman_network_set_associating(network, false); - g_free(network->group); - } + network->connected = true; - network->group = g_strdup(group); + service = connman_service_lookup_from_network(network); - if (network->group != NULL) - network_probe(network); -} + ipconfig_ipv4 = __connman_service_get_ip4config(service); + ipconfig_ipv6 = __connman_service_get_ip6config(service); -/** - * connman_network_get_group: - * @network: network structure - * - * Get group name for automatic clustering - */ -const char *connman_network_get_group(struct connman_network *network) -{ - return network->group; + DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4, + ipconfig_ipv6); + + __connman_network_enable_ipconfig(network, ipconfig_ipv4); + __connman_network_enable_ipconfig(network, ipconfig_ipv6); } -const char *__connman_network_get_ident(struct connman_network *network) +static void set_disconnected(struct connman_network *network) { - if (network->device == NULL) - return NULL; + struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6; + enum connman_ipconfig_method ipv4_method, ipv6_method; + enum connman_service_state state; + struct connman_service *service; - return connman_device_get_ident(network->device); -} + service = connman_service_lookup_from_network(network); -connman_bool_t __connman_network_get_weakness(struct connman_network *network) -{ - switch (network->type) { - case CONNMAN_NETWORK_TYPE_UNKNOWN: - case CONNMAN_NETWORK_TYPE_VENDOR: - case CONNMAN_NETWORK_TYPE_ETHERNET: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: - case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: - case CONNMAN_NETWORK_TYPE_CELLULAR: - case CONNMAN_NETWORK_TYPE_WIMAX: - break; - case CONNMAN_NETWORK_TYPE_WIFI: - if (g_strcmp0(network->wifi.mode, "adhoc") == 0) - return TRUE; - if (network->strength > 0 && network->strength < 20) - return TRUE; - break; + 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); + + /* + * 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); + + if (network->connected) { + 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: + release_dhcpv6(network); + break; + } + + switch (ipv4_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_AUTO: + /* + * If the current method is AUTO then next time we + * try first DHCP. DHCP also needs to be stopped + * in this case because if we fell in AUTO means + * that DHCP was launched for IPv4 but it failed. + */ + __connman_ipconfig_set_method(ipconfig_ipv4, + CONNMAN_IPCONFIG_METHOD_DHCP); + __connman_service_notify_ipv4_configuration(service); + /* fall through */ + case CONNMAN_IPCONFIG_METHOD_DHCP: + __connman_dhcp_stop(ipconfig_ipv4); + break; + } } - return FALSE; -} + /* + * 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); -connman_bool_t connman_network_get_connecting(struct connman_network *network) -{ - return network->connecting; -} + 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_network_set_available: - * @network: network structure - * @available: availability state - * - * Change availability state of network (in range) - */ -int connman_network_set_available(struct connman_network *network, - connman_bool_t available) -{ - DBG("network %p available %d", network, available); + if (network->connected) { +#if defined TIZEN_EXT + /** + * Do not remove gateway and its address, + * if there are connected profiles that use same interface (multiple PDN) + */ + if (connman_service_get_type(service) != CONNMAN_SERVICE_TYPE_CELLULAR || + __connman_service_get_connected_count_of_iface(service) <= 0) { +#endif + __connman_connection_gateway_remove(service, + CONNMAN_IPCONFIG_TYPE_ALL); - if (network->available == available) - return -EALREADY; + __connman_ipconfig_address_unset(ipconfig_ipv4); + __connman_ipconfig_address_unset(ipconfig_ipv6); +#if defined TIZEN_EXT + } +#endif + /* + * 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); + } + } - network->available = available; + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV4); - return 0; -} + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV6); -/** - * connman_network_get_available: - * @network: network structure - * - * Get network available setting - */ -connman_bool_t connman_network_get_available(struct connman_network *network) -{ - return network->available; + network->connecting = false; + network->connected = false; + + connman_network_set_associating(network, false); } -/** - * connman_network_set_associating: - * @network: network structure - * @associating: associating state - * - * Change associating state of network - */ -int connman_network_set_associating(struct connman_network *network, - connman_bool_t associating) + + +static int network_probe(struct connman_network *network) { - DBG("network %p associating %d", network, associating); + GSList *list; + struct connman_network_driver *driver = NULL; - if (network->associating == associating) + DBG("network %p name %s", network, network->name); + + if (network->driver) return -EALREADY; - network->associating = associating; + for (list = driver_list; list; list = list->next) { + driver = list->data; - if (associating == TRUE) { - struct connman_service *service; + if (!match_driver(network, driver)) { + driver = NULL; + continue; + } - service = __connman_service_lookup_from_network(network); - __connman_service_ipconfig_indicate_state(service, - CONNMAN_SERVICE_STATE_ASSOCIATION, - CONNMAN_IPCONFIG_TYPE_IPV4); - __connman_service_ipconfig_indicate_state(service, - CONNMAN_SERVICE_STATE_ASSOCIATION, - CONNMAN_IPCONFIG_TYPE_IPV6); + DBG("driver %p name %s", driver, driver->name); + + if (driver->probe(network) == 0) + break; + + driver = NULL; + } + + if (!driver) + return -ENODEV; + + if (!network->group) + return -EINVAL; + + switch (network->type) { + case CONNMAN_NETWORK_TYPE_UNKNOWN: + case CONNMAN_NETWORK_TYPE_VENDOR: + return 0; + case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_GADGET: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: + case CONNMAN_NETWORK_TYPE_CELLULAR: + case CONNMAN_NETWORK_TYPE_WIFI: + network->driver = driver; + if (!__connman_service_create_from_network(network)) { + network->driver = NULL; + return -EINVAL; + } } return 0; } -static void set_associate_error(struct connman_network *network) +static void network_remove(struct connman_network *network) { - struct connman_service *service; - - service = __connman_service_lookup_from_network(network); - - __connman_service_indicate_error(service, - CONNMAN_SERVICE_ERROR_CONNECT_FAILED); -} + DBG("network %p name %s", network, network->name); -static void set_configure_error(struct connman_network *network) -{ - struct connman_service *service; + if (!network->driver) + return; - service = __connman_service_lookup_from_network(network); + if (network->connected) + set_disconnected(network); - __connman_service_indicate_error(service, - CONNMAN_SERVICE_ERROR_CONNECT_FAILED); -} + switch (network->type) { + case CONNMAN_NETWORK_TYPE_UNKNOWN: + case CONNMAN_NETWORK_TYPE_VENDOR: + break; + case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_GADGET: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: + case CONNMAN_NETWORK_TYPE_CELLULAR: + case CONNMAN_NETWORK_TYPE_WIFI: + if (network->group) { + __connman_service_remove_from_network(network); -static void set_invalid_key_error(struct connman_network *network) -{ - struct connman_service *service; + g_free(network->group); + network->group = NULL; + } + break; + } - service = __connman_service_lookup_from_network(network); + if (network->driver->remove) + network->driver->remove(network); - __connman_service_indicate_error(service, - CONNMAN_SERVICE_ERROR_INVALID_KEY); + network->driver = NULL; } -static void set_connect_error(struct connman_network *network) +static void probe_driver(struct connman_network_driver *driver) { - struct connman_service *service; + GSList *list; - service = __connman_service_lookup_from_network(network); + DBG("driver %p name %s", driver, driver->name); - __connman_service_indicate_error(service, - CONNMAN_SERVICE_ERROR_CONNECT_FAILED); -} + for (list = network_list; list; list = list->next) { + struct connman_network *network = list->data; -void connman_network_set_ipv4_method(struct connman_network *network, - enum connman_ipconfig_method method) -{ - struct connman_service *service; - struct connman_ipconfig *ipconfig; + if (network->driver) + continue; - service = __connman_service_lookup_from_network(network); - if (service == NULL) - return; + if (driver->type != network->type) + continue; - ipconfig = __connman_service_get_ip4config(service); - if (ipconfig == NULL) - return; + if (driver->probe(network) < 0) + continue; - __connman_ipconfig_set_method(ipconfig, method); + network->driver = driver; + } } -void connman_network_set_ipv6_method(struct connman_network *network, - enum connman_ipconfig_method method) +static gint compare_priority(gconstpointer a, gconstpointer b) { - 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; + const struct connman_network_driver *driver1 = a; + const struct connman_network_driver *driver2 = b; - __connman_ipconfig_set_method(ipconfig, method); + return driver2->priority - driver1->priority; } -void connman_network_set_error(struct connman_network *network, - enum connman_network_error error) +/** + * connman_network_driver_register: + * @driver: network driver definition + * + * Register a new network driver + * + * Returns: %0 on success + */ +int connman_network_driver_register(struct connman_network_driver *driver) { - DBG("nework %p, error %d", network, error); + DBG("driver %p name %s", driver, driver->name); - network->connecting = FALSE; - network->associating = FALSE; + driver_list = g_slist_insert_sorted(driver_list, driver, + compare_priority); - switch (error) { - case CONNMAN_NETWORK_ERROR_UNKNOWN: - return; - case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL: - set_associate_error(network); - break; - case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL: - set_configure_error(network); - break; - case CONNMAN_NETWORK_ERROR_INVALID_KEY: - set_invalid_key_error(network); - break; - case CONNMAN_NETWORK_ERROR_CONNECT_FAIL: - set_connect_error(network); - break; - } + probe_driver(driver); - network_change(network); + return 0; } -void connman_network_clear_error(struct connman_network *network) +/** + * connman_network_driver_unregister: + * @driver: network driver definition + * + * Remove a previously registered network driver + */ +void connman_network_driver_unregister(struct connman_network_driver *driver) { - struct connman_service *service; + GSList *list; - DBG("network %p", network); + DBG("driver %p name %s", driver, driver->name); - if (network == NULL) - return; + driver_list = g_slist_remove(driver_list, driver); - if (network->connecting == TRUE || network->associating == TRUE) - return; + for (list = network_list; list; list = list->next) { + struct connman_network *network = list->data; - service = __connman_service_lookup_from_network(network); - __connman_service_clear_error(service); + if (network->driver == driver) + network_remove(network); + } } -static void set_configuration(struct connman_network *network, - enum connman_ipconfig_type type) +static void network_destruct(struct connman_network *network) { - struct connman_service *service; - - DBG("network %p", network); - - if (network->device == NULL) - return; + DBG("network %p name %s", network, network->name); - __connman_device_set_network(network->device, network); + g_free(network->wifi.ssid); + g_free(network->wifi.mode); + g_free(network->wifi.security); + g_free(network->wifi.passphrase); + g_free(network->wifi.eap); + g_free(network->wifi.identity); + g_free(network->wifi.anonymous_identity); + g_free(network->wifi.agent_identity); + g_free(network->wifi.ca_cert_path); + g_free(network->wifi.subject_match); + g_free(network->wifi.altsubject_match); + g_free(network->wifi.domain_suffix_match); + g_free(network->wifi.domain_match); + g_free(network->wifi.client_cert_path); + g_free(network->wifi.private_key_path); + g_free(network->wifi.private_key_passphrase); + g_free(network->wifi.phase2_auth); + g_free(network->wifi.pin_wps); +#if defined TIZEN_EXT + g_slist_free_full(network->wifi.vsie_list, g_free); + g_slist_free_full(network->wifi.bssid_list, g_free); +#endif + g_free(network->path); + g_free(network->group); + g_free(network->node); + g_free(network->name); + g_free(network->identifier); - connman_device_set_disconnected(network->device, FALSE); + network->device = NULL; - service = __connman_service_lookup_from_network(network); - __connman_service_ipconfig_indicate_state(service, - CONNMAN_SERVICE_STATE_CONFIGURATION, - type); + g_free(network); } -static void dhcp_success(struct connman_network *network) +/** + * connman_network_create: + * @identifier: network identifier (for example an unqiue name) + * + * Allocate a new network and assign the #identifier to it. + * + * Returns: a newly-allocated #connman_network structure + */ +struct connman_network *connman_network_create(const char *identifier, + enum connman_network_type type) { - struct connman_service *service; - struct connman_ipconfig *ipconfig_ipv4; - int err; + struct connman_network *network; + char *ident; - service = __connman_service_lookup_from_network(network); - if (service == NULL) - goto err; + network = g_try_new0(struct connman_network, 1); + if (!network) + return NULL; - connman_network_set_associating(network, FALSE); + network->refcount = 1; - network->connecting = FALSE; + ident = g_strdup(identifier); - ipconfig_ipv4 = __connman_service_get_ip4config(service); - err = __connman_ipconfig_address_add(ipconfig_ipv4); - if (err < 0) - goto err; + if (!ident) { + g_free(network); + return NULL; + } - err = __connman_ipconfig_gateway_add(ipconfig_ipv4); - if (err < 0) - goto err; + network->type = type; + network->identifier = ident; - return; + network_list = g_slist_prepend(network_list, network); -err: - connman_network_set_error(network, - CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); + DBG("network %p identifier %s type %s", network, identifier, + type2string(type)); + return network; } -static void dhcp_failure(struct connman_network *network) +/** + * connman_network_ref: + * @network: network structure + * + * Increase reference counter of network + */ +struct connman_network * +connman_network_ref_debug(struct connman_network *network, + const char *file, int line, const char *caller) { - struct connman_service *service; - - service = __connman_service_lookup_from_network(network); - if (service == NULL) - return; - - __connman_service_ipconfig_indicate_state(service, - CONNMAN_SERVICE_STATE_IDLE, - CONNMAN_IPCONFIG_TYPE_IPV4); -} + DBG("%p name %s ref %d by %s:%d:%s()", network, network->name, + network->refcount + 1, file, line, caller); -static void dhcp_callback(struct connman_network *network, - connman_bool_t success) -{ - DBG("success %d", success); + __sync_fetch_and_add(&network->refcount, 1); - if (success == TRUE) - dhcp_success(network); - else - dhcp_failure(network); + return network; } -static int set_connected_fixed(struct connman_network *network) +/** + * connman_network_unref: + * @network: network structure + * + * Decrease reference counter of network + */ +void connman_network_unref_debug(struct connman_network *network, + const char *file, int line, const char *caller) { - struct connman_service *service; - struct connman_ipconfig *ipconfig_ipv4; - int err; - - DBG(""); - - service = __connman_service_lookup_from_network(network); - - ipconfig_ipv4 = __connman_service_get_ip4config(service); - - set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4); + DBG("%p name %s ref %d by %s:%d:%s()", network, network->name, + network->refcount - 1, file, line, caller); - network->connecting = FALSE; - - connman_network_set_associating(network, FALSE); - - err = __connman_ipconfig_address_add(ipconfig_ipv4); - if (err < 0) - goto err; + if (__sync_fetch_and_sub(&network->refcount, 1) != 1) + return; - err = __connman_ipconfig_gateway_add(ipconfig_ipv4); - if (err < 0) - goto err; + network_list = g_slist_remove(network_list, network); - return 0; + network_destruct(network); +} -err: - connman_network_set_error(network, - CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); +const char *__connman_network_get_type(struct connman_network *network) +{ + return type2string(network->type); +} - return err; +/** + * connman_network_get_type: + * @network: network structure + * + * Get type of network + */ +enum connman_network_type connman_network_get_type( + struct connman_network *network) +{ + return network->type; +} + +/** + * connman_network_get_identifier: + * @network: network structure + * + * Get identifier of network + */ +const char *connman_network_get_identifier(struct connman_network *network) +{ + return network->identifier; } -static void set_connected_manual(struct connman_network *network) +/** + * connman_network_set_index: + * @network: network structure + * @index: index number + * + * Set index number of network + */ +void connman_network_set_index(struct connman_network *network, int index) { struct connman_service *service; struct connman_ipconfig *ipconfig; - int err; - - DBG("network %p", network); - service = __connman_service_lookup_from_network(network); + service = connman_service_lookup_from_network(network); + if (!service) + goto done; ipconfig = __connman_service_get_ip4config(service); + if (ipconfig) { + __connman_ipconfig_set_index(ipconfig, index); - if (__connman_ipconfig_get_local(ipconfig) == NULL) - __connman_service_read_ip4config(service); - - set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4); - - err = __connman_ipconfig_address_add(ipconfig); - if (err < 0) - goto err; - - err = __connman_ipconfig_gateway_add(ipconfig); - if (err < 0) - goto err; + DBG("index %d service %p ip4config %p", network->index, + service, ipconfig); + } - network->connecting = FALSE; + ipconfig = __connman_service_get_ip6config(service); + if (ipconfig) { + __connman_ipconfig_set_index(ipconfig, index); - connman_network_set_associating(network, FALSE); + DBG("index %d service %p ip6config %p", network->index, + service, ipconfig); + } - return; +done: + network->index = index; +} -err: - connman_network_set_error(network, - CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); - return; +/** + * connman_network_get_index: + * @network: network structure + * + * Get index number of network + */ +int connman_network_get_index(struct connman_network *network) +{ + return network->index; } -static int set_connected_dhcp(struct connman_network *network) +/** + * connman_network_set_group: + * @network: network structure + * @group: group name + * + * Set group name for automatic clustering + */ +void connman_network_set_group(struct connman_network *network, + const char *group) { - int err; + switch (network->type) { + case CONNMAN_NETWORK_TYPE_UNKNOWN: + case CONNMAN_NETWORK_TYPE_VENDOR: + return; + case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_GADGET: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: + case CONNMAN_NETWORK_TYPE_CELLULAR: + case CONNMAN_NETWORK_TYPE_WIFI: + break; + } - DBG("network %p", network); + if (g_strcmp0(network->group, group) == 0) { + if (group) + __connman_service_update_from_network(network); + return; + } - set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4); + if (network->group) { + __connman_service_remove_from_network(network); - err = __connman_dhcp_start(network, dhcp_callback); - if (err < 0) { - connman_error("Can not request DHCP lease"); - return err; + g_free(network->group); } - return 0; + network->group = g_strdup(group); + + if (network->group) + network_probe(network); } -static int manual_ipv6_set(struct connman_network *network, - struct connman_ipconfig *ipconfig_ipv6) +/** + * connman_network_get_group: + * @network: network structure + * + * Get group name for automatic clustering + */ +const char *connman_network_get_group(struct connman_network *network) { - struct connman_service *service; - int err; - - DBG("network %p ipv6 %p", network, ipconfig_ipv6); + return network->group; +} - service = __connman_service_lookup_from_network(network); - if (service == NULL) - return -EINVAL; +const char *__connman_network_get_ident(struct connman_network *network) +{ + if (!network->device) + return NULL; - if (__connman_ipconfig_get_local(ipconfig_ipv6) == NULL) - __connman_service_read_ip6config(service); + return connman_device_get_ident(network->device); +} - err = __connman_ipconfig_address_add(ipconfig_ipv6); - if (err < 0) { - connman_network_set_error(network, - CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); - return err; +bool __connman_network_get_weakness(struct connman_network *network) +{ + switch (network->type) { + case CONNMAN_NETWORK_TYPE_UNKNOWN: + case CONNMAN_NETWORK_TYPE_VENDOR: + case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_GADGET: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: + case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: + case CONNMAN_NETWORK_TYPE_CELLULAR: + break; + case CONNMAN_NETWORK_TYPE_WIFI: + if (network->strength > 0 && network->strength < 20) + return true; + break; } - err = __connman_ipconfig_gateway_add(ipconfig_ipv6); - if (err < 0) - return err; - - __connman_connection_gateway_activate(service, - CONNMAN_IPCONFIG_TYPE_IPV6); - - __connman_device_set_network(network->device, network); - - connman_device_set_disconnected(network->device, FALSE); - - network->connecting = FALSE; - - return 0; + return false; } -static void stop_dhcpv6(struct connman_network *network) +#if defined TIZEN_EXT +void connman_network_set_connecting(struct connman_network *network) { - __connman_dhcpv6_stop(network); + DBG("set network connecting true"); + network->connecting = TRUE; + return; } +#endif -static void dhcpv6_release_callback(struct connman_network *network, - connman_bool_t success) +bool connman_network_get_connecting(struct connman_network *network) { - DBG("success %d", success); - - stop_dhcpv6(network); + return network->connecting; } -static void release_dhcpv6(struct connman_network *network) +/** + * connman_network_set_available: + * @network: network structure + * @available: availability state + * + * Change availability state of network (in range) + */ +int connman_network_set_available(struct connman_network *network, + bool available) { - __connman_dhcpv6_start_release(network, dhcpv6_release_callback); - stop_dhcpv6(network); +#if !defined TIZEN_EXT + DBG("network %p available %d", network, available); +#endif + + if (network->available == available) + return -EALREADY; + + network->available = available; + + return 0; } -static void dhcpv6_info_callback(struct connman_network *network, - connman_bool_t success) +/** + * connman_network_get_available: + * @network: network structure + * + * Get network available setting + */ +bool connman_network_get_available(struct connman_network *network) { - DBG("success %d", success); - - stop_dhcpv6(network); + return network->available; } -static gboolean dhcpv6_set_addresses(struct connman_network *network) +#if defined TIZEN_EXT +void connman_network_clear_associating(struct connman_network *network) { struct connman_service *service; - struct connman_ipconfig *ipconfig_ipv6; - int err = -EINVAL; + enum connman_service_state state; - service = __connman_service_lookup_from_network(network); - if (service == NULL) - goto err; - - connman_network_set_associating(network, FALSE); + DBG("network %p", network); network->connecting = FALSE; + network->associating = FALSE; - ipconfig_ipv6 = __connman_service_get_ip6config(service); - err = __connman_ipconfig_address_add(ipconfig_ipv6); - if (err < 0) - goto err; + service = connman_service_lookup_from_network(network); + if (!service) + return; - err = __connman_ipconfig_gateway_add(ipconfig_ipv6); - if (err < 0) - goto err; + 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); - return 0; + 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); -err: - connman_network_set_error(network, - CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); - return err; -} + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV4); -static void autoconf_ipv6_set(struct connman_network *network); -static void dhcpv6_callback(struct connman_network *network, - connman_bool_t success); + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV6); +} -/* - * 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) +static gboolean __connman_network_clear_associating_delayed(gpointer user_data) { - if (success == TRUE) - dhcpv6_callback(network, success); - else { - stop_dhcpv6(network); + GSList *list; + gboolean found = FALSE; + enum connman_service_state state_ipv4; + enum connman_service_state state_ipv6; + struct connman_service *service; + struct connman_network *network = (struct connman_network *)user_data; - /* restart and do solicit again. */ - autoconf_ipv6_set(network); + for (list = network_list; list != NULL; list = list->next) { + struct connman_network *item = list->data; + + if (item == network) { + found = TRUE; + break; + } } -} -static void dhcpv6_callback(struct connman_network *network, - connman_bool_t success) -{ - DBG("success %d", success); + if (found != TRUE) + return FALSE; - /* Start the renew process if necessary */ - if (success == TRUE) { + DBG("network %p name %s", network, network->name); + service = connman_service_lookup_from_network(network); - if (dhcpv6_set_addresses(network) < 0) { - stop_dhcpv6(network); - return; + state_ipv4 = __connman_service_ipconfig_get_state(service, + CONNMAN_IPCONFIG_TYPE_IPV4); + state_ipv6 = __connman_service_ipconfig_get_state(service, + CONNMAN_IPCONFIG_TYPE_IPV6); + + DBG("service %p state %d/%d", service, state_ipv4, state_ipv6); + + if (network->associating == FALSE && + state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION && + state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION) { + __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); + } else { + if (network->associating == FALSE) { + struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6; + enum connman_ipconfig_method ipv4_method, ipv6_method; + + ipconfig_ipv4 = __connman_service_get_ip4config(service); + ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4); + ipconfig_ipv6 = __connman_service_get_ip4config(service); + ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6); + + if((ipv4_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv4_method == CONNMAN_IPCONFIG_METHOD_OFF) && + (state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION)) + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV6); + if((ipv6_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv6_method == CONNMAN_IPCONFIG_METHOD_OFF) && + (state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION)) + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV4); } + } - if (__connman_dhcpv6_start_renew(network, - dhcpv6_renew_callback) == -ETIMEDOUT) - dhcpv6_renew_callback(network, FALSE); - } else - stop_dhcpv6(network); + return FALSE; } +#endif -static void check_dhcpv6(struct nd_router_advert *reply, - unsigned int length, void *user_data) +/** + * connman_network_set_associating: + * @network: network structure + * @associating: associating state + * + * Change associating state of network + */ +int connman_network_set_associating(struct connman_network *network, + bool associating) { - struct connman_network *network = user_data; - GSList *prefixes; + DBG("network %p associating %d", network, associating); - DBG("reply %p", reply); + if (network->associating == associating) + return -EALREADY; - 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->associating = associating; - network->router_solicit_count = 0; + if (associating) { + struct connman_service *service; - /* - * If we were disconnected while waiting router advertisement, - * we just quit and do not start DHCPv6 - */ - if (network->connected == FALSE) { - connman_network_unref(network); - return; + service = connman_service_lookup_from_network(network); + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_ASSOCIATION, + CONNMAN_IPCONFIG_TYPE_IPV4); + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_ASSOCIATION, + CONNMAN_IPCONFIG_TYPE_IPV6); } - 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); +#if defined TIZEN_EXT + if (associating == FALSE && + connman_network_get_bool(network, "WiFi.UseWPS") == FALSE) + g_timeout_add_seconds(1, + __connman_network_clear_associating_delayed, + network); +#endif - connman_network_unref(network); + return 0; } -static void autoconf_ipv6_set(struct connman_network *network) +static void set_associate_error(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); + service = connman_service_lookup_from_network(network); - connman_device_set_disconnected(network->device, FALSE); +#if defined TIZEN_EXT + __connman_service_indicate_error(service, + CONNMAN_SERVICE_ERROR_AUTH_FAILED); +#else + __connman_service_indicate_error(service, + CONNMAN_SERVICE_ERROR_CONNECT_FAILED); +#endif +} - network->connecting = FALSE; +static void set_configure_error(struct connman_network *network) +{ + struct connman_service *service; - service = __connman_service_lookup_from_network(network); - if (service == NULL) - return; + service = connman_service_lookup_from_network(network); - ipconfig = __connman_service_get_ip6config(service); - if (ipconfig == NULL) - return; + __connman_service_indicate_error(service, + CONNMAN_SERVICE_ERROR_CONNECT_FAILED); +} - index = __connman_ipconfig_get_index(ipconfig); +static void set_invalid_key_error(struct connman_network *network) +{ + struct connman_service *service; - connman_network_ref(network); + service = connman_service_lookup_from_network(network); - /* Try to get stateless DHCPv6 information, RFC 3736 */ - network->router_solicit_count = 3; - __connman_inet_ipv6_send_rs(index, 1, check_dhcpv6, network); +#if defined TIZEN_EXT + if (service) + __connman_service_set_favorite(service, false); +#endif + __connman_service_indicate_error(service, + CONNMAN_SERVICE_ERROR_INVALID_KEY); } -static gboolean set_connected(gpointer user_data) +static void set_connect_error(struct connman_network *network) { - 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); + service = connman_service_lookup_from_network(network); - ipconfig_ipv4 = __connman_service_get_ip4config(service); - ipconfig_ipv6 = __connman_service_get_ip6config(service); + __connman_service_indicate_error(service, + CONNMAN_SERVICE_ERROR_CONNECT_FAILED); +} - DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4, - ipconfig_ipv6); +static void set_blocked_error(struct connman_network *network) +{ + struct connman_service *service; - ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4); - ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6); + service = connman_service_lookup_from_network(network); - DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method); - DBG("network connected %d", network->connected); + __connman_service_indicate_error(service, + CONNMAN_SERVICE_ERROR_BLOCKED); +} - if (network->connected == TRUE) { - int ret; - switch (ipv6_method) { - 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; - 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; - } +#if defined TIZEN_EXT +static void set_dhcp_error(struct connman_network *network) +{ + struct connman_service *service; - 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; - } - } + if (network->associating != FALSE) + network->associating = FALSE; - } else { - enum connman_service_state state; + service = connman_service_lookup_from_network(network); - /* - * Resetting solicit count here will prevent the RS resend loop - * from sending packets in check_dhcpv6() - */ - network->router_solicit_count = 0; + __connman_service_indicate_error(service, + CONNMAN_SERVICE_ERROR_DHCP_FAILED); +} +#endif - __connman_device_set_network(network->device, NULL); +void connman_network_set_ipv4_method(struct connman_network *network, + enum connman_ipconfig_method method) +{ + struct connman_service *service; + struct connman_ipconfig *ipconfig; - 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: - release_dhcpv6(network); - break; - } + service = connman_service_lookup_from_network(network); + if (!service) + return; - 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; - } + ipconfig = __connman_service_get_ip4config(service); + if (!ipconfig) + return; - /* - * 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); + __connman_ipconfig_set_method(ipconfig, method); +} - 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); +void connman_network_set_ipv6_method(struct connman_network *network, + enum connman_ipconfig_method method) +{ + struct connman_service *service; + struct connman_ipconfig *ipconfig; - __connman_connection_gateway_remove(service, - CONNMAN_IPCONFIG_TYPE_ALL); + service = connman_service_lookup_from_network(network); + if (!service) + return; - __connman_ipconfig_address_unset(ipconfig_ipv4); - __connman_ipconfig_address_unset(ipconfig_ipv6); + ipconfig = __connman_service_get_ip6config(service); + if (!ipconfig) + return; - /* - * 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); - } + __connman_ipconfig_set_method(ipconfig, method); +} - __connman_service_ipconfig_indicate_state(service, - CONNMAN_SERVICE_STATE_IDLE, - CONNMAN_IPCONFIG_TYPE_IPV4); +void connman_network_set_error(struct connman_network *network, + enum connman_network_error error) +{ + DBG("network %p error %d", network, error); - __connman_service_ipconfig_indicate_state(service, - CONNMAN_SERVICE_STATE_IDLE, - CONNMAN_IPCONFIG_TYPE_IPV6); - } + switch (error) { + case CONNMAN_NETWORK_ERROR_UNKNOWN: + return; + case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL: + set_associate_error(network); + break; + case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL: + set_configure_error(network); + break; + case CONNMAN_NETWORK_ERROR_INVALID_KEY: + set_invalid_key_error(network); + break; + case CONNMAN_NETWORK_ERROR_CONNECT_FAIL: + set_connect_error(network); + break; +#if defined TIZEN_EXT + case CONNMAN_NETWORK_ERROR_DHCP_FAIL: + set_dhcp_error(network); + break; +#endif - network->connecting = FALSE; + case CONNMAN_NETWORK_ERROR_BLOCKED: + set_blocked_error(network); + break; - connman_network_set_associating(network, FALSE); + } - return FALSE; + __connman_network_disconnect(network); } /** @@ -1312,25 +1575,26 @@ static gboolean set_connected(gpointer user_data) * Change connected state of network */ int connman_network_set_connected(struct connman_network *network, - connman_bool_t connected) + bool connected) { DBG("network %p connected %d/%d connecting %d associating %d", network, network->connected, connected, network->connecting, network->associating); - if ((network->connecting == TRUE || network->associating == TRUE) && - connected == FALSE) { + if ((network->connecting || network->associating) && + !connected) { connman_network_set_error(network, CONNMAN_NETWORK_ERROR_CONNECT_FAIL); - __connman_network_disconnect(network); + return 0; } if (network->connected == connected) return -EALREADY; - network->connected = connected; - - set_connected(network); + if (!connected) + set_disconnected(network); + else + set_connected(network); return 0; } @@ -1341,7 +1605,7 @@ int connman_network_set_connected(struct connman_network *network, * * Get network connection status */ -connman_bool_t connman_network_get_connected(struct connman_network *network) +bool connman_network_get_connected(struct connman_network *network) { return network->connected; } @@ -1352,29 +1616,60 @@ connman_bool_t connman_network_get_connected(struct connman_network *network) * * Get network associating status */ -connman_bool_t connman_network_get_associating(struct connman_network *network) +bool connman_network_get_associating(struct connman_network *network) { return network->associating; } +void connman_network_clear_hidden(void *user_data) +{ + if (!user_data) + return; + + DBG("user_data %p", user_data); + + /* + * Hidden service does not have a connect timeout so + * we do not need to remove it. We can just return + * error to the caller telling that we could not find + * any network that we could connect to. + */ + connman_dbus_reply_pending(user_data, EIO, NULL); +} + int connman_network_connect_hidden(struct connman_network *network, - char *identity, char* passphrase) + char *identity, char *passphrase, void *user_data) { + int err = 0; struct connman_service *service; - DBG(""); + service = connman_service_lookup_from_network(network); - service = __connman_service_lookup_from_network(network); - if (service == NULL) + DBG("network %p service %p user_data %p", network, service, user_data); + + if (!service) return -EINVAL; - if (identity != NULL) + if (identity) __connman_service_set_agent_identity(service, identity); - if (passphrase != NULL) - __connman_service_add_passphrase(service, passphrase); + if (passphrase) + err = __connman_service_set_passphrase(service, passphrase); + + if (err == -ENOKEY) { + __connman_service_indicate_error(service, + CONNMAN_SERVICE_ERROR_INVALID_KEY); + goto out; + } else { + __connman_service_set_hidden(service); + __connman_service_set_hidden_data(service, user_data); + return __connman_service_connect(service, + CONNMAN_SERVICE_CONNECT_REASON_USER); + } - return __connman_service_connect(service); +out: + __connman_service_return_error(service, -err, user_data); + return err; } /** @@ -1389,37 +1684,43 @@ int __connman_network_connect(struct connman_network *network) DBG("network %p", network); - if (network->connected == TRUE) + if (network->connected) return -EISCONN; - if (network->connecting == TRUE || network->associating == TRUE) + if (network->connecting || network->associating) return -EALREADY; - if (network->driver == NULL) + if (!network->driver) return -EUNATCH; - if (network->driver->connect == NULL) + if (!network->driver->connect) return -ENOSYS; - if (network->device == NULL) + if (!network->device) return -ENODEV; - network->connecting = TRUE; + network->connecting = true; +#if defined TIZEN_EXT + if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR) +#endif __connman_device_disconnect(network->device); - +#if defined TIZEN_EXT + DBG("ConnMan, Connect Request [%s]", network->name); +#endif err = network->driver->connect(network); if (err < 0) { - if (err == -EINPROGRESS) - connman_network_set_associating(network, TRUE); - else { - network->connecting = FALSE; - } + if (err == -EINPROGRESS) { +#if defined TIZEN_EXT + if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR) +#endif + connman_network_set_associating(network, true); + } else + network->connecting = false; return err; } - network->connected = TRUE; set_connected(network); return err; @@ -1433,62 +1734,43 @@ int __connman_network_connect(struct connman_network *network) */ int __connman_network_disconnect(struct connman_network *network) { - int err; + int err = 0; DBG("network %p", network); - if (network->connected == FALSE && network->connecting == FALSE && - network->associating == FALSE) + if (!network->connected && !network->connecting && + !network->associating) return -ENOTCONN; - if (network->driver == NULL) + if (!network->driver) return -EUNATCH; - if (network->driver->disconnect == NULL) - return -ENOSYS; - - network->connecting = FALSE; + network->connecting = false; +#if defined TIZEN_EXT + DBG("ConnMan, Disconnect request"); +#endif + if (network->driver->disconnect) + err = network->driver->disconnect(network); - err = network->driver->disconnect(network); - if (err == 0) { - connman_network_set_connected(network, FALSE); - set_connected(network); - } + if (err != -EINPROGRESS) + set_disconnected(network); return err; } -static int manual_ipv4_set(struct connman_network *network, - struct connman_ipconfig *ipconfig) -{ - struct connman_service *service; - int err; - - service = __connman_service_lookup_from_network(network); - if (service == NULL) - return -EINVAL; - - err = __connman_ipconfig_address_add(ipconfig); - if (err < 0) { - connman_network_set_error(network, - CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); - return err; - } - - return __connman_ipconfig_gateway_add(ipconfig); -} - int __connman_network_clear_ipconfig(struct connman_network *network, struct connman_ipconfig *ipconfig) { struct connman_service *service; + struct connman_ipconfig *ipconfig_ipv4; enum connman_ipconfig_method method; enum connman_ipconfig_type type; - service = __connman_service_lookup_from_network(network); - if (service == NULL) + service = connman_service_lookup_from_network(network); + if (!service) return -EINVAL; + ipconfig_ipv4 = __connman_service_get_ip4config(service); method = __connman_ipconfig_get_method(ipconfig); type = __connman_ipconfig_get_config_type(ipconfig); @@ -1504,7 +1786,7 @@ int __connman_network_clear_ipconfig(struct connman_network *network, __connman_ipconfig_address_remove(ipconfig); break; case CONNMAN_IPCONFIG_METHOD_DHCP: - __connman_dhcp_stop(network); + __connman_dhcp_stop(ipconfig_ipv4); break; } @@ -1520,57 +1802,122 @@ int __connman_network_clear_ipconfig(struct connman_network *network, return 0; } -int __connman_network_set_ipconfig(struct connman_network *network, - struct connman_ipconfig *ipconfig_ipv4, - struct connman_ipconfig *ipconfig_ipv6) +#if defined TIZEN_EXT +void __connman_network_set_auto_ipv6_gateway(char *gateway, void *user_data) +{ + DBG(""); + + struct connman_network *network = user_data; + struct connman_service *service; + struct connman_ipconfig *ipconfig = NULL; + + service = connman_service_lookup_from_network(network); + if (service == NULL) + return; + + ipconfig = __connman_service_get_ipconfig(service, AF_INET6); + if (ipconfig == NULL) + return; + + __connman_ipconfig_set_gateway(ipconfig, gateway); + + return; +} +#endif + +int __connman_network_enable_ipconfig(struct connman_network *network, + struct connman_ipconfig *ipconfig) { + int r = 0; + enum connman_ipconfig_type type; enum connman_ipconfig_method method; - int ret; +#if defined TIZEN_EXT + struct connman_service *service; +#endif - if (network == NULL) + if (!network || !ipconfig) return -EINVAL; - if (ipconfig_ipv6) { - method = __connman_ipconfig_get_method(ipconfig_ipv6); + type = __connman_ipconfig_get_config_type(ipconfig); + + switch (type) { + case CONNMAN_IPCONFIG_TYPE_UNKNOWN: + case CONNMAN_IPCONFIG_TYPE_ALL: + return -ENOSYS; + + case CONNMAN_IPCONFIG_TYPE_IPV6: + set_configuration(network, type); + + method = __connman_ipconfig_get_method(ipconfig); + + DBG("ipv6 ipconfig method %d", method); switch (method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + break; + case CONNMAN_IPCONFIG_METHOD_OFF: + __connman_ipconfig_disable_ipv6(ipconfig); break; + case CONNMAN_IPCONFIG_METHOD_AUTO: +#if defined TIZEN_EXT + service = connman_service_lookup_from_network(network); + + if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR) + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_CONFIGURATION, + CONNMAN_IPCONFIG_TYPE_IPV6); +#endif 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 ret; - } + r = manual_ipv6_set(network, ipconfig); break; + case CONNMAN_IPCONFIG_METHOD_DHCP: + r = -ENOSYS; break; } - } - if (ipconfig_ipv4) { - method = __connman_ipconfig_get_method(ipconfig_ipv4); + break; + + case CONNMAN_IPCONFIG_TYPE_IPV4: + set_configuration(network, type); + + method = __connman_ipconfig_get_method(ipconfig); + + DBG("ipv4 ipconfig method %d", method); switch (method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: - case CONNMAN_IPCONFIG_METHOD_FIXED: + break; + case CONNMAN_IPCONFIG_METHOD_AUTO: - return -EINVAL; + r = -ENOSYS; + break; + + case CONNMAN_IPCONFIG_METHOD_FIXED: case CONNMAN_IPCONFIG_METHOD_MANUAL: - return manual_ipv4_set(network, ipconfig_ipv4); + r = set_connected_manual(network); + break; + case CONNMAN_IPCONFIG_METHOD_DHCP: - return __connman_dhcp_start(network, dhcp_callback); + r = set_connected_dhcp(network); + break; } + + break; } - return 0; + if (r < 0) + connman_network_set_error(network, + CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL); + + return r; } int connman_network_set_ipaddress(struct connman_network *network, @@ -1581,12 +1928,12 @@ int connman_network_set_ipaddress(struct connman_network *network, DBG("network %p", network); - service = __connman_service_lookup_from_network(network); - if (service == NULL) + service = connman_service_lookup_from_network(network); + if (!service) return -EINVAL; ipconfig = __connman_service_get_ipconfig(service, ipaddress->family); - if (ipconfig == NULL) + if (!ipconfig) return -EINVAL; __connman_ipconfig_set_local(ipconfig, ipaddress->local); @@ -1598,6 +1945,178 @@ int connman_network_set_ipaddress(struct connman_network *network, return 0; } +#if defined TIZEN_EXT +/* + * Description: Network client requires additional wifi specific info + */ +int connman_network_set_bssid(struct connman_network *network, + const unsigned char *bssid) +{ + int i = 0; + + if (bssid == NULL) + return -EINVAL; + + DBG("network %p bssid %02x:%02x:%02x:%02x:%02x:%02x", network, + bssid[0], bssid[1], bssid[2], + bssid[3], bssid[4], bssid[5]); + + for (;i < WIFI_BSSID_LEN_MAX;i++) + network->wifi.bssid[i] = bssid[i]; + + return 0; +} + +unsigned char *connman_network_get_bssid(struct connman_network *network) +{ + return (unsigned char *)network->wifi.bssid; +} + +int connman_network_set_maxrate(struct connman_network *network, + unsigned int maxrate) +{ +#if !defined TIZEN_EXT + DBG("network %p maxrate %d", network, maxrate); +#endif + + network->wifi.maxrate = maxrate; + + return 0; +} + +unsigned int connman_network_get_maxrate(struct connman_network *network) +{ + return network->wifi.maxrate; +} + +int connman_network_set_enc_mode(struct connman_network *network, + const char *encryption_mode) +{ + if (encryption_mode == NULL) + return -EINVAL; + + DBG("network %p encryption mode %s", network, encryption_mode); + + g_strlcpy(network->wifi.encryption_mode, encryption_mode, + WIFI_ENCYPTION_MODE_LEN_MAX); + + return 0; +} + +const char *connman_network_get_enc_mode(struct connman_network *network) +{ + return (const char *)network->wifi.encryption_mode; +} + +int connman_network_set_rsn_mode(struct connman_network *network, + bool rsn_mode) +{ + network->wifi.rsn_mode = rsn_mode; + + return 0; +} + +int connman_network_set_proxy(struct connman_network *network, + const char *proxies) +{ + struct connman_service *service; + + DBG("network %p proxies %s", network, proxies); + + service = connman_service_lookup_from_network(network); + if (service == NULL) + return -EINVAL; + + __connman_service_set_proxy(service, proxies); + + connman_service_set_proxy_method(service, + CONNMAN_SERVICE_PROXY_METHOD_MANUAL); + + return 0; +} + +int connman_network_set_keymgmt(struct connman_network *network, + unsigned int keymgmt) +{ + if (network == NULL) + return 0; + + network->wifi.keymgmt = keymgmt; + + return 0; +} + +unsigned int connman_network_get_keymgmt(struct connman_network *network) +{ + if (network == NULL) + return 0; + + return network->wifi.keymgmt; +} + +int connman_network_set_disconnect_reason(struct connman_network *network, + int reason_code) +{ + if (network == NULL) + return 0; + + network->wifi.disconnect_reason = reason_code; + + return 0; +} + +int connman_network_get_disconnect_reason(struct connman_network *network) +{ + if (network == NULL) + return 0; + + return network->wifi.disconnect_reason; +} +int connman_network_get_assoc_status_code(struct connman_network *network) +{ + if (network == NULL) + return 0; + + return network->wifi.assoc_status_code; +} + +int connman_network_set_countrycode(struct connman_network *network, + const unsigned char *country_code) +{ + int i = 0; + + if (country_code == NULL) + return -EINVAL; + + DBG("network %p Country Code %02x:%02x",network, + country_code[0],country_code[1]); + + for (; i < WIFI_COUNTRY_CODE_LEN; i++) + network->wifi.country_code[i] = country_code[i]; + + return 0; +} + +unsigned char *connman_network_get_countrycode(struct connman_network *network) +{ + return (unsigned char *)network->wifi.country_code; +} + +int connman_network_set_bssid_list(struct connman_network *network, + GSList *bssids) +{ + g_slist_free_full(network->wifi.bssid_list, g_free); + network->wifi.bssid_list = bssids; + + return 0; +} + +void *connman_network_get_bssid_list(struct connman_network *network) +{ + return network->wifi.bssid_list; +} +#endif + int connman_network_set_nameservers(struct connman_network *network, const char *nameservers) { @@ -1607,20 +2126,26 @@ int connman_network_set_nameservers(struct connman_network *network, DBG("network %p nameservers %s", network, nameservers); - service = __connman_service_lookup_from_network(network); - if (service == NULL) + service = connman_service_lookup_from_network(network); + if (!service) return -EINVAL; __connman_service_nameserver_clear(service); - if (nameservers == NULL) + if (!nameservers) return 0; nameservers_array = g_strsplit(nameservers, " ", 0); - for (i = 0; nameservers_array[i] != NULL; i++) { + for (i = 0; nameservers_array[i]; i++) { +#if defined TIZEN_EXT + __connman_service_nameserver_append(service, + nameservers_array[i], false, + CONNMAN_IPCONFIG_TYPE_ALL); +#else __connman_service_nameserver_append(service, - nameservers_array[i], FALSE); + nameservers_array[i], false); +#endif } g_strfreev(nameservers_array); @@ -1635,8 +2160,8 @@ int connman_network_set_domain(struct connman_network *network, DBG("network %p domain %s", network, domain); - service = __connman_service_lookup_from_network(network); - if (service == NULL) + service = connman_service_lookup_from_network(network); + if (!service) return -EINVAL; __connman_service_set_domainname(service, domain); @@ -1671,46 +2196,40 @@ int connman_network_set_name(struct connman_network *network, */ int connman_network_set_strength(struct connman_network *network, - connman_uint8_t strength) + uint8_t strength) { - DBG("network %p strengh %d", network, strength); - network->strength = strength; return 0; } -connman_uint8_t connman_network_get_strength(struct connman_network *network) +uint8_t connman_network_get_strength(struct connman_network *network) { return network->strength; } int connman_network_set_frequency(struct connman_network *network, - connman_uint16_t frequency) + uint16_t frequency) { - DBG("network %p frequency %d", network, frequency); - network->frequency = frequency; return 0; } -connman_uint16_t connman_network_get_frequency(struct connman_network *network) +uint16_t connman_network_get_frequency(struct connman_network *network) { return network->frequency; } int connman_network_set_wifi_channel(struct connman_network *network, - connman_uint16_t channel) + uint16_t channel) { - DBG("network %p wifi channel %d", network, channel); - network->wifi.channel = channel; return 0; } -connman_uint16_t connman_network_get_wifi_channel(struct connman_network *network) +uint16_t connman_network_get_wifi_channel(struct connman_network *network) { return network->wifi.channel; } @@ -1726,54 +2245,67 @@ connman_uint16_t connman_network_get_wifi_channel(struct connman_network *networ int connman_network_set_string(struct connman_network *network, const char *key, const char *value) { - DBG("network %p key %s value %s", network, key, value); - if (g_strcmp0(key, "Name") == 0) return connman_network_set_name(network, value); - if (g_str_equal(key, "Path") == TRUE) { + if (g_str_equal(key, "Path")) { g_free(network->path); network->path = g_strdup(value); - } else if (g_str_equal(key, "Node") == TRUE) { + } else if (g_str_equal(key, "Node")) { g_free(network->node); network->node = g_strdup(value); - } else if (g_str_equal(key, "WiFi.Mode") == TRUE) { + } else if (g_str_equal(key, "WiFi.Mode")) { g_free(network->wifi.mode); network->wifi.mode = g_strdup(value); - } else if (g_str_equal(key, "WiFi.Security") == TRUE) { + } else if (g_str_equal(key, "WiFi.Security")) { g_free(network->wifi.security); network->wifi.security = g_strdup(value); - } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) { + } else if (g_str_equal(key, "WiFi.Passphrase")) { +#if defined TIZEN_EXT + DBG("ConnMan, %p key %s", network, key); +#endif g_free(network->wifi.passphrase); network->wifi.passphrase = g_strdup(value); - } else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) { - g_free(network->wifi.agent_passphrase); - network->wifi.agent_passphrase = g_strdup(value); - } else if (g_str_equal(key, "WiFi.EAP") == TRUE) { + } else if (g_str_equal(key, "WiFi.EAP")) { g_free(network->wifi.eap); network->wifi.eap = g_strdup(value); - } else if (g_str_equal(key, "WiFi.Identity") == TRUE) { + } else if (g_str_equal(key, "WiFi.Identity")) { g_free(network->wifi.identity); network->wifi.identity = g_strdup(value); - } else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) { + } else if (g_str_equal(key, "WiFi.AnonymousIdentity")) { + g_free(network->wifi.anonymous_identity); + network->wifi.anonymous_identity = g_strdup(value); + } else if (g_str_equal(key, "WiFi.AgentIdentity")) { g_free(network->wifi.agent_identity); network->wifi.agent_identity = g_strdup(value); - } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) { + } else if (g_str_equal(key, "WiFi.CACertFile")) { g_free(network->wifi.ca_cert_path); network->wifi.ca_cert_path = g_strdup(value); - } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) { + } else if (g_str_equal(key, "WiFi.SubjectMatch")) { + g_free(network->wifi.subject_match); + network->wifi.subject_match = g_strdup(value); + } else if (g_str_equal(key, "WiFi.AltSubjectMatch")) { + g_free(network->wifi.altsubject_match); + network->wifi.altsubject_match = g_strdup(value); + } else if (g_str_equal(key, "WiFi.DomainSuffixMatch")) { + g_free(network->wifi.domain_suffix_match); + network->wifi.domain_suffix_match = g_strdup(value); + } else if (g_str_equal(key, "WiFi.DomainMatch")) { + g_free(network->wifi.domain_match); + network->wifi.domain_match = g_strdup(value); + } else if (g_str_equal(key, "WiFi.ClientCertFile")) { g_free(network->wifi.client_cert_path); network->wifi.client_cert_path = g_strdup(value); - } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) { + } else if (g_str_equal(key, "WiFi.PrivateKeyFile")) { g_free(network->wifi.private_key_path); network->wifi.private_key_path = g_strdup(value); - } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) { + } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase")) { g_free(network->wifi.private_key_passphrase); network->wifi.private_key_passphrase = g_strdup(value); - } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) { + } else if (g_str_equal(key, "WiFi.Phase2")) { g_free(network->wifi.phase2_auth); network->wifi.phase2_auth = g_strdup(value); - } else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) { + } else if (g_str_equal(key, "WiFi.PinWPS")) { g_free(network->wifi.pin_wps); network->wifi.pin_wps = g_strdup(value); } else { @@ -1793,39 +2325,53 @@ int connman_network_set_string(struct connman_network *network, const char *connman_network_get_string(struct connman_network *network, const char *key) { - DBG("network %p key %s", network, key); - - if (g_str_equal(key, "Path") == TRUE) + if (g_str_equal(key, "Path")) return network->path; - else if (g_str_equal(key, "Name") == TRUE) + else if (g_str_equal(key, "Name")) return network->name; - else if (g_str_equal(key, "Node") == TRUE) + else if (g_str_equal(key, "Node")) return network->node; - else if (g_str_equal(key, "WiFi.Mode") == TRUE) + else if (g_str_equal(key, "WiFi.Mode")) return network->wifi.mode; - else if (g_str_equal(key, "WiFi.Security") == TRUE) + else if (g_str_equal(key, "WiFi.Security")) +#if defined TIZEN_EXT + if (network->wifi.rsn_mode != true || + g_str_equal(network->wifi.security, "ieee8021x")) + return network->wifi.security; + else + return "rsn"; +#else return network->wifi.security; - else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) +#endif + else if (g_str_equal(key, "WiFi.Passphrase")) return network->wifi.passphrase; - else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) - return network->wifi.agent_passphrase; - else if (g_str_equal(key, "WiFi.EAP") == TRUE) + else if (g_str_equal(key, "WiFi.EAP")) return network->wifi.eap; - else if (g_str_equal(key, "WiFi.Identity") == TRUE) + else if (g_str_equal(key, "WiFi.Identity")) return network->wifi.identity; - else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) + else if (g_str_equal(key, "WiFi.AnonymousIdentity")) + return network->wifi.anonymous_identity; + else if (g_str_equal(key, "WiFi.AgentIdentity")) return network->wifi.agent_identity; - else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) + else if (g_str_equal(key, "WiFi.CACertFile")) return network->wifi.ca_cert_path; - else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) + else if (g_str_equal(key, "WiFi.SubjectMatch")) + return network->wifi.subject_match; + else if (g_str_equal(key, "WiFi.AltSubjectMatch")) + return network->wifi.altsubject_match; + else if (g_str_equal(key, "WiFi.DomainSuffixMatch")) + return network->wifi.domain_suffix_match; + else if (g_str_equal(key, "WiFi.DomainMatch")) + return network->wifi.domain_match; + else if (g_str_equal(key, "WiFi.ClientCertFile")) return network->wifi.client_cert_path; - else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) + else if (g_str_equal(key, "WiFi.PrivateKeyFile")) return network->wifi.private_key_path; - else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) + else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase")) return network->wifi.private_key_passphrase; - else if (g_str_equal(key, "WiFi.Phase2") == TRUE) + else if (g_str_equal(key, "WiFi.Phase2")) return network->wifi.phase2_auth; - else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) + else if (g_str_equal(key, "WiFi.PinWPS")) return network->wifi.pin_wps; return NULL; @@ -1840,16 +2386,20 @@ const char *connman_network_get_string(struct connman_network *network, * Set boolean value for specific key */ int connman_network_set_bool(struct connman_network *network, - const char *key, connman_bool_t value) + const char *key, bool value) { - DBG("network %p key %s value %d", network, key, value); - if (g_strcmp0(key, "Roaming") == 0) network->roaming = value; else if (g_strcmp0(key, "WiFi.WPS") == 0) network->wifi.wps = value; else if (g_strcmp0(key, "WiFi.UseWPS") == 0) network->wifi.use_wps = value; +#if defined TIZEN_EXT + else if (g_strcmp0(key, "DefaultInternet") == 0) + network->default_internet = value; + else if (g_strcmp0(key, "WiFi.HS20AP") == 0) + network->wifi.isHS20AP = value; +#endif return -EINVAL; } @@ -1861,20 +2411,50 @@ int connman_network_set_bool(struct connman_network *network, * * Get boolean value for specific key */ -connman_bool_t connman_network_get_bool(struct connman_network *network, +bool connman_network_get_bool(struct connman_network *network, const char *key) { - DBG("network %p key %s", network, key); - - if (g_str_equal(key, "Roaming") == TRUE) + if (g_str_equal(key, "Roaming")) return network->roaming; - else if (g_str_equal(key, "WiFi.WPS") == TRUE) + else if (g_str_equal(key, "WiFi.WPS")) return network->wifi.wps; - else if (g_str_equal(key, "WiFi.UseWPS") == TRUE) + else if (g_str_equal(key, "WiFi.UseWPS")) return network->wifi.use_wps; +#if defined TIZEN_EXT + else if (g_str_equal(key, "DefaultInternet")) + return network->default_internet; + else if (g_str_equal(key, "WiFi.HS20AP")) + return network->wifi.isHS20AP; +#endif - return FALSE; + return false; +} + +#if defined TIZEN_EXT +/** + * connman_network_set_vsie_list: + * @network: network structure + * @vsie_list: GSList pointer + * + * Set vendor specific list pointer + */ +void connman_network_set_vsie_list(struct connman_network *network, GSList *vsie_list) +{ + g_slist_free_full(network->wifi.vsie_list, g_free); + network->wifi.vsie_list = vsie_list; +} + +/** + * connman_network_get_vsie_list: + * @network: network structure + * + * Get vendor specific list pointer + */ +void *connman_network_get_vsie_list(struct connman_network *network) +{ + return network->wifi.vsie_list; } +#endif /** * connman_network_set_blob: @@ -1888,12 +2468,10 @@ connman_bool_t connman_network_get_bool(struct connman_network *network, int connman_network_set_blob(struct connman_network *network, const char *key, const void *data, unsigned int size) { - DBG("network %p key %s size %d", network, key, size); - - if (g_str_equal(key, "WiFi.SSID") == TRUE) { + if (g_str_equal(key, "WiFi.SSID")) { g_free(network->wifi.ssid); network->wifi.ssid = g_try_malloc(size); - if (network->wifi.ssid != NULL) { + if (network->wifi.ssid) { memcpy(network->wifi.ssid, data, size); network->wifi.ssid_len = size; } else @@ -1916,10 +2494,8 @@ int connman_network_set_blob(struct connman_network *network, const void *connman_network_get_blob(struct connman_network *network, const char *key, unsigned int *size) { - DBG("network %p key %s", network, key); - - if (g_str_equal(key, "WiFi.SSID") == TRUE) { - if (size != NULL) + if (g_str_equal(key, "WiFi.SSID")) { + if (size) *size = network->wifi.ssid_len; return network->wifi.ssid; } @@ -1933,12 +2509,12 @@ void __connman_network_set_device(struct connman_network *network, if (network->device == device) return; - if (network->device != NULL) + if (network->device) network_remove(network); network->device = device; - if (network->device != NULL) + if (network->device) network_probe(network); } @@ -1983,15 +2559,15 @@ void connman_network_update(struct connman_network *network) case CONNMAN_NETWORK_TYPE_VENDOR: return; case CONNMAN_NETWORK_TYPE_ETHERNET: + case CONNMAN_NETWORK_TYPE_GADGET: case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN: case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN: case CONNMAN_NETWORK_TYPE_CELLULAR: case CONNMAN_NETWORK_TYPE_WIFI: - case CONNMAN_NETWORK_TYPE_WIMAX: break; } - if (network->group != NULL) + if (network->group) __connman_service_update_from_network(network); }