#define ASSOC_STATUS_NO_CLIENT 17
#define LOAD_SHAPING_MAX_RETRIES 3
+#if defined TIZEN_EXT
+#define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
+#endif
+
static struct connman_technology *wifi_technology = NULL;
static struct connman_technology *p2p_technology = NULL;
#endif
int disconnect_code;
int assoc_code;
+#if defined TIZEN_EXT_WIFI_MESH
+ bool mesh_interface;
+ struct wifi_mesh_info *mesh_info;
+#endif
};
#if defined TIZEN_EXT
pending_wifi_device = g_list_append(pending_wifi_device, wifi);
}
+#if defined TIZEN_EXT_WIFI_MESH
+struct wifi_mesh_info {
+ struct wifi_data *wifi;
+ GSupplicantInterface *interface;
+ struct connman_mesh *mesh;
+ char *parent_ifname;
+ char *ifname;
+ char *identifier;
+ int index;
+};
+
+struct mesh_change_peer_status_info {
+ char *peer_address;
+ enum connman_mesh_peer_status peer_status;
+ mesh_change_peer_status_cb_t callback;
+ void *user_data;
+};
+
+static struct connman_technology_driver mesh_tech_driver = {
+ .name = "mesh",
+ .type = CONNMAN_SERVICE_TYPE_MESH,
+};
+
+static void mesh_interface_create_callback(int result,
+ GSupplicantInterface *interface,
+ void *user_data)
+{
+ struct wifi_mesh_info *mesh_info = user_data;
+ struct wifi_data *wifi;
+ bool success = false;
+
+ DBG("result %d ifname %s, mesh_info %p", result,
+ g_supplicant_interface_get_ifname(interface),
+ mesh_info);
+
+ if (result < 0 || !mesh_info)
+ goto done;
+
+ wifi = mesh_info->wifi;
+
+ mesh_info->interface = interface;
+ mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
+ mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
+ DBG("Mesh Interface identifier %s", mesh_info->identifier);
+ wifi->mesh_interface = true;
+ wifi->mesh_info = mesh_info;
+ g_supplicant_interface_set_data(interface, wifi);
+ success = true;
+
+done:
+ connman_mesh_notify_interface_create(success);
+}
+
+static int add_mesh_interface(const char *ifname, const char *parent_ifname)
+{
+ GList *list;
+ struct wifi_data *wifi;
+ struct wifi_mesh_info *mesh_info;
+ const char *wifi_ifname;
+ bool parent_found = false;
+ const char *driver = "nl80211";
+
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (!g_supplicant_interface_has_mesh(wifi->interface))
+ continue;
+
+ wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
+ if (!wifi_ifname)
+ continue;
+
+ if (!g_strcmp0(wifi_ifname, parent_ifname)) {
+ parent_found = true;
+ break;
+ }
+ }
+
+ if (!parent_found) {
+ DBG("Parent interface %s doesn't exist", parent_ifname);
+ return -ENODEV;
+ }
+
+ mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
+ if (!mesh_info)
+ return -ENOMEM;
+
+ mesh_info->wifi = wifi;
+ mesh_info->ifname = g_strdup(ifname);
+ mesh_info->parent_ifname = g_strdup(parent_ifname);
+
+ g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
+ mesh_interface_create_callback, mesh_info);
+ return -EINPROGRESS;
+}
+
+static void mesh_interface_remove_callback(int result,
+ GSupplicantInterface *interface,
+ void *user_data)
+{
+ struct wifi_data *wifi = user_data;
+ struct wifi_mesh_info *mesh_info = wifi->mesh_info;
+ bool success = false;
+
+ DBG("result %d mesh_info %p", result, mesh_info);
+
+ if (result < 0 || !mesh_info)
+ goto done;
+
+ mesh_info->interface = NULL;
+ g_free(mesh_info->parent_ifname);
+ g_free(mesh_info->ifname);
+ g_free(mesh_info->identifier);
+ g_free(mesh_info);
+ wifi->mesh_interface = false;
+ wifi->mesh_info = NULL;
+ success = true;
+
+done:
+ connman_mesh_notify_interface_remove(success);
+}
+
+static int remove_mesh_interface(const char *ifname)
+{
+ GList *list;
+ struct wifi_data *wifi;
+ struct wifi_mesh_info *mesh_info;
+ bool mesh_if_found = false;
+ int ret;
+
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (wifi->mesh_interface) {
+ mesh_if_found = true;
+ break;
+ }
+ }
+
+ if (!mesh_if_found) {
+ DBG("Mesh interface %s doesn't exist", ifname);
+ return -ENODEV;
+ }
+
+ mesh_info = wifi->mesh_info;
+ ret = g_supplicant_interface_remove(mesh_info->interface,
+ mesh_interface_remove_callback, wifi);
+ if (ret < 0)
+ return ret;
+
+ return -EINPROGRESS;
+}
+
+static void mesh_disconnect_callback(int result,
+ GSupplicantInterface *interface, void *user_data)
+{
+ struct connman_mesh *mesh = user_data;
+
+ DBG("result %d interface %p mesh %p", result, interface, mesh);
+}
+
+static int mesh_peer_disconnect(struct connman_mesh *mesh)
+{
+ GList *list;
+ struct wifi_data *wifi;
+ struct wifi_mesh_info *mesh_info;
+ bool mesh_if_found = false;
+ GSupplicantInterface *interface;
+
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (wifi->mesh_interface) {
+ mesh_if_found = true;
+ break;
+ }
+ }
+
+ if (!mesh_if_found) {
+ DBG("Mesh interface is not created");
+ return -ENODEV;
+ }
+
+ mesh_info = wifi->mesh_info;
+
+ interface = mesh_info->interface;
+ return g_supplicant_interface_disconnect(interface,
+ mesh_disconnect_callback, mesh);
+}
+
+static void mesh_connect_callback(int result, GSupplicantInterface *interface,
+ void *user_data)
+{
+ struct connman_mesh *mesh = user_data;
+ DBG("mesh %p result %d", mesh, result);
+
+ if (result < 0)
+ connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
+ else
+ connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
+}
+
+static GSupplicantSecurity mesh_network_security(const char *security)
+{
+ if (g_str_equal(security, "none"))
+ return G_SUPPLICANT_SECURITY_NONE;
+ else if (g_str_equal(security, "sae"))
+ return G_SUPPLICANT_SECURITY_SAE;
+
+ return G_SUPPLICANT_SECURITY_UNKNOWN;
+}
+
+static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
+{
+ const char *name;
+ const char *security;
+
+ if (ssid->ssid)
+ g_free(ssid->ssid);
+
+ memset(ssid, 0, sizeof(*ssid));
+ ssid->mode = G_SUPPLICANT_MODE_MESH;
+
+ security = connman_mesh_get_security(mesh);
+ ssid->security = mesh_network_security(security);
+
+ if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
+ ssid->passphrase = connman_mesh_get_passphrase(mesh);
+
+ ssid->freq = connman_mesh_get_frequency(mesh);
+ name = connman_mesh_get_name(mesh);
+ if (name) {
+ ssid->ssid_len = strlen(name);
+ ssid->ssid = g_malloc0(ssid->ssid_len + 1);
+ memcpy(ssid->ssid, name, ssid->ssid_len);
+ ssid->scan_ssid = 1;
+ }
+}
+
+static int mesh_peer_connect(struct connman_mesh *mesh)
+{
+ GList *list;
+ struct wifi_data *wifi;
+ struct wifi_mesh_info *mesh_info;
+ bool mesh_if_found = false;
+ GSupplicantInterface *interface;
+ GSupplicantSSID *ssid;
+
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (wifi->mesh_interface) {
+ mesh_if_found = true;
+ break;
+ }
+ }
+
+ if (!mesh_if_found) {
+ DBG("Mesh interface is not created");
+ return -ENODEV;
+ }
+
+ mesh_info = wifi->mesh_info;
+
+ interface = mesh_info->interface;
+
+ ssid = g_try_malloc0(sizeof(GSupplicantSSID));
+ if (!ssid)
+ return -ENOMEM;
+
+ mesh_info->mesh = mesh;
+
+ mesh_ssid_init(ssid, mesh);
+ return g_supplicant_interface_connect(interface, ssid,
+ mesh_connect_callback, mesh);
+}
+
+static void mesh_peer_change_status_callback(int result,
+ GSupplicantInterface *interface,
+ void *user_data)
+{
+ struct mesh_change_peer_status_info *data = user_data;
+
+ DBG("result %d Peer Status %d", result, data->peer_status);
+
+ if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
+ /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
+ connman_mesh_remove_connected_peer(data->peer_address, 52);
+ }
+
+ if (data->callback)
+ data->callback(result, data->user_data);
+
+ g_free(data->peer_address);
+ g_free(data);
+ return;
+}
+
+static int mesh_change_peer_status(const char *peer_address,
+ enum connman_mesh_peer_status status,
+ mesh_change_peer_status_cb_t callback, void *user_data)
+{
+ GList *list;
+ struct wifi_data *wifi;
+ struct wifi_mesh_info *mesh_info;
+ bool mesh_if_found = false;
+ GSupplicantInterface *interface;
+ struct mesh_change_peer_status_info *data;
+ const char *method;
+
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (wifi->mesh_interface) {
+ mesh_if_found = true;
+ break;
+ }
+ }
+
+ if (!mesh_if_found) {
+ DBG("Mesh interface is not created");
+ return -ENODEV;
+ }
+
+ mesh_info = wifi->mesh_info;
+
+ interface = mesh_info->interface;
+
+ switch (status) {
+ case CONNMAN_MESH_PEER_ADD:
+ method = "MeshPeerAdd";
+ break;
+ case CONNMAN_MESH_PEER_REMOVE:
+ method = "MeshPeerRemove";
+ break;
+ default:
+ DBG("Invalid method");
+ return -EINVAL;
+ }
+
+ data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
+ if (data == NULL) {
+ DBG("Memory allocation failed");
+ return -ENOMEM;
+ }
+
+ data->peer_address = g_strdup(peer_address);
+ data->peer_status = status;
+ data->callback = callback;
+ data->user_data = user_data;
+
+ return g_supplicant_interface_mesh_peer_change_status(interface,
+ mesh_peer_change_status_callback, peer_address, method,
+ data);
+}
+
+static struct connman_mesh_driver mesh_driver = {
+ .add_interface = add_mesh_interface,
+ .remove_interface = remove_mesh_interface,
+ .connect = mesh_peer_connect,
+ .disconnect = mesh_peer_disconnect,
+ .change_peer_status = mesh_change_peer_status,
+};
+
+static void mesh_support(GSupplicantInterface *interface)
+{
+ DBG("");
+
+ if (!g_supplicant_interface_has_mesh(interface))
+ return;
+
+ if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
+ DBG("Could not register Mesh technology driver");
+ return;
+ }
+
+ connman_mesh_driver_register(&mesh_driver);
+}
+
+static void check_mesh_technology(void)
+{
+ bool mesh_exists = false;
+ GList *list;
+
+ for (list = iface_list; list; list = list->next) {
+ struct wifi_data *w = list->data;
+
+ if (w->interface &&
+ g_supplicant_interface_has_mesh(w->interface))
+ mesh_exists = true;
+ }
+
+ if (!mesh_exists) {
+ connman_technology_driver_unregister(&mesh_tech_driver);
+ connman_mesh_driver_unregister(&mesh_driver);
+ }
+}
+
+static void mesh_group_started(GSupplicantInterface *interface)
+{
+ struct wifi_data *wifi;
+ struct wifi_mesh_info *mesh_info;
+ struct connman_mesh *mesh;
+ const unsigned char *ssid;
+ unsigned int ssid_len;
+ char name[33];
+
+ ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
+ memcpy(name, ssid, ssid_len);
+ name[ssid_len] = '\0';
+ DBG("name %s", name);
+ wifi = g_supplicant_interface_get_data(interface);
+ DBG("wifi %p", wifi);
+
+ if (!wifi)
+ return;
+
+ mesh_info = wifi->mesh_info;
+ if (!mesh_info)
+ return;
+
+ mesh = mesh_info->mesh;
+ if (!mesh)
+ return;
+
+ connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
+}
+
+static void mesh_group_removed(GSupplicantInterface *interface)
+{
+ struct wifi_data *wifi;
+ struct wifi_mesh_info *mesh_info;
+ struct connman_mesh *mesh;
+ const unsigned char *ssid;
+ unsigned int ssid_len;
+ int disconnect_reason;
+ char name[33];
+
+ ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
+ memcpy(name, ssid, ssid_len);
+ name[ssid_len] = '\0';
+ DBG("name %s", name);
+
+ disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
+ DBG("Disconnect Reason %d", disconnect_reason);
+
+ wifi = g_supplicant_interface_get_data(interface);
+ DBG("wifi %p", wifi);
+
+ if (!wifi)
+ return;
+
+ mesh_info = wifi->mesh_info;
+ if (!mesh_info)
+ return;
+
+ mesh = connman_get_connected_mesh_from_name(name);
+ if (!mesh) {
+ DBG("%s is not connected", name);
+ mesh = connman_get_connecting_mesh_from_name(name);
+ if (!mesh) {
+ DBG("%s is not connecting", name);
+ return;
+ }
+ }
+
+ connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
+ connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
+}
+
+static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
+{
+ const char *peer_address;
+
+ peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
+
+ if (!peer_address)
+ return;
+
+ DBG("Peer %s connected", peer_address);
+ connman_mesh_add_connected_peer(peer_address);
+}
+
+static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
+{
+ const char *peer_address;
+ int reason;
+
+ peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
+
+ if (!peer_address)
+ return;
+
+ reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
+
+ DBG("Peer %s disconnected with reason %d", peer_address, reason);
+ connman_mesh_remove_connected_peer(peer_address, reason);
+}
+#endif
+
static struct wifi_data *get_pending_wifi_data(const char *ifname)
{
GList *list;
iface_list = g_list_remove(iface_list, wifi);
check_p2p_technology();
+#if defined TIZEN_EXT_WIFI_MESH
+ check_mesh_technology();
+#endif
remove_pending_wifi_device(wifi);
return -EALREADY;
DBG("scan_type: %d", scan_type);
- if (scan_type == 1) { /* ssid based scan */
+ if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
if (!scan_params) {
DBG("Failed to allocate memory.");
}
memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
- DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
+ /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
scan_ssid->ssid_len = ssid_len;
scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
count++;
}
scan_params->num_ssids = count;
- } else if (scan_type == 2) { /* frequency based scan */
+ } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
if (!scan_params) {
}
scan_params->num_freqs = count;
+ } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
+ int freq_count, ap_count;
+ scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
+ if (!scan_params) {
+ DBG("Failed to allocate memory.");
+ return -ENOMEM;
+ }
+
+ guint size = g_slist_length(specific_scan_list);
+
+ scan_params->freqs = g_try_new0(uint16_t, size/2);
+ if (!scan_params->freqs) {
+ DBG("Failed to allocate memory.");
+ g_free(scan_params);
+ return -ENOMEM;
+ }
+
+ ap_count = freq_count = 0;
+ for (list = specific_scan_list; list; list = list->next) {
+ if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
+ ssid = ((connman_multi_scan_ap_s *)list->data)->str;
+ int ssid_len = strlen(ssid);
+
+ scan_ssid = g_try_new0(struct scan_ssid, 1);
+ if (!scan_ssid) {
+ DBG("Failed to allocate memory.");
+ g_supplicant_free_scan_params(scan_params);
+ return -ENOMEM;
+ }
+
+ memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
+ /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
+ scan_ssid->ssid_len = ssid_len;
+ scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
+ ap_count++;
+
+ } else { /* freq */
+ freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
+ scan_params->freqs[freq_count] = freq;
+ DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
+ freq_count++;
+ }
+ }
+ scan_params->num_ssids = ap_count;
+ scan_params->num_freqs = freq_count;
} else {
DBG("Invalid scan");
return -EINVAL;
}
#endif
+#if defined TIZEN_EXT_WIFI_MESH
+static void mesh_scan_callback(int result, GSupplicantInterface *interface,
+ void *user_data)
+{
+ struct connman_device *device = user_data;
+ struct wifi_data *wifi = connman_device_get_data(device);
+ bool scanning;
+
+ DBG("result %d wifi %p", result, wifi);
+
+ scanning = connman_device_get_scanning(device);
+ if (scanning)
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_MESH, false);
+
+ if (scanning)
+ connman_device_unref(device);
+}
+
+static int mesh_scan(struct connman_device *device)
+{
+ struct wifi_data *wifi;
+ struct wifi_mesh_info *mesh_info;
+ int ret;
+
+ DBG("");
+
+ wifi = connman_device_get_data(device);
+
+ if (!wifi->mesh_interface)
+ return -ENOTSUP;
+
+ mesh_info = wifi->mesh_info;
+ reset_autoscan(device);
+ connman_device_ref(device);
+
+ ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
+ mesh_scan_callback, device);
+ if (ret)
+ connman_device_unref(device);
+ else
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_MESH, true);
+
+ return ret;
+}
+
+static void abort_scan_callback(int result, GSupplicantInterface *interface,
+ void *user_data)
+{
+ struct connman_device *device = user_data;
+ struct wifi_data *wifi = connman_device_get_data(device);
+
+ DBG("result %d wifi %p", result, wifi);
+
+ __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
+}
+
+static int mesh_abort_scan(enum connman_service_type type,
+ struct connman_device *device)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+ struct wifi_mesh_info *mesh_info;
+ bool scanning;
+ int ret;
+
+ if (!wifi || !wifi->mesh_interface)
+ return -ENODEV;
+
+ if (type != CONNMAN_SERVICE_TYPE_MESH)
+ return -EINVAL;
+
+ mesh_info = wifi->mesh_info;
+
+ scanning = connman_device_get_scanning(device);
+ if (!scanning)
+ return -EEXIST;
+
+ ret = g_supplicant_interface_abort_scan(mesh_info->interface,
+ abort_scan_callback, device);
+
+ return ret;
+}
+
+static int mesh_specific_scan(enum connman_service_type type,
+ struct connman_device *device, const char *ssid,
+ unsigned int freq, void *user_data)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+ GSupplicantScanParams *scan_params = NULL;
+ struct wifi_mesh_info *mesh_info;
+ struct scan_ssid *scan_ssid;
+ bool scanning;
+ int ret;
+
+ if (!wifi || !wifi->mesh_interface)
+ return -ENODEV;
+
+ if (type != CONNMAN_SERVICE_TYPE_MESH)
+ return -EINVAL;
+
+ if (wifi->p2p_device)
+ return 0;
+
+ mesh_info = wifi->mesh_info;
+
+ scanning = connman_device_get_scanning(device);
+ if (scanning)
+ return -EALREADY;
+
+ scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
+ if (!scan_params)
+ return -ENOMEM;
+
+ scan_ssid = g_try_new(struct scan_ssid, 1);
+ if (!scan_ssid) {
+ g_free(scan_params);
+ return -ENOMEM;
+ }
+
+ scan_ssid->ssid_len = strlen(ssid);
+ memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
+ scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
+ scan_params->num_ssids = 1;
+
+ scan_params->freqs = g_try_new(uint16_t, 1);
+ if (!scan_params->freqs) {
+ g_slist_free_full(scan_params->ssids, g_free);
+ g_free(scan_params);
+ return -ENOMEM;
+ }
+
+ scan_params->freqs[0] = freq;
+ scan_params->num_freqs = 1;
+
+ reset_autoscan(device);
+ connman_device_ref(device);
+
+ ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
+ mesh_scan_callback, device);
+
+ if (ret == 0) {
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_MESH, true);
+ } else {
+ g_supplicant_free_scan_params(scan_params);
+ connman_device_unref(device);
+ }
+
+ return ret;
+}
+#endif
+
/*
* Note that the hidden scan is only used when connecting to this specific
* hidden AP first time. It is not used when system autoconnects to hidden AP.
if (type == CONNMAN_SERVICE_TYPE_P2P)
return p2p_find(device);
+#if defined TIZEN_EXT_WIFI_MESH
+ if (type == CONNMAN_SERVICE_TYPE_MESH)
+ return mesh_scan(device);
+#endif
+
DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
scanning = connman_device_get_scanning(device);
#if defined TIZEN_EXT
.specific_scan = wifi_specific_scan,
#endif
+#if defined TIZEN_EXT_WIFI_MESH
+ .abort_scan = mesh_abort_scan,
+ .mesh_specific_scan = mesh_specific_scan,
+#endif
};
static void system_ready(void)
DBG("network %p result %d", network, result);
#if defined TIZEN_EXT
+ set_connman_bssid(RESET_BSSID, NULL);
+
for (list = iface_list; list; list = list->next) {
wifi = list->data;
return G_SUPPLICANT_SECURITY_UNKNOWN;
}
+#if defined TIZEN_EXT
+static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
+{
+ if (security == NULL)
+ return G_SUPPLICANT_EAP_KEYMGMT_NONE;
+
+ if (g_str_equal(security, "FT") == TRUE)
+ return G_SUPPLICANT_EAP_KEYMGMT_FT;
+ else if (g_str_equal(security, "CCKM") == TRUE)
+ return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
+
+ return G_SUPPLICANT_EAP_KEYMGMT_NONE;
+}
+#endif
+
static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
{
const char *security;
+#if defined TIZEN_EXT
+ const void *ssid_data;
+#endif
memset(ssid, 0, sizeof(*ssid));
ssid->mode = G_SUPPLICANT_MODE_INFRA;
+#if defined TIZEN_EXT
+ ssid_data = connman_network_get_blob(network, "WiFi.SSID",
+ &ssid->ssid_len);
+ ssid->ssid = g_try_malloc0(ssid->ssid_len);
+ memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
+#else
ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
&ssid->ssid_len);
+#endif
ssid->scan_ssid = 1;
security = connman_network_get_string(network, "WiFi.Security");
ssid->security = network_security(security);
#if defined TIZEN_EXT
ssid->bssid = connman_network_get_bssid(network);
-#endif
-#if defined TIZEN_EXT
- ssid->freq = connman_network_get_frequency(network);
+
+ ssid->eap_keymgmt = network_eap_keymgmt(
+ connman_network_get_string(network, "WiFi.KeymgmtType"));
+ ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
+
+ if(g_strcmp0(ssid->eap, "fast") == 0)
+ ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
+
+ if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
+ ssid->bssid_for_connect_len = 6;
+ set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
+ DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
+ ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
+ ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
+ ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
+ } else {
+ ssid->freq = connman_network_get_frequency(network);
+ }
#endif
if (connman_setting_get_bool("BackgroundScanning"))
if (wifi->disconnecting) {
wifi->pending_network = network;
+#if defined TIZEN_EXT
+ g_free(ssid->ssid);
+#endif
g_free(ssid);
} else {
wifi->network = connman_network_ref(network);
return true;
}
- ret = send_encryption_request(passphrase, passphrase);
+ ret = send_encryption_request(passphrase, network);
g_free(passphrase);
}
#if defined TIZEN_EXT
- int err;
-
- err = g_supplicant_interface_remove_network(wifi->interface);
- if (err < 0)
- DBG("Failed to remove network(%d)", err);
-
-
/* Some of Wi-Fi networks are not comply Wi-Fi specification.
* Retry association until its retry count is expired */
if (handle_wifi_assoc_retry(network, wifi) == true) {
DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
connman_network_set_disconnect_reason(network, wifi->disconnect_code);
}
-
- /* To avoid unnecessary repeated association in wpa_supplicant,
- * "RemoveNetwork" should be made when Wi-Fi is disconnected */
- if (wps != true && wifi->network && wifi->disconnecting == false) {
- wifi->disconnecting = true;
- err = g_supplicant_interface_disconnect(wifi->interface,
- disconnect_callback, wifi->network);
- if (err < 0)
- wifi->disconnecting = false;
-
- connman_network_set_connected(network, false);
- connman_network_set_associating(network, false);
-
- start_autoscan(device);
-
- break;
- }
#endif
connman_network_set_connected(network, false);
wifi = g_supplicant_interface_get_data(interface);
+#if defined TIZEN_EXT_WIFI_MESH
+ if (wifi && wifi->mesh_interface) {
+ DBG("Notify mesh interface remove");
+ connman_mesh_notify_interface_remove(true);
+ struct wifi_mesh_info *mesh_info = wifi->mesh_info;
+ g_free(mesh_info->parent_ifname);
+ g_free(mesh_info->ifname);
+ g_free(mesh_info->identifier);
+ g_free(mesh_info);
+ wifi->mesh_interface = false;
+ wifi->mesh_info = NULL;
+ return;
+ }
+#endif
+
if (wifi)
wifi->interface = NULL;
connman_device_set_powered(wifi->device, false);
check_p2p_technology();
+#if defined TIZEN_EXT_WIFI_MESH
+ check_mesh_technology();
+#endif
}
static void set_device_type(const char *type, char dev_type[17])
return strength;
}
+#if defined TIZEN_EXT_WIFI_MESH
+static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
+{
+ GSupplicantInterface *interface;
+ struct wifi_data *wifi;
+ const char *name, *security;
+ struct connman_mesh *connman_mesh;
+ struct wifi_mesh_info *mesh_info;
+ const unsigned char *bssid;
+ const char *identifier;
+ char *address;
+ uint16_t frequency;
+ int ret;
+
+ interface = g_supplicant_network_get_interface(supplicant_network);
+ wifi = g_supplicant_interface_get_data(interface);
+ if (!wifi || !wifi->mesh_interface) {
+ DBG("Virtual Mesh interface not created");
+ return;
+ }
+
+ bssid = g_supplicant_network_get_bssid(supplicant_network);
+ address = g_malloc0(19);
+ snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
+ bssid[2], bssid[3], bssid[4], bssid[5]);
+
+ identifier = g_supplicant_network_get_identifier(supplicant_network);
+ name = g_supplicant_network_get_name(supplicant_network);
+ security = g_supplicant_network_get_security(supplicant_network);
+ frequency = g_supplicant_network_get_frequency(supplicant_network);
+
+ mesh_info = wifi->mesh_info;
+ connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
+ if (connman_mesh)
+ goto done;
+
+ DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
+ security);
+ connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
+ connman_mesh_set_name(connman_mesh, name);
+ connman_mesh_set_security(connman_mesh, security);
+ connman_mesh_set_frequency(connman_mesh, frequency);
+ connman_mesh_set_address(connman_mesh, address);
+ connman_mesh_set_index(connman_mesh, mesh_info->index);
+ connman_mesh_set_strength(connman_mesh,
+ calculate_strength(supplicant_network));
+ connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
+
+ ret = connman_mesh_register(connman_mesh);
+ if (ret == -EALREADY)
+ DBG("Mesh Peer is already registered");
+
+done:
+ g_free(address);
+}
+
+static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
+{
+ GSupplicantInterface *interface;
+ struct wifi_data *wifi;
+ struct connman_mesh *connman_mesh;
+ struct wifi_mesh_info *mesh_info;
+ const char *identifier;
+
+ interface = g_supplicant_network_get_interface(supplicant_network);
+ wifi = g_supplicant_interface_get_data(interface);
+ if (!wifi || !wifi->mesh_interface) {
+ DBG("Virtual Mesh interface not created");
+ return;
+ }
+
+ identifier = g_supplicant_network_get_identifier(supplicant_network);
+ if (!identifier) {
+ DBG("Failed to get Mesh Peer identifier");
+ return;
+ }
+
+ mesh_info = wifi->mesh_info;
+ connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
+ if (connman_mesh) {
+ /* Do not unregister connected mesh peer */
+ if (connman_mesh_peer_is_connected_state(connman_mesh)) {
+ DBG("Mesh Peer %s is connected", identifier);
+ return;
+ }
+ DBG("Mesh Peer identifier %s removed", identifier);
+ connman_mesh_unregister(connman_mesh);
+ }
+}
+#endif
+
static void network_added(GSupplicantNetwork *supplicant_network)
{
struct connman_network *network;
#if defined TIZEN_EXT
GSList *vsie_list = NULL;
+ const unsigned char *country_code;
#endif
mode = g_supplicant_network_get_mode(supplicant_network);
if (!g_strcmp0(mode, "adhoc"))
return;
+#if defined TIZEN_EXT_WIFI_MESH
+ if (!g_strcmp0(mode, "mesh")) {
+ mesh_peer_added(supplicant_network);
+ return;
+ }
+#endif
+
interface = g_supplicant_network_get_interface(supplicant_network);
wifi = g_supplicant_interface_get_data(interface);
name = g_supplicant_network_get_name(supplicant_network);
connman_network_set_vsie_list(network, vsie_list);
else
DBG("vsie_list is NULL");
+ country_code = g_supplicant_network_get_countrycode(supplicant_network);
+ connman_network_set_countrycode(network, country_code);
#endif
connman_network_set_string(network, "WiFi.Security", security);
connman_network_set_strength(network,
g_supplicant_network_get_keymgmt(supplicant_network));
connman_network_set_bool(network, "WiFi.HS20AP",
g_supplicant_network_is_hs20AP(supplicant_network));
+ connman_network_set_bssid_list(network,
+ (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
#endif
connman_network_set_available(network, true);
connman_network_set_string(network, "WiFi.Mode", mode);
const char *name, *identifier;
struct connman_network *connman_network;
+#if defined TIZEN_EXT_WIFI_MESH
+ const char *mode;
+ mode = g_supplicant_network_get_mode(network);
+ if (!g_strcmp0(mode, "mesh")) {
+ mesh_peer_removed(network);
+ return;
+ }
+#endif
+
interface = g_supplicant_network_get_interface(network);
wifi = g_supplicant_interface_get_data(interface);
identifier = g_supplicant_network_get_identifier(network);
unsigned int maxrate;
uint16_t frequency;
bool wps;
+ const unsigned char *country_code;
+ GSList *bssid_list;
#endif
interface = g_supplicant_network_get_interface(network);
connman_network_set_maxrate(connman_network, maxrate);
connman_network_set_frequency(connman_network, frequency);
connman_network_set_bool(connman_network, "WiFi.WPS", wps);
+ country_code = g_supplicant_network_get_countrycode(network);
+ connman_network_set_countrycode(connman_network, country_code);
+ bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
+ connman_network_set_bssid_list(connman_network, bssid_list);
#endif
}
struct connman_peer *connman_peer;
const char *identifier;
-#if defined TIZEN_EXT
- if (!wifi)
- return;
-#endif
-
identifier = g_supplicant_peer_get_identifier(peer);
DBG("ident: %s", identifier);
.debug = debug,
.disconnect_reasoncode = disconnect_reasoncode,
.assoc_status_code = assoc_status_code,
+#if defined TIZEN_EXT_WIFI_MESH
+ .mesh_support = mesh_support,
+ .mesh_group_started = mesh_group_started,
+ .mesh_group_removed = mesh_group_removed,
+ .mesh_peer_connected = mesh_peer_connected,
+ .mesh_peer_disconnected = mesh_peer_disconnected,
+#endif
};
return NULL;
ap->mode = G_SUPPLICANT_MODE_MASTER;
+#if defined TIZEN_EXT
+ ap->ssid = (void *) ssid;
+#else
ap->ssid = ssid;
+#endif
ap->ssid_len = strlen(ssid);
ap->scan_ssid = 0;
ap->freq = 2412;