5 * Copyright (C) 2007-2009 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 #define CONNMAN_API_SUBJECT_TO_CHANGE
33 #include <connman/device.h>
34 #include <connman/dbus.h>
35 #include <connman/log.h>
38 #include "supplicant.h"
42 #define IEEE80211_CAP_ESS 0x0001
43 #define IEEE80211_CAP_IBSS 0x0002
44 #define IEEE80211_CAP_PRIVACY 0x0010
46 #define SUPPLICANT_NAME "fi.epitest.hostap.WPASupplicant"
47 #define SUPPLICANT_INTF "fi.epitest.hostap.WPASupplicant"
48 #define SUPPLICANT_PATH "/fi/epitest/hostap/WPASupplicant"
50 enum supplicant_state {
56 STATE_GROUP_HANDSHAKE,
61 struct supplicant_result {
64 unsigned int ssid_len;
65 dbus_uint16_t capabilities;
76 struct supplicant_task {
79 struct connman_device *device;
80 struct connman_network *network;
84 enum supplicant_state state;
89 static GSList *task_list = NULL;
91 static DBusConnection *connection;
93 static void free_task(struct supplicant_task *task)
102 static struct supplicant_task *find_task_by_index(int index)
106 for (list = task_list; list; list = list->next) {
107 struct supplicant_task *task = list->data;
109 if (task->ifindex == index)
116 static struct supplicant_task *find_task_by_path(const char *path)
120 for (list = task_list; list; list = list->next) {
121 struct supplicant_task *task = list->data;
123 if (g_str_equal(task->path, path) == TRUE)
130 static void add_interface_reply(DBusPendingCall *call, void *user_data)
132 struct supplicant_task *task = user_data;
137 DBG("task %p", task);
139 reply = dbus_pending_call_steal_reply(call);
143 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
146 dbus_error_init(&error);
148 if (dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &path,
149 DBUS_TYPE_INVALID) == FALSE) {
150 if (dbus_error_is_set(&error) == TRUE) {
151 connman_error("%s", error.message);
152 dbus_error_free(&error);
154 connman_error("Wrong arguments for add interface");
158 DBG("path %s", path);
160 task->path = g_strdup(path);
161 task->created = TRUE;
163 connman_device_set_powered(task->device, TRUE);
166 dbus_message_unref(reply);
169 static int add_interface(struct supplicant_task *task)
171 DBusMessage *message;
172 DBusPendingCall *call;
174 DBG("task %p", task);
176 message = dbus_message_new_method_call(SUPPLICANT_NAME, SUPPLICANT_PATH,
177 SUPPLICANT_INTF, "addInterface");
181 dbus_message_append_args(message, DBUS_TYPE_STRING, &task->ifname,
184 if (dbus_connection_send_with_reply(connection, message,
185 &call, TIMEOUT) == FALSE) {
186 connman_error("Failed to add interface");
187 dbus_message_unref(message);
191 dbus_pending_call_set_notify(call, add_interface_reply, task, NULL);
193 dbus_message_unref(message);
198 static void get_interface_reply(DBusPendingCall *call, void *user_data)
200 struct supplicant_task *task = user_data;
205 DBG("task %p", task);
207 reply = dbus_pending_call_steal_reply(call);
211 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
216 dbus_error_init(&error);
218 if (dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &path,
219 DBUS_TYPE_INVALID) == FALSE) {
220 if (dbus_error_is_set(&error) == TRUE) {
221 connman_error("%s", error.message);
222 dbus_error_free(&error);
224 connman_error("Wrong arguments for get interface");
228 DBG("path %s", path);
230 task->path = g_strdup(path);
231 task->created = FALSE;
233 connman_device_set_powered(task->device, TRUE);
236 dbus_message_unref(reply);
239 static int create_interface(struct supplicant_task *task)
241 DBusMessage *message;
242 DBusPendingCall *call;
244 DBG("task %p", task);
246 message = dbus_message_new_method_call(SUPPLICANT_NAME, SUPPLICANT_PATH,
247 SUPPLICANT_INTF, "getInterface");
251 dbus_message_append_args(message, DBUS_TYPE_STRING, &task->ifname,
254 if (dbus_connection_send_with_reply(connection, message,
255 &call, TIMEOUT) == FALSE) {
256 connman_error("Failed to get interface");
257 dbus_message_unref(message);
261 dbus_pending_call_set_notify(call, get_interface_reply, task, NULL);
263 dbus_message_unref(message);
268 static void remove_interface_reply(DBusPendingCall *call, void *user_data)
270 struct supplicant_task *task = user_data;
273 DBG("task %p", task);
275 reply = dbus_pending_call_steal_reply(call);
277 connman_device_set_powered(task->device, FALSE);
281 dbus_message_unref(reply);
284 static int remove_interface(struct supplicant_task *task)
286 DBusMessage *message;
287 DBusPendingCall *call;
289 DBG("task %p", task);
291 if (task->created == FALSE) {
292 connman_device_set_powered(task->device, FALSE);
296 message = dbus_message_new_method_call(SUPPLICANT_NAME, SUPPLICANT_PATH,
297 SUPPLICANT_INTF, "removeInterface");
301 dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &task->path,
304 if (dbus_connection_send_with_reply(connection, message,
305 &call, TIMEOUT) == FALSE) {
306 connman_error("Failed to remove interface");
307 dbus_message_unref(message);
311 dbus_pending_call_set_notify(call, remove_interface_reply, task, NULL);
313 dbus_message_unref(message);
319 static int set_ap_scan(struct supplicant_task *task)
321 DBusMessage *message, *reply;
325 DBG("task %p", task);
327 message = dbus_message_new_method_call(SUPPLICANT_NAME, task->path,
328 SUPPLICANT_INTF ".Interface", "setAPScan");
332 dbus_message_append_args(message, DBUS_TYPE_UINT32, &ap_scan,
335 dbus_error_init(&error);
337 reply = dbus_connection_send_with_reply_and_block(connection,
338 message, -1, &error);
340 if (dbus_error_is_set(&error) == TRUE) {
341 connman_error("%s", error.message);
342 dbus_error_free(&error);
344 connman_error("Failed to set AP scan");
345 dbus_message_unref(message);
349 dbus_message_unref(message);
351 dbus_message_unref(reply);
357 static int add_network(struct supplicant_task *task)
359 DBusMessage *message, *reply;
363 DBG("task %p", task);
365 if (task->netpath != NULL)
368 message = dbus_message_new_method_call(SUPPLICANT_NAME, task->path,
369 SUPPLICANT_INTF ".Interface", "addNetwork");
373 dbus_error_init(&error);
375 reply = dbus_connection_send_with_reply_and_block(connection,
376 message, -1, &error);
378 if (dbus_error_is_set(&error) == TRUE) {
379 connman_error("%s", error.message);
380 dbus_error_free(&error);
382 connman_error("Failed to add network");
383 dbus_message_unref(message);
387 dbus_message_unref(message);
389 dbus_error_init(&error);
391 if (dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &path,
392 DBUS_TYPE_INVALID) == FALSE) {
393 if (dbus_error_is_set(&error) == TRUE) {
394 connman_error("%s", error.message);
395 dbus_error_free(&error);
397 connman_error("Wrong arguments for network");
398 dbus_message_unref(reply);
402 DBG("path %s", path);
404 task->netpath = g_strdup(path);
406 dbus_message_unref(reply);
411 static int remove_network(struct supplicant_task *task)
413 DBusMessage *message, *reply;
416 DBG("task %p", task);
418 if (task->netpath == NULL)
421 message = dbus_message_new_method_call(SUPPLICANT_NAME, task->path,
422 SUPPLICANT_INTF ".Interface", "removeNetwork");
426 dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &task->netpath,
429 dbus_error_init(&error);
431 reply = dbus_connection_send_with_reply_and_block(connection,
432 message, -1, &error);
434 if (dbus_error_is_set(&error) == TRUE) {
435 connman_error("%s", error.message);
436 dbus_error_free(&error);
438 connman_error("Failed to remove network");
439 dbus_message_unref(message);
443 dbus_message_unref(message);
445 dbus_message_unref(reply);
447 g_free(task->netpath);
448 task->netpath = NULL;
453 static int select_network(struct supplicant_task *task)
455 DBusMessage *message, *reply;
458 DBG("task %p", task);
460 if (task->netpath == NULL)
463 message = dbus_message_new_method_call(SUPPLICANT_NAME, task->path,
464 SUPPLICANT_INTF ".Interface", "selectNetwork");
468 dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &task->netpath,
471 dbus_error_init(&error);
473 reply = dbus_connection_send_with_reply_and_block(connection,
474 message, -1, &error);
476 if (dbus_error_is_set(&error) == TRUE) {
477 connman_error("%s", error.message);
478 dbus_error_free(&error);
480 connman_error("Failed to select network");
481 dbus_message_unref(message);
485 dbus_message_unref(message);
487 dbus_message_unref(reply);
492 static int enable_network(struct supplicant_task *task)
494 DBusMessage *message, *reply;
497 DBG("task %p", task);
499 if (task->netpath == NULL)
502 message = dbus_message_new_method_call(SUPPLICANT_NAME, task->netpath,
503 SUPPLICANT_INTF ".Network", "enable");
507 dbus_error_init(&error);
509 reply = dbus_connection_send_with_reply_and_block(connection,
510 message, -1, &error);
512 if (dbus_error_is_set(&error) == TRUE) {
513 connman_error("%s", error.message);
514 dbus_error_free(&error);
516 connman_error("Failed to enable network");
517 dbus_message_unref(message);
521 dbus_message_unref(message);
523 dbus_message_unref(reply);
528 static int disable_network(struct supplicant_task *task)
530 DBusMessage *message, *reply;
533 DBG("task %p", task);
535 if (task->netpath == NULL)
538 message = dbus_message_new_method_call(SUPPLICANT_NAME, task->netpath,
539 SUPPLICANT_INTF ".Network", "disable");
543 dbus_error_init(&error);
545 reply = dbus_connection_send_with_reply_and_block(connection,
546 message, -1, &error);
548 if (dbus_error_is_set(&error) == TRUE) {
549 connman_error("%s", error.message);
550 dbus_error_free(&error);
552 connman_error("Failed to disable network");
553 dbus_message_unref(message);
557 dbus_message_unref(message);
559 dbus_message_unref(reply);
564 static int set_network(struct supplicant_task *task,
565 const unsigned char *network, int len,
566 const char *security, const char *passphrase)
568 DBusMessage *message, *reply;
569 DBusMessageIter array, dict;
572 DBG("task %p", task);
574 if (task->netpath == NULL)
577 message = dbus_message_new_method_call(SUPPLICANT_NAME, task->netpath,
578 SUPPLICANT_INTF ".Network", "set");
582 dbus_message_iter_init_append(message, &array);
584 dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
585 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
586 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
587 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
589 connman_dbus_dict_append_array(&dict, "ssid",
590 DBUS_TYPE_BYTE, &network, len);
592 if (g_ascii_strcasecmp(security, "wpa") == 0 ||
593 g_ascii_strcasecmp(security, "wpa2") == 0) {
594 const char *key_mgmt = "WPA-PSK";
595 connman_dbus_dict_append_variant(&dict, "key_mgmt",
596 DBUS_TYPE_STRING, &key_mgmt);
598 if (passphrase && strlen(passphrase) > 0)
599 connman_dbus_dict_append_variant(&dict, "psk",
600 DBUS_TYPE_STRING, &passphrase);
601 } else if (g_ascii_strcasecmp(security, "wep") == 0) {
602 const char *key_mgmt = "NONE", *index = "0";
603 connman_dbus_dict_append_variant(&dict, "key_mgmt",
604 DBUS_TYPE_STRING, &key_mgmt);
607 int size = strlen(passphrase);
608 if (size == 10 || size == 26) {
609 unsigned char *key = malloc(13);
612 memset(tmp, 0, sizeof(tmp));
615 for (i = 0; i < size / 2; i++) {
616 memcpy(tmp, passphrase + (i * 2), 2);
617 key[i] = (unsigned char) strtol(tmp,
620 connman_dbus_dict_append_array(&dict,
621 "wep_key0", DBUS_TYPE_BYTE,
625 connman_dbus_dict_append_variant(&dict,
626 "wep_key0", DBUS_TYPE_STRING,
628 connman_dbus_dict_append_variant(&dict, "wep_tx_keyidx",
629 DBUS_TYPE_STRING, &index);
632 const char *key_mgmt = "NONE";
633 connman_dbus_dict_append_variant(&dict, "key_mgmt",
634 DBUS_TYPE_STRING, &key_mgmt);
637 dbus_message_iter_close_container(&array, &dict);
639 dbus_error_init(&error);
641 reply = dbus_connection_send_with_reply_and_block(connection,
642 message, -1, &error);
644 if (dbus_error_is_set(&error) == TRUE) {
645 connman_error("%s", error.message);
646 dbus_error_free(&error);
648 connman_error("Failed to set network options");
649 dbus_message_unref(message);
653 dbus_message_unref(message);
655 dbus_message_unref(reply);
660 static int initiate_scan(struct supplicant_task *task)
662 DBusMessage *message;
663 DBusPendingCall *call;
665 DBG("task %p", task);
667 message = dbus_message_new_method_call(SUPPLICANT_NAME, task->path,
668 SUPPLICANT_INTF ".Interface", "scan");
672 if (dbus_connection_send_with_reply(connection, message,
673 &call, TIMEOUT) == FALSE) {
674 connman_error("Failed to initiate scan");
675 dbus_message_unref(message);
679 dbus_message_unref(message);
684 static void extract_ssid(DBusMessageIter *value,
685 struct supplicant_result *result)
687 DBusMessageIter array;
691 dbus_message_iter_recurse(value, &array);
692 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
697 result->ssid = g_try_malloc(ssid_len);
698 if (result->ssid == NULL)
701 memcpy(result->ssid, ssid, ssid_len);
702 result->ssid_len = ssid_len;
704 result->identifier = g_try_malloc0(ssid_len + 1);
705 if (result->identifier == NULL)
708 memcpy(result->identifier, ssid, ssid_len);
711 static void extract_wpaie(DBusMessageIter *value,
712 struct supplicant_result *result)
714 DBusMessageIter array;
718 dbus_message_iter_recurse(value, &array);
719 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
722 result->has_wpa = TRUE;
725 static void extract_rsnie(DBusMessageIter *value,
726 struct supplicant_result *result)
728 DBusMessageIter array;
732 dbus_message_iter_recurse(value, &array);
733 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
736 result->has_rsn = TRUE;
739 static void extract_capabilites(DBusMessageIter *value,
740 struct supplicant_result *result)
742 dbus_message_iter_get_basic(value, &result->capabilities);
744 if (result->capabilities & IEEE80211_CAP_ESS)
745 result->adhoc = FALSE;
746 else if (result->capabilities & IEEE80211_CAP_IBSS)
747 result->adhoc = TRUE;
749 if (result->capabilities & IEEE80211_CAP_PRIVACY)
750 result->has_wep = TRUE;
753 static int get_properties(struct supplicant_task *task);
755 static void properties_reply(DBusPendingCall *call, void *user_data)
757 struct supplicant_task *task = user_data;
758 struct supplicant_result result;
759 struct connman_network *network;
761 DBusMessageIter array, dict;
762 char *security, *temp = NULL;
763 unsigned char strength;
766 DBG("task %p", task);
768 reply = dbus_pending_call_steal_reply(call);
770 get_properties(task);
774 memset(&result, 0, sizeof(result));
776 dbus_message_iter_init(reply, &array);
778 dbus_message_iter_recurse(&array, &dict);
780 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
781 DBusMessageIter entry, value;
784 dbus_message_iter_recurse(&dict, &entry);
785 dbus_message_iter_get_basic(&entry, &key);
787 dbus_message_iter_next(&entry);
789 dbus_message_iter_recurse(&entry, &value);
791 //type = dbus_message_iter_get_arg_type(&value);
792 //dbus_message_iter_get_basic(&value, &val);
799 * frequency : i (105)
800 * capabilities : q (113)
807 if (g_str_equal(key, "ssid") == TRUE)
808 extract_ssid(&value, &result);
809 else if (g_str_equal(key, "wpaie") == TRUE)
810 extract_wpaie(&value, &result);
811 else if (g_str_equal(key, "rsnie") == TRUE)
812 extract_rsnie(&value, &result);
813 else if (g_str_equal(key, "capabilities") == TRUE)
814 extract_capabilites(&value, &result);
815 else if (g_str_equal(key, "quality") == TRUE)
816 dbus_message_iter_get_basic(&value, &result.quality);
817 else if (g_str_equal(key, "noise") == TRUE)
818 dbus_message_iter_get_basic(&value, &result.noise);
819 else if (g_str_equal(key, "level") == TRUE)
820 dbus_message_iter_get_basic(&value, &result.level);
821 else if (g_str_equal(key, "maxrate") == TRUE)
822 dbus_message_iter_get_basic(&value, &result.maxrate);
824 dbus_message_iter_next(&dict);
827 if (result.identifier == NULL)
830 if (result.identifier[0] == '\0')
833 temp = g_strdup(result.identifier);
837 for (i = 0; i < strlen(temp); i++) {
839 if ((tmp < '0' || tmp > '9') && (tmp < 'A' || tmp > 'Z') &&
840 (tmp < 'a' || tmp > 'z'))
844 strength = result.quality;
846 if (result.has_rsn == TRUE)
848 else if (result.has_wpa == TRUE)
850 else if (result.has_wep == TRUE)
855 network = connman_device_get_network(task->device, temp);
856 if (network == NULL) {
860 network = connman_network_create(temp,
861 CONNMAN_NETWORK_TYPE_WIFI);
865 index = connman_device_get_index(task->device);
866 connman_network_set_index(network, index);
868 connman_network_set_protocol(network,
869 CONNMAN_NETWORK_PROTOCOL_IP);
871 connman_network_set_string(network, "Name", result.identifier);
873 connman_network_set_blob(network, "WiFi.SSID",
874 result.ssid, result.ssid_len);
876 mode = (result.adhoc == TRUE) ? "adhoc" : "managed";
877 connman_network_set_string(network, "WiFi.Mode", mode);
879 DBG("%s (%s %s) strength %d", result.identifier, mode,
882 if (connman_device_add_network(task->device, network) < 0) {
883 connman_network_unref(network);
888 connman_network_set_uint8(network, "Strength", strength);
890 connman_network_set_string(network, "WiFi.Security", security);
893 g_free(result.identifier);
897 dbus_message_unref(reply);
899 get_properties(task);
902 static int get_properties(struct supplicant_task *task)
904 DBusMessage *message;
905 DBusPendingCall *call;
908 path = g_slist_nth_data(task->scan_results, 0);
910 if (task->doscan == FALSE)
911 connman_device_set_scanning(task->device, FALSE);
915 message = dbus_message_new_method_call(SUPPLICANT_NAME, path,
916 SUPPLICANT_INTF ".BSSID",
919 task->scan_results = g_slist_remove(task->scan_results, path);
925 if (dbus_connection_send_with_reply(connection, message,
926 &call, TIMEOUT) == FALSE) {
927 connman_error("Failed to get network properties");
928 dbus_message_unref(message);
932 dbus_pending_call_set_notify(call, properties_reply, task, NULL);
934 dbus_message_unref(message);
939 static void scan_results_reply(DBusPendingCall *call, void *user_data)
941 struct supplicant_task *task = user_data;
947 DBG("task %p", task);
949 reply = dbus_pending_call_steal_reply(call);
951 if (task->doscan == FALSE)
952 connman_device_set_scanning(task->device, FALSE);
956 dbus_error_init(&error);
958 if (dbus_message_get_args(reply, &error,
959 DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH,
960 &results, &num_results,
961 DBUS_TYPE_INVALID) == FALSE) {
962 if (dbus_error_is_set(&error) == TRUE) {
963 connman_error("%s", error.message);
964 dbus_error_free(&error);
966 connman_error("Wrong arguments for scan result");
967 if (task->doscan == FALSE)
968 connman_device_set_scanning(task->device, FALSE);
972 for (i = 0; i < num_results; i++) {
973 char *path = g_strdup(results[i]);
977 task->scan_results = g_slist_append(task->scan_results, path);
982 get_properties(task);
985 dbus_message_unref(reply);
988 static int scan_results_available(struct supplicant_task *task)
990 DBusMessage *message;
991 DBusPendingCall *call;
993 DBG("task %p", task);
995 message = dbus_message_new_method_call(SUPPLICANT_NAME, task->path,
996 SUPPLICANT_INTF ".Interface",
1001 if (dbus_connection_send_with_reply(connection, message,
1002 &call, TIMEOUT) == FALSE) {
1003 connman_error("Failed to request scan result");
1004 dbus_message_unref(message);
1008 connman_device_set_scanning(task->device, TRUE);
1010 dbus_pending_call_set_notify(call, scan_results_reply, task, NULL);
1012 dbus_message_unref(message);
1017 static void state_change(struct supplicant_task *task, DBusMessage *msg)
1020 const char *state, *previous;
1022 dbus_error_init(&error);
1024 if (dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &state,
1025 DBUS_TYPE_STRING, &previous,
1026 DBUS_TYPE_INVALID) == FALSE) {
1027 if (dbus_error_is_set(&error) == TRUE) {
1028 connman_error("%s", error.message);
1029 dbus_error_free(&error);
1031 connman_error("Wrong arguments for state change");
1035 DBG("state %s ==> %s", previous, state);
1037 if (g_str_equal(state, "INACTIVE") == TRUE)
1038 task->state = STATE_INACTIVE;
1039 else if (g_str_equal(state, "SCANNING") == TRUE)
1040 task->state = STATE_SCANNING;
1041 else if (g_str_equal(state, "ASSOCIATING") == TRUE)
1042 task->state = STATE_ASSOCIATING;
1043 else if (g_str_equal(state, "ASSOCIATED") == TRUE)
1044 task->state = STATE_ASSOCIATED;
1045 else if (g_str_equal(state, "GROUP_HANDSHAKE") == TRUE)
1046 task->state = STATE_GROUP_HANDSHAKE;
1047 else if (g_str_equal(state, "4WAY_HANDSHAKE") == TRUE)
1048 task->state = STATE_4WAY_HANDSHAKE;
1049 else if (g_str_equal(state, "COMPLETED") == TRUE)
1050 task->state = STATE_COMPLETED;
1051 else if (g_str_equal(state, "DISCONNECTED") == TRUE)
1052 task->state = STATE_DISCONNECTED;
1054 if (task->state == STATE_SCANNING) {
1055 task->doscan = TRUE;
1056 connman_device_set_scanning(task->device, TRUE);
1057 } else if (task->state == STATE_INACTIVE) {
1058 task->doscan = FALSE;
1059 connman_device_set_scanning(task->device, FALSE);
1062 if (task->network == NULL)
1065 switch (task->state) {
1066 case STATE_COMPLETED:
1068 connman_network_set_connected(task->network, TRUE);
1070 case STATE_DISCONNECTED:
1072 connman_network_set_connected(task->network, FALSE);
1079 static DBusHandlerResult supplicant_filter(DBusConnection *conn,
1080 DBusMessage *msg, void *data)
1082 struct supplicant_task *task;
1083 const char *member, *path;
1085 if (dbus_message_has_interface(msg,
1086 SUPPLICANT_INTF ".Interface") == FALSE)
1087 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1089 member = dbus_message_get_member(msg);
1091 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1093 path = dbus_message_get_path(msg);
1095 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1097 task = find_task_by_path(path);
1099 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1101 DBG("task %p member %s", task, member);
1103 if (g_str_equal(member, "ScanResultsAvailable") == TRUE)
1104 scan_results_available(task);
1105 else if (g_str_equal(member, "StateChange") == TRUE)
1106 state_change(task, msg);
1108 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1111 int supplicant_start(struct connman_device *device)
1113 struct supplicant_task *task;
1115 DBG("device %p", device);
1117 task = g_try_new0(struct supplicant_task, 1);
1121 task->ifindex = connman_device_get_index(device);
1122 task->ifname = inet_index2name(task->ifindex);
1123 task->device = device;
1125 if (task->ifname == NULL) {
1130 task->created = FALSE;
1131 task->state = STATE_INACTIVE;
1133 task_list = g_slist_append(task_list, task);
1135 return create_interface(task);
1138 int supplicant_stop(struct connman_device *device)
1140 int index = connman_device_get_index(device);
1141 struct supplicant_task *task;
1143 DBG("device %p", device);
1145 task = find_task_by_index(index);
1149 task_list = g_slist_remove(task_list, task);
1151 disable_network(task);
1153 remove_network(task);
1155 return remove_interface(task);
1158 int supplicant_scan(struct connman_device *device)
1160 int index = connman_device_get_index(device);
1161 struct supplicant_task *task;
1164 DBG("device %p", device);
1166 task = find_task_by_index(index);
1170 switch (task->state) {
1171 case STATE_SCANNING:
1173 case STATE_ASSOCIATING:
1174 case STATE_ASSOCIATED:
1175 case STATE_4WAY_HANDSHAKE:
1176 case STATE_GROUP_HANDSHAKE:
1182 err = initiate_scan(task);
1187 int supplicant_connect(struct connman_network *network)
1189 struct supplicant_task *task;
1190 const char *security, *passphrase;
1192 unsigned int ssid_len;
1195 DBG("network %p", network);
1197 security = connman_network_get_string(network, "WiFi.Security");
1198 passphrase = connman_network_get_string(network, "WiFi.Passphrase");
1200 ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len);
1202 DBG("security %s passphrase %s", security, passphrase);
1204 if (security == NULL && passphrase == NULL)
1207 if (g_str_equal(security, "none") == FALSE && passphrase == NULL)
1210 index = connman_network_get_index(network);
1212 task = find_task_by_index(index);
1216 task->network = connman_network_ref(network);
1220 select_network(task);
1221 disable_network(task);
1223 set_network(task, ssid, ssid_len, security, passphrase);
1225 enable_network(task);
1230 int supplicant_disconnect(struct connman_network *network)
1232 struct supplicant_task *task;
1235 DBG("network %p", network);
1237 index = connman_network_get_index(network);
1239 task = find_task_by_index(index);
1243 disable_network(task);
1245 remove_network(task);
1247 connman_network_unref(task->network);
1252 static void supplicant_activate(DBusConnection *conn)
1254 DBusMessage *message;
1256 DBG("conn %p", conn);
1258 message = dbus_message_new_method_call(SUPPLICANT_NAME, "/",
1259 DBUS_INTERFACE_INTROSPECTABLE, "Introspect");
1260 if (message == NULL)
1263 dbus_message_set_no_reply(message, TRUE);
1265 dbus_connection_send(conn, message, NULL);
1267 dbus_message_unref(message);
1270 static GSList *driver_list = NULL;
1272 static void supplicant_probe(DBusConnection *conn, void *user_data)
1276 DBG("conn %p", conn);
1278 for (list = driver_list; list; list = list->next) {
1279 struct supplicant_driver *driver = list->data;
1281 DBG("driver %p name %s", driver, driver->name);
1288 static void supplicant_remove(DBusConnection *conn, void *user_data)
1292 DBG("conn %p", conn);
1294 for (list = driver_list; list; list = list->next) {
1295 struct supplicant_driver *driver = list->data;
1297 DBG("driver %p name %s", driver, driver->name);
1304 static const char *supplicant_rule = "type=signal,"
1305 "interface=" SUPPLICANT_INTF ".Interface";
1308 static int supplicant_create(void)
1310 if (g_slist_length(driver_list) > 0)
1313 connection = connman_dbus_get_connection();
1314 if (connection == NULL)
1317 DBG("connection %p", connection);
1319 if (dbus_connection_add_filter(connection,
1320 supplicant_filter, NULL, NULL) == FALSE) {
1321 connection = connman_dbus_get_connection();
1325 dbus_bus_add_match(connection, supplicant_rule, NULL);
1326 dbus_connection_flush(connection);
1328 watch = g_dbus_add_service_watch(connection, SUPPLICANT_NAME,
1329 supplicant_probe, supplicant_remove, NULL, NULL);
1334 static void supplicant_destroy(void)
1336 if (g_slist_length(driver_list) > 0)
1339 DBG("connection %p", connection);
1342 g_dbus_remove_watch(connection, watch);
1344 dbus_bus_remove_match(connection, supplicant_rule, NULL);
1345 dbus_connection_flush(connection);
1347 dbus_connection_remove_filter(connection, supplicant_filter, NULL);
1349 dbus_connection_unref(connection);
1353 int supplicant_register(struct supplicant_driver *driver)
1357 DBG("driver %p name %s", driver, driver->name);
1359 err = supplicant_create();
1363 driver_list = g_slist_append(driver_list, driver);
1365 if (g_dbus_check_service(connection, SUPPLICANT_NAME) == TRUE)
1366 supplicant_probe(connection, NULL);
1368 supplicant_activate(connection);
1373 void supplicant_unregister(struct supplicant_driver *driver)
1375 DBG("driver %p name %s", driver, driver->name);
1377 supplicant_remove(connection, NULL);
1379 driver_list = g_slist_remove(driver_list, driver);
1381 supplicant_destroy();