Merge "[CONNMAN][Change AP's max speed logic]" into tizen
[platform/upstream/connman.git] / src / service.c
old mode 100755 (executable)
new mode 100644 (file)
index 9510def..ea61f32
@@ -167,6 +167,10 @@ struct connman_service {
        char *keymgmt_type;
        int disconnect_reason;
        int assoc_status_code;
+       /*
+        * Only for EAP-FAST
+        */
+       char *phase1;
 #endif
 #ifdef TIZEN_EXT
        enum connman_dnsconfig_method dns_config_method_ipv4;
@@ -294,6 +298,10 @@ const char *__connman_service_type2string(enum connman_service_type type)
                return "gadget";
        case CONNMAN_SERVICE_TYPE_P2P:
                return "p2p";
+#if defined TIZEN_EXT_WIFI_MESH
+       case CONNMAN_SERVICE_TYPE_MESH:
+               return "mesh";
+#endif
        }
 
        return NULL;
@@ -592,6 +600,9 @@ int __connman_service_load_modifiable(struct connman_service *service)
        case CONNMAN_SERVICE_TYPE_SYSTEM:
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+       case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                break;
        case CONNMAN_SERVICE_TYPE_VPN:
                set_split_routing(service, g_key_file_get_boolean(keyfile,
@@ -667,6 +678,9 @@ static int service_load(struct connman_service *service)
        case CONNMAN_SERVICE_TYPE_SYSTEM:
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+       case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                break;
        case CONNMAN_SERVICE_TYPE_VPN:
                set_split_routing(service, g_key_file_get_boolean(keyfile,
@@ -782,11 +796,17 @@ static int service_load(struct connman_service *service)
 
        dns_method = g_key_file_get_string(keyfile, service->identifier,
                        "Nameservers.IPv4method", NULL);
-       service->dns_config_method_ipv4 = __connman_dnsconfig_string2method(dns_method);
+       if (dns_method) {
+               service->dns_config_method_ipv4 = __connman_dnsconfig_string2method(dns_method);
+               g_free(dns_method);
+       }
 
        dns_method = g_key_file_get_string(keyfile, service->identifier,
                        "Nameservers.IPv6method", NULL);
-       service->dns_config_method_ipv6 = __connman_dnsconfig_string2method(dns_method);
+       if (dns_method) {
+               service->dns_config_method_ipv6 = __connman_dnsconfig_string2method(dns_method);
+               g_free(dns_method);
+       }
 #endif
 
        service->timeservers_config = g_key_file_get_string_list(keyfile,
@@ -923,6 +943,9 @@ static int service_save(struct connman_service *service)
        case CONNMAN_SERVICE_TYPE_SYSTEM:
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+       case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                break;
        case CONNMAN_SERVICE_TYPE_VPN:
                g_key_file_set_boolean(keyfile, service->identifier,
@@ -2152,8 +2175,13 @@ struct connman_service *connman_service_get_default_connection(void)
                                state2string(service->state),
                                __connman_service_type2string(service->type));
 
+#if defined TIZEN_MAINTAIN_ONLINE
+               if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+                               service->state == CONNMAN_SERVICE_STATE_ONLINE) {
+#else
                if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
                                is_connected(service->state) == TRUE) {
+#endif
                        return service;
                } else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
                                __connman_service_is_internet_profile(service) == TRUE) {
@@ -2179,6 +2207,9 @@ struct connman_service *connman_service_get_default_connection(void)
 
 struct connman_service *__connman_service_get_default(void)
 {
+#if defined TIZEN_MAINTAIN_ONLINE
+       return connman_service_get_default_connection();
+#else
        struct connman_service *service;
 
        if (!service_list)
@@ -2190,6 +2221,7 @@ struct connman_service *__connman_service_get_default(void)
                return NULL;
 
        return service;
+#endif
 }
 
 bool __connman_service_index_is_default(int index)
@@ -3221,30 +3253,42 @@ static void append_wifi_ext_info(DBusMessageIter *dict,
        unsigned int ssid_len;
        unsigned char *bssid;
        unsigned int maxrate;
+       int maxspeed;
        unsigned int keymgmt;
        uint16_t frequency;
        const char *enc_mode;
        const char *str;
        gboolean passpoint;
+       char country_code_buff[WIFI_COUNTRY_CODE_LEN + 1] = {0,};
+       char *country_code_str = country_code_buff;
+       unsigned char *country_code;
 
        ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len);
        bssid = connman_network_get_bssid(network);
        maxrate = connman_network_get_maxrate(network);
+       maxspeed = connman_network_get_maxspeed(network);
        frequency = connman_network_get_frequency(network);
        enc_mode = connman_network_get_enc_mode(network);
        passpoint = connman_network_get_bool(network, "WiFi.HS20AP");
        keymgmt = connman_network_get_keymgmt(network);
+       country_code = connman_network_get_countrycode(network);
 
        snprintf(bssid_str, WIFI_BSSID_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
                                bssid[0], bssid[1], bssid[2],
                                bssid[3], bssid[4], bssid[5]);
 
+       snprintf(country_code_str, (WIFI_COUNTRY_CODE_LEN + 1), "%c%c",
+                country_code[0], country_code[1]);
+
+
        connman_dbus_dict_append_fixed_array(dict, "SSID",
                                        DBUS_TYPE_BYTE, &ssid, ssid_len);
        connman_dbus_dict_append_basic(dict, "BSSID",
                                        DBUS_TYPE_STRING, &bssid_str);
        connman_dbus_dict_append_basic(dict, "MaxRate",
                                        DBUS_TYPE_UINT32, &maxrate);
+       connman_dbus_dict_append_basic(dict, "MaxSpeed",
+                                       DBUS_TYPE_INT32, &maxspeed);
        connman_dbus_dict_append_basic(dict, "Frequency",
                                        DBUS_TYPE_UINT16, &frequency);
        connman_dbus_dict_append_basic(dict, "EncryptionMode",
@@ -3253,6 +3297,8 @@ static void append_wifi_ext_info(DBusMessageIter *dict,
                                        DBUS_TYPE_BOOLEAN, &passpoint);
        connman_dbus_dict_append_basic(dict, "Keymgmt",
                                        DBUS_TYPE_UINT32, &keymgmt);
+       connman_dbus_dict_append_basic(dict, "Country", DBUS_TYPE_STRING,
+                                      &country_code_str);
 
        str = connman_network_get_string(network, "WiFi.Security");
        if (str != NULL && g_str_equal(str, "ieee8021x") == TRUE) {
@@ -3289,6 +3335,33 @@ static void append_wifi_ext_info(DBusMessageIter *dict,
                                        DBUS_TYPE_STRING, &str);
        }
 }
+
+static void append_bssid_info(DBusMessageIter *iter, void *user_data)
+{
+        GSList *bssid_list = NULL;
+       struct connman_network *network = user_data;
+        struct connman_bssids *bssids;
+        char bssid_buf[18] = {0,};
+        char *bssid_str = bssid_buf;
+
+        bssid_list = (GSList *)connman_network_get_bssid_list(network);
+        if(bssid_list) {
+                GSList *list;
+                for (list = bssid_list; list; list = list->next) {
+                        bssids = (struct connman_bssids *)list->data;
+                        memcpy(bssid_str, bssids->bssid, 18);
+
+                       connman_dbus_dict_append_basic(iter, "BSSID",
+                                        DBUS_TYPE_STRING, &bssid_str);
+
+                        connman_dbus_dict_append_basic(iter, "Strength",
+                                        DBUS_TYPE_UINT16, &bssids->strength);
+
+                        connman_dbus_dict_append_basic(iter, "Frequency",
+                                        DBUS_TYPE_UINT16, &bssids->frequency);
+                }
+        }
+}
 #endif
 
 static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
@@ -3314,7 +3387,6 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
                vsie_list = (GSList *)connman_network_get_vsie_list(service->network);
 
        if (vsie_list) {
-               DBG("ConnMan, service->path=%s No.of elements in list: %d", service->path, g_slist_length(vsie_list));
                GSList *list;
                for (list = vsie_list; list; list = list->next) {
                        wifi_vsie = (unsigned char *)list->data;
@@ -3381,6 +3453,9 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+       case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                break;
        case CONNMAN_SERVICE_TYPE_CELLULAR:
                val = service->roaming;
@@ -3392,8 +3467,11 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
                break;
        case CONNMAN_SERVICE_TYPE_WIFI:
 #if defined TIZEN_EXT
-               if (service->network != NULL)
+               if (service->network != NULL) {
                        append_wifi_ext_info(dict, service->network);
+                       connman_dbus_dict_append_dict(dict, "BSSID.List",
+                                       append_bssid_info, service->network);
+               }
 
                connman_dbus_dict_append_dict(dict, "Ethernet",
                                                append_ethernet, service);
@@ -4804,6 +4882,19 @@ static DBusMessage *set_property(DBusConnection *conn,
                }
 
                service_save(service);
+#if defined TIZEN_EXT
+               /* When AP is connected using WPS without SSID then its password needs
+                * to be saved for autoconnection */
+       } else if (g_str_equal(name, "Passphrase")) {
+               char *passphrase;
+
+               if (type != DBUS_TYPE_STRING)
+                       return __connman_error_invalid_arguments(msg);
+
+               dbus_message_iter_get_basic(&value, &passphrase);
+
+               __connman_service_set_passphrase(service, passphrase);
+#endif
        } else
                return __connman_error_invalid_property(msg);
 
@@ -4984,6 +5075,9 @@ void __connman_service_set_active_session(bool enable, GSList *list)
                case CONNMAN_SERVICE_TYPE_GPS:
                case CONNMAN_SERVICE_TYPE_VPN:
                case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+               case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                        break;
                }
 
@@ -5119,6 +5213,12 @@ static bool auto_connect_service(GList *services,
 
        ignore[CONNMAN_SERVICE_TYPE_VPN] = true;
 
+#if defined TIZEN_EXT_WIFI_MESH
+       /* Don't auto connect wifi if mesh interface is created */
+       if (connman_mesh_is_interface_created())
+               ignore[CONNMAN_SERVICE_TYPE_WIFI] = true;
+#endif
+
        for (list = services; list; list = list->next) {
                service = list->data;
 
@@ -5601,6 +5701,7 @@ static void __connman_service_cleanup_network_8021x(struct connman_service *serv
        connman_network_set_string(service->network, "WiFi.PrivateKeyFile", NULL);
        connman_network_set_string(service->network, "WiFi.PrivateKeyPassphrase", NULL);
        connman_network_set_string(service->network, "WiFi.Phase2", NULL);
+       connman_network_set_string(service->network, "WiFi.AnonymousIdentity", NULL);
 }
 #endif
 
@@ -5965,6 +6066,19 @@ static DBusMessage *get_user_favorite(DBusConnection *conn,
        return reply;
 }
 
+#if defined TIZEN_MAINTAIN_ONLINE
+static DBusMessage *downgrade_service(DBusConnection *conn,
+                                       DBusMessage *msg, void *user_data)
+{
+       struct connman_service *service = user_data;
+
+       downgrade_state(service);
+       __connman_connection_update_gateway();
+
+       return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+#endif
+
 static struct _services_notify {
        int id;
        GHashTable *add;
@@ -6117,6 +6231,9 @@ static const GDBusMethodTable service_methods[] = {
        { GDBUS_METHOD("GetUserFavorite",
                        NULL, GDBUS_ARGS({ "value", "v" }),
                        get_user_favorite) },
+#if defined TIZEN_MAINTAIN_ONLINE
+       { GDBUS_METHOD("Downgrade", NULL, NULL, downgrade_service) },
+#endif
        { },
 };
 
@@ -7074,7 +7191,12 @@ static void __connman_service_disconnect_default(struct connman_service *service
                default_connecting_device = NULL;
 }
 
+#if defined TIZEN_MAINTAIN_ONLINE
+static void __connman_service_connect_default(struct connman_service *current,
+                                                                 enum connman_service_state old_state)
+#else
 static void __connman_service_connect_default(struct connman_service *current)
+#endif
 {
        int err;
        GList *list;
@@ -7111,6 +7233,11 @@ static void __connman_service_connect_default(struct connman_service *current)
                }
 
                return;
+#if defined TIZEN_MAINTAIN_ONLINE
+       } else if (current->state == CONNMAN_SERVICE_STATE_READY &&
+                          old_state == CONNMAN_SERVICE_STATE_ONLINE) {
+               DBG("Device is downgraded: online --> ready");
+#endif
        } else if (is_connected(current->state) == TRUE || is_connecting(current->state) == TRUE)
                return;
 
@@ -7214,7 +7341,19 @@ static void set_priority_connected_service(void)
                if (is_connected(service->state) == FALSE)
                        service->order = 5;
                else
+#if defined TIZEN_MAINTAIN_ONLINE
+               {
+                       if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+                               service->state == CONNMAN_SERVICE_STATE_ONLINE)
+                               service->order = 6;
+                       else if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+                               service->order = 6;
+                       else
+                               service->order = 5;
+               }
+#else
                        service->order = 6;
+#endif
        }
 }
 #endif
@@ -7357,10 +7496,15 @@ static int service_indicate_state(struct connman_service *service)
                        __connman_ipconfig_disable_ipv6(
                                                service->ipconfig_ipv6);
 
+#if !defined TIZEN_MAINTAIN_ONLINE
                if (connman_setting_get_bool("SingleConnectedTechnology"))
                        single_connected_tech(service);
                else if (service->type != CONNMAN_SERVICE_TYPE_VPN)
                        vpn_auto_connect();
+#else
+               if (service->type != CONNMAN_SERVICE_TYPE_VPN)
+                       vpn_auto_connect();
+#endif
 
 #if defined TIZEN_EXT
                if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
@@ -7370,6 +7514,15 @@ static int service_indicate_state(struct connman_service *service)
                break;
 
        case CONNMAN_SERVICE_STATE_ONLINE:
+#if defined TIZEN_MAINTAIN_ONLINE
+#if defined TIZEN_EXT
+               if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
+                       set_priority_connected_service();
+#endif
+
+               if (connman_setting_get_bool("SingleConnectedTechnology"))
+                       single_connected_tech(service);
+#endif
 
                break;
 
@@ -7439,8 +7592,12 @@ static int service_indicate_state(struct connman_service *service)
        service_list_sort();
 
 #if defined TIZEN_EXT
+#if defined TIZEN_MAINTAIN_ONLINE
+       __connman_service_connect_default(service, old_state);
+#else
        __connman_service_connect_default(service);
 #endif
+#endif
 
        __connman_connection_update_gateway();
 
@@ -7683,12 +7840,35 @@ static gboolean redo_wispr(gpointer user_data)
        return FALSE;
 }
 
+#if defined TIZEN_MAINTAIN_ONLINE
+static gboolean redo_wispr_ipv4(gpointer user_data)
+{
+       struct connman_service *service = user_data;
+
+       DBG("");
+
+       __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
+
+       return FALSE;
+}
+#endif
+
 int __connman_service_online_check_failed(struct connman_service *service,
                                        enum connman_ipconfig_type type)
 {
        DBG("service %p type %d count %d", service, type,
                                                service->online_check_count);
 
+#if defined TIZEN_MAINTAIN_ONLINE
+       /* Retry IPv4 stuff also */
+       if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
+               connman_warn("Online check failed for %p %s", service,
+                                       service->name);
+
+               g_timeout_add_seconds(1, redo_wispr_ipv4, service);
+               return 0;
+       }
+#else
        /* currently we only retry IPv6 stuff */
        if (type == CONNMAN_IPCONFIG_TYPE_IPV4 ||
                        service->online_check_count != 1) {
@@ -7696,6 +7876,7 @@ int __connman_service_online_check_failed(struct connman_service *service,
                        service->name);
                return 0;
        }
+#endif
 
        service->online_check_count = 0;
 
@@ -7804,6 +7985,10 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service,
 #if !defined TIZEN_EXT
                                check_proxy_setup(service);
 #endif
+#if defined TIZEN_MAINTAIN_ONLINE
+/*             if (old_state == CONNMAN_SERVICE_STATE_ONLINE) */
+                       check_proxy_setup(service);
+#endif
                        } else {
                                service->online_check_count = 1;
                                __connman_wispr_start(service, type);
@@ -7945,6 +8130,17 @@ static void prepare_8021x(struct connman_service *service)
        if (service->phase2)
                connman_network_set_string(service->network, "WiFi.Phase2",
                                                        service->phase2);
+
+#if defined TIZEN_EXT
+       if (service->keymgmt_type)
+               connman_network_set_string(service->network, "WiFi.KeymgmtType",
+                                                       service->keymgmt_type);
+
+       DBG("service->phase1 : %s", service->phase1);
+       if (service->phase1)
+               connman_network_set_string(service->network, "WiFi.Phase1",
+                                                       service->phase1);
+#endif
 }
 
 static int service_connect(struct connman_service *service)
@@ -7986,6 +8182,9 @@ static int service_connect(struct connman_service *service)
        case CONNMAN_SERVICE_TYPE_SYSTEM:
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+       case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                return -EINVAL;
        case CONNMAN_SERVICE_TYPE_ETHERNET:
        case CONNMAN_SERVICE_TYPE_GADGET:
@@ -8032,7 +8231,10 @@ static int service_connect(struct connman_service *service)
                        DBG("service eap: %s", service->eap);
                        if (g_str_equal(service->eap, "tls") ||
                                g_str_equal(service->eap, "sim") ||
-                               g_str_equal(service->eap, "aka"))
+                               g_str_equal(service->eap, "aka") ||
+                               g_str_equal(service->eap, "aka'") ||
+                               g_str_equal(service->eap, "pwd") ||
+                               g_str_equal(service->eap, "fast"))
                                break;
 #else
                        /*
@@ -8126,6 +8328,9 @@ int __connman_service_connect(struct connman_service *service,
        case CONNMAN_SERVICE_TYPE_SYSTEM:
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+       case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                return -EINVAL;
 
        case CONNMAN_SERVICE_TYPE_ETHERNET:
@@ -8398,8 +8603,15 @@ static int service_register(struct connman_service *service)
 
        DBG("path %s", service->path);
 
+#if defined TIZEN_EXT
+       service_load(service);
+       int ret = __connman_config_provision_service(service);
+       if (ret < 0)
+               DBG("Failed to provision service");
+#else
        if (__connman_config_provision_service(service) < 0)
                service_load(service);
+#endif
 
        g_dbus_register_interface(connection, service->path,
                                        CONNMAN_SERVICE_INTERFACE,
@@ -8730,8 +8942,15 @@ unsigned int __connman_service_get_order(struct connman_service *service)
                        service->do_split_routing == FALSE)
                order = 10;
        else if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
+#if defined TIZEN_MAINTAIN_ONLINE
+               if (service->state != CONNMAN_SERVICE_STATE_ONLINE)
+                       service->order = 0;
+               else if (service->order < 5)
+                       service->order = 5;
+#else
                if (service->order < 5)
                        order = 5;
+#endif
        } else if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
                order = 4;
        else if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
@@ -8948,6 +9167,9 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne
        case CONNMAN_SERVICE_TYPE_WIFI:
        case CONNMAN_SERVICE_TYPE_CELLULAR:
        case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+       case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                break;
        case CONNMAN_SERVICE_TYPE_ETHERNET:
                service->favorite = true;
@@ -8979,6 +9201,9 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne
                        case CONNMAN_SERVICE_TYPE_UNKNOWN:
                        case CONNMAN_SERVICE_TYPE_SYSTEM:
                        case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+                       case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                                break;
 
                        case CONNMAN_SERVICE_TYPE_GADGET: