X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=plugins%2Fsupplicant.c;h=69e79eb2261800a23f208c761752b33236c885f5;hb=6e84765a8dda6c0cb5f13fbaf7bdecf9016c8de4;hp=b5c96992806f4435dce0c4516ea5ea3d936fecb2;hpb=72ed7e7dd6a3b944c7edc35c407b719aa679fbca;p=connman diff --git a/plugins/supplicant.c b/plugins/supplicant.c index b5c9699..69e79eb 100644 --- a/plugins/supplicant.c +++ b/plugins/supplicant.c @@ -23,9 +23,11 @@ #include #endif +#include #include #include #include +#include #include @@ -145,7 +147,9 @@ enum supplicant_state { }; struct supplicant_result { - char *identifier; + char *path; + char *name; + char *addr; unsigned char *ssid; unsigned int ssid_len; dbus_uint16_t capabilities; @@ -153,6 +157,7 @@ struct supplicant_result { gboolean has_wep; gboolean has_wpa; gboolean has_rsn; + gboolean has_wps; dbus_int32_t quality; dbus_int32_t noise; dbus_int32_t level; @@ -274,6 +279,12 @@ static int add_interface(struct supplicant_task *task) return -EIO; } + if (call == NULL) { + connman_error("D-Bus connection not available"); + dbus_message_unref(message); + return -EIO; + } + dbus_pending_call_set_notify(call, add_interface_reply, task, NULL); dbus_message_unref(message); @@ -344,6 +355,12 @@ static int create_interface(struct supplicant_task *task) return -EIO; } + if (call == NULL) { + connman_error("D-Bus connection not available"); + dbus_message_unref(message); + return -EIO; + } + dbus_pending_call_set_notify(call, get_interface_reply, task, NULL); dbus_message_unref(message); @@ -362,6 +379,10 @@ static void remove_interface_reply(DBusPendingCall *call, void *user_data) connman_device_set_powered(task->device, FALSE); + connman_device_unref(task->device); + + inet_ifdown(task->ifindex); + free_task(task); dbus_message_unref(reply); @@ -394,6 +415,12 @@ static int remove_interface(struct supplicant_task *task) return -EIO; } + if (call == NULL) { + connman_error("D-Bus connection not available"); + dbus_message_unref(message); + return -EIO; + } + dbus_pending_call_set_notify(call, remove_interface_reply, task, NULL); dbus_message_unref(message); @@ -649,7 +676,8 @@ static int disable_network(struct supplicant_task *task) static int set_network(struct supplicant_task *task, const unsigned char *network, int len, - const char *security, const char *passphrase) + const char *address, const char *security, + const char *passphrase) { DBusMessage *message, *reply; DBusMessageIter array, dict; @@ -672,6 +700,14 @@ static int set_network(struct supplicant_task *task, DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + if (address == NULL) { + dbus_uint32_t scan_ssid = 1; + connman_dbus_dict_append_variant(&dict, "scan_ssid", + DBUS_TYPE_UINT32, &scan_ssid); + } else + connman_dbus_dict_append_variant(&dict, "bssid", + DBUS_TYPE_STRING, &address); + connman_dbus_dict_append_array(&dict, "ssid", DBUS_TYPE_BYTE, &network, len); @@ -767,6 +803,77 @@ static int initiate_scan(struct supplicant_task *task) return 0; } +static char *build_group(const char *addr, + const unsigned char *ssid, unsigned int ssid_len, + const char *mode, const char *security) +{ + GString *str; + unsigned int i; + + if (ssid_len > 0 && ssid[0] != '\0') { + str = g_string_sized_new((ssid_len * 2) + 24); + if (str == NULL) + return NULL; + + for (i = 0; i < ssid_len; i++) + g_string_append_printf(str, "%02x", ssid[i]); + } else { + if (addr == NULL) + return NULL; + + str = g_string_sized_new(15 + 24); + if (str == NULL) + return NULL; + + g_string_append_printf(str, "hidden_%s", addr); + } + + g_string_append_printf(str, "_%s_%s", mode, security); + + return g_string_free(str, FALSE); +} + +static void extract_addr(DBusMessageIter *value, + struct supplicant_result *result) +{ + DBusMessageIter array; + struct ether_addr *eth; + unsigned char *addr; + int addr_len; + + dbus_message_iter_recurse(value, &array); + dbus_message_iter_get_fixed_array(&array, &addr, &addr_len); + + if (addr_len != 6) + return; + + eth = (void *) addr; + + result->addr = g_try_malloc0(18); + if (result->addr == NULL) + return; + + snprintf(result->addr, 18, "%02X:%02X:%02X:%02X:%02X:%02X", + eth->ether_addr_octet[0], + eth->ether_addr_octet[1], + eth->ether_addr_octet[2], + eth->ether_addr_octet[3], + eth->ether_addr_octet[4], + eth->ether_addr_octet[5]); + + result->path = g_try_malloc0(18); + if (result->path == NULL) + return; + + snprintf(result->path, 18, "%02x%02x%02x%02x%02x%02x", + eth->ether_addr_octet[0], + eth->ether_addr_octet[1], + eth->ether_addr_octet[2], + eth->ether_addr_octet[3], + eth->ether_addr_octet[4], + eth->ether_addr_octet[5]); +} + static void extract_ssid(DBusMessageIter *value, struct supplicant_result *result) { @@ -780,6 +887,9 @@ static void extract_ssid(DBusMessageIter *value, if (ssid_len < 1) return; + if (ssid[0] == '\0') + return; + result->ssid = g_try_malloc(ssid_len); if (result->ssid == NULL) return; @@ -787,11 +897,11 @@ static void extract_ssid(DBusMessageIter *value, memcpy(result->ssid, ssid, ssid_len); result->ssid_len = ssid_len; - result->identifier = g_try_malloc0(ssid_len + 1); - if (result->identifier == NULL) + result->name = g_try_malloc0(ssid_len + 1); + if (result->name == NULL) return; - memcpy(result->identifier, ssid, ssid_len); + memcpy(result->name, ssid, ssid_len); } static void extract_wpaie(DBusMessageIter *value, @@ -822,6 +932,20 @@ static void extract_rsnie(DBusMessageIter *value, result->has_rsn = TRUE; } +static void extract_wpsie(DBusMessageIter *value, + struct supplicant_result *result) +{ + DBusMessageIter array; + unsigned char *ie; + int ie_len; + + dbus_message_iter_recurse(value, &array); + dbus_message_iter_get_fixed_array(&array, &ie, &ie_len); + + if (ie_len > 0) + result->has_wps = TRUE; +} + static void extract_capabilites(DBusMessageIter *value, struct supplicant_result *result) { @@ -845,8 +969,9 @@ static void properties_reply(DBusPendingCall *call, void *user_data) struct connman_network *network; DBusMessage *reply; DBusMessageIter array, dict; - char *security; unsigned char strength; + const char *mode, *security; + char *group; DBG("task %p", task); @@ -887,6 +1012,7 @@ static void properties_reply(DBusPendingCall *call, void *user_data) * ssid : a (97) * wpaie : a (97) * rsnie : a (97) + * wpsie : a (97) * frequency : i (105) * capabilities : q (113) * quality : i (105) @@ -895,12 +1021,16 @@ static void properties_reply(DBusPendingCall *call, void *user_data) * maxrate : i (105) */ - if (g_str_equal(key, "ssid") == TRUE) + if (g_str_equal(key, "bssid") == TRUE) + extract_addr(&value, &result); + else if (g_str_equal(key, "ssid") == TRUE) extract_ssid(&value, &result); else if (g_str_equal(key, "wpaie") == TRUE) extract_wpaie(&value, &result); else if (g_str_equal(key, "rsnie") == TRUE) extract_rsnie(&value, &result); + else if (g_str_equal(key, "wpsie") == TRUE) + extract_wpsie(&value, &result); else if (g_str_equal(key, "capabilities") == TRUE) extract_capabilites(&value, &result); else if (g_str_equal(key, "quality") == TRUE) @@ -915,10 +1045,10 @@ static void properties_reply(DBusPendingCall *call, void *user_data) dbus_message_iter_next(&dict); } - if (result.identifier == NULL) + if (result.path == NULL) goto done; - if (result.identifier[0] == '\0') + if (result.path[0] == '\0') goto done; strength = result.quality; @@ -932,12 +1062,16 @@ static void properties_reply(DBusPendingCall *call, void *user_data) else security = "none"; - network = connman_device_get_network(task->device, result.identifier); + mode = (result.adhoc == TRUE) ? "adhoc" : "managed"; + + group = build_group(result.path, result.ssid, result.ssid_len, + mode, security); + + network = connman_device_get_network(task->device, result.path); if (network == NULL) { - const char *mode; int index; - network = connman_network_create(result.identifier, + network = connman_network_create(result.path, CONNMAN_NETWORK_TYPE_WIFI); if (network == NULL) goto done; @@ -948,16 +1082,17 @@ static void properties_reply(DBusPendingCall *call, void *user_data) connman_network_set_protocol(network, CONNMAN_NETWORK_PROTOCOL_IP); - connman_network_set_string(network, "Name", result.identifier); + connman_network_set_string(network, "Address", result.addr); - connman_network_set_blob(network, "WiFi.SSID", - result.ssid, result.ssid_len); + connman_network_set_group(network, group); - mode = (result.adhoc == TRUE) ? "adhoc" : "managed"; - connman_network_set_string(network, "WiFi.Mode", mode); + if (result.name != NULL && result.name[0] != '\0') + connman_network_set_string(network, "Name", result.name); - DBG("%s (%s %s) strength %d", result.identifier, mode, - security, strength); + connman_network_set_uint8(network, "Strength", strength); + + connman_network_set_string(network, "WiFi.Mode", mode); + connman_network_set_string(network, "WiFi.Security", security); if (connman_device_add_network(task->device, network) < 0) { connman_network_unref(network); @@ -965,13 +1100,31 @@ static void properties_reply(DBusPendingCall *call, void *user_data) } } + connman_network_set_group(network, group); + + g_free(group); + + if (result.name != NULL && result.name[0] != '\0') + connman_network_set_string(network, "Name", result.name); + + connman_network_set_blob(network, "WiFi.SSID", + result.ssid, result.ssid_len); + + connman_network_set_string(network, "WiFi.Mode", mode); + + DBG("%s (%s %s) strength %d (%s)", + result.name, mode, security, strength, + (result.has_wps == TRUE) ? "WPS" : "no WPS"); + connman_network_set_available(network, TRUE); connman_network_set_uint8(network, "Strength", strength); connman_network_set_string(network, "WiFi.Security", security); done: - g_free(result.identifier); + g_free(result.path); + g_free(result.addr); + g_free(result.name); g_free(result.ssid); dbus_message_unref(reply); @@ -1006,6 +1159,12 @@ static void get_properties(struct supplicant_task *task) goto noscan; } + if (call == NULL) { + connman_error("D-Bus connection not available"); + dbus_message_unref(message); + goto noscan; + } + dbus_pending_call_set_notify(call, properties_reply, task, NULL); dbus_message_unref(message); @@ -1097,6 +1256,11 @@ static void scan_results_available(struct supplicant_task *task) if (task->noscan == FALSE) connman_device_set_scanning(task->device, TRUE); + if (call == NULL) { + connman_error("D-Bus connection not available"); + goto done; + } + dbus_pending_call_set_notify(call, scan_results_reply, task, NULL); done: @@ -1189,7 +1353,11 @@ static void state_change(struct supplicant_task *task, DBusMessage *msg) connman_network_set_connected(task->network, FALSE); connman_device_set_scanning(task->device, FALSE); break; + case WPA_ASSOCIATING: + connman_network_set_associating(task->network, TRUE); + break; default: + connman_network_set_associating(task->network, FALSE); break; } } @@ -1238,13 +1406,14 @@ int supplicant_start(struct connman_device *device) task->ifindex = connman_device_get_index(device); task->ifname = inet_index2name(task->ifindex); - task->device = device; if (task->ifname == NULL) { g_free(task); return -ENOMEM; } + task->device = connman_device_ref(device); + task->created = FALSE; task->noscan = FALSE; task->state = WPA_INVALID; @@ -1306,19 +1475,21 @@ int supplicant_scan(struct connman_device *device) int supplicant_connect(struct connman_network *network) { struct supplicant_task *task; - const char *security, *passphrase; + const char *address, *security, *passphrase; const void *ssid; unsigned int ssid_len; int index; DBG("network %p", network); + address = connman_network_get_string(network, "Address"); security = connman_network_get_string(network, "WiFi.Security"); passphrase = connman_network_get_string(network, "WiFi.Passphrase"); ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len); - DBG("security %s passphrase %s", security, passphrase); + DBG("address %s security %s passphrase %s", + address, security, passphrase); if (security == NULL && passphrase == NULL) return -EINVAL; @@ -1339,10 +1510,12 @@ int supplicant_connect(struct connman_network *network) select_network(task); disable_network(task); - set_network(task, ssid, ssid_len, security, passphrase); + set_network(task, ssid, ssid_len, address, security, passphrase); enable_network(task); + connman_network_set_associating(task->network, TRUE); + return 0; }