00001
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <glib.h>
00030 #include <net/ethernet.h>
00031 #include <linux/socket.h>
00032 #include <gconf/gconf-client.h>
00033 #include <osso-ic-dbus.h>
00034 #include <syslog.h>
00035
00036 #define DBUS_API_SUBJECT_TO_CHANGE
00037 #include <dbus/dbus.h>
00038 #include <eap-dbus.h>
00039 #include <wlancond-dbus.h>
00040 #ifdef USE_MCE_MODE
00041 #include <mce/dbus-names.h>
00042 #endif
00043 #include "log.h"
00044 #include "dbus.h"
00045 #include "dbus-helper.h"
00046 #include "dbus-handler.h"
00047 #include "common.h"
00048 #include "wpa.h"
00049
00050 #define WLANCOND_SHUTDOWN_DELAY 4 //4s
00051 #define WLANCOND_CONNECT_TIMEOUT 10 //10s
00052 #define WLANCOND_SCAN_TIMEOUT 8 //8s
00053 #define WLANCOND_RESCAN_DELAY 1
00054
00055
00056 static char *scan_name_cache = NULL;
00057 static char *connect_name_cache = NULL;
00058
00059 static int wlan_socket = -1;
00060
00061 struct wlan_status_t wlan_status;
00062
00063 static gboolean _flight_mode = FALSE;
00064 static gboolean power_down_after_scan = FALSE;
00065 static dbus_bool_t saved_inactivity = FALSE;
00066 static dbus_bool_t saved_bt_power = FALSE;
00067
00068
00069 static guint wlan_if_down_timer_id = 0;
00070 static guint wlan_connect_timer_id = 0;
00071
00072
00073 static guint powersave = WLANCOND_SHORT_CAM;
00074
00075
00076 static gint debug_level = 0;
00077
00078 #define WLAN_PREFIX_STR "wlan"
00079
00082 void wlancond_print(guint priority, const char *debug, ...) {
00083 va_list args;
00084 char buffer[200];
00085
00086 switch (debug_level) {
00087
00088 case 0:
00089 if (priority > WLANCOND_PRIO_MEDIUM) {
00090 va_start(args, debug);
00091 vsnprintf(buffer, sizeof(buffer), debug, args);
00092 va_end(args);
00093
00094 syslog(LOG_INFO | LOG_DAEMON, "%s", buffer);
00095 return;
00096 }
00097 break;
00098 case 1:
00099 if (priority > WLANCOND_PRIO_LOW) {
00100 va_start(args, debug);
00101 vsnprintf(buffer, sizeof(buffer), debug, args);
00102 va_end(args);
00103
00104 syslog(LOG_INFO | LOG_DAEMON, "%s", buffer);
00105 return;
00106 }
00107 break;
00108
00109 default:
00110 va_start(args, debug);
00111 vsnprintf(buffer, sizeof(buffer), debug, args);
00112 va_end(args);
00113
00114 syslog(LOG_INFO | LOG_DAEMON, "%s", buffer);
00115 return;
00116 }
00117 }
00121 int socket_open(void)
00122 {
00123 if (wlan_socket > 0)
00124 return wlan_socket;
00125
00126 wlan_socket = socket(AF_INET, SOCK_DGRAM, 0);
00127
00128 if (wlan_socket < 0)
00129 die("socket() failed");
00130
00131 return wlan_socket;
00132 }
00136 void init_iwreq(struct iwreq* req)
00137 {
00138 memset(req, 0, sizeof(struct iwreq));
00139 strncpy(req->ifr_name, wlan_status.ifname, IFNAMSIZ);
00140 }
00144 static int get_own_mac(void)
00145 {
00146 struct ifreq req;
00147
00148 memset(&req , 0, sizeof(req));
00149 memcpy(req.ifr_name, wlan_status.ifname, IFNAMSIZ);
00150
00151 if (ioctl(socket_open(), SIOCGIFHWADDR, &req) < 0)
00152 {
00153 return -1;
00154 }
00155
00156 memcpy(wlan_status.own_mac, req.ifr_hwaddr.sa_data, ETH_ALEN);
00157
00158 return 0;
00159 }
00160
00166 static gint get_gconf_int(const gchar* path)
00167 {
00168 GConfClient *client;
00169 GConfValue *gconf_value;
00170 GError *error = NULL;
00171 gint value = -1;
00172
00173 client = gconf_client_get_default();
00174 if (client == NULL) {
00175 return -1;
00176 }
00177
00178 gconf_value = gconf_client_get(client, path, &error);
00179
00180 g_object_unref(client);
00181
00182 if (error != NULL) {
00183 DLOG_ERR("Could not get setting:%s, error:%s", path,
00184 error->message);
00185
00186 g_clear_error(&error);
00187 return -1;
00188 }
00189
00190 if (gconf_value == NULL) {
00191 return -1;
00192 }
00193 if (gconf_value->type == GCONF_VALUE_INT) {
00194 value = gconf_value_get_int(gconf_value);
00195 DLOG_DEBUG("User selected value: %d", value);
00196 }
00197
00198 gconf_value_free(gconf_value);
00199 return value;
00200 }
00201
00208 static gboolean get_setting_bool(const gchar* path, gboolean *error)
00209 {
00210 gboolean value = FALSE;
00211 GConfClient *client;
00212 GConfValue *gconf_value;
00213 GError *g_error = NULL;
00214
00215 *error = TRUE;
00216
00217 client = gconf_client_get_default();
00218 if (client == NULL) {
00219 return value;
00220 }
00221
00222 gconf_value = gconf_client_get(client, path, &g_error);
00223
00224 g_object_unref(client);
00225
00226 if (g_error != NULL) {
00227 DLOG_ERR("Could not get setting:%s, error:%s", path,
00228 g_error->message);
00229
00230 g_clear_error(&g_error);
00231 return value;
00232 }
00233
00234 if (gconf_value == NULL) {
00235 return value;
00236 }
00237 if (gconf_value->type == GCONF_VALUE_BOOL) {
00238 value = gconf_value_get_bool(gconf_value);
00239 DLOG_DEBUG("User selected value: %d for %s", value, path);
00240 *error = FALSE;
00241 }
00242
00243 gconf_value_free(gconf_value);
00244
00245 return value;
00246 }
00247
00251 void init_logging(void) {
00252 debug_level = get_gconf_int(DEBUG_LEVEL);
00253 if (debug_level < 0)
00254 debug_level = 0;
00255
00256 if (debug_level > 0) {
00257 DLOG_DEBUG("Debug level increased to %d", debug_level);
00258 }
00259 }
00260
00266 void update_own_ie(unsigned char* wpa_ie, guint wpa_ie_len)
00267 {
00268 g_free(wlan_status.wpa_ie.ie);
00269 wlan_status.wpa_ie.ie = wpa_ie;
00270 wlan_status.wpa_ie.ie_len = wpa_ie_len;
00271 }
00276 guint get_encryption_info(void)
00277 {
00278 guint auth_status = 0;
00279
00280 if (wlan_status.pairwise_cipher & CIPHER_SUITE_CCMP) {
00281 auth_status |= WLANCOND_WPA_AES;
00282 } else if (wlan_status.pairwise_cipher & CIPHER_SUITE_TKIP) {
00283 auth_status |= WLANCOND_WPA_TKIP;
00284 } else if (wlan_status.pairwise_cipher & CIPHER_SUITE_WEP40 ||
00285 wlan_status.pairwise_cipher & CIPHER_SUITE_WEP104) {
00286 auth_status |= WLANCOND_WEP;
00287 } else {
00288 auth_status |= WLANCOND_OPEN;
00289 }
00290 return auth_status;
00291 }
00292
00296 int clean_dbus_handler(void)
00297 {
00298 if (wlan_socket > 0)
00299 close(wlan_socket);
00300
00301 return 0;
00302 }
00307 void mode_change(const char *mode) {
00308
00309 DLOG_INFO("WLAN flight mode changed to \"%s\"", mode);
00310
00311 if (g_str_equal(mode, "flight")) {
00312 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
00313 FORCE_YES);
00314 _flight_mode = TRUE;
00315 }
00316 else if (g_str_equal(mode, "normal")) {
00317 _flight_mode = FALSE;
00318 }
00319 else {
00320 DLOG_ERR("Invalid mode \"%s\" passed to mode_change()", mode);
00321 }
00322 }
00327 #ifdef USE_MCE_MODE
00328 static DBusHandlerResult mode_change_dbus(DBusMessage *message) {
00329
00330 char *mode;
00331
00332 if (!dbus_message_get_args(message, NULL,
00333 DBUS_TYPE_STRING, &mode,
00334 DBUS_TYPE_INVALID)) {
00335 DLOG_ERR("Invalid arguments for device_mode_ind signal");
00336 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00337 }
00338
00339 mode_change(mode);
00340
00341 return DBUS_HANDLER_RESULT_HANDLED;
00342 }
00343 #ifdef ACTIVITY_CHECK
00344 static DBusHandlerResult activity_check_dbus(DBusMessage *message) {
00345
00346 if (!dbus_message_get_args(message, NULL,
00347 DBUS_TYPE_BOOLEAN, &saved_inactivity,
00348 DBUS_TYPE_INVALID)) {
00349 DLOG_ERR("Invalid arguments for device_activity signal");
00350 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00351 }
00352 activity_check(saved_inactivity);
00353
00354 return DBUS_HANDLER_RESULT_HANDLED;
00355 }
00356 #endif
00357 #endif
00358
00359 #ifdef ACTIVITY_CHECK
00360
00363 void activity_check(dbus_bool_t inactivity) {
00364
00365 int sock;
00366
00367 if (get_wlan_state() != WLAN_CONNECTED) {
00368 return;
00369 }
00370
00371 sock = socket_open();
00372
00373 if (inactivity == FALSE) {
00374
00375 } else {
00376
00377 }
00378
00379 set_power_state(powersave, sock);
00380 }
00381
00385 static gboolean get_inactivity_status(void)
00386 {
00387 return saved_inactivity;
00388 }
00389 #endif
00390
00395 static DBusHandlerResult icd_check_signal_dbus(DBusMessage *message) {
00396
00397 char *icd_name;
00398 char *icd_type;
00399 char *icd_state;
00400 char *icd_disconnect_reason;
00401 DBusError dbus_error;
00402
00403 if ((get_wlan_state() != WLAN_CONNECTED &&
00404 get_wlan_state() != WLAN_NO_ADDRESS) ||
00405 get_mode() != WLANCOND_INFRA) {
00406 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00407 }
00408
00409 dbus_error_init(&dbus_error);
00410 if (!dbus_message_get_args(message, &dbus_error,
00411 DBUS_TYPE_STRING, &icd_name,
00412 DBUS_TYPE_STRING, &icd_type,
00413 DBUS_TYPE_STRING, &icd_state,
00414 DBUS_TYPE_STRING, &icd_disconnect_reason,
00415 DBUS_TYPE_INVALID ) )
00416 {
00417 DLOG_ERR("Could not get args from signal, '%s'",
00418 dbus_error.message);
00419 dbus_error_free(&dbus_error);
00420 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00421 }
00422
00423 if (icd_state != NULL && strncmp(icd_state, "CONNECTED", 9) == 0) {
00424
00425 set_wlan_state(WLAN_CONNECTED, NO_SIGNAL, FORCE_NO);
00426
00427 DLOG_DEBUG("Going to power save");
00428
00429 if (set_power_state(powersave, socket_open()) == FALSE) {
00430 DLOG_ERR("Failed to set power save");
00431 }
00432
00433 }
00434
00435
00436
00437 return DBUS_HANDLER_RESULT_HANDLED;
00438 }
00442 static gint run_calibration(void) {
00443 gchar *args[2];
00444 gint count = 0;
00445 args[count++] = (gchar*)"/usr/bin/wl1251-cal";
00446 args[count++] = NULL;
00447
00448 if (!g_spawn_sync (NULL, args, NULL, 0,
00449 NULL, NULL, NULL, NULL, NULL, NULL)) {
00450 return -1;
00451 }
00452 return 0;
00453 }
00457 #define KILL_SUPPLICANT "/usr/bin/killall"
00458 #define SUPPLICANT_NAME "eapd"
00459 static void kill_supplicant(void) {
00460 gchar *args[3];
00461 guint count = 0;
00462 args[count++] = (gchar*)KILL_SUPPLICANT;
00463 args[count++] = (gchar*)"-9";
00464 args[count++] = (gchar*)SUPPLICANT_NAME;
00465
00466 if (!g_spawn_sync (NULL, args, NULL, 0,
00467 NULL, NULL, NULL, NULL, NULL, NULL)) {
00468 DLOG_ERR("Failed to run %s", KILL_SUPPLICANT);
00469 }
00470 }
00471 #define WLANCOND_WAIT_COUNTRY 2000 //2s
00472
00476 static gint check_country_code(void) {
00477 DBusMessage *msg, *reply;
00478 DBusError error;
00479 dbus_uint32_t current_cell_id;
00480 dbus_uint32_t network_code;
00481 dbus_uint32_t country_code;
00482 dbus_uint16_t current_lac;
00483 guchar reg_status;
00484 guchar network_type;
00485 guchar supported_services;
00486
00487 dbus_error_init(&error);
00488
00489 msg = dbus_message_new_method_call(
00490 "com.nokia.phone.net",
00491 "/com/nokia/phone/net",
00492 "Phone.Net",
00493 "get_registration_status");
00494
00495 if (msg == NULL) {
00496 return -1;
00497 }
00498
00499 reply = dbus_connection_send_with_reply_and_block(
00500 get_dbus_connection(), msg, WLANCOND_WAIT_COUNTRY, &error);
00501
00502 dbus_message_unref(msg);
00503
00504 if (dbus_error_is_set(&error)) {
00505 DLOG_ERR("Failed to ask registration status: %s",
00506 error.name);
00507 dbus_error_free(&error);
00508 if (reply)
00509 dbus_message_unref(reply);
00510 return -1;
00511 }
00512 dbus_error_init(&error);
00513
00514 if (!dbus_message_get_args(reply, &error,
00515 DBUS_TYPE_BYTE, ®_status,
00516 DBUS_TYPE_UINT16, ¤t_lac,
00517 DBUS_TYPE_UINT32, ¤t_cell_id,
00518 DBUS_TYPE_UINT32, &network_code,
00519 DBUS_TYPE_UINT32, &country_code,
00520 DBUS_TYPE_BYTE, &network_type,
00521 DBUS_TYPE_BYTE, &supported_services,
00522 DBUS_TYPE_INVALID))
00523 {
00524 DLOG_ERR("Could not get args from reply, '%s'",
00525 error.message);
00526 dbus_error_free(&error);
00527 if (reply)
00528 dbus_message_unref(reply);
00529 return -1;
00530 }
00531 DLOG_INFO("Device country: %d", country_code);
00532
00533 dbus_message_unref(reply);
00534
00535 return country_code;
00536 }
00537 static void set_bt_coex_state(unsigned int state) {
00538 FILE * file;
00539 char buf[4];
00540
00541 DLOG_DEBUG("Setting coex state to %i", state);
00542
00543 file = fopen(WLANCOND_BT_COEX_FILE, "w");
00544 if (file == NULL) {
00545 DLOG_DEBUG("Cannot open: %s", WLANCOND_BT_COEX_FILE);
00546 return;
00547 }
00548
00549 sprintf(buf, "%d", state);
00550
00551 if (fwrite(buf, 1, 1, file) != 1) {
00552 DLOG_DEBUG("Could not write to: %s", WLANCOND_BT_COEX_FILE);
00553 }
00554 fclose(file);
00555
00556 wlan_status.coex_state = state;
00557 if (wlan_status.state != WLAN_NOT_INITIALIZED)
00558 if (!set_power_state(wlan_status.requested_power,
00559 socket_open()))
00560 DLOG_DEBUG("Unable to set the power state");
00561
00562 return;
00563 }
00569 static DBusHandlerResult csd_check_signal_dbus(DBusMessage *message) {
00570
00571 DBusError error;
00572 dbus_uint32_t current_cell_id;
00573 dbus_uint32_t network_code;
00574 dbus_uint32_t country_code;
00575 dbus_uint16_t current_lac;
00576 guchar reg_status;
00577 guchar network_type;
00578 guchar supported_services;
00579
00580 dbus_error_init(&error);
00581
00582 if (!dbus_message_get_args(message, &error,
00583 DBUS_TYPE_BYTE, ®_status,
00584 DBUS_TYPE_UINT16, ¤t_lac,
00585 DBUS_TYPE_UINT32, ¤t_cell_id,
00586 DBUS_TYPE_UINT32, &network_code,
00587 DBUS_TYPE_UINT32, &country_code,
00588 DBUS_TYPE_BYTE, &network_type,
00589 DBUS_TYPE_BYTE, &supported_services,
00590 DBUS_TYPE_INVALID))
00591 {
00592 DLOG_ERR("Could not get args from signal, '%s'",
00593 error.message);
00594 dbus_error_free(&error);
00595 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00596 }
00597
00598 DLOG_DEBUG("Handled csd signal, country:%d", country_code);
00599
00600 if ((gint)country_code != wlan_status.country_code &&
00601 wlan_status.country_code != -1) {
00602 wlan_status.country_code = -1;
00603 DLOG_INFO("Country changed to: %d", country_code);
00604 }
00605
00606 return DBUS_HANDLER_RESULT_HANDLED;
00607 }
00613 static DBusHandlerResult bluez_check_adapter_signal_dbus(DBusMessage *message) {
00614 DBusError error;
00615 const gchar *property_name = NULL;
00616 DBusMessageIter msg_iter;
00617 DBusMessageIter variant_iter;
00618 dbus_error_init(&error);
00619
00620 if (!dbus_message_get_args (message, &error,
00621 DBUS_TYPE_STRING, &property_name,
00622 DBUS_TYPE_INVALID))
00623 {
00624 DLOG_ERR("Could not get args from signal, '%s'",
00625 error.message);
00626 dbus_error_free(&error);
00627 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00628 }
00629
00630 if (property_name != NULL &&
00631 strcmp (property_name, BLUEZ_ADAPTER_PROPERTY_POWERED) == 0)
00632 {
00633 dbus_message_iter_init (message, &msg_iter);
00634 dbus_message_iter_next(&msg_iter);
00635 if (dbus_message_iter_get_arg_type(&msg_iter)
00636 != DBUS_TYPE_VARIANT) {
00637 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00638 }
00639 dbus_message_iter_recurse(&msg_iter, &variant_iter);
00640 if (dbus_message_iter_get_arg_type(&variant_iter)
00641 != DBUS_TYPE_BOOLEAN) {
00642 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00643 }
00644 dbus_message_iter_get_basic(&variant_iter, &saved_bt_power);
00645
00646 DLOG_DEBUG("Got signal, powered: %d", saved_bt_power);
00647
00648 if (saved_bt_power == TRUE)
00649 set_bt_coex_state(WLANCOND_BT_COEX_ON);
00650 else
00651 set_bt_coex_state(WLANCOND_BT_COEX_OFF);
00652 }
00653 return DBUS_HANDLER_RESULT_HANDLED;
00654 }
00660 static DBusHandlerResult bluez_check_headset_signal_dbus(DBusMessage *message) {
00661 DBusError error;
00662 const gchar *property_name = NULL;
00663 DBusMessageIter msg_iter;
00664 DBusMessageIter variant_iter;
00665 const gchar *state;
00666 dbus_error_init(&error);
00667
00668 if (!dbus_message_get_args (message, &error,
00669 DBUS_TYPE_STRING, &property_name,
00670 DBUS_TYPE_INVALID))
00671 {
00672 DLOG_ERR("Could not get args from signal, '%s'",
00673 error.message);
00674 dbus_error_free(&error);
00675 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00676 }
00677
00678 if (property_name != NULL &&
00679 strcmp (property_name, BLUEZ_HEADSET_PROPERTY_STATE) == 0)
00680 {
00681 dbus_message_iter_init (message, &msg_iter);
00682 dbus_message_iter_next(&msg_iter);
00683 if (dbus_message_iter_get_arg_type(&msg_iter)
00684 != DBUS_TYPE_VARIANT) {
00685 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00686 }
00687 dbus_message_iter_recurse(&msg_iter, &variant_iter);
00688 if (dbus_message_iter_get_arg_type(&variant_iter)
00689 != DBUS_TYPE_STRING) {
00690 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00691 }
00692 dbus_message_iter_get_basic(&variant_iter, &state);
00693
00694 if (state != NULL) {
00695 DLOG_DEBUG("State: %s", state);
00696
00697
00698
00699
00700 if (!strcmp(state, BLUEZ_HEADSET_PROPERTY_PLAYING)) {
00701 set_bt_coex_state(WLANCOND_BT_COEX_MONOAUDIO);
00702 } else {
00703 if (saved_bt_power == TRUE)
00704 set_bt_coex_state(WLANCOND_BT_COEX_ON);
00705 else
00706 set_bt_coex_state(WLANCOND_BT_COEX_OFF);
00707 }
00708 }
00709 }
00710 return DBUS_HANDLER_RESULT_HANDLED;
00711 }
00712
00717 static gchar *gateway_bluez_default_adapter_path (void)
00718 {
00719 DBusMessage *msg, *reply = NULL;
00720 gchar *path = NULL;
00721 DBusError derr;
00722
00723 msg = dbus_message_new_method_call(
00724 BLUEZ_SERVICE_NAME,
00725 BLUEZ_MANAGER_PATH_NAME,
00726 BLUEZ_MANAGER_INTERFACE_NAME,
00727 BLUEZ_MANAGER_DEFAULT_ADAPTER_METHOD);
00728
00729 if (msg == NULL) {
00730 return NULL;
00731 }
00732
00733 dbus_error_init(&derr);
00734
00735 reply = dbus_connection_send_with_reply_and_block(
00736 get_dbus_connection(), msg, -1, &derr);
00737
00738 dbus_message_unref(msg);
00739
00740 if (dbus_error_is_set(&derr)) {
00741 DLOG_ERR("BlueZ returned error: %s", derr.name);
00742
00743 dbus_error_free(&derr);
00744 if (reply)
00745 dbus_message_unref(reply);
00746 return NULL;
00747 }
00748
00749 if (reply == NULL)
00750 return NULL;
00751
00752 dbus_error_init (&derr);
00753 if (!dbus_message_get_args (reply, &derr,
00754 DBUS_TYPE_OBJECT_PATH, &path,
00755 DBUS_TYPE_INVALID))
00756 {
00757 DLOG_ERR("Could not get arguments: %s",
00758 derr.message);
00759 dbus_error_free (&derr);
00760 dbus_message_unref (reply);
00761 return NULL;
00762 }
00763
00764 path = g_strdup(path);
00765 dbus_message_unref (reply);
00766
00767 return path;
00768 }
00769 static gboolean gateway_adapter_point_iter_to_value (
00770 DBusMessageIter *msg_iter,
00771 const gchar *property_name)
00772 {
00773 DBusMessageIter array_iter;
00774
00775
00776
00777 if (dbus_message_iter_get_arg_type (msg_iter) != DBUS_TYPE_ARRAY ||
00778 dbus_message_iter_get_element_type (msg_iter) !=
00779 DBUS_TYPE_DICT_ENTRY)
00780 return FALSE;
00781
00782 for (dbus_message_iter_recurse(msg_iter, &array_iter);
00783 dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_INVALID;
00784 dbus_message_iter_next (&array_iter))
00785 {
00786 DBusMessageIter dict_iter;
00787 const gchar *name = NULL;
00788
00789
00790 if (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_DICT_ENTRY)
00791 continue;
00792
00793
00794 dbus_message_iter_recurse (&array_iter, &dict_iter);
00795
00796 if (dbus_message_iter_get_arg_type(&dict_iter)
00797 != DBUS_TYPE_STRING)
00798 return FALSE;
00799
00800 dbus_message_iter_get_basic(&dict_iter, &name);
00801 dbus_message_iter_next(&dict_iter);
00802
00803
00804
00805 if (name == NULL || strcmp (name, property_name) != 0)
00806 continue;
00807
00808
00809 if (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_VARIANT)
00810 {
00811 dbus_message_iter_recurse(&dict_iter, msg_iter);
00812 return TRUE;
00813 }
00814 }
00815 return FALSE;
00816 }
00817
00818 static DBusMessage *gateway_adapter_get_property_values (
00819 const gchar *adapter_path,
00820 ...)
00821 {
00822 DBusMessage *request = NULL, *reply = NULL;
00823 const gchar *property_name = NULL;
00824 DBusMessageIter msg_iter;
00825 va_list ap;
00826
00827 request = dbus_message_new_method_call(
00828 BLUEZ_SERVICE_NAME,
00829 adapter_path,
00830 BLUEZ_ADAPTER_SERVICE_NAME,
00831 BLUEZ_ADAPTER_GET_PROPERTIES_METHOD);
00832
00833 if (request == NULL)
00834 return NULL;
00835
00836 reply = dbus_connection_send_with_reply_and_block(
00837 get_dbus_connection(), request, -1, NULL);
00838
00839 dbus_message_unref(request);
00840
00841 if (reply == NULL)
00842 return NULL;
00843
00844 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
00845 {
00846 DLOG_ERR("gateway_adapter_get_property_values: %s",
00847 dbus_message_get_error_name(reply));
00848 dbus_message_unref(reply);
00849 return NULL;
00850 }
00851
00852 for (va_start(ap, adapter_path);
00853 (property_name = va_arg(ap, const gchar *)) != NULL;)
00854 {
00855 DBusMessageIter *msg_iter_ret = va_arg(ap, DBusMessageIter *);
00856
00857 if (!dbus_message_iter_init(reply, &msg_iter) ||
00858 !gateway_adapter_point_iter_to_value (
00859 &msg_iter, property_name))
00860 {
00861 DLOG_ERR("Unable to point to property '%s'",
00862 property_name);
00863 va_end(ap);
00864 dbus_message_unref(reply);
00865 return NULL;
00866 }
00867
00868 if (msg_iter_ret != NULL)
00869 *msg_iter_ret = msg_iter;
00870 else
00871 break;
00872 }
00873 va_end(ap);
00874
00875 return reply;
00876 }
00881 static gint handle_country(void) {
00882
00883
00884
00885
00886 if (wlan_status.country_code < 0) {
00887
00888
00889
00890 gint code = check_country_code();
00891 if (code >= 0)
00892 wlan_status.country_code = code;
00893 if (run_calibration() < 0) {
00894 DLOG_ERR("Fatal: Could not calibrate");
00895 }
00896 }
00897 return 0;
00898 }
00902 static void check_bt_status(void) {
00903 DBusMessageIter msg_iter;
00904 char* default_adapter;
00905 dbus_bool_t powered;
00906 DBusMessage *property_message = NULL;
00907
00908 default_adapter = gateway_bluez_default_adapter_path();
00909
00910 if (default_adapter != NULL) {
00911 property_message = gateway_adapter_get_property_values(
00912 default_adapter,
00913 BLUEZ_ADAPTER_PROPERTY_POWERED, &msg_iter,
00914 NULL);
00915
00916 g_free(default_adapter);
00917
00918 if (property_message == NULL)
00919 {
00920 DLOG_ERR("Unable to get properties");
00921 return;
00922 }
00923
00924 dbus_message_iter_get_basic(&msg_iter, &powered);
00925
00926 DLOG_DEBUG("Default adapter is %s", powered == TRUE?"powered":
00927 "not powered");
00928
00929 if (powered == TRUE)
00930 set_bt_coex_state(WLANCOND_BT_COEX_ON);
00931 else
00932 set_bt_coex_state(WLANCOND_BT_COEX_OFF);
00933
00934 dbus_message_unref(property_message);
00935 } else {
00936 DLOG_DEBUG("Default adapter was NULL");
00937 set_bt_coex_state(WLANCOND_BT_COEX_OFF);
00938 }
00939 }
00943 int init_dbus_handler(void)
00944 {
00945 gboolean error;
00946
00947 handle_country();
00948
00949 if (get_own_mac() < 0) {
00950 DLOG_ERR("Could not get own MAC address");
00951 return -1;
00952 }
00953
00954 check_bt_status();
00955
00956 wlan_status.allow_all_ciphers = get_setting_bool(
00957 WLANCOND_ALLOW_ALL_CIPHERS, &error);
00958
00959 return 0;
00960 }
00961
00962 static gboolean in_flight_mode(void) {
00963 return _flight_mode;
00964 }
00965
00966 void set_wlan_signal(gboolean high_or_low)
00967 {
00968 if (high_or_low == WLANCOND_HIGH) {
00969 wlan_status.signal = WLANCOND_HIGH;
00970 remove_roam_scan_timer();
00971 } else {
00972 wlan_status.signal = WLANCOND_LOW;
00973 }
00974 }
00975
00976 void remove_roam_scan_timer(void)
00977 {
00978 if (wlan_status.roam_scan_id) {
00979 g_source_remove(wlan_status.roam_scan_id);
00980 wlan_status.roam_scan_id = 0;
00981 }
00982 }
00983
00984 void remove_connect_timer(void)
00985 {
00986 if (wlan_connect_timer_id) {
00987 g_source_remove(wlan_connect_timer_id);
00988 wlan_connect_timer_id = 0;
00989 }
00990 }
00991
00992 static void remove_wlan_if_timer(void)
00993 {
00994
00995 if (wlan_if_down_timer_id) {
00996 g_source_remove(wlan_if_down_timer_id);
00997 wlan_if_down_timer_id = 0;
00998 }
00999 }
01000
01001 void remove_scan_timer(void)
01002 {
01003 if (wlan_status.scan_id) {
01004 g_source_remove(wlan_status.scan_id);
01005 wlan_status.scan_id = 0;
01006 }
01007 }
01008
01014 static gboolean wlan_connect_timer_cb(void* data)
01015 {
01016 if (wlan_connect_timer_id && get_wlan_state() ==
01017 WLAN_INITIALIZED_FOR_CONNECTION) {
01018
01019 wlan_connect_timer_id = 0;
01020
01021 DLOG_DEBUG("Association timeout, try: %d",
01022 wlan_status.retry_count);
01023
01024
01025 remove_from_roam_cache(wlan_status.conn.bssid);
01026
01027
01028 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
01029
01030 if (find_connection_and_associate(wlan_status.roam_cache,
01031 FALSE, FALSE, FALSE) == 0)
01032 return FALSE;
01033
01034
01035 if (++wlan_status.retry_count < WLANCOND_MAX_SCAN_TRIES) {
01036 if (scan(wlan_status.conn.ssid,
01037 wlan_status.conn.ssid_len, TRUE) == 0) {
01038 return FALSE;
01039 }
01040 }
01041
01042 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
01043 FORCE_YES);
01044 return FALSE;
01045 }
01046
01047 wlan_connect_timer_id = 0;
01048
01049
01050
01051 return FALSE;
01052 }
01058 static gboolean wlan_scan_cb(void* data)
01059 {
01060
01061 wlan_status.scan_id = 0;
01062
01063 DLOG_ERR("Scan failed, should not happen!");
01064
01065 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, FORCE_YES);
01066
01067 return FALSE;
01068 }
01074 static gboolean wlan_if_down_cb(void* data)
01075 {
01076
01077 wlan_if_down_timer_id = 0;
01078
01079 if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
01080 DLOG_DEBUG("Delayed shutdown occurred");
01081 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
01082 return FALSE;
01083 }
01084
01085
01086
01087 return FALSE;
01088 }
01096 int mlme_command(guchar* addr, guint16 cmd, guint16 reason_code)
01097 {
01098 struct iwreq req;
01099 struct iw_mlme mlme;
01100
01101 init_iwreq(&req);
01102
01103 DLOG_INFO("%s", cmd==IW_MLME_DEAUTH?"Deauthenticating":
01104 "Disassociating");
01105
01106 memset(&mlme, 0, sizeof(mlme));
01107
01108 mlme.cmd = cmd;
01109 mlme.reason_code = reason_code;
01110 mlme.addr.sa_family = ARPHRD_ETHER;
01111 memcpy(mlme.addr.sa_data, addr, ETH_ALEN);
01112
01113 req.u.data.pointer = (caddr_t) &mlme;
01114 req.u.data.length = sizeof(mlme);
01115
01116 if (ioctl(socket_open(), SIOCSIWMLME, &req) < 0) {
01117 DLOG_ERR("Failed to run MLME command");
01118 return -1;
01119 }
01120
01121 return 0;
01122 }
01126 static int set_mode(guint32 mode)
01127 {
01128 struct iwreq req;
01129
01130 init_iwreq(&req);
01131
01132 switch (mode) {
01133 case WLANCOND_ADHOC:
01134 req.u.mode = IW_MODE_ADHOC;
01135 DLOG_DEBUG("Setting mode: adhoc");
01136 break;
01137 case WLANCOND_INFRA:
01138 req.u.mode = IW_MODE_INFRA;
01139 DLOG_DEBUG("Setting mode: infra");
01140 break;
01141 default:
01142 DLOG_ERR("Operating mode undefined\n");
01143 return -1;
01144 }
01145
01146 if (ioctl(socket_open(), SIOCSIWMODE, &req) < 0) {
01147 DLOG_ERR("Operating mode setting failed\n");
01148 return -1;
01149 }
01150 return 0;
01151 }
01157 static int set_wep_keys(struct connect_params_t *conn)
01158 {
01159 struct iwreq req;
01160 guint nbr_of_keys = 0;
01161 int sock;
01162 guint i;
01163
01164 sock = socket_open();
01165
01166
01167 for (i=0;i<4;i++) {
01168 if(conn->key_len[i] == 0) {
01169 continue;
01170 } else {
01171 if (conn->key_len[i] < WLANCOND_MIN_KEY_LEN ||
01172 conn->key_len[i] > WLANCOND_MAX_KEY_LEN) {
01173 return -1;
01174 }
01175
01176 init_iwreq(&req);
01177 req.u.data.length = conn->key_len[i];
01178 req.u.data.pointer = (caddr_t) &conn->key[i][0];
01179 req.u.data.flags |= IW_ENCODE_RESTRICTED;
01180 req.u.encoding.flags = i+1;
01181 nbr_of_keys++;
01182 }
01183
01184 #ifdef DEBUG_KEY
01185 int k;
01186 unsigned char* p = &conn->key[i][0];
01187 for (k=0;k<conn->key_len[i];k++) {
01188 DLOG_DEBUG("Key %d, 0x%02x\n", i, *(p+k));
01189 }
01190 #endif
01191 if (ioctl(sock, SIOCSIWENCODE, &req) < 0) {
01192 DLOG_ERR("Set encode failed\n");
01193 return -1;
01194 }
01195
01196 }
01197
01198 if (nbr_of_keys) {
01199
01200 DLOG_DEBUG("Default key: %d\n", conn->default_key);
01201
01202 init_iwreq(&req);
01203
01204
01205 req.u.encoding.flags = conn->default_key;
01206
01207 if (ioctl(sock, SIOCSIWENCODE, &req) < 0) {
01208 DLOG_ERR("Set encode failed\n");
01209 return -1;
01210 }
01211 }
01212
01213 return 0;
01214 }
01215
01222 int set_essid(char* essid, int essid_len)
01223 {
01224 struct iwreq req;
01225
01226 DLOG_INFO("Setting SSID: %s", essid);
01227
01228 init_iwreq(&req);
01229
01230 req.u.essid.pointer = (caddr_t)essid;
01231 req.u.essid.length = essid_len -1;
01232 req.u.essid.flags = 1;
01233
01234 if (ioctl(socket_open(), SIOCSIWESSID, &req) < 0) {
01235 DLOG_ERR("set ESSID failed");
01236 return -1;
01237 }
01238 return 0;
01239 }
01245 int set_bssid(unsigned char *bssid)
01246 {
01247 struct iwreq req;
01248
01249 print_mac(WLANCOND_PRIO_HIGH, "Setting BSSID", bssid);
01250
01251 init_iwreq(&req);
01252
01253 req.u.ap_addr.sa_family = ARPHRD_ETHER;
01254
01255 memcpy(req.u.ap_addr.sa_data, bssid, ETH_ALEN);
01256
01257 if (ioctl(socket_open(), SIOCSIWAP, &req) < 0) {
01258 DLOG_ERR("Failed to set BSSID");
01259 return -1;
01260 }
01261 return 0;
01262 }
01263
01270 void set_wlan_state(int new_state, int send_signal, force_t force)
01271 {
01272 const char *status_table[] =
01273 {
01274 (char*)"WLAN_NOT_INITIALIZED",
01275 (char*)"WLAN_INITIALIZED",
01276 (char*)"WLAN_INITIALIZED_FOR_SCAN",
01277 (char*)"WLAN_INITIALIZED_FOR_CONNECTION",
01278 (char*)"WLAN_NO_ADDRESS",
01279 (char*)"WLAN_CONNECTED"
01280 };
01281
01282 switch (new_state) {
01283
01284 case WLAN_NOT_INITIALIZED:
01285
01286 if (wlan_status.state == WLAN_CONNECTED ||
01287 wlan_status.state == WLAN_NO_ADDRESS) {
01288
01289 mlme_command(wlan_status.conn.bssid,
01290 IW_MLME_DEAUTH,
01291 WLANCOND_REASON_LEAVING);
01292 set_bssid(NULL_BSSID);
01293 set_essid((char*)"", 1);
01294 }
01295
01296 set_scan_state(SCAN_NOT_ACTIVE);
01297
01298 if (get_wlan_state() != WLAN_NOT_INITIALIZED &&
01299 get_wlan_state() != WLAN_INITIALIZED_FOR_SCAN)
01300 clear_wpa_mode();
01301
01302 wlan_status.retry_count = 0;
01303 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
01304 wlan_status.ip_ok = FALSE;
01305 wlan_status.last_scan = 0;
01306
01307
01308 remove_connect_timer();
01309
01310
01311 remove_scan_timer();
01312
01313 set_wlan_signal(WLANCOND_HIGH);
01314
01315
01316 remove_wlan_if_timer();
01317
01318 if (force == FORCE_YES) {
01319
01320 clean_roam_cache();
01321
01322 if (set_interface_state(socket_open(), CLEAR,
01323 IFF_UP)<0) {
01324 DLOG_ERR("Could not set interface down");
01325 }
01326
01327 } else {
01328
01329 DLOG_DEBUG("Delaying interface shutdown");
01330
01331
01332
01333
01334
01335 wlan_if_down_timer_id = g_timeout_add_seconds(
01336 WLANCOND_SHUTDOWN_DELAY,
01337 wlan_if_down_cb,
01338 NULL);
01339
01340 }
01341
01342 if (send_signal == DISCONNECTED_SIGNAL)
01343 disconnected_signal();
01344
01345 break;
01346 case WLAN_INITIALIZED_FOR_CONNECTION:
01347
01348
01349
01350
01351 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
01352
01353
01354 remove_connect_timer();
01355
01356 set_power_state(WLANCOND_POWER_ON, socket_open());
01357
01358 break;
01359 case WLAN_CONNECTED:
01360
01361
01362 if (get_wpa_mode() == FALSE)
01363 set_power_state(powersave, socket_open());
01364
01365 wlan_status.ip_ok = TRUE;
01366 break;
01367 default:
01368 break;
01369 }
01370 DLOG_DEBUG("Wlancond state change, old_state: %s, new_state: %s",
01371 status_table[wlan_status.state], status_table[new_state]);
01372 wlan_status.state = new_state;
01373 }
01374
01379 guint get_wlan_state(void)
01380 {
01381 return wlan_status.state;
01382 }
01383
01388 void set_scan_state(guint new_state)
01389 {
01390 if (wlan_status.scan == new_state) {
01391 return;
01392 }
01393 if (new_state == SCAN_NOT_ACTIVE && wlan_status.scan == SCAN_ACTIVE &&
01394 scan_name_cache != NULL) {
01395 remove_scan_timer();
01396 DLOG_DEBUG("Sending empty results");
01397 send_dbus_scan_results(NULL, scan_name_cache, 0);
01398 g_free(scan_name_cache);
01399 scan_name_cache = NULL;
01400 }
01401
01402 DLOG_DEBUG("Wlancond scan change, old_state: %s, new_state: %s",
01403 wlan_status.scan==SCAN_NOT_ACTIVE ? "SCAN_IDLE":"SCANNING",
01404 new_state == SCAN_NOT_ACTIVE ? "SCAN_IDLE":"SCANNING");
01405 wlan_status.scan = new_state;
01406 }
01407
01412 guint get_scan_state(void)
01413 {
01414 return wlan_status.scan;
01415 }
01420 guint get_mode(void)
01421 {
01422 return wlan_status.conn.mode;
01423 }
01424
01431 gboolean set_real_power_state(guint new_state, int sock)
01432 {
01433 struct iwreq req;
01434 gint sleep_timeout;
01435
01436 if (wlan_status.real_power == new_state) {
01437 return TRUE;
01438 }
01439
01440 init_iwreq(&req);
01441
01442 switch (new_state) {
01443 case WLANCOND_POWER_ON:
01444 req.u.power.disabled = 1;
01445 break;
01446 case WLANCOND_LONG_CAM:
01447 req.u.power.flags = IW_POWER_TIMEOUT | IW_POWER_ALL_R;
01448 req.u.power.value = WLANCOND_LONG_CAM_TIMEOUT;
01449 break;
01450 case WLANCOND_SHORT_CAM:
01451 req.u.power.flags = IW_POWER_TIMEOUT | IW_POWER_ALL_R;
01452 sleep_timeout = get_gconf_int(SLEEP_GCONF_PATH);
01453 if (sleep_timeout < 0)
01454 sleep_timeout = WLANCOND_DEFAULT_SLEEP_TIMEOUT;
01455 req.u.power.value = sleep_timeout;
01456 break;
01457 case WLANCOND_VERY_SHORT_CAM:
01458 req.u.power.flags = IW_POWER_TIMEOUT | IW_POWER_ALL_R ;
01459 sleep_timeout = get_gconf_int(INACTIVE_SLEEP_GCONF_PATH);
01460 if (sleep_timeout < 0)
01461 sleep_timeout = WLANCOND_VERY_SHORT_CAM_TIMEOUT;
01462 req.u.power.value = sleep_timeout;
01463 break;
01464 case WLANCOND_FULL_POWERSAVE:
01465 req.u.power.flags = IW_POWER_TIMEOUT | IW_POWER_ALL_R;
01466 req.u.power.value = 0;
01467 default:
01468 req.u.power.flags = IW_POWER_ALL_R;
01469 break;
01470 }
01471
01472 if (ioctl(sock, SIOCSIWPOWER, &req) < 0) {
01473 DLOG_ERR("set power failed, state:%d", new_state);
01474 return FALSE;
01475 }
01476
01477 if (req.u.power.value) {
01478 DLOG_DEBUG("CAM timeout: %d ms", req.u.power.value / 1000);
01479 }
01480
01481 wlan_status.real_power = new_state;
01482 DLOG_DEBUG("New power state set: %i", new_state);
01483
01484 return TRUE;
01485 }
01486
01493 gboolean set_power_state(guint new_state, int sock)
01494 {
01495 gboolean status;
01496
01497 if (new_state == WLANCOND_SHORT_CAM && get_inactivity_status() == TRUE)
01498 new_state = WLANCOND_VERY_SHORT_CAM;
01499
01500
01501 if (wlan_status.coex_state == WLANCOND_BT_COEX_MONOAUDIO &&
01502 wlan_status.call_state != WLANCOND_CALL_VOIP) {
01503 DLOG_DEBUG("Overriding power state with full power save.");
01504 new_state = WLANCOND_FULL_POWERSAVE;
01505 }
01506
01507 status = set_real_power_state(new_state, sock);
01508
01509
01510
01511 if (status && wlan_status.coex_state != WLANCOND_BT_COEX_MONOAUDIO)
01512 wlan_status.requested_power = new_state;
01513
01514 return status;
01515 }
01516
01522 static int init_if(int sock)
01523 {
01524 int previous_state = get_wlan_state();
01525
01526 if (previous_state == WLAN_NOT_INITIALIZED) {
01527
01528 if (wlan_if_down_timer_id == 0) {
01529
01530
01531 if (handle_country() < 0)
01532 return -1;
01533
01534 if (set_interface_state(sock, SET,
01535 IFF_UP | IFF_RUNNING) < 0) {
01536 return -1;
01537 }
01538 }
01539 set_power_state(WLANCOND_POWER_ON, sock);
01540 set_wlan_state(WLAN_INITIALIZED, NO_SIGNAL, FORCE_YES);
01541 }
01542
01543 return previous_state;
01544 }
01545
01554 static int set_we_name(int sock, char *name, char *args[], int count)
01555 {
01556 struct iwreq req;
01557
01558 memset(&req, 0, sizeof(req));
01559 strncpy(req.ifr_name, name, IFNAMSIZ);
01560
01561 if (ioctl(sock, SIOCGIWNAME, &req) < 0) {
01562
01563 } else {
01564
01565 if (g_str_has_prefix(name, WLAN_PREFIX_STR)) {
01566 DLOG_DEBUG("Found WLAN interface %s", name);
01567 memcpy(&wlan_status.ifname, name, IFNAMSIZ);
01568 wlan_status.ifname[IFNAMSIZ] = '\0';
01569 }
01570 }
01571
01572 return 0;
01573 }
01579 int get_we_device_name(void)
01580 {
01581 memset(&wlan_status, 0, sizeof(wlan_status));
01582
01583 wlan_status.country_code = -1;
01584
01585 iw_enum_devices(socket_open(), &set_we_name, NULL, 0);
01586
01587 if (strnlen(wlan_status.ifname, IFNAMSIZ) < 2)
01588 return -1;
01589
01590 return 0;
01591 }
01599 int set_interface_state(int sock, int dir, short flags)
01600 {
01601 struct ifreq ifr;
01602
01603 memset(&ifr, 0, sizeof(ifr));
01604
01605 strncpy(ifr.ifr_name, wlan_status.ifname, IFNAMSIZ);
01606
01607 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
01608 DLOG_ERR("Could not get interface %s flags\n",
01609 wlan_status.ifname);
01610 return -1;
01611 }
01612 if (dir == SET) {
01613 ifr.ifr_flags |= flags;
01614 } else {
01615 ifr.ifr_flags &= ~flags;
01616 }
01617
01618 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
01619 DLOG_ERR("Could not set interface %s flags\n",
01620 wlan_status.ifname);
01621 return -1;
01622 }
01623
01624 DLOG_DEBUG("%s is %s", wlan_status.ifname, dir == SET ? "UP":"DOWN");
01625
01626 return 0;
01627 }
01628
01635 static gboolean set_tx_power(guint power, int sock)
01636 {
01637 struct iwreq req;
01638 init_iwreq(&req);
01639
01640 req.u.txpower.fixed = 1;
01641 req.u.txpower.disabled = 0;
01642 req.u.txpower.flags = IW_TXPOW_DBM;
01643
01644 if (power == WLANCOND_TX_POWER10) {
01645 req.u.txpower.value = WLANCOND_TX_POWER10DBM;
01646 } else if (power == WLANCOND_TX_POWER100) {
01647 req.u.txpower.value = WLANCOND_TX_POWER100DBM;
01648 } else {
01649 return FALSE;
01650 }
01651
01652 if (ioctl(sock, SIOCSIWTXPOW, &req) < 0) {
01653 DLOG_ERR("set power failed\n");
01654 return FALSE;
01655 }
01656 return TRUE;
01657
01658 }
01664 static int update_algorithms(guint32 encryption,
01665 struct scan_results_t *scan_results)
01666 {
01667 wlan_status.group_cipher = 0;
01668 wlan_status.pairwise_cipher = 0;
01669
01670
01671 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_OPEN) {
01672 DLOG_DEBUG("Open mode");
01673 wlan_status.pairwise_cipher = CIPHER_SUITE_NONE;
01674 return 0;
01675 }
01676
01677
01678 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP) {
01679 DLOG_DEBUG("WEP enabled");
01680 wlan_status.pairwise_cipher = CIPHER_SUITE_WEP40;
01681 return 0;
01682 }
01683
01684
01685 if ((encryption & WLANCOND_ENCRYPT_ALG_MASK)
01686 == WLANCOND_WPA_TKIP) {
01687 DLOG_DEBUG("TKIP Selected for unicast");
01688 wlan_status.pairwise_cipher = CIPHER_SUITE_TKIP;
01689 } else if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) ==
01690 WLANCOND_WPA_AES) {
01691 DLOG_DEBUG("AES selected for unicast");
01692 wlan_status.pairwise_cipher = CIPHER_SUITE_CCMP;
01693 } else if (wlan_status.allow_all_ciphers == TRUE) {
01694 if (scan_results->extra_cap_bits & WLANCOND_WEP40) {
01695 DLOG_DEBUG("WEP40 selected for unicast");
01696 wlan_status.pairwise_cipher = CIPHER_SUITE_WEP40;
01697 } else if (scan_results->extra_cap_bits & WLANCOND_WEP104) {
01698 DLOG_DEBUG("WEP104 selected for unicast");
01699 wlan_status.pairwise_cipher = CIPHER_SUITE_WEP104;
01700 } else {
01701 DLOG_ERR("Not supported encryption %08x", encryption);
01702 return -1;
01703 }
01704 } else {
01705 DLOG_ERR("Not supported encryption %08x", encryption);
01706 return -1;
01707 }
01708
01709 if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
01710 WLANCOND_WPA_TKIP_GROUP) {
01711 DLOG_DEBUG("TKIP Selected for multicast");
01712 wlan_status.group_cipher = CIPHER_SUITE_TKIP;
01713 } else if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
01714 (unsigned int)WLANCOND_WPA_AES_GROUP) {
01715 DLOG_DEBUG("AES Selected for multicast");
01716 wlan_status.group_cipher = CIPHER_SUITE_CCMP;
01717 } else if (wlan_status.allow_all_ciphers == TRUE) {
01718 if (scan_results->extra_cap_bits & WLANCOND_WEP40_GROUP) {
01719 DLOG_DEBUG("WEP40 selected for group key");
01720 wlan_status.group_cipher = CIPHER_SUITE_WEP40;
01721 } else if (scan_results->extra_cap_bits
01722 & WLANCOND_WEP104_GROUP) {
01723 DLOG_DEBUG("WEP104 selected for group key");
01724 wlan_status.group_cipher = CIPHER_SUITE_WEP104;
01725 } else {
01726 DLOG_ERR("Not supported encryption %08x", encryption);
01727 return -1;
01728 }
01729 } else {
01730 DLOG_ERR("Not supported encryption %08x", encryption);
01731 return -1;
01732 }
01733
01734 return 0;
01735 }
01739 void clean_roam_cache(void)
01740 {
01741 clean_scan_results(&wlan_status.roam_cache);
01742 }
01746 void clear_wpa_mode(void)
01747 {
01748 g_free(wlan_status.wpa_ie.ie);
01749 wlan_status.wpa_ie.ie_len = 0;
01750 wlan_status.wpa_ie.ie = NULL;
01751
01752 wlan_status.pairwise_cipher = CIPHER_SUITE_NONE;
01753 wlan_status.group_cipher = CIPHER_SUITE_NONE;
01754
01755
01756 clear_wpa_keys(NULL);
01757
01758 g_slist_foreach(wlan_status.pmk_cache, (GFunc)g_free, NULL);
01759 g_slist_free(wlan_status.pmk_cache);
01760 wlan_status.pmk_cache = NULL;
01761 }
01766 gboolean get_wpa_mode(void)
01767 {
01768 if (wlan_status.pairwise_cipher & CIPHER_SUITE_TKIP ||
01769 wlan_status.pairwise_cipher & CIPHER_SUITE_CCMP) {
01770 return TRUE;
01771 }
01772 return FALSE;
01773 }
01774
01775 static gint compare_pmk_entry(gconstpointer a, gconstpointer b)
01776 {
01777 const struct pmksa_cache_t *pmk_cache = a;
01778
01779 return memcmp(pmk_cache->mac, b, ETH_ALEN);
01780 }
01781
01787 static void add_to_pmksa_cache(unsigned char* pmkid, unsigned char* mac)
01788 {
01789 guint i = 0;
01790 GSList *list;
01791 gboolean entry_found = FALSE;
01792
01793 for (list = wlan_status.pmk_cache; list != NULL &&
01794 entry_found == FALSE; list = list->next) {
01795 struct pmksa_cache_t *pmk_cache = list->data;
01796
01797 if (memcmp(pmk_cache->mac, mac, ETH_ALEN) == 0) {
01798 DLOG_DEBUG("Found old entry: %i", i);
01799
01800 wlan_status.pmk_cache = g_slist_remove(
01801 wlan_status.pmk_cache, pmk_cache);
01802 g_free(pmk_cache);
01803
01804 entry_found = TRUE;
01805 } else {
01806 i++;
01807 }
01808 }
01809
01810 if (i == PMK_CACHE_SIZE) {
01811 DLOG_DEBUG("Cache full, remove oldest");
01812 GSList *last_entry = g_slist_last(wlan_status.pmk_cache);
01813 wlan_status.pmk_cache = g_slist_remove(wlan_status.pmk_cache,
01814 last_entry->data);
01815 g_free(last_entry->data);
01816 }
01817 print_mac(WLANCOND_PRIO_LOW, "Adding new entry:", mac);
01818
01819 struct pmksa_cache_t *new_entry = g_malloc(sizeof(*new_entry));
01820 memcpy(new_entry->mac, mac, ETH_ALEN);
01821 memcpy(new_entry->pmkid, pmkid, IW_PMKID_LEN);
01822
01823 wlan_status.pmk_cache = g_slist_prepend(wlan_status.pmk_cache,
01824 new_entry);
01825 return;
01826 }
01827
01834 gboolean remove_from_pmksa_cache(unsigned char* mac)
01835 {
01836 GSList *list = g_slist_find_custom(wlan_status.pmk_cache, mac,
01837 &compare_pmk_entry);
01838 if(!list)
01839 return FALSE;
01840
01841 struct pmksa_cache_t *entry = list->data;
01842
01843 print_mac(WLANCOND_PRIO_MEDIUM, "Removing PMKSA entry for:", mac);
01844
01845 wlan_status.pmk_cache = g_slist_remove(wlan_status.pmk_cache,
01846 entry);
01847
01848 g_free(entry);
01849
01850 return TRUE;
01851 }
01852
01860 int find_pmkid_from_pmk_cache(unsigned char* mac,
01861 unsigned char **pmkid)
01862 {
01863 GSList *list;
01864 int pmksa_found;
01865
01866 if (check_pmksa_cache((unsigned char *)wlan_status.own_mac, ETH_ALEN,
01867 mac, ETH_ALEN,
01868 wlan_status.conn.authentication_type,
01869 wlan_status.pairwise_cipher,
01870 wlan_status.group_cipher,
01871 &pmksa_found))
01872 {
01873 DLOG_ERR("Error while querying the pmksa cache status "
01874 "from eapd");
01875 return -1;
01876 }
01877
01878 if(!pmksa_found) {
01879 DLOG_DEBUG("No cached pmksa found from eapd");
01880
01881 remove_from_pmksa_cache(mac);
01882 *pmkid = NULL;
01883
01884 return 0;
01885 }
01886
01887 list = g_slist_find_custom(wlan_status.pmk_cache, mac, &compare_pmk_entry);
01888 if (list != NULL) {
01889 struct pmksa_cache_t *pmk_cache = list->data;
01890 print_mac(WLANCOND_PRIO_MEDIUM, "Found PMKSA entry for:", mac);
01891 *pmkid = pmk_cache->pmkid;
01892 return 0;
01893 }
01894
01895 DLOG_DEBUG("No cached pmksa found from eapd");
01896 *pmkid = NULL;
01897
01898 return 0;
01899 }
01900
01907 int scan(gchar *ssid, int ssid_len, gboolean add_timer)
01908 {
01909 struct iwreq req;
01910 struct iw_scan_req scan_req;
01911
01912 if (get_scan_state() == SCAN_ACTIVE)
01913 return 0;
01914
01915 set_scan_state(SCAN_ACTIVE);
01916
01917 init_iwreq(&req);
01918
01919 memset(&scan_req, 0, sizeof(scan_req));
01920
01921 if (ssid_len > 1 && ssid != NULL) {
01922
01923 scan_req.essid_len = ssid_len -1;
01924 scan_req.bssid.sa_family = ARPHRD_ETHER;
01925 memset(scan_req.bssid.sa_data, 0xff, ETH_ALEN);
01926 memcpy(scan_req.essid, ssid, ssid_len -1);
01927 req.u.data.pointer = (caddr_t) &scan_req;
01928 req.u.data.length = sizeof(scan_req);
01929 req.u.data.flags = IW_SCAN_THIS_ESSID;
01930 }
01931
01932 if (ioctl(socket_open(), SIOCSIWSCAN, &req) < 0) {
01933 DLOG_ERR("Scan failed");
01934 return -1;
01935 }
01936
01937 if (add_timer == TRUE) {
01938 wlan_status.scan_id = g_timeout_add_seconds(
01939 WLANCOND_SCAN_TIMEOUT,
01940 wlan_scan_cb,
01941 NULL);
01942 }
01943
01944 DLOG_INFO("Scan issued");
01945
01946 return 0;
01947 }
01953 static int set_freq(int channel)
01954 {
01955 struct iwreq req;
01956
01957 DLOG_DEBUG("Setting channel: %d", channel);
01958
01959 init_iwreq(&req);
01960
01961 req.u.freq.m = channel;
01962
01963 if (ioctl(socket_open(), SIOCSIWFREQ, &req) < 0) {
01964 DLOG_ERR("Freq failed");
01965 return -1;
01966 }
01967
01968 return 0;
01969 }
01970 static void init_conn_params(struct connect_params_t *conn_params)
01971 {
01972 memset(conn_params, 0, sizeof(*conn_params));
01973 }
01978 void clear_wpa_keys(unsigned char* bssid)
01979 {
01980 struct iwreq req;
01981 struct iw_encode_ext ext;
01982 int sock;
01983 guint i;
01984
01985 init_iwreq(&req);
01986
01987 sock = socket_open();
01988
01989 for (i=0;i<4;i++) {
01990
01991 memset(&ext, 0, sizeof(ext));
01992
01993 req.u.encoding.flags = i + 1;
01994 req.u.encoding.flags |= IW_ENCODE_DISABLED;
01995 req.u.encoding.pointer = (caddr_t) &ext;
01996 req.u.encoding.length = sizeof(ext);
01997
01998 ext.ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
01999 ext.addr.sa_family = ARPHRD_ETHER;
02000
02001 memset(ext.addr.sa_data, 0xff, ETH_ALEN);
02002 ext.alg = IW_ENCODE_ALG_NONE;
02003
02004 if (ioctl(sock, SIOCSIWENCODEEXT, &req) < 0) {
02005 DLOG_ERR("Key %i clearing failed", i);
02006 }
02007 }
02008 if (bssid != NULL) {
02009
02010 memset(&ext, 0, sizeof(ext));
02011
02012 req.u.encoding.flags = 1;
02013 req.u.encoding.flags |= IW_ENCODE_DISABLED;
02014 req.u.encoding.pointer = (caddr_t) &ext;
02015 req.u.encoding.length = sizeof(ext);
02016
02017 ext.addr.sa_family = ARPHRD_ETHER;
02018
02019 memcpy(ext.addr.sa_data, bssid, ETH_ALEN);
02020 ext.alg = IW_ENCODE_ALG_NONE;
02021
02022 if (ioctl(sock, SIOCSIWENCODEEXT, &req) < 0) {
02023 DLOG_ERR("Key clearing failed");
02024 }
02025 }
02026
02027 return;
02028 }
02036 static int check_connect_arguments(struct connect_params_t *conn, char* ssid,
02037 unsigned char** key)
02038 {
02039 guint i;
02040
02041 if (conn->flags & WLANCOND_DISABLE_POWERSAVE) {
02042 DLOG_DEBUG("Powersave disabled");
02043 powersave = WLANCOND_POWER_ON;
02044 } else if (conn->flags & WLANCOND_MINIMUM_POWERSAVE) {
02045 DLOG_DEBUG("Powersave minimum");
02046 powersave = WLANCOND_LONG_CAM;
02047 } else if (conn->flags & WLANCOND_MAXIMUM_POWERSAVE) {
02048 DLOG_DEBUG("Powersave maximum");
02049 powersave = WLANCOND_SHORT_CAM;
02050 } else {
02051 powersave = WLANCOND_SHORT_CAM;
02052 }
02053
02054 if (conn->power_level != WLANCOND_TX_POWER10 &&
02055 conn->power_level != WLANCOND_TX_POWER100) {
02056 DLOG_ERR("Invalid power level");
02057 return -1;
02058 }
02059
02060 switch (conn->mode) {
02061 case WLANCOND_ADHOC:
02062 case WLANCOND_INFRA:
02063 break;
02064 default:
02065 DLOG_ERR("Operating mode undefined\n");
02066 return -1;
02067 }
02068
02069 guint32 wpa2_mode = conn->encryption & WLANCOND_ENCRYPT_WPA2_MASK;
02070
02071 DLOG_DEBUG("Encryption setting: %08x", conn->encryption);
02072
02073 switch (conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) {
02074 case WLANCOND_OPEN:
02075 break;
02076 case WLANCOND_WEP:
02077 break;
02078 case WLANCOND_WPA_PSK:
02079 DLOG_DEBUG("%s PSK selected",
02080 wpa2_mode!=0?"WPA2":"WPA");
02081 if (wpa2_mode != 0)
02082 conn->authentication_type = EAP_AUTH_TYPE_WPA2_PSK;
02083 else
02084 conn->authentication_type = EAP_AUTH_TYPE_WPA_PSK;
02085 break;
02086 case WLANCOND_WPA_EAP:
02087 DLOG_DEBUG("%s EAP selected", wpa2_mode!=0?"WPA2":"WPA");
02088 if (wpa2_mode != 0)
02089 conn->authentication_type = EAP_AUTH_TYPE_WPA2_EAP;
02090 else
02091 conn->authentication_type = EAP_AUTH_TYPE_WPA_EAP;
02092 break;
02093 default:
02094 DLOG_DEBUG("Unsupported encryption mode");
02095 return -1;
02096 }
02097 if ((conn->encryption & WLANCOND_WPS_MASK) != 0) {
02098 DLOG_DEBUG("WPS selected");
02099 conn->authentication_type = EAP_AUTH_TYPE_WFA_SC;
02100 }
02101
02102 if (!ssid || conn->ssid_len == 0 ||
02103 conn->ssid_len > WLANCOND_MAX_SSID_SIZE + 1) {
02104 DLOG_DEBUG("Invalid SSID");
02105 return -1;
02106 }
02107 for (i=0;i<4;i++) {
02108 if (conn->key_len[i] != 0) {
02109 DLOG_DEBUG("Found key %d", i);
02110 memcpy(&conn->key[i][0], key[i], conn->key_len[i]);
02111 }
02112 }
02113 return 0;
02114 }
02115
02122 static DBusHandlerResult settings_and_connect_request(
02123 DBusMessage *message,
02124 DBusConnection *connection) {
02125
02126 DBusMessage *reply = NULL;
02127 DBusError derror;
02128 struct connect_params_t *conn;
02129 char *ssid;
02130 unsigned char* key[4];
02131 dbus_int32_t old_mode;
02132 int res;
02133 gboolean autoconnect = FALSE;
02134
02135 dbus_error_init(&derror);
02136
02137 if (in_flight_mode()) {
02138 reply = new_dbus_error(message, WLANCOND_ERROR_WLAN_DISABLED);
02139 send_and_unref(connection, reply);
02140 return DBUS_HANDLER_RESULT_HANDLED;
02141 }
02142
02143 remove_wlan_if_timer();
02144
02145 conn = &wlan_status.conn;
02146
02147 old_mode = conn->mode;
02148 init_conn_params(conn);
02149
02150 if (dbus_message_get_args(
02151 message, NULL,
02152 DBUS_TYPE_INT32, &conn->power_level,
02153 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid, &conn->ssid_len,
02154 DBUS_TYPE_INT32, &conn->mode,
02155 DBUS_TYPE_INT32, &conn->encryption,
02156 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[0], &conn->key_len[0],
02157 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[1], &conn->key_len[1],
02158 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[2], &conn->key_len[2],
02159 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[3], &conn->key_len[3],
02160 DBUS_TYPE_INT32, &conn->default_key,
02161 DBUS_TYPE_UINT32, &conn->adhoc_channel,
02162 DBUS_TYPE_UINT32, &conn->flags,
02163 DBUS_TYPE_INVALID) == FALSE)
02164 {
02165
02166 if (dbus_message_get_args(
02167 message, &derror,
02168 DBUS_TYPE_INT32, &conn->power_level,
02169 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid,
02170 &conn->ssid_len,
02171 DBUS_TYPE_INT32, &conn->mode,
02172 DBUS_TYPE_INT32, &conn->encryption,
02173 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02174 &key[0], &conn->key_len[0],
02175 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02176 &key[1], &conn->key_len[1],
02177 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02178 &key[2], &conn->key_len[2],
02179 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02180 &key[3], &conn->key_len[3],
02181 DBUS_TYPE_INT32, &conn->default_key,
02182 DBUS_TYPE_UINT32, &conn->adhoc_channel,
02183 DBUS_TYPE_INVALID) == FALSE) {
02184
02185 DLOG_ERR("Failed to parse setting_and_connect: %s",
02186 derror.message);
02187 dbus_error_free(&derror);
02188 goto param_err;
02189 }
02190 }
02191
02192 if (check_connect_arguments(conn, ssid, key) < 0)
02193 goto param_err;
02194
02195 set_power_state(WLANCOND_POWER_ON, socket_open());
02196
02197
02198
02199
02200
02201 if (old_mode != conn->mode ||
02202 conn->encryption & WLANCOND_WPS_PUSH_BUTTON) {
02203 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
02204 }
02205
02206
02207 if (set_mode(conn->mode) < 0) {
02208 goto param_err;
02209 }
02210
02211 if (init_if(socket_open()) < 0) {
02212 reply = new_dbus_error(message, WLANCOND_ERROR_INIT_FAILED);
02213 goto param_err;
02214 }
02215
02216 if (set_tx_power(conn->power_level, socket_open()) != TRUE) {
02217 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02218 goto param_err;
02219 }
02220
02221 if (conn->flags & WLANCOND_AUTOCONNECT) {
02222 DLOG_DEBUG("Autoconnect attempt");
02223 autoconnect = TRUE;
02224 }
02225
02226 memcpy(conn->ssid, ssid, conn->ssid_len);
02227
02228 set_scan_state(SCAN_NOT_ACTIVE);
02229 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL, FORCE_NO);
02230
02231
02232 if (conn->encryption & WLANCOND_WPS_PUSH_BUTTON) {
02233 DLOG_DEBUG("Broadcast scan for WPS");
02234 if (scan(NULL, 0, TRUE) < 0) {
02235 goto param_err;
02236 }
02237 } else {
02238
02239 if ((res = find_connection_and_associate(
02240 wlan_status.roam_cache,
02241 FALSE, FALSE, autoconnect)) != 0) {
02242
02243
02244
02245 if (res == ETOOWEAKAP)
02246 goto param_err;
02247
02248
02249 DLOG_DEBUG("Checking mac80211 cache...");
02250
02251 GSList *scan_results = NULL;
02252 scan_results_ioctl(0, &scan_results);
02253
02254 if (find_connection_and_associate(
02255 scan_results,
02256 TRUE, FALSE, autoconnect) != 0) {
02257
02258
02259
02260 if (res == ETOOWEAKAP)
02261 goto param_err;
02262
02263 clean_scan_results(&scan_results);
02264 if (scan(conn->ssid, conn->ssid_len, TRUE)
02265 < 0) {
02266 goto param_err;
02267 }
02268 } else {
02269 clean_scan_results(&scan_results);
02270 }
02271 }
02272 }
02273
02274 g_free(connect_name_cache);
02275 connect_name_cache = g_strdup(dbus_message_get_sender(message));
02276
02277 reply = new_dbus_method_return(message);
02278
02279 gchar* ifname = wlan_status.ifname;
02280
02281 append_dbus_args(reply,
02282 DBUS_TYPE_STRING, &ifname,
02283 DBUS_TYPE_INVALID);
02284
02285 send_and_unref(connection, reply);
02286
02287 return DBUS_HANDLER_RESULT_HANDLED;
02288
02289 param_err:
02290 if (reply == NULL) {
02291 DLOG_DEBUG("Parameter error in settings_and_connect\n");
02292 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
02293 }
02294 send_and_unref(connection, reply);
02295 return DBUS_HANDLER_RESULT_HANDLED;
02296 }
02302 int associate(struct scan_results_t *scan_results)
02303 {
02304 struct connect_params_t *conn = &wlan_status.conn;
02305 gint ret;
02306
02307 DLOG_INFO("Starting to associate");
02308
02309 if (memcmp(conn->bssid, "\0\0\0\0\0\0", ETH_ALEN)) {
02310 clear_wpa_keys(conn->bssid);
02311 }
02312
02313 if (update_algorithms(conn->encryption, scan_results) < 0) {
02314 return -1;
02315 }
02316
02317
02318 if ((conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP){
02319 if (set_wep_keys(conn) < 0) {
02320 return -1;
02321 }
02322 }
02323
02324 memcpy(conn->bssid, scan_results->bssid, ETH_ALEN);
02325
02326 if ((ret = set_encryption_method(conn->encryption, &wlan_status,
02327 scan_results)) < 0) {
02328 return ret;
02329 }
02330
02331 if (get_wpa_mode() == TRUE ||
02332 conn->authentication_type == EAP_AUTH_TYPE_WFA_SC) {
02333
02334
02335 if (wpa_ie_push(scan_results->bssid,
02336 scan_results->wpa_ie,
02337 scan_results->wpa_ie_len,
02338 scan_results->ssid,
02339 scan_results->ssid_len -1,
02340 conn->authentication_type) < 0)
02341 return -1;
02342 }
02343
02344
02345
02346 if (conn->adhoc_channel != 0 && (conn->mode & WLANCOND_ADHOC)) {
02347 if (conn->adhoc_channel < WLANCOND_MIN_WLAN_CHANNEL ||
02348 conn->adhoc_channel > WLANCOND_MAX_WLAN_CHANNEL) {
02349 DLOG_ERR("Invalid ad-hoc channel: %d",
02350 conn->adhoc_channel);
02351 return -1;
02352 }
02353
02354 scan_results->channel = conn->adhoc_channel;
02355 }
02356
02357 set_freq(scan_results->channel);
02358
02359
02360 if (conn->mode != WLANCOND_ADHOC &&
02361 memcmp(scan_results->bssid, "\0\0\0\0\0\0", ETH_ALEN)) {
02362 if (set_bssid(scan_results->bssid) < 0) {
02363 return -1;
02364 }
02365 }
02366
02367 if (set_essid(conn->ssid, conn->ssid_len) < 0) {
02368 return -1;
02369 }
02370
02371
02372 wlan_connect_timer_id = g_timeout_add_seconds(
02373 WLANCOND_CONNECT_TIMEOUT,
02374 wlan_connect_timer_cb, NULL);
02375
02376 return 0;
02377 }
02378
02385 static DBusHandlerResult scan_request(DBusMessage *message,
02386 DBusConnection *connection) {
02387
02388 DBusMessage *reply = NULL;
02389 DBusMessageIter iter, array_iter;
02390 char *ssid;
02391 const char* sender;
02392 dbus_int32_t power_level;
02393 dbus_int32_t flags;
02394 gint previous_state = 0;
02395
02396 if (in_flight_mode()) {
02397 reply = new_dbus_error(message, WLANCOND_ERROR_WLAN_DISABLED);
02398 send_and_unref(connection, reply);
02399 return DBUS_HANDLER_RESULT_HANDLED;
02400 }
02401
02402 sender = dbus_message_get_sender(message);
02403 if (sender == NULL) {
02404 goto param_err;
02405 }
02406
02407 DLOG_DEBUG("Got scan request from %s", sender);
02408
02409
02410 if (get_scan_state() == SCAN_ACTIVE || wlan_connect_timer_id != 0) {
02411 reply = new_dbus_error(message, WLANCOND_ERROR_ALREADY_ACTIVE);
02412 send_and_unref(connection, reply);
02413 return DBUS_HANDLER_RESULT_HANDLED;
02414 }
02415
02416 if ((previous_state = init_if(socket_open())) < 0) {
02417 reply = new_dbus_error(message, WLANCOND_ERROR_INIT_FAILED);
02418 goto param_err;
02419 }
02420
02421 if (previous_state == WLAN_NOT_INITIALIZED) {
02422 set_wlan_state(WLAN_INITIALIZED_FOR_SCAN, NO_SIGNAL, FORCE_NO);
02423 }
02424
02425 dbus_message_iter_init(message, &iter);
02426
02427 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
02428 goto param_err;
02429 dbus_message_iter_get_basic(&iter, &power_level);
02430
02431 dbus_message_iter_next(&iter);
02432
02433 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
02434 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
02435 goto param_err;
02436 dbus_message_iter_recurse(&iter, &array_iter);
02437 dbus_message_iter_get_fixed_array(&array_iter, &ssid,
02438 &wlan_status.scan_ssid_len);
02439
02440 if (wlan_status.scan_ssid_len > WLANCOND_MAX_SSID_SIZE+1)
02441 goto param_err;
02442
02443 dbus_message_iter_next(&iter);
02444
02445 power_down_after_scan = FALSE;
02446
02447 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32) {
02448 dbus_message_iter_get_basic(&iter, &flags);
02449 DLOG_DEBUG("Found flags: %08x", flags);
02450
02451 if (flags & WLANCOND_NO_DELAYED_SHUTDOWN)
02452 power_down_after_scan = TRUE;
02453 }
02454
02455 if (power_level != WLANCOND_TX_POWER10 &&
02456 power_level != WLANCOND_TX_POWER100) {
02457 DLOG_ERR("Invalid power level");
02458 goto param_err;
02459 }
02460
02461 if (set_tx_power(power_level, socket_open()) != TRUE) {
02462 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02463 goto param_err;
02464 }
02465
02466 memset(wlan_status.scan_ssid, 0, sizeof(wlan_status.scan_ssid));
02467
02468 if (ssid != NULL && wlan_status.scan_ssid_len > 1) {
02469 memcpy(wlan_status.scan_ssid, ssid, wlan_status.scan_ssid_len);
02470 }
02471
02472 if (scan(wlan_status.scan_ssid, wlan_status.scan_ssid_len, TRUE) < 0) {
02473 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02474 goto param_err;
02475 }
02476
02477 g_free(scan_name_cache);
02478 scan_name_cache = g_strdup(sender);
02479
02480 reply = new_dbus_method_return(message);
02481 send_and_unref(connection, reply);
02482
02483 return DBUS_HANDLER_RESULT_HANDLED;
02484
02485 param_err:
02486 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
02487 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
02488 }
02489 if (reply == NULL) {
02490 DLOG_DEBUG("Parameter error in scan request");
02491 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
02492 }
02493 send_and_unref(connection, reply);
02494 return DBUS_HANDLER_RESULT_HANDLED;
02495 }
02502 static int network_compare(gconstpointer a, gconstpointer b)
02503 {
02504 const struct scan_results_t *results_a = a;
02505 const struct scan_results_t *results_b = b;
02506
02507 if (wlan_status.scan_ssid_len > 1) {
02508
02509
02510
02511 gint a_eq = strncmp(wlan_status.scan_ssid,
02512 results_a->ssid, WLANCOND_MAX_SSID_SIZE);
02513 gint b_eq = strncmp(wlan_status.scan_ssid,
02514 results_b->ssid, WLANCOND_MAX_SSID_SIZE);
02515
02516 if (!a_eq && !b_eq) {
02517
02518
02519 return 0;
02520 }
02521
02522 if (!a_eq && b_eq) {
02523
02524
02525 return -1;
02526 }
02527
02528 if (a_eq && !b_eq) {
02529
02530
02531
02532 return 1;
02533 }
02534
02535 }
02536
02537
02538 return (results_a->rssi > results_b->rssi) ?
02539 -1 : (results_a->rssi < results_b->rssi) ? 1 : 0;
02540 }
02541
02542 static gint compare_scan_entry(gconstpointer a, gconstpointer b)
02543 {
02544 const struct scan_results_t *scan_entry = a;
02545 return memcmp(scan_entry->bssid, b, ETH_ALEN);
02546 }
02551 static void add_to_roam_cache(struct scan_results_t *scan_results)
02552 {
02553 GSList *list;
02554
02555 list = g_slist_find_custom(wlan_status.roam_cache, scan_results->bssid,
02556 &compare_scan_entry);
02557
02558 if (list != NULL) {
02559 struct scan_results_t *roam_cache_entry = list->data;
02560 print_mac(WLANCOND_PRIO_LOW, "Found old entry for:",
02561 scan_results->bssid);
02562
02563
02564 wlan_status.roam_cache = g_slist_remove(
02565 wlan_status.roam_cache, roam_cache_entry);
02566
02567 clean_scan_results_item(roam_cache_entry, NULL);
02568 }
02569
02570 print_mac(WLANCOND_PRIO_LOW, "New AP to roam cache:",
02571 scan_results->bssid);
02572
02573 struct scan_results_t *results_to_list =
02574 g_slice_dup(struct scan_results_t, scan_results);
02575 results_to_list->wpa_ie = g_memdup(scan_results->wpa_ie,
02576 scan_results->wpa_ie_len);
02577 wlan_status.roam_cache = g_slist_prepend(wlan_status.roam_cache,
02578 results_to_list);
02579
02580 return;
02581 }
02587 gboolean remove_from_roam_cache(unsigned char *bssid)
02588 {
02589 GSList *list;
02590
02591 list = g_slist_find_custom(wlan_status.roam_cache, bssid,
02592 &compare_scan_entry);
02593
02594 if (list != NULL) {
02595 struct scan_results_t *roam_cache_entry = list->data;
02596 print_mac(WLANCOND_PRIO_LOW, "Found entry to be removed:",
02597 bssid);
02598
02599 wlan_status.roam_cache = g_slist_remove(
02600 wlan_status.roam_cache, roam_cache_entry);
02601
02602 clean_scan_results_item(roam_cache_entry, NULL);
02603
02604 return TRUE;
02605 }
02606
02607 return FALSE;
02608 }
02609
02615 gboolean decrease_signal_in_roam_cache(unsigned char *bssid)
02616 {
02617 GSList *list;
02618
02619 list = g_slist_find_custom(wlan_status.roam_cache, bssid,
02620 &compare_scan_entry);
02621
02622 if (list != NULL) {
02623 struct scan_results_t *roam_cache_entry = list->data;
02624 print_mac(WLANCOND_PRIO_LOW, "Found entry to be decreased:",
02625 bssid);
02626
02627 roam_cache_entry->rssi -= WLANCOND_RSSI_PENALTY;
02628
02629 return TRUE;
02630 }
02631
02632 return FALSE;
02633 }
02640 static int check_group_cipher(guint32 c1, guint32 c2)
02641 {
02642 guint32 m1 = (c1 & WLANCOND_ENCRYPT_GROUP_ALG_MASK);
02643 guint32 m2 = (c2 & WLANCOND_ENCRYPT_GROUP_ALG_MASK);
02644
02645 if (m1 == m2)
02646 return 1;
02647 if (m2 == WLANCOND_WPA_TKIP_GROUP && (m1 & WLANCOND_WPA_TKIP_GROUP))
02648 return 1;
02649 if (m2 == (unsigned int)WLANCOND_WPA_AES_GROUP &&
02650 (m1 & WLANCOND_WPA_AES_GROUP))
02651 return 1;
02652
02653 DLOG_DEBUG("Group ciphers don't match");
02654
02655 return -1;
02656 }
02663 static int check_ciphers(guint32 c1, guint32 c2)
02664 {
02665 guint32 u1 = (c1 & WLANCOND_ENCRYPT_ALG_MASK);
02666 guint32 u2 = (c2 & WLANCOND_ENCRYPT_ALG_MASK);
02667
02668 if (check_group_cipher(c1, c2) < 0)
02669 return -1;
02670
02671 if (u1 == u2)
02672 return 1;
02673 if (u2 == WLANCOND_WPA_TKIP && (u1 & WLANCOND_WPA_TKIP))
02674 return 1;
02675 if (u2 == WLANCOND_WPA_AES && (u1 & WLANCOND_WPA_AES))
02676 return 1;
02677
02678 DLOG_DEBUG("Unicast ciphers don't match");
02679
02680 return -1;
02681 }
02682
02683 static gboolean wlan_roam_scan_cb(void* data)
02684 {
02685 wlan_status.roam_scan_id = 0;
02686 struct timeval tv;
02687
02688 if (wlan_status.signal == WLANCOND_LOW &&
02689 get_wlan_state() == WLAN_CONNECTED) {
02690
02691 DLOG_DEBUG("Roam scan timeout, initiating new scan");
02692
02693 if (scan(wlan_status.conn.ssid, wlan_status.conn.ssid_len,
02694 TRUE) <0) {
02695 set_wlan_state(WLAN_NOT_INITIALIZED,
02696 DISCONNECTED_SIGNAL,
02697 FORCE_YES);
02698 return FALSE;
02699 }
02700 if (gettimeofday(&tv, NULL) >= 0)
02701 wlan_status.last_scan = tv.tv_sec;
02702 }
02703
02704 return FALSE;
02705 }
02706
02711 void schedule_scan(guint seconds) {
02712
02713
02714 remove_roam_scan_timer();
02715 wlan_status.roam_scan_id = g_timeout_add_seconds(
02716 seconds,
02717 wlan_roam_scan_cb,
02718 NULL);
02719 }
02720
02724 static void reschedule_scan(void)
02725 {
02726
02727
02728
02729
02730 if (get_inactivity_status() == TRUE) {
02731 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
02732 } else {
02733 if (wlan_status.roam_scan <= WLANCOND_MIN_ROAM_SCAN_INTERVAL) {
02734 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
02735 } else if (wlan_status.roam_scan >=
02736 WLANCOND_MAX_ROAM_SCAN_INTERVAL) {
02737 wlan_status.roam_scan = WLANCOND_MAX_ROAM_SCAN_INTERVAL;
02738 } else {
02739 wlan_status.roam_scan = wlan_status.roam_scan * 2;
02740 }
02741 }
02742
02743 schedule_scan(wlan_status.roam_scan);
02744 }
02745
02752 static gboolean check_capabilities(struct scan_results_t *scan_results,
02753 struct connect_params_t *conn)
02754 {
02755
02756 if ((scan_results->cap_bits & WLANCOND_MODE_MASK) != (guint32)conn->mode)
02757 return FALSE;
02758 if ((scan_results->cap_bits & WLANCOND_ENCRYPT_METHOD_MASK) !=
02759 (guint32)(conn->encryption &
02760 WLANCOND_ENCRYPT_METHOD_MASK))
02761 return FALSE;
02762 if ((scan_results->cap_bits & WLANCOND_ENCRYPT_WPA2_MASK) !=
02763 (guint32)(conn->encryption &
02764 WLANCOND_ENCRYPT_WPA2_MASK))
02765 return FALSE;
02766 if (check_ciphers(scan_results->cap_bits, conn->encryption) < 0)
02767 return FALSE;
02768
02769 return TRUE;
02770 }
02771
02779 struct scan_results_t* find_connection(
02780 GSList* ap_list, struct connect_params_t *conn,
02781 gboolean update_roam_cache)
02782 {
02783 GSList *list;
02784 struct scan_results_t *best_connection = NULL;
02785 gint current_rssi = 0;
02786
02787
02788 if (update_roam_cache == TRUE)
02789 clean_roam_cache();
02790
02791 for (list = ap_list; list != NULL; list = list->next) {
02792 struct scan_results_t *scan_results = list->data;
02793 if (memcmp(scan_results->ssid, conn->ssid,
02794 scan_results->ssid_len) == 0) {
02795 print_mac(WLANCOND_PRIO_LOW, "Found AP:",
02796 scan_results->bssid);
02797
02798
02799 if (memcmp(scan_results->bssid, wlan_status.conn.bssid,
02800 ETH_ALEN) == 0) {
02801 current_rssi = scan_results->rssi;
02802 DLOG_DEBUG("Current AP: %d", current_rssi);
02803 }
02804
02805 if (check_capabilities(scan_results, conn) ==
02806 FALSE)
02807 continue;
02808
02809 if (is_ap_in_black_list(scan_results->bssid) == TRUE) {
02810 DLOG_INFO("AP is in black list, discarded");
02811 continue;
02812 }
02813
02814
02815
02816
02817 if (update_roam_cache == TRUE) {
02818 add_to_roam_cache(scan_results);
02819 }
02820
02821 if (best_connection == NULL ||
02822 best_connection->rssi < scan_results->rssi) {
02823 DLOG_DEBUG("Best connection: %d (old %d)",
02824 scan_results->rssi,
02825 best_connection == NULL ?
02826 WLANCOND_MINIMUM_SIGNAL:
02827 best_connection->rssi);
02828 best_connection = scan_results;
02829 }
02830 }
02831 }
02832
02833
02834 if (best_connection == NULL)
02835 return NULL;
02836
02837
02838
02839
02840 if (current_rssi != 0) {
02841 if (best_connection->rssi < current_rssi +
02842 WLANCOND_ROAM_THRESHOLD) {
02843 DLOG_DEBUG("Best connection not good enough");
02844 return NULL;
02845 }
02846 }
02847
02848
02849 if (best_connection->rssi < WLANCOND_MINIMUM_SIGNAL)
02850 return NULL;
02851
02852 return best_connection;
02853 }
02859 static dbus_uint32_t find_adhoc_channel(GSList *ap_list) {
02860
02861 dbus_uint32_t used_channel_list = 0;
02862 dbus_uint32_t selected_channel = 0;
02863 GSList* list;
02864 guint32 i;
02865
02866
02867 for (list = ap_list; list != NULL; list = list->next) {
02868 struct scan_results_t *scan_results = list->data;
02869 used_channel_list |= 1 << scan_results->channel;
02870 }
02871
02872 for (i = 1; i <= 11; i++) {
02873 if (!(used_channel_list & (1 << i))) {
02874 selected_channel = i;
02875 break;
02876 }
02877 }
02878
02879 if (selected_channel == 0) {
02880
02881
02882 selected_channel = g_random_int_range(1, 12);
02883 }
02884
02885
02886
02887 return selected_channel;
02888 }
02894 int find_connection_and_associate(GSList *scan_results,
02895 gboolean update_roam_cache,
02896 gboolean create_new_adhoc,
02897 gboolean autoconnect)
02898 {
02899 struct scan_results_t adhoc;
02900 struct connect_params_t *conn = &wlan_status.conn;
02901 guint wps_pbc_registrars = 0;
02902 GSList* list;
02903
02904
02905
02906 if (conn->encryption & WLANCOND_WPS_PUSH_BUTTON) {
02907 for (list = scan_results; list != NULL; list = list->next) {
02908 struct scan_results_t *scan_results = list->data;
02909
02910 if (scan_results->cap_bits & WLANCOND_WPS_PUSH_BUTTON
02911 &&
02912 scan_results->cap_bits & WLANCOND_WPS_CONFIGURED) {
02913 if (++wps_pbc_registrars > 1) {
02914 DLOG_ERR("Too many WPS PBC registrars");
02915 return ETOOMANYREGISTRARS;
02916 }
02917 }
02918 }
02919 }
02920
02921 struct scan_results_t *connection = find_connection(
02922 scan_results, &wlan_status.conn, update_roam_cache);
02923
02924 if (connection == NULL && conn->mode == WLANCOND_ADHOC &&
02925 create_new_adhoc == TRUE) {
02926 DLOG_DEBUG("No existing adhoc connection");
02927 memset(&adhoc, 0, sizeof(adhoc));
02928 connection = &adhoc;
02929 memcpy(connection->ssid, conn->ssid, conn->ssid_len);
02930 connection->channel = find_adhoc_channel(scan_results);
02931 }
02932
02933 if (connection) {
02934 if (autoconnect == TRUE &&
02935 connection->rssi < WLANCOND_MINIMUM_AUTOCONNECT_RSSI) {
02936 DLOG_WARN("RSSI too low for autoconnect");
02937 return ETOOWEAKAP;
02938 }
02939 int ret = associate(connection);
02940 if (ret < 0)
02941 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
02942 return ret;
02943 }
02944 return -1;
02945 }
02949 static void registrar_error_signal(void)
02950 {
02951 DBusMessage *registrar_error;
02952
02953 registrar_error = new_dbus_signal(
02954 WLANCOND_SIG_PATH,
02955 WLANCOND_SIG_INTERFACE,
02956 WLANCOND_REGISTRAR_ERROR_SIG,
02957 NULL);
02958
02959 send_and_unref(get_dbus_connection(), registrar_error);
02960 }
02964 static gboolean rescan(void* data)
02965 {
02966 if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
02967 if (scan(wlan_status.conn.ssid,
02968 wlan_status.conn.ssid_len, TRUE) < 0) {
02969 set_wlan_state(WLAN_NOT_INITIALIZED,
02970 DISCONNECTED_SIGNAL,
02971 FORCE_YES);
02972 }
02973 }
02974 return FALSE;
02975 }
02980 static void connect_from_scan_results(GSList *scan_results)
02981 {
02982 gboolean autoconnect = !!(wlan_status.conn.flags & WLANCOND_AUTOCONNECT);
02983
02984 int status = find_connection_and_associate(
02985 scan_results, TRUE, TRUE, autoconnect);
02986
02987 clean_scan_results(&scan_results);
02988
02989 if (status == 0)
02990 return;
02991
02992 DLOG_DEBUG("Could not find suitable network");
02993
02994 if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
02995
02996 if (status != ETOOWEAKAP && status != ESUPPLICANT &&
02997 ++wlan_status.retry_count <= WLANCOND_MAX_SCAN_TRIES) {
02998 DLOG_DEBUG("Rescanning");
02999 g_timeout_add_seconds(
03000 WLANCOND_RESCAN_DELAY,
03001 rescan,
03002 NULL);
03003 } else {
03004
03005
03006
03007 if (status == ETOOMANYREGISTRARS) {
03008 set_wlan_state(WLAN_NOT_INITIALIZED,
03009 NO_SIGNAL, FORCE_YES);
03010 registrar_error_signal();
03011 } else {
03012 if (status == ESUPPLICANT) {
03013 DLOG_ERR("Supplicant error");
03014 kill_supplicant();
03015 }
03016 set_wlan_state(WLAN_NOT_INITIALIZED,
03017 DISCONNECTED_SIGNAL, FORCE_YES);
03018 }
03019 }
03020 return;
03021 }
03022
03023
03024 reschedule_scan();
03025 }
03032 int scan_results_ioctl(int ifindex, GSList** scan_results_save)
03033 {
03034 struct iwreq req;
03035 char *buffer;
03036 unsigned int buflen = IW_SCAN_MAX_DATA*2;
03037 int sock;
03038 unsigned int counter = 3;
03039
03040
03041
03042 init_iwreq(&req);
03043
03044 sock = socket_open();
03045
03046 buffer = g_malloc(buflen);
03047
03048 try_again:
03049
03050
03051 req.u.data.pointer = buffer;
03052 req.u.data.flags = 0;
03053 req.u.data.length = buflen;
03054
03055 if (ioctl(sock, SIOCGIWSCAN, &req) < 0) {
03056
03057
03058 if (errno == E2BIG && buflen != G_MAXUINT16) {
03059 DLOG_DEBUG("Too much data for buffer length %d "
03060 "needed %d\n", buflen, req.u.data.length);
03061
03062 char* new_buffer = NULL;
03063 buflen = (req.u.data.length > buflen ?
03064 req.u.data.length : buflen * 2);
03065
03066
03067 if (buflen > G_MAXUINT16)
03068 buflen = G_MAXUINT16;
03069 new_buffer = g_realloc(buffer, buflen);
03070
03071 buffer = new_buffer;
03072 goto try_again;
03073 }
03074
03075
03076 if (errno == EAGAIN)
03077 {
03078 DLOG_DEBUG("Not yet ready...");
03079 if (counter-- > 0) {
03080 sleep(1);
03081 goto try_again;
03082 }
03083 }
03084
03085 DLOG_ERR("Get scan results failed");
03086
03087 g_free(buffer);
03088 return -1;
03089 }
03090
03091 if (req.u.data.length)
03092 {
03093 struct iw_event iwe;
03094 struct stream_descr stream;
03095 struct scan_results_t *scan_results;
03096 struct wireless_iface *wireless_if;
03097 int ret;
03098 gboolean wap_handled = FALSE;
03099 int we_version;
03100
03101 scan_results = g_slice_new0(struct scan_results_t);
03102 memset(&iwe, 0, sizeof(iwe));
03103
03104 if (ifindex != 0) {
03105 wireless_if = get_interface_data(ifindex);
03106 we_version = wireless_if->range.we_version_compiled;
03107 } else {
03108 struct iw_range range;
03109 if (iw_get_range_info(socket_open(),
03110 wlan_status.ifname,
03111 &range)<0)
03112 memset(&range, 0, sizeof(range));
03113 we_version = range.we_version_compiled;
03114 }
03115
03116 iw_init_event_stream(&stream, buffer, req.u.data.length);
03117 do
03118 {
03119
03120 ret = iw_extract_event_stream(
03121 &stream, &iwe,
03122 we_version);
03123 if (ret > 0) {
03124
03125
03126
03127
03128 if (iwe.cmd == SIOCGIWAP) {
03129
03130
03131
03132 if (wap_handled == TRUE) {
03133 *scan_results_save =
03134 save_scan_results(
03135 scan_results,
03136 *scan_results_save);
03137 scan_results = g_slice_new0(
03138 struct scan_results_t);
03139 } else {
03140 wap_handled = TRUE;
03141 }
03142 }
03143 print_event_token(&iwe, scan_results, ifindex,
03144 TRUE);
03145 }
03146
03147 }
03148 while (ret > 0);
03149
03150
03151
03152 if (wap_handled == TRUE) {
03153 *scan_results_save = save_scan_results(
03154 scan_results,
03155 *scan_results_save);
03156 } else {
03157
03158 g_slice_free(struct scan_results_t, scan_results);
03159 }
03160 }
03161
03162 g_free(buffer);
03163
03164 return 0;
03165 }
03166
03167
03173 gboolean ask_scan_results(int ifindex)
03174 {
03175 GSList *scan_results_save = NULL;
03176 dbus_int32_t number_of_results;
03177
03178 if (scan_results_ioctl(ifindex, &scan_results_save) < 0)
03179 return FALSE;
03180
03181
03182 if (scan_name_cache != NULL) {
03183 number_of_results = g_slist_length(scan_results_save);
03184
03185
03186
03187 if (number_of_results > WLANCOND_MAX_NETWORKS)
03188 scan_results_save = g_slist_sort(scan_results_save,
03189 network_compare);
03190
03191 send_dbus_scan_results(scan_results_save, scan_name_cache,
03192 number_of_results);
03193 g_free(scan_name_cache);
03194 scan_name_cache = NULL;
03195 }
03196
03197
03198
03199 if ((get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION ||
03200 wlan_status.signal == WLANCOND_LOW) &&
03201 get_scan_state() == SCAN_ACTIVE) {
03202
03203 DLOG_DEBUG("Connect from scan");
03204
03205 set_scan_state(SCAN_NOT_ACTIVE);
03206
03207 connect_from_scan_results(scan_results_save);
03208
03209 return TRUE;
03210 }
03211
03212 set_scan_state(SCAN_NOT_ACTIVE);
03213
03214 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN &&
03215 power_down_after_scan == TRUE) {
03216 set_interface_state(socket_open(), CLEAR, IFF_UP);
03217 }
03218
03219 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
03220
03221 if (wlan_status.roam_cache) {
03222 clean_roam_cache();
03223 }
03224 wlan_status.roam_cache = scan_results_save;
03225 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_NO);
03226 } else {
03227 clean_scan_results(&scan_results_save);
03228 }
03229
03230 return TRUE;
03231 }
03232
03239 static DBusHandlerResult disconnect_request(DBusMessage *message,
03240 DBusConnection *connection) {
03241 DBusMessage *reply;
03242
03243 set_scan_state(SCAN_NOT_ACTIVE);
03244
03245
03246 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, FORCE_YES);
03247
03248 reply = new_dbus_method_return(message);
03249 send_and_unref(connection, reply);
03250
03251 return DBUS_HANDLER_RESULT_HANDLED;
03252 }
03259 static DBusHandlerResult disassociate_request(DBusMessage *message,
03260 DBusConnection *connection) {
03261 DBusMessage *reply;
03262
03263 if (get_wlan_state() != WLAN_CONNECTED &&
03264 get_wlan_state() != WLAN_NO_ADDRESS) {
03265 DLOG_DEBUG("Not in correct state for disassociation");
03266
03267 reply = new_dbus_method_return(message);
03268 send_and_unref(connection, reply);
03269 return DBUS_HANDLER_RESULT_HANDLED;
03270 }
03271
03272 if (get_wpa_mode() == TRUE) {
03273 clear_wpa_keys(wlan_status.conn.bssid);
03274 }
03275
03276 mlme_command(wlan_status.conn.bssid, IW_MLME_DISASSOC,
03277 WLANCOND_REASON_LEAVING);
03278
03279 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL, FORCE_NO);
03280
03281 DLOG_DEBUG("Disassociated, trying to find a new connection");
03282
03283 if (scan(wlan_status.conn.ssid, wlan_status.conn.ssid_len, TRUE) < 0) {
03284
03285 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
03286 FORCE_YES);
03287 }
03288
03289 reply = new_dbus_method_return(message);
03290 send_and_unref(connection, reply);
03291
03292 return DBUS_HANDLER_RESULT_HANDLED;
03293 }
03300 static DBusHandlerResult status_request(DBusMessage *message,
03301 DBusConnection *connection) {
03302 DBusMessage *reply = NULL;
03303 struct iwreq req;
03304 struct iw_range range;
03305 char *essid = NULL;
03306 int essid_len;
03307 dbus_uint32_t sens = 0;
03308 dbus_uint32_t security = 0;
03309 dbus_uint32_t capability = 0;
03310 dbus_uint32_t channel = 0;
03311 unsigned char *bssid = NULL;
03312
03313 int sock;
03314
03315 if (get_wlan_state() != WLAN_CONNECTED &&
03316 get_wlan_state() != WLAN_NO_ADDRESS &&
03317 get_mode() != WLANCOND_ADHOC) {
03318 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03319 send_and_unref(connection, reply);
03320 return DBUS_HANDLER_RESULT_HANDLED;
03321 }
03322
03323 sock = socket_open();
03324
03325 init_iwreq(&req);
03326
03327 essid = g_malloc0(IW_ESSID_MAX_SIZE+1);
03328 req.u.essid.pointer = (caddr_t)essid;
03329 req.u.essid.length = IW_ESSID_MAX_SIZE;
03330 req.u.essid.flags = 0;
03331
03332
03333 if (ioctl(sock, SIOCGIWESSID, &req) < 0) {
03334 DLOG_ERR("Could not get ESSID");
03335 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03336 goto param_err;
03337 }
03338 essid_len = req.u.essid.length;
03339
03340
03341 if (essid_len == 0 || essid_len == 32)
03342 essid_len++;
03343
03344 init_iwreq(&req);
03345
03346
03347 if (ioctl(sock, SIOCGIWAP, &req) < 0) {
03348 DLOG_ERR("Could not get BSSID");
03349 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03350 goto param_err;
03351 }
03352 bssid = g_malloc(ETH_ALEN);
03353 memcpy(bssid, &req.u.ap_addr.sa_data, ETH_ALEN);
03354
03355 init_iwreq(&req);
03356 struct iw_statistics stats;
03357 memset(&stats, 0, sizeof(struct iw_statistics));
03358
03359 req.u.data.pointer = (caddr_t) &stats;
03360 req.u.data.length = sizeof(struct iw_statistics);
03361 req.u.data.flags = 1;
03362
03363
03364 if (ioctl(sock, SIOCGIWSTATS, &req) < 0) {
03365 DLOG_ERR("Could not get statistics");
03366 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03367 goto param_err;
03368 }
03369 sens = stats.qual.level - 0x100;
03370
03371
03372 init_iwreq(&req);
03373
03374 if (ioctl(sock, SIOCGIWFREQ, &req) < 0) {
03375 DLOG_DEBUG("Could not get channel");
03376 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03377 goto param_err;
03378 }
03379
03380 if (iw_get_range_info(sock, wlan_status.ifname, &range) >= 0) {
03381 double freq = iw_freq2float(&(req.u.freq));
03382 channel = iw_freq_to_channel(freq, &range);
03383 }
03384
03385 if (channel < WLANCOND_MIN_WLAN_CHANNEL ||
03386 channel > WLANCOND_MAX_WLAN_CHANNEL) {
03387 channel = 0;
03388 DLOG_DEBUG("Got invalid channel\n");
03389 }
03390
03391
03392 init_iwreq(&req);
03393
03394 if (ioctl(sock, SIOCGIWMODE, &req) < 0) {
03395 DLOG_ERR("Could not get operating mode");
03396 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03397 goto param_err;
03398 }
03399
03400 if (req.u.mode == IW_MODE_ADHOC) {
03401 capability |= WLANCOND_ADHOC;
03402 } else if (req.u.mode == IW_MODE_INFRA) {
03403 capability |= WLANCOND_INFRA;
03404 }
03405
03406 init_iwreq(&req);
03407
03408
03409 security = wlan_status.conn.encryption;
03410
03411 #if 0
03412 key = g_malloc(IW_ENCODING_TOKEN_MAX);
03413 req.u.data.pointer = (caddr_t) key;
03414 req.u.data.length = IW_ENCODING_TOKEN_MAX;
03415 req.u.data.flags = 0;
03416
03417 if (ioctl(sock, SIOCGIWENCODE, &req) < 0) {
03418 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03419 goto param_err;
03420 }
03421
03422 if (req.u.data.flags & IW_ENCODE_OPEN)
03423 security |= WLANCOND_OPEN;
03424
03425 if (req.u.data.flags & IW_ENCODE_RESTRICTED)
03426 security |= WLANCOND_WEP;
03427
03428
03429 if (req.u.data.flags & IW_ENCODE_TKIP)
03430 security |= WLANCOND_WPA_PSK & WLANCOND_WPA_EAP &
03431 WLANCOND_WPA_TKIP;
03432
03433 if (req.u.data.flags & IW_ENCODE_AES)
03434 security |= WLANCOND_WPA_PSK & WLANCOND_WPA_EAP &
03435 WLANCOND_WPA_AES;
03436
03437 g_free(key);
03438 #endif
03439 init_iwreq(&req);
03440
03441
03442 if (ioctl(sock, SIOCGIWRATE, &req) < 0) {
03443 DLOG_ERR("Could not get the rate");
03444 }
03445 capability |= req.u.bitrate.value;
03446
03447 reply = new_dbus_method_return(message);
03448
03449 gchar* ifname = wlan_status.ifname;
03450
03451 append_dbus_args(reply,
03452 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03453 &essid, essid_len,
03454 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, ETH_ALEN,
03455 DBUS_TYPE_UINT32, &sens,
03456 DBUS_TYPE_UINT32, &channel,
03457 DBUS_TYPE_UINT32, &capability,
03458 DBUS_TYPE_UINT32, &security,
03459 DBUS_TYPE_STRING, &ifname,
03460 DBUS_TYPE_INVALID);
03461
03462 send_and_unref(connection, reply);
03463
03464 g_free(essid);
03465 g_free(bssid);
03466
03467 return DBUS_HANDLER_RESULT_HANDLED;
03468
03469 param_err:
03470 g_free(essid);
03471 g_free(bssid);
03472
03473 if (reply == NULL) {
03474 DLOG_DEBUG("Parameter error in status request");
03475 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
03476 }
03477 send_and_unref(connection, reply);
03478 return DBUS_HANDLER_RESULT_HANDLED;
03479 }
03480
03487 static DBusHandlerResult interface_request(DBusMessage *message,
03488 DBusConnection *connection) {
03489 DBusMessage *reply;
03490 gchar* ifname = wlan_status.ifname;
03491
03492 reply = new_dbus_method_return(message);
03493
03494 append_dbus_args(reply,
03495 DBUS_TYPE_STRING, &ifname,
03496 DBUS_TYPE_INVALID);
03497
03498 send_and_unref(connection, reply);
03499
03500 return DBUS_HANDLER_RESULT_HANDLED;
03501 }
03502
03509 static DBusHandlerResult connection_status_request(
03510 DBusMessage *message,
03511 DBusConnection *connection) {
03512
03513 DBusMessage *reply;
03514 dbus_bool_t state = FALSE;
03515
03516 guint state_v = get_wlan_state();
03517
03518 if (state_v == WLAN_INITIALIZED ||
03519 state_v == WLAN_NO_ADDRESS ||
03520 state_v == WLAN_CONNECTED)
03521 state = TRUE;
03522
03523 reply = new_dbus_method_return(message);
03524
03525 append_dbus_args(reply,
03526 DBUS_TYPE_BOOLEAN, &state,
03527 DBUS_TYPE_INVALID);
03528
03529 send_and_unref(connection, reply);
03530
03531 return DBUS_HANDLER_RESULT_HANDLED;
03532 }
03539 static DBusHandlerResult set_pmksa_request(DBusMessage *message,
03540 DBusConnection *connection) {
03541
03542 DBusMessage *reply = NULL;
03543 unsigned int pmkid_len, mac_len;
03544 unsigned char *pmkid;
03545 unsigned char *mac;
03546 dbus_uint32_t action;
03547 DBusError derror;
03548
03549 dbus_error_init(&derror);
03550
03551 if (dbus_message_get_args(
03552 message, &derror,
03553 DBUS_TYPE_UINT32, &action,
03554 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &pmkid, &pmkid_len,
03555 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &mac, &mac_len,
03556 DBUS_TYPE_INVALID) == FALSE)
03557 {
03558 DLOG_ERR("Failed to parse set_pmksa request: %s",
03559 derror.message);
03560 dbus_error_free(&derror);
03561 goto param_err;
03562 }
03563
03564 if (action != IW_PMKSA_ADD) {
03565 DLOG_ERR("Invalid action");
03566 goto param_err;
03567 }
03568
03569 if (pmkid == NULL || pmkid_len != WLANCOND_PMKID_LEN || mac == NULL
03570 || mac_len != ETH_ALEN) {
03571 DLOG_ERR("Invalid arguments");
03572 goto param_err;
03573 }
03574
03575 add_to_pmksa_cache(pmkid, mac);
03576
03577 print_mac(WLANCOND_PRIO_LOW, "PMKSA added successfully for address:",
03578 mac);
03579
03580 reply = new_dbus_method_return(message);
03581 send_and_unref(connection, reply);
03582
03583 return DBUS_HANDLER_RESULT_HANDLED;
03584
03585 param_err:
03586 if (reply == NULL) {
03587 DLOG_DEBUG("Parameter error in set_pmksa");
03588 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
03589 }
03590 send_and_unref(connection, reply);
03591 return DBUS_HANDLER_RESULT_HANDLED;
03592 }
03593
03600 static DBusHandlerResult set_powersave_request(DBusMessage *message,
03601 DBusConnection *connection) {
03602
03603 DBusMessage *reply = NULL;
03604 int sock;
03605 DBusError error;
03606 dbus_bool_t onoff;
03607
03608 sock = socket_open();
03609
03610 dbus_error_init(&error);
03611
03612 if (dbus_message_get_args(message, &error,
03613 DBUS_TYPE_BOOLEAN, &onoff,
03614 DBUS_TYPE_INVALID) == FALSE) {
03615 DLOG_ERR("Failed to parse message: %s",
03616 error.message);
03617 dbus_error_free(&error);
03618
03619 send_invalid_args(connection, message);
03620 return DBUS_HANDLER_RESULT_HANDLED;
03621 }
03622
03623
03624
03625
03626 if (onoff == TRUE) {
03627 if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
03628 set_wlan_state(WLAN_NOT_INITIALIZED,
03629 NO_SIGNAL, FORCE_YES);
03630 } else if (get_wlan_state() != WLAN_NO_ADDRESS ||
03631 (connect_name_cache != NULL &&
03632 strcmp(dbus_message_get_sender(message),
03633 connect_name_cache) == 0)) {
03634 if (set_power_state(powersave, sock) == FALSE) {
03635 DLOG_ERR("Setting powersave failed");
03636
03637 }
03638 }
03639 } else {
03640
03641 if (set_power_state(WLANCOND_POWER_ON, sock) == FALSE) {
03642 DLOG_ERR("Setting powersave failed");
03643
03644 }
03645 }
03646
03647 DLOG_DEBUG("WLAN powersave %s", onoff==TRUE?"on":"off");
03648
03649 reply = new_dbus_method_return(message);
03650 send_and_unref(connection, reply);
03651
03652 return DBUS_HANDLER_RESULT_HANDLED;
03653 }
03654
03661 static void wpa_ie_push_cb(DBusPendingCall *pending,
03662 void *user_data)
03663 {
03664 DBusMessage *reply;
03665 DBusError error;
03666
03667
03668
03669 dbus_error_init (&error);
03670
03671 reply = dbus_pending_call_steal_reply(pending);
03672
03673 if (dbus_set_error_from_message(&error, reply)) {
03674
03675 DLOG_DEBUG("EAP WPA IE push call result:%s", error.name);
03676
03677 dbus_error_free(&error);
03678
03679 set_wlan_state(WLAN_NOT_INITIALIZED,
03680 DISCONNECTED_SIGNAL,
03681 FORCE_YES);
03682 }
03683
03684 if (reply)
03685 dbus_message_unref(reply);
03686 dbus_pending_call_unref(pending);
03687 }
03688
03697 int wpa_ie_push(unsigned char* ap_mac_addr, unsigned char* ap_wpa_ie,
03698 int ap_wpa_ie_len, char* ssid, int ssid_len,
03699 unsigned int authentication_type) {
03700
03701 DBusMessage *msg;
03702 DBusPendingCall *pending;
03703
03704 if (authentication_type != EAP_AUTH_TYPE_WFA_SC) {
03705 if (wlan_status.wpa_ie.ie_len == 0 || ap_wpa_ie == NULL ||
03706 ssid == NULL) {
03707 DLOG_ERR("WPA IE / SSID (%s) not valid", ssid);
03708 return -1;
03709 }
03710 }
03711
03712 msg = dbus_message_new_method_call(
03713 EAP_SERVICE,
03714 EAP_REQ_PATH,
03715 EAP_REQ_INTERFACE,
03716 EAP_WPA_IE_PUSH_REQ);
03717
03718 if (msg == NULL) {
03719 return -1;
03720 }
03721
03722 append_dbus_args(
03723 msg,
03724 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03725 &wlan_status.wpa_ie.ie, wlan_status.wpa_ie.ie_len,
03726 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ap_wpa_ie,
03727 ap_wpa_ie_len,
03728 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03729 &ssid, ssid_len,
03730 DBUS_TYPE_UINT32, &wlan_status.pairwise_cipher,
03731 DBUS_TYPE_UINT32, &wlan_status.group_cipher,
03732 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03733 &ap_mac_addr, ETH_ALEN,
03734 DBUS_TYPE_UINT32, &authentication_type,
03735 DBUS_TYPE_INVALID);
03736
03737 if (!dbus_connection_send_with_reply(get_dbus_connection(),
03738 msg, &pending, -1))
03739 die("Out of memory");
03740
03741 if (!dbus_pending_call_set_notify (pending, wpa_ie_push_cb, NULL, NULL))
03742 die("Out of memory");
03743
03744 dbus_message_unref(msg);
03745
03746 return 0;
03747 }
03754 int wpa_mic_failure_event(dbus_bool_t key_type, dbus_bool_t is_fatal) {
03755 DBusMessage *msg;
03756 DBusMessage *reply;
03757 DBusError derr;
03758
03759 msg = dbus_message_new_method_call(
03760 EAP_SERVICE,
03761 EAP_REQ_PATH,
03762 EAP_REQ_INTERFACE,
03763 EAP_WPA_MIC_FAILURE_REQ);
03764
03765 if (msg == NULL) {
03766 return -1;
03767 }
03768
03769 append_dbus_args(msg,
03770 DBUS_TYPE_BOOLEAN, &key_type,
03771 DBUS_TYPE_BOOLEAN, &is_fatal,
03772 DBUS_TYPE_INVALID);
03773
03774 dbus_error_init(&derr);
03775
03776 reply = dbus_connection_send_with_reply_and_block(
03777 get_dbus_connection(), msg, -1, &derr);
03778
03779 dbus_message_unref(msg);
03780
03781 if (dbus_error_is_set(&derr)) {
03782 DLOG_ERR("EAP returned error: %s", derr.name);
03783
03784 dbus_error_free(&derr);
03785 if (reply)
03786 dbus_message_unref(reply);
03787 return -1;
03788 }
03789
03790 dbus_message_unref(reply);
03791
03792 return 0;
03793 }
03798 int associate_supplicant(void) {
03799 DBusMessage *msg;
03800 DBusMessage *reply;
03801 DBusError derr;
03802
03803 msg = dbus_message_new_method_call(
03804 EAP_SERVICE,
03805 EAP_REQ_PATH,
03806 EAP_REQ_INTERFACE,
03807 EAP_ASSOCIATE_REQ);
03808
03809 if (msg == NULL) {
03810 return -1;
03811 }
03812
03813 dbus_error_init(&derr);
03814
03815 reply = dbus_connection_send_with_reply_and_block(
03816 get_dbus_connection(), msg, -1, &derr);
03817
03818 dbus_message_unref(msg);
03819
03820 if (dbus_error_is_set(&derr)) {
03821 DLOG_ERR("EAP returned error: %s", derr.name);
03822
03823 dbus_error_free(&derr);
03824 if (reply)
03825 dbus_message_unref(reply);
03826 return -1;
03827 }
03828
03829 dbus_message_unref(reply);
03830
03831 return 0;
03832 }
03839 static void disassociate_cb(DBusPendingCall *pending,
03840 void *user_data)
03841 {
03842 DBusMessage *reply;
03843 DBusError error;
03844
03845 dbus_error_init (&error);
03846
03847 reply = dbus_pending_call_steal_reply(pending);
03848
03849 if (dbus_set_error_from_message(&error, reply)) {
03850
03851 DLOG_DEBUG("EAP disassociate call result:%s", error.name);
03852
03853 dbus_error_free(&error);
03854 }
03855
03856 if (reply)
03857 dbus_message_unref(reply);
03858 dbus_pending_call_unref(pending);
03859 }
03860
03865 int disassociate_eap(void) {
03866 DBusMessage *msg;
03867 DBusPendingCall *pending;
03868
03869 msg = dbus_message_new_method_call(
03870 EAP_SERVICE,
03871 EAP_REQ_PATH,
03872 EAP_REQ_INTERFACE,
03873 EAP_DISASSOCIATE_REQ);
03874
03875 if (msg == NULL) {
03876 return -1;
03877 }
03878
03879 if (!dbus_connection_send_with_reply(get_dbus_connection(),
03880 msg, &pending, -1))
03881 die("Out of memory");
03882
03883 if (!dbus_pending_call_set_notify (pending, disassociate_cb, NULL,
03884 NULL))
03885 die("Out of memory");
03886
03887 dbus_message_unref(msg);
03888
03889 return 0;
03890 }
03891
03906 int check_pmksa_cache(unsigned char* own_mac, int own_mac_len,
03907 unsigned char* bssid, int bssid_len,
03908 uint32_t authentication_type,
03909 uint32_t pairwise_key_cipher_suite,
03910 uint32_t group_key_cipher_suite,
03911 int *status)
03912 {
03913 DBusMessage *msg = NULL;
03914 DBusMessage *reply = NULL;
03915 DBusError error;
03916 dbus_bool_t found;
03917
03918 dbus_error_init (&error);
03919
03920 msg = dbus_message_new_method_call(
03921 EAP_SERVICE,
03922 EAP_REQ_PATH,
03923 EAP_REQ_INTERFACE,
03924 EAP_CHECK_PMKSA_CACHE_REQ);
03925
03926 if (msg == NULL)
03927 return -1;
03928
03929 if (dbus_message_append_args(
03930 msg,
03931 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &own_mac, own_mac_len,
03932 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, bssid_len,
03933 DBUS_TYPE_UINT32, &authentication_type,
03934 DBUS_TYPE_UINT32, &pairwise_key_cipher_suite,
03935 DBUS_TYPE_UINT32, &group_key_cipher_suite,
03936 DBUS_TYPE_INVALID) == FALSE)
03937 {
03938 DLOG_ERR("Unable to add args to dbus method call.");
03939 dbus_message_unref(msg);
03940 return -1;
03941 }
03942
03943 reply = dbus_connection_send_with_reply_and_block(
03944 get_dbus_connection(), msg, -1, &error);
03945
03946 dbus_message_unref(msg);
03947
03948 if (dbus_error_is_set(&error)) {
03949 DLOG_ERR("EAP returned error: %s", error.message);
03950 dbus_error_free(&error);
03951
03952 goto error;
03953 }
03954
03955 if (!dbus_message_get_args(reply, &error,
03956 DBUS_TYPE_BOOLEAN, &found,
03957 DBUS_TYPE_INVALID))
03958 {
03959 DLOG_ERR("Error parsing the return value: %s", error.message);
03960 if (dbus_error_is_set(&error))
03961 dbus_error_free(&error);
03962
03963 goto error;
03964 }
03965
03966 dbus_message_unref(reply);
03967
03968 *status = found;
03969
03970 return 0;
03971
03972 error:
03973 if(reply)
03974 dbus_message_unref(reply);
03975
03976 return -1;
03977 }
03978
03979 #ifdef ENABLE_CALL_TYPE_CHECKING
03980
03985 void set_call_type(const char *type)
03986 {
03987 guint new_type;
03988
03989 if (!type || !strcmp(type, "none"))
03990 new_type = WLANCOND_CALL_NONE;
03991 else if (!strcmp(type, "skype"))
03992 new_type = WLANCOND_CALL_VOIP;
03993 else if (!strcmp(type, "cellular"))
03994 new_type = WLANCOND_CALL_CELL;
03995 else {
03996 DLOG_DEBUG("Unknown call type: %s", type);
03997 new_type = WLANCOND_CALL_UNKNOWN;
03998 }
03999
04000 if (new_type == wlan_status.call_state)
04001 return;
04002
04003 DLOG_DEBUG("Switching call type to %i (%s)", new_type, type);
04004
04005 wlan_status.call_state = new_type;
04006
04007
04008 set_power_state(wlan_status.requested_power, socket_open());
04009 }
04010
04018 int context_parser(DBusMessageIter *actit)
04019 {
04020 DBusMessageIter cmdit;
04021 DBusMessageIter argit;
04022 DBusMessageIter valit;
04023 char *argname;
04024 char *argval;
04025 char *variable;
04026 char *value;
04027
04028 do {
04029 variable = value = NULL;
04030
04031 dbus_message_iter_recurse(actit, &cmdit);
04032
04033 do {
04034 if (dbus_message_iter_get_arg_type(&cmdit) !=
04035 DBUS_TYPE_STRUCT)
04036 return FALSE;
04037
04038 dbus_message_iter_recurse(&cmdit, &argit);
04039
04040 if (dbus_message_iter_get_arg_type(&argit) !=
04041 DBUS_TYPE_STRING)
04042 return FALSE;
04043
04044 dbus_message_iter_get_basic(&argit, (void *)&argname);
04045
04046 if (!dbus_message_iter_next(&argit))
04047 return FALSE;
04048
04049 if (dbus_message_iter_get_arg_type(&argit) !=
04050 DBUS_TYPE_VARIANT)
04051 return FALSE;
04052
04053 dbus_message_iter_recurse(&argit, &valit);
04054
04055 if (dbus_message_iter_get_arg_type(&valit) !=
04056 DBUS_TYPE_STRING)
04057 return FALSE;
04058
04059 dbus_message_iter_get_basic(&valit, (void *)&argval);
04060
04061 if (!strcmp(argname, "variable")) {
04062 variable = argval;
04063 }
04064 else if (!strcmp(argname, "value")) {
04065 value = argval;
04066 }
04067
04068 if (!strcmp(variable, "call_audio_type"))
04069 set_call_type(value);
04070
04071 } while (dbus_message_iter_next(&cmdit));
04072
04073 } while (dbus_message_iter_next(actit));
04074
04075 return TRUE;
04076 }
04077
04082 void handle_policy_actions(DBusMessage *msg)
04083 {
04084 dbus_uint32_t txid;
04085 char *actname;
04086 DBusMessageIter msgit;
04087 DBusMessageIter arrit;
04088 DBusMessageIter entit;
04089 DBusMessageIter actit;
04090 int success = TRUE;
04091
04092 dbus_message_iter_init(msg, &msgit);
04093
04094 if (dbus_message_iter_get_arg_type(&msgit) != DBUS_TYPE_UINT32)
04095 return;
04096
04097 dbus_message_iter_get_basic(&msgit, (void *)&txid);
04098
04099 if (!dbus_message_iter_next(&msgit) ||
04100 dbus_message_iter_get_arg_type(&msgit) !=
04101 DBUS_TYPE_ARRAY) {
04102 success = FALSE;
04103 goto out;
04104 }
04105
04106 dbus_message_iter_recurse(&msgit, &arrit);
04107
04108 do {
04109 if (dbus_message_iter_get_arg_type(&arrit) !=
04110 DBUS_TYPE_DICT_ENTRY) {
04111 success = FALSE;
04112 continue;
04113 }
04114
04115 dbus_message_iter_recurse(&arrit, &entit);
04116
04117 do {
04118 if (dbus_message_iter_get_arg_type(&entit) !=
04119 DBUS_TYPE_STRING) {
04120 success = FALSE;
04121 continue;
04122 }
04123
04124 dbus_message_iter_get_basic(&entit, (void *)&actname);
04125
04126 if (!dbus_message_iter_next(&entit) ||
04127 dbus_message_iter_get_arg_type(&entit)
04128 != DBUS_TYPE_ARRAY) {
04129 success = FALSE;
04130 continue;
04131 }
04132
04133 dbus_message_iter_recurse(&entit, &actit);
04134
04135 if (dbus_message_iter_get_arg_type(&actit) !=
04136 DBUS_TYPE_ARRAY) {
04137 success = FALSE;
04138 continue;
04139 }
04140
04141 if (!strcmp(actname, "com.nokia.policy.context"))
04142 success &= context_parser(&actit);
04143
04144 } while (dbus_message_iter_next(&entit));
04145
04146 } while (dbus_message_iter_next(&arrit));
04147
04148 out:
04149 if (!success)
04150 DLOG_DEBUG("Failed to parse the policy actions message.");
04151 }
04152 #endif
04153
04154
04155 typedef DBusHandlerResult (*handler_func)(DBusMessage *message,
04156 DBusConnection *connection);
04157
04158 typedef struct {
04159 const char *interface;
04160 const char *name;
04161 handler_func func;
04162 } method_handler_t;
04163
04164 static method_handler_t handlers[] = {
04165 { WLANCOND_REQ_INTERFACE, WLANCOND_SETTINGS_AND_CONNECT_REQ,
04166 settings_and_connect_request},
04167 { WLANCOND_REQ_INTERFACE, WLANCOND_SCAN_REQ, scan_request},
04168 { WLANCOND_REQ_INTERFACE, WLANCOND_STATUS_REQ, status_request},
04169 { WLANCOND_REQ_INTERFACE, WLANCOND_INTERFACE_REQ, interface_request},
04170 { WLANCOND_REQ_INTERFACE, WLANCOND_CONNECTION_STATUS_REQ,
04171 connection_status_request},
04172 { WLANCOND_REQ_INTERFACE, WLANCOND_SET_PMKSA_REQ, set_pmksa_request},
04173 { WLANCOND_REQ_INTERFACE, WLANCOND_SET_POWERSAVE_REQ,
04174 set_powersave_request},
04175 { WLANCOND_REQ_INTERFACE, WLANCOND_DISCONNECT_REQ, disconnect_request},
04176 { WLANCOND_REQ_INTERFACE, WLANCOND_DISASSOCIATE_REQ,
04177 disassociate_request},
04178 { NULL }
04179 };
04180
04187 DBusHandlerResult wlancond_req_handler(DBusConnection *connection,
04188 DBusMessage *message,
04189 void *user_data)
04190 {
04191 method_handler_t *handler;
04192
04193 DLOG_DEBUG("Received %s.%s",
04194 dbus_message_get_interface(message),
04195 dbus_message_get_member(message));
04196
04197
04198 #ifdef USE_MCE_MODE
04199 if (dbus_message_is_signal(message,
04200 MCE_SIGNAL_IF,
04201 MCE_DEVICE_MODE_SIG)) {
04202 return mode_change_dbus(message);
04203 }
04204 #ifdef ACTIVITY_CHECK
04205 if (dbus_message_is_signal(message,
04206 MCE_SIGNAL_IF,
04207 MCE_INACTIVITY_SIG)) {
04208 return activity_check_dbus(message);
04209 }
04210 #endif
04211 #endif
04212 if (dbus_message_is_signal(message,
04213 ICD_DBUS_INTERFACE,
04214 ICD_STATUS_CHANGED_SIG))
04215 return icd_check_signal_dbus(message);
04216
04217 if (dbus_message_is_signal(message,
04218 PHONE_NET_DBUS_INTERFACE,
04219 PHONE_REGISTRATION_STATUS_CHANGE_SIG))
04220 return csd_check_signal_dbus(message);
04221
04222 if (dbus_message_is_signal (message,
04223 BLUEZ_ADAPTER_SERVICE_NAME,
04224 BLUEZ_ADAPTER_PROPERTY_CHANGED_SIG))
04225 return bluez_check_adapter_signal_dbus(message);
04226
04227 if (dbus_message_is_signal (message,
04228 BLUEZ_HEADSET_SERVICE_NAME,
04229 BLUEZ_HEADSET_PROPERTY_CHANGED_SIG))
04230 return bluez_check_headset_signal_dbus(message);
04231
04232 if (dbus_message_is_signal (message,
04233 BLUEZ_AUDIOSINK_SERVICE_NAME,
04234 BLUEZ_AUDIOSINK_PROPERTY_CHANGED_SIG))
04235 return bluez_check_headset_signal_dbus(message);
04236
04237 #ifdef ENABLE_CALL_TYPE_CHECKING
04238 if (dbus_message_is_signal(message, POLICY_SERVICE_NAME,
04239 POLICY_ACTIONS_SIG)) {
04240 handle_policy_actions(message);
04241 return DBUS_HANDLER_RESULT_HANDLED;
04242 }
04243 #endif
04244
04245
04246 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
04247 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04248 }
04249
04250 for (handler = handlers; handler->interface != NULL; handler++) {
04251 if (dbus_message_is_method_call(message,
04252 handler->interface,
04253 handler->name)) {
04254 DLOG_DEBUG("Received %s", handler->name);
04255 return handler->func(message, connection);
04256 }
04257 }
04258 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04259 }
04260
04261 static DBusObjectPathVTable wlancond_req_vtable = {
04262 .message_function = wlancond_req_handler,
04263 .unregister_function = NULL
04264 };
04265
04266
04271 void init_dbus_handlers(DBusConnection *connection) {
04272 dbus_bool_t ret;
04273 ret = dbus_connection_register_object_path(connection,
04274 WLANCOND_REQ_PATH,
04275 &wlancond_req_vtable,
04276 NULL);
04277 if (ret == FALSE) {
04278 DLOG_ERR("dbus_connection_register_object_path failed");
04279 }
04280 #ifdef USE_MCE_MODE
04281 if (!add_mode_listener(connection)) {
04282 DLOG_ERR("Adding mode listener failed");
04283 }
04284 #endif
04285 if (!add_icd_listener(connection)) {
04286 DLOG_ERR("Adding icd listener failed");
04287 }
04288
04289 if (!add_csd_listener(connection)) {
04290 DLOG_ERR("Adding csd listener failed");
04291 }
04292 if (!add_bluez_listener(connection)) {
04293 DLOG_ERR("Adding Bluez listener failed");
04294 }
04295 }
04296
04301 void destroy_dbus_handlers(DBusConnection *connection) {
04302 dbus_connection_unregister_object_path(connection, WLANCOND_REQ_PATH);
04303 }