static GSList *bss_info_list = NULL;
-void __netconfig_notify_netlink_scan_done(void)
+static gint __netconfig_compare_bss_by_rssi(gconstpointer a, gconstpointer b)
+{
+ struct bss_scan_info_t *entry_a = (struct bss_scan_info_t *) a;
+ struct bss_scan_info_t *entry_b = (struct bss_scan_info_t *) b;
+
+ if (entry_a->signal > entry_b->signal)
+ return -1;
+
+ if (entry_a->signal < entry_b->signal)
+ return 1;
+
+ return 0;
+}
+
+void __netconfig_notify_netlink_scan_done(const char *interface_name)
{
GVariantBuilder *builder = NULL;
GVariantBuilder *builder1 = NULL;
const char *prop_vsie_list = "vsie_list";
const char *prop_sec = "security";
const char *prop_enc = "encryption";
+ const char *prop_pmf = "pmf";
+
+ bss_info_list = g_slist_sort(bss_info_list, __netconfig_compare_bss_by_rssi);
builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
for (list = bss_info_list; list != NULL; list = list->next) {
int signal = (int)bss_info->signal;
int sec_type = (int)bss_info->security_type;
int enc_type = (int)bss_info->encryption_type;
+ int pmf_required = (int)bss_info->pmf_required;
g_variant_builder_add(builder, "{sv}", prop_ssid, g_variant_new_string(ssid));
g_variant_builder_add(builder, "{sv}", prop_bssid, g_variant_new_string(bssid));
g_variant_builder_add(builder, "{sv}", prop_sec, g_variant_new_int32(sec_type));
g_variant_builder_add(builder, "{sv}", prop_enc, g_variant_new_int32(enc_type));
+ g_variant_builder_add(builder, "{sv}", prop_pmf, g_variant_new_int32(pmf_required));
}
}
- wifi_emit_netlink_scan_completed((Wifi *)get_wifi_object(), g_variant_builder_end(builder));
+ wifi_emit_netlink_scan_completed((Wifi *)get_wifi_object(),
+ interface_name, g_variant_builder_end(builder));
g_variant_builder_unref(builder);
if (bss_info_list != NULL)
{
int *ret = user_data;
*ret = 0;
+
+ DBG("");
return NL_SKIP;
}
{
int *ret = user_data;
*ret = err->error;
- return NL_SKIP;
+
+ DBG("");
+ return NL_STOP;
}
static int no_seq_check(struct nl_msg *msg, void *user_data)
WIFI_SECURITY_TYPE_WEP = 1,
WIFI_SECURITY_TYPE_WPA_PSK = 2,
WIFI_SECURITY_TYPE_WPA2_PSK = 3,
- WIFI_SECURITY_TYPE_EAP = 4,
+ WIFI_SECURITY_TYPE_SAE = 4,
+ WIFI_SECURITY_TYPE_EAP = 5,
} wifi_security_type_e;
typedef enum {
static unsigned char ms_oui[3] = { 0x00, 0x50, 0xf2 };
static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac };
-static void __netconfig_get_security(unsigned char *bss_element, int length, wifi_security_type_e *sec_type, wifi_encryption_type_e *enc_type)
+static void __netconfig_get_security(unsigned char *bss_element, int length,
+ wifi_security_type_e *sec_type, wifi_encryption_type_e *enc_type, int *pmf_required)
{
int i;
unsigned char *data;
uint8_t *t_data;
int len;
__u16 count;
+ gboolean ieee80211_psk = false;
*sec_type = WIFI_SECURITY_TYPE_NONE;
*enc_type = WIFI_ENCRYPTION_TYPE_NONE;
if (t_data[3] == 1 || t_data[3] == 3 || t_data[3] == 5) { // 1 : IEEE 802.1X, 3 : FT/IEEE 802.1X, 5 : IEEE 802.1X/SHA-256
*sec_type = WIFI_SECURITY_TYPE_EAP;
} else if (t_data[3] == 2 || t_data[3] == 4 || t_data[3] == 6) { // 2 : PSK, 4 : FT/PSK, 6 : PSK/SHA-256
+ if (t_data[3] == 6)
+ *pmf_required = 1;
if (*sec_type != WIFI_SECURITY_TYPE_WPA2_PSK)
*sec_type = WIFI_SECURITY_TYPE_WPA_PSK;
}
if (t_data[3] == 1 || t_data[3] == 3 || t_data[3] == 5) { // 1 : IEEE 802.1X, 3 : FT/IEEE 802.1X, 5 : IEEE 802.1X/SHA-256
*sec_type = WIFI_SECURITY_TYPE_EAP;
} else if (t_data[3] == 2 || t_data[3] == 4 || t_data[3] == 6) { // 2 : PSK, 4 : FT/PSK, 6 : PSK/SHA-256
+ if (t_data[3] == 6)
+ *pmf_required = 1;
*sec_type = WIFI_SECURITY_TYPE_WPA2_PSK;
+ ieee80211_psk = true;
+ } else if (t_data[3] == 8) { // Add SAE security type for netlink scan
+ if (ieee80211_psk != true)
+ *sec_type = WIFI_SECURITY_TYPE_SAE;
}
}
} //for
[NL80211_BSS_SIGNAL_MBM] = {.type = NLA_U32},
};
+ int pmf_needed = 0;
+
/** Parse nl message and check error. */
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
if (!tb[NL80211_ATTR_BSS]) {
}
}
__netconfig_get_security(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
- nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), &sec_type, &enc_type);
+ nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), &sec_type, &enc_type, &pmf_needed);
if (wep_check && sec_type == WIFI_SECURITY_TYPE_NONE) {
sec_type = WIFI_SECURITY_TYPE_WEP;
bss_info->security_type = sec_type;
bss_info->encryption_type = enc_type;
- DBG("%s %d %d %s %d %d ", bss_info->bssid, bss_info->freq,
+ bss_info->pmf_required = pmf_needed;
+ SECURE_LOGD("%s %d %d %s %d %d %d ", bss_info->bssid, bss_info->freq,
bss_info->signal, bss_info->ssid, bss_info->security_type,
- bss_info->encryption_type);
+ bss_info->encryption_type, bss_info->pmf_required);
if (bss_info->ssid[0] == '\0')
g_free(bss_info);
return NL_SKIP;
}
-static int __netconfig_request_netlink_scan(struct nl_sock *socket,
- int if_index, int id, GVariant *params)
+static int __netconfig_trigger_netlink_scan(struct nl_sock *socket,
+ int if_index, int id, GSList *ssid_list, char *vsie)
{
struct netconfig_netlink_scan_results results = { .done = 0, .aborted = 0 };
struct nl_msg *msg = NULL;
int ret = 0;
unsigned char ies[NETCONFIG_MAX_VSIE_LEN+1] = {0x00, };
int ies_len = 0;
- GVariantIter *iter;
- GVariant *value;
- gchar *key;
- gboolean ssid_found = FALSE;
int mcid = __netconfig_get_multicast_id(socket, "nl80211", "scan");
+ DBG("");
ret = nl_socket_add_membership(socket, mcid);
if (ret < 0) {
DBG("Failed to add membership, error: (%s)", nl_geterror(-ret));
goto out;
}
- g_variant_get(params, "a{sv}", &iter);
- while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
- if (g_strcmp0(key, "SSID") == 0) {
- if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
- char *ssid = g_strdup(g_variant_get_string(value, NULL));
- ssid_found = TRUE;
- DBG("ssid [%s]", ssid);
-
- ret = nla_put(ssids, 1, strlen(ssid), ssid);
- g_free(ssid);
- if (ret < 0) {
- DBG("Failed to add ssid to netlink message, error: (%s)", nl_geterror(-ret));
- g_variant_iter_free(iter);
- goto out;
- }
- }
- } else if (g_strcmp0(key, "VSIE") == 0) {
- if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
- char *vsie = g_strdup(g_variant_get_string(value, NULL));
- int vsie_len = strlen(vsie);
- DBG("vsie: %s vsie_len: %d", vsie, vsie_len);
-
- ies_len = (vsie_len % 2) ? ((vsie_len / 2) + 1) : (vsie_len / 2);
- __netconfig_hex_str_to_bin(vsie, ies, ies_len);
- g_free(vsie);
- }
+ for (GSList *i = ssid_list; i; i = i->next) {
+ char *ssid = (char *)i->data;
+ ret = nla_put(ssids, 1, strlen(ssid), ssid);
+ if (ret < 0) {
+ DBG("Failed to add ssid to netlink message, error: (%s)", nl_geterror(-ret));
+ goto out;
}
}
- g_variant_iter_free(iter);
- if (!ssid_found) {
+ if (g_slist_length(ssid_list) == 0) {
+ DBG("Scan with no ssids");
ret = nla_put(ssids, 1, 0, "");
if (ret < 0) {
DBG("nla_put error: (%s)", nl_geterror(-ret));
}
nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
+ if (vsie) {
+ int vsie_len = strlen(vsie);
+ DBG("vsie: %s vsie_len: %d", vsie, vsie_len);
+ ies_len = (vsie_len % 2) ? ((vsie_len / 2) + 1) : (vsie_len / 2);
+ __netconfig_hex_str_to_bin(vsie, ies, ies_len);
+ }
+
if (ies[0] == NETCONFIG_VENDOR_SPECIFIC_ID && ies[1] >= 4) {
DBG("ies_len: %d ies: %02x %02x %02x %02x %02x %02x %02x", ies_len,
ies[0], ies[1], ies[2], ies[3], ies[4], ies[5], ies[6]);
}
DBG("Sent %d bytes to the kernel", ret);
- ssid_found = FALSE;
while (err > 0) {
ret = nl_recvmsgs(socket, cb);
}
}
+ if (err < 0) {
+ DBG("error code = %d", err);
+ ret = -1;
+ goto out;
+ }
+
while (!results.done) {
ret = nl_recvmsgs(socket, cb);
#if !defined TIZEN_WEARABLE
if (ret == -NLE_AGAIN && err >= 0)
continue;
#endif
- if (ret < 0 || err < 0) {
+ if (ret < 0) {
DBG("scan failed");
+ goto out;
+ }
+ if (err < 0) {
+ DBG("scan failed err: %d", err);
ret = -1;
goto out;
}
return 0;
}
-static int __netconfig_initialize_nl80211(netconfig_nl_global *global)
+static int __netconfig_netlink_scan(netconfig_nl_global *global, GSList *ssid_list, char *vsie)
+{
+ DBG("");
+ int ret = __netconfig_trigger_netlink_scan(global->socket, global->if_index, global->id, ssid_list, vsie);
+ if (ret == -NLE_AGAIN) {
+ DBG("Try Again");
+ ret = __netconfig_trigger_netlink_scan(global->socket, global->if_index, global->id, ssid_list, vsie);
+ }
+ return ret;
+}
+
+static int __netconfig_initialize_nl80211(netconfig_nl_global *global,
+ const char *interface_name)
{
int err = 0;
- global->if_index = __netconfig_get_interface_index(WIFI_IFNAME);
+ global->if_index = __netconfig_get_interface_index(interface_name);
if (global->if_index < 0) {
DBG("Failed to get interface index");
return -1;
return err;
}
+static void __netconfig_deinitialize_nl80211(netconfig_nl_global *global)
+{
+ if (global == NULL)
+ return;
+
+ if (global->socket) {
+ nl_socket_free(global->socket);
+ global->socket = NULL;
+ }
+}
+
static int __netconfig_initialize_nl_msg(netconfig_nl_global *global)
{
int rv;
return 0;
}
-int handle_netlink_scan(Wifi *wifi, GDBusMethodInvocation *context, GVariant *params)
+static void __netconfig_get_netlink_scan_parameters(GVariant *params, GSList *ssid_list, char **vsie)
+{
+ GVariantIter *iter;
+ GVariant *value;
+ gchar *key;
+ g_variant_get(params, "a{sv}", &iter);
+ while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
+ if (g_strcmp0(key, "SSID") == 0) {
+ if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
+ char *ssid = g_strdup(g_variant_get_string(value, NULL));
+ DBG("ssid [%s]", ssid);
+ ssid_list = g_slist_append(ssid_list, ssid);
+ }
+ } else if (g_strcmp0(key, "VSIE") == 0) {
+ if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING))
+ *vsie = g_strdup(g_variant_get_string(value, NULL));
+ }
+ }
+ g_variant_iter_free(iter);
+}
+
+static int __netconfig_get_scan_results(netconfig_nl_global *global)
+{
+ int ret = __netconfig_initialize_nl_msg(global);
+ if (ret < 0) {
+ DBG("__netconfig_initialize_nl_msg() failed, error %d", ret);
+ return ret;
+ }
+
+ ret = nl_send_auto_complete(global->socket, global->msg);
+ if (ret < 0) {
+ DBG("nl_send_auto_complete() failed, error %d", ret);
+ return ret;
+ }
+ DBG("NL80211_CMD_GET_SCAN sent %d bytes to the kernel", ret);
+
+ /** Receive the kernel message. */
+ ret = nl_recvmsgs_default(global->socket);
+ nlmsg_free(global->msg);
+ if (ret < 0) {
+ DBG("nl_recvmsgs_default() failed. ret: %d (error: %s)", ret, nl_geterror(-ret));
+ return ret;
+ }
+ return 0;
+}
+
+int handle_netlink_scan(Wifi *wifi, GDBusMethodInvocation *context,
+ const gchar *ifname, GVariant *params)
{
DBG("");
netconfig_nl_global global = {
};
/** Initialize netlink socket */
- int ret = __netconfig_initialize_nl80211(&global);
+ int ret = __netconfig_initialize_nl80211(&global, ifname);
if (ret < 0) {
DBG("__netconfig_initialize_nl80211() failed, error %d", ret);
netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AccessDenied");
- wifi_complete_netlink_scan(wifi, context);
return TRUE;
}
+ GSList *ssid_list = NULL;
+ char *vsie = NULL;
+ __netconfig_get_netlink_scan_parameters(params, ssid_list, &vsie);
/** Request NL80211_CMD_TRIGGER_SCAN to the kernel. */
- ret = __netconfig_request_netlink_scan(global.socket, global.if_index, global.id, params);
- if (ret < 0) {
- DBG("__netconfig_request_netlink_scan() failed, error %d", ret);
- netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AccessDenied");
- wifi_complete_netlink_scan(wifi, context);
- return TRUE;
- }
+ ret = __netconfig_netlink_scan(&global, ssid_list, vsie);
+ g_slist_free_full(ssid_list, g_free);
+ g_free(vsie);
- ret = __netconfig_initialize_nl_msg(&global);
if (ret < 0) {
- DBG("__netconfig_initialize_nl_msg() failed, error %d", ret);
+ DBG("__netconfig_netlink_scan() failed, error %d", ret);
netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AccessDenied");
- wifi_complete_netlink_scan(wifi, context);
+ __netconfig_deinitialize_nl80211(&global);
return TRUE;
}
- ret = nl_send_auto_complete(global.socket, global.msg);
- DBG("NL80211_CMD_GET_SCAN sent %d bytes to the kernel", ret);
-
- /** Receive the kernel message. */
- ret = nl_recvmsgs_default(global.socket);
- nlmsg_free(global.msg);
+ ret = __netconfig_get_scan_results(&global);
if (ret < 0) {
- DBG("nl_recvmsgs_default() failed. ret: %d (error: %s)", ret, nl_geterror(-ret));
netconfig_error_dbus_method_return(context, NETCONFIG_ERROR_INTERNAL, "AccessDenied");
- wifi_complete_netlink_scan(wifi, context);
+ __netconfig_deinitialize_nl80211(&global);
return TRUE;
}
wifi_complete_netlink_scan(wifi, context);
- __netconfig_notify_netlink_scan_done();
+ __netconfig_notify_netlink_scan_done(ifname);
+ __netconfig_deinitialize_nl80211(&global);
return TRUE;
}