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 }
00204 void init_logging(void) {
00205 debug_level = get_gconf_int(DEBUG_LEVEL);
00206 if (debug_level < 0)
00207 debug_level = 0;
00208
00209 if (debug_level > 0) {
00210 DLOG_DEBUG("Debug level increased to %d", debug_level);
00211 }
00212 }
00213
00219 void update_own_ie(unsigned char* wpa_ie, guint wpa_ie_len)
00220 {
00221 g_free(wlan_status.wpa_ie.ie);
00222 wlan_status.wpa_ie.ie = wpa_ie;
00223 wlan_status.wpa_ie.ie_len = wpa_ie_len;
00224 }
00229 guint get_encryption_info(void)
00230 {
00231 guint auth_status = 0;
00232
00233 if (wlan_status.pairwise_cipher & CIPHER_SUITE_CCMP) {
00234 auth_status |= WLANCOND_WPA_AES;
00235 } else if (wlan_status.pairwise_cipher & CIPHER_SUITE_TKIP) {
00236 auth_status |= WLANCOND_WPA_TKIP;
00237 } else if (wlan_status.pairwise_cipher & CIPHER_SUITE_WEP40 ||
00238 wlan_status.pairwise_cipher & CIPHER_SUITE_WEP104) {
00239 auth_status |= WLANCOND_WEP;
00240 } else {
00241 auth_status |= WLANCOND_OPEN;
00242 }
00243 return auth_status;
00244 }
00245
00249 int clean_dbus_handler(void)
00250 {
00251 if (wlan_socket > 0)
00252 close(wlan_socket);
00253 return 0;
00254 }
00259 void mode_change(const char *mode) {
00260
00261 DLOG_INFO("WLAN flight mode changed to \"%s\"", mode);
00262
00263 if (g_str_equal(mode, "flight")) {
00264 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
00265 FORCE_YES);
00266 _flight_mode = TRUE;
00267 }
00268 else if (g_str_equal(mode, "normal")) {
00269 _flight_mode = FALSE;
00270 }
00271 else {
00272 DLOG_ERR("Invalid mode \"%s\" passed to mode_change()", mode);
00273 }
00274 }
00279 #ifdef USE_MCE_MODE
00280 static DBusHandlerResult mode_change_dbus(DBusMessage *message) {
00281
00282 char *mode;
00283
00284 if (!dbus_message_get_args(message, NULL,
00285 DBUS_TYPE_STRING, &mode,
00286 DBUS_TYPE_INVALID)) {
00287 DLOG_ERR("Invalid arguments for device_mode_ind signal");
00288 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00289 }
00290
00291 mode_change(mode);
00292
00293 return DBUS_HANDLER_RESULT_HANDLED;
00294 }
00295 #ifdef ACTIVITY_CHECK
00296 static DBusHandlerResult activity_check_dbus(DBusMessage *message) {
00297
00298 if (!dbus_message_get_args(message, NULL,
00299 DBUS_TYPE_BOOLEAN, &saved_inactivity,
00300 DBUS_TYPE_INVALID)) {
00301 DLOG_ERR("Invalid arguments for device_activity signal");
00302 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00303 }
00304 activity_check(saved_inactivity);
00305
00306 return DBUS_HANDLER_RESULT_HANDLED;
00307 }
00308 #endif
00309 #endif
00310
00311 #ifdef ACTIVITY_CHECK
00312
00315 void activity_check(dbus_bool_t inactivity) {
00316
00317 int sock;
00318
00319 if (get_wlan_state() != WLAN_CONNECTED) {
00320 return;
00321 }
00322
00323 sock = socket_open();
00324
00325 if (inactivity == FALSE) {
00326
00327 } else {
00328
00329 }
00330
00331 set_power_state(powersave, sock);
00332 }
00333
00337 static gboolean get_inactivity_status(void)
00338 {
00339 return saved_inactivity;
00340 }
00341 #endif
00342
00347 static DBusHandlerResult icd_check_signal_dbus(DBusMessage *message) {
00348
00349 char *icd_name;
00350 char *icd_type;
00351 char *icd_state;
00352 char *icd_disconnect_reason;
00353 DBusError dbus_error;
00354
00355 if ((get_wlan_state() != WLAN_CONNECTED &&
00356 get_wlan_state() != WLAN_NO_ADDRESS) ||
00357 get_mode() != WLANCOND_INFRA) {
00358 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00359 }
00360
00361 dbus_error_init(&dbus_error);
00362 if (!dbus_message_get_args(message, &dbus_error,
00363 DBUS_TYPE_STRING, &icd_name,
00364 DBUS_TYPE_STRING, &icd_type,
00365 DBUS_TYPE_STRING, &icd_state,
00366 DBUS_TYPE_STRING, &icd_disconnect_reason,
00367 DBUS_TYPE_INVALID ) )
00368 {
00369 DLOG_ERR("Could not get args from signal, '%s'",
00370 dbus_error.message);
00371 dbus_error_free(&dbus_error);
00372 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00373 }
00374
00375 if (icd_state != NULL && strncmp(icd_state, "CONNECTED", 9) == 0) {
00376
00377 set_wlan_state(WLAN_CONNECTED, NO_SIGNAL, FORCE_NO);
00378
00379 DLOG_DEBUG("Going to power save");
00380
00381 if (set_power_state(powersave, socket_open()) == FALSE) {
00382 DLOG_ERR("Failed to set power save");
00383 }
00384
00385 }
00386
00387
00388
00389 return DBUS_HANDLER_RESULT_HANDLED;
00390 }
00394 static gint run_calibration(void) {
00395 gchar *args[2];
00396 gint count = 0;
00397 args[count++] = (gchar*)"/usr/bin/wl1251-cal";
00398 args[count++] = NULL;
00399
00400 if (!g_spawn_sync (NULL, args, NULL, 0,
00401 NULL, NULL, NULL, NULL, NULL, NULL)) {
00402 return -1;
00403 }
00404 return 0;
00405 }
00409 #define KILL_SUPPLICANT "/usr/bin/killall"
00410 #define SUPPLICANT_NAME "eapd"
00411 static void kill_supplicant(void) {
00412 gchar *args[3];
00413 guint count = 0;
00414 args[count++] = (gchar*)KILL_SUPPLICANT;
00415 args[count++] = (gchar*)"-9";
00416 args[count++] = (gchar*)SUPPLICANT_NAME;
00417
00418 if (!g_spawn_sync (NULL, args, NULL, 0,
00419 NULL, NULL, NULL, NULL, NULL, NULL)) {
00420 DLOG_ERR("Failed to run %s", KILL_SUPPLICANT);
00421 }
00422 }
00423 #define WLANCOND_WAIT_COUNTRY 2000 //2s
00424
00428 static gint check_country_code(void) {
00429 DBusMessage *msg, *reply;
00430 DBusError error;
00431 dbus_uint32_t current_cell_id;
00432 dbus_uint32_t network_code;
00433 dbus_uint32_t country_code;
00434 dbus_uint16_t current_lac;
00435 guchar reg_status;
00436 guchar network_type;
00437 guchar supported_services;
00438
00439 dbus_error_init(&error);
00440
00441 msg = dbus_message_new_method_call(
00442 "com.nokia.phone.net",
00443 "/com/nokia/phone/net",
00444 "Phone.Net",
00445 "get_registration_status");
00446
00447 if (msg == NULL) {
00448 return -1;
00449 }
00450
00451 reply = dbus_connection_send_with_reply_and_block(
00452 get_dbus_connection(), msg, WLANCOND_WAIT_COUNTRY, &error);
00453
00454 dbus_message_unref(msg);
00455
00456 if (dbus_error_is_set(&error)) {
00457 DLOG_ERR("Failed to ask registration status: %s",
00458 error.name);
00459 dbus_error_free(&error);
00460 if (reply)
00461 dbus_message_unref(reply);
00462 return -1;
00463 }
00464 dbus_error_init(&error);
00465
00466 if (!dbus_message_get_args(reply, &error,
00467 DBUS_TYPE_BYTE, ®_status,
00468 DBUS_TYPE_UINT16, ¤t_lac,
00469 DBUS_TYPE_UINT32, ¤t_cell_id,
00470 DBUS_TYPE_UINT32, &network_code,
00471 DBUS_TYPE_UINT32, &country_code,
00472 DBUS_TYPE_BYTE, &network_type,
00473 DBUS_TYPE_BYTE, &supported_services,
00474 DBUS_TYPE_INVALID))
00475 {
00476 DLOG_ERR("Could not get args from reply, '%s'",
00477 error.message);
00478 dbus_error_free(&error);
00479 if (reply)
00480 dbus_message_unref(reply);
00481 return -1;
00482 }
00483 DLOG_INFO("Device country: %d", country_code);
00484
00485 dbus_message_unref(reply);
00486
00487 return country_code;
00488 }
00489 static void set_bt_coex_state(unsigned int state) {
00490 FILE * file;
00491 char buf[4];
00492
00493 DLOG_DEBUG("Setting coex state to %i", state);
00494
00495 file = fopen(WLANCOND_BT_COEX_FILE, "w");
00496 if (file == NULL) {
00497 DLOG_DEBUG("Cannot open: %s", WLANCOND_BT_COEX_FILE);
00498 return;
00499 }
00500
00501 sprintf(buf, "%d", state);
00502
00503 if (fwrite(buf, 1, 1, file) != 1) {
00504 DLOG_DEBUG("Could not write to: %s", WLANCOND_BT_COEX_FILE);
00505 }
00506 fclose(file);
00507
00508 wlan_status.coex_state = state;
00509 if (wlan_status.state != WLAN_NOT_INITIALIZED)
00510 if (!set_power_state(wlan_status.requested_power,
00511 socket_open()))
00512 DLOG_DEBUG("Unable to set the power state");
00513
00514 return;
00515 }
00521 static DBusHandlerResult csd_check_signal_dbus(DBusMessage *message) {
00522
00523 DBusError error;
00524 dbus_uint32_t current_cell_id;
00525 dbus_uint32_t network_code;
00526 dbus_uint32_t country_code;
00527 dbus_uint16_t current_lac;
00528 guchar reg_status;
00529 guchar network_type;
00530 guchar supported_services;
00531
00532 dbus_error_init(&error);
00533
00534 if (!dbus_message_get_args(message, &error,
00535 DBUS_TYPE_BYTE, ®_status,
00536 DBUS_TYPE_UINT16, ¤t_lac,
00537 DBUS_TYPE_UINT32, ¤t_cell_id,
00538 DBUS_TYPE_UINT32, &network_code,
00539 DBUS_TYPE_UINT32, &country_code,
00540 DBUS_TYPE_BYTE, &network_type,
00541 DBUS_TYPE_BYTE, &supported_services,
00542 DBUS_TYPE_INVALID))
00543 {
00544 DLOG_ERR("Could not get args from signal, '%s'",
00545 error.message);
00546 dbus_error_free(&error);
00547 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00548 }
00549
00550 DLOG_DEBUG("Handled csd signal, country:%d", country_code);
00551
00552 if ((gint)country_code != wlan_status.country_code &&
00553 wlan_status.country_code != -1) {
00554 wlan_status.country_code = -1;
00555 DLOG_INFO("Country changed to: %d", country_code);
00556 }
00557
00558 return DBUS_HANDLER_RESULT_HANDLED;
00559 }
00565 static DBusHandlerResult bluez_check_adapter_signal_dbus(DBusMessage *message) {
00566 DBusError error;
00567 const gchar *property_name = NULL;
00568 DBusMessageIter msg_iter;
00569 DBusMessageIter variant_iter;
00570 dbus_error_init(&error);
00571
00572 if (!dbus_message_get_args (message, &error,
00573 DBUS_TYPE_STRING, &property_name,
00574 DBUS_TYPE_INVALID))
00575 {
00576 DLOG_ERR("Could not get args from signal, '%s'",
00577 error.message);
00578 dbus_error_free(&error);
00579 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00580 }
00581
00582 if (property_name != NULL &&
00583 strcmp (property_name, BLUEZ_ADAPTER_PROPERTY_POWERED) == 0)
00584 {
00585 dbus_message_iter_init (message, &msg_iter);
00586 dbus_message_iter_next(&msg_iter);
00587 if (dbus_message_iter_get_arg_type(&msg_iter)
00588 != DBUS_TYPE_VARIANT) {
00589 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00590 }
00591 dbus_message_iter_recurse(&msg_iter, &variant_iter);
00592 if (dbus_message_iter_get_arg_type(&variant_iter)
00593 != DBUS_TYPE_BOOLEAN) {
00594 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00595 }
00596 dbus_message_iter_get_basic(&variant_iter, &saved_bt_power);
00597
00598 DLOG_DEBUG("Got signal, powered: %d", saved_bt_power);
00599
00600 if (saved_bt_power == TRUE)
00601 set_bt_coex_state(WLANCOND_BT_COEX_ON);
00602 else
00603 set_bt_coex_state(WLANCOND_BT_COEX_OFF);
00604 }
00605 return DBUS_HANDLER_RESULT_HANDLED;
00606 }
00612 static DBusHandlerResult bluez_check_headset_signal_dbus(DBusMessage *message) {
00613 DBusError error;
00614 const gchar *property_name = NULL;
00615 DBusMessageIter msg_iter;
00616 DBusMessageIter variant_iter;
00617 const gchar *state;
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_HEADSET_PROPERTY_STATE) == 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_STRING) {
00642 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00643 }
00644 dbus_message_iter_get_basic(&variant_iter, &state);
00645
00646 if (state != NULL) {
00647 DLOG_DEBUG("State: %s", state);
00648
00649
00650
00651
00652 if (!strcmp(state, BLUEZ_HEADSET_PROPERTY_PLAYING)) {
00653 set_bt_coex_state(WLANCOND_BT_COEX_MONOAUDIO);
00654 } else {
00655 if (saved_bt_power == TRUE)
00656 set_bt_coex_state(WLANCOND_BT_COEX_ON);
00657 else
00658 set_bt_coex_state(WLANCOND_BT_COEX_OFF);
00659 }
00660 }
00661 }
00662 return DBUS_HANDLER_RESULT_HANDLED;
00663 }
00664
00669 static gchar *gateway_bluez_default_adapter_path (void)
00670 {
00671 DBusMessage *msg, *reply = NULL;
00672 gchar *path = NULL;
00673 DBusError derr;
00674
00675 msg = dbus_message_new_method_call(
00676 BLUEZ_SERVICE_NAME,
00677 BLUEZ_MANAGER_PATH_NAME,
00678 BLUEZ_MANAGER_INTERFACE_NAME,
00679 BLUEZ_MANAGER_DEFAULT_ADAPTER_METHOD);
00680
00681 if (msg == NULL) {
00682 return NULL;
00683 }
00684
00685 dbus_error_init(&derr);
00686
00687 reply = dbus_connection_send_with_reply_and_block(
00688 get_dbus_connection(), msg, -1, &derr);
00689
00690 dbus_message_unref(msg);
00691
00692 if (dbus_error_is_set(&derr)) {
00693 DLOG_ERR("BlueZ returned error: %s", derr.name);
00694
00695 dbus_error_free(&derr);
00696 if (reply)
00697 dbus_message_unref(reply);
00698 return NULL;
00699 }
00700
00701 if (reply == NULL)
00702 return NULL;
00703
00704 dbus_error_init (&derr);
00705 if (!dbus_message_get_args (reply, &derr,
00706 DBUS_TYPE_OBJECT_PATH, &path,
00707 DBUS_TYPE_INVALID))
00708 {
00709 DLOG_ERR("Could not get arguments: %s",
00710 derr.message);
00711 dbus_error_free (&derr);
00712 dbus_message_unref (reply);
00713 return NULL;
00714 }
00715
00716 path = g_strdup(path);
00717 dbus_message_unref (reply);
00718
00719 return path;
00720 }
00721 static gboolean gateway_adapter_point_iter_to_value (
00722 DBusMessageIter *msg_iter,
00723 const gchar *property_name)
00724 {
00725 DBusMessageIter array_iter;
00726
00727
00728
00729 if (dbus_message_iter_get_arg_type (msg_iter) != DBUS_TYPE_ARRAY ||
00730 dbus_message_iter_get_element_type (msg_iter) !=
00731 DBUS_TYPE_DICT_ENTRY)
00732 return FALSE;
00733
00734 for (dbus_message_iter_recurse(msg_iter, &array_iter);
00735 dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_INVALID;
00736 dbus_message_iter_next (&array_iter))
00737 {
00738 DBusMessageIter dict_iter;
00739 const gchar *name = NULL;
00740
00741
00742 if (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_DICT_ENTRY)
00743 continue;
00744
00745
00746 dbus_message_iter_recurse (&array_iter, &dict_iter);
00747
00748 if (dbus_message_iter_get_arg_type(&dict_iter)
00749 != DBUS_TYPE_STRING)
00750 return FALSE;
00751
00752 dbus_message_iter_get_basic(&dict_iter, &name);
00753 dbus_message_iter_next(&dict_iter);
00754
00755
00756
00757 if (name == NULL || strcmp (name, property_name) != 0)
00758 continue;
00759
00760
00761 if (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_VARIANT)
00762 {
00763 dbus_message_iter_recurse(&dict_iter, msg_iter);
00764 return TRUE;
00765 }
00766 }
00767 return FALSE;
00768 }
00769
00770 static DBusMessage *gateway_adapter_get_property_values (
00771 const gchar *adapter_path,
00772 ...)
00773 {
00774 DBusMessage *request = NULL, *reply = NULL;
00775 const gchar *property_name = NULL;
00776 DBusMessageIter msg_iter;
00777 va_list ap;
00778
00779 request = dbus_message_new_method_call(
00780 BLUEZ_SERVICE_NAME,
00781 adapter_path,
00782 BLUEZ_ADAPTER_SERVICE_NAME,
00783 BLUEZ_ADAPTER_GET_PROPERTIES_METHOD);
00784
00785 if (request == NULL)
00786 return NULL;
00787
00788 reply = dbus_connection_send_with_reply_and_block(
00789 get_dbus_connection(), request, -1, NULL);
00790
00791 dbus_message_unref(request);
00792
00793 if (reply == NULL)
00794 return NULL;
00795
00796 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
00797 {
00798 DLOG_ERR("gateway_adapter_get_property_values: %s",
00799 dbus_message_get_error_name(reply));
00800 dbus_message_unref(reply);
00801 return NULL;
00802 }
00803
00804 for (va_start(ap, adapter_path);
00805 (property_name = va_arg(ap, const gchar *)) != NULL;)
00806 {
00807 DBusMessageIter *msg_iter_ret = va_arg(ap, DBusMessageIter *);
00808
00809 if (!dbus_message_iter_init(reply, &msg_iter) ||
00810 !gateway_adapter_point_iter_to_value (
00811 &msg_iter, property_name))
00812 {
00813 DLOG_ERR("Unable to point to property '%s'",
00814 property_name);
00815 va_end(ap);
00816 dbus_message_unref(reply);
00817 return NULL;
00818 }
00819
00820 if (msg_iter_ret != NULL)
00821 *msg_iter_ret = msg_iter;
00822 else
00823 break;
00824 }
00825 va_end(ap);
00826
00827 return reply;
00828 }
00833 static gint handle_country(void) {
00834
00835
00836
00837
00838 if (wlan_status.country_code < 0) {
00839
00840
00841
00842 gint code = check_country_code();
00843 if (code >= 0)
00844 wlan_status.country_code = code;
00845 if (run_calibration() < 0) {
00846 DLOG_ERR("Fatal: Could not calibrate");
00847 }
00848 }
00849 return 0;
00850 }
00854 static void check_bt_status(void) {
00855 DBusMessageIter msg_iter;
00856 char* default_adapter;
00857 dbus_bool_t powered;
00858 DBusMessage *property_message = NULL;
00859
00860 default_adapter = gateway_bluez_default_adapter_path();
00861
00862 if (default_adapter != NULL) {
00863 property_message = gateway_adapter_get_property_values(
00864 default_adapter,
00865 BLUEZ_ADAPTER_PROPERTY_POWERED, &msg_iter,
00866 NULL);
00867
00868 g_free(default_adapter);
00869
00870 if (property_message == NULL)
00871 {
00872 DLOG_ERR("Unable to get properties");
00873 return;
00874 }
00875
00876 dbus_message_iter_get_basic(&msg_iter, &powered);
00877
00878 DLOG_DEBUG("Default adapter is %s", powered == TRUE?"powered":
00879 "not powered");
00880
00881 if (powered == TRUE)
00882 set_bt_coex_state(WLANCOND_BT_COEX_ON);
00883 else
00884 set_bt_coex_state(WLANCOND_BT_COEX_OFF);
00885
00886 dbus_message_unref(property_message);
00887 } else {
00888 DLOG_DEBUG("Default adapter was NULL");
00889 set_bt_coex_state(WLANCOND_BT_COEX_OFF);
00890 }
00891 }
00895 int init_dbus_handler(void)
00896 {
00897 handle_country();
00898
00899 if (get_own_mac() < 0) {
00900 DLOG_ERR("Could not get own MAC address");
00901 return -1;
00902 }
00903
00904 check_bt_status();
00905
00906 return 0;
00907 }
00908
00909 static gboolean in_flight_mode(void) {
00910 return _flight_mode;
00911 }
00912
00913 void set_wlan_signal(gboolean high_or_low)
00914 {
00915 if (high_or_low == WLANCOND_HIGH) {
00916 wlan_status.signal = WLANCOND_HIGH;
00917 remove_roam_scan_timer();
00918 } else {
00919 wlan_status.signal = WLANCOND_LOW;
00920 }
00921 }
00922
00923 void remove_roam_scan_timer(void)
00924 {
00925 if (wlan_status.roam_scan_id) {
00926 g_source_remove(wlan_status.roam_scan_id);
00927 wlan_status.roam_scan_id = 0;
00928 }
00929 }
00930
00931 void remove_connect_timer(void)
00932 {
00933 if (wlan_connect_timer_id) {
00934 g_source_remove(wlan_connect_timer_id);
00935 wlan_connect_timer_id = 0;
00936 }
00937 }
00938
00939 static void remove_wlan_if_timer(void)
00940 {
00941
00942 if (wlan_if_down_timer_id) {
00943 g_source_remove(wlan_if_down_timer_id);
00944 wlan_if_down_timer_id = 0;
00945 }
00946 }
00947
00948 void remove_scan_timer(void)
00949 {
00950 if (wlan_status.scan_id) {
00951 g_source_remove(wlan_status.scan_id);
00952 wlan_status.scan_id = 0;
00953 }
00954 }
00955
00961 static gboolean wlan_connect_timer_cb(void* data)
00962 {
00963 if (wlan_connect_timer_id && get_wlan_state() ==
00964 WLAN_INITIALIZED_FOR_CONNECTION) {
00965
00966 wlan_connect_timer_id = 0;
00967
00968 DLOG_DEBUG("Association timeout, try: %d",
00969 wlan_status.retry_count);
00970
00971
00972 remove_from_roam_cache(wlan_status.conn.bssid);
00973
00974
00975 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
00976
00977 if (find_connection_and_associate(wlan_status.roam_cache,
00978 FALSE, FALSE, FALSE) == 0)
00979 return FALSE;
00980
00981
00982 if (++wlan_status.retry_count < WLANCOND_MAX_SCAN_TRIES) {
00983 if (scan(wlan_status.conn.ssid,
00984 wlan_status.conn.ssid_len, TRUE) == 0) {
00985 return FALSE;
00986 }
00987 }
00988
00989 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
00990 FORCE_YES);
00991 return FALSE;
00992 }
00993
00994 wlan_connect_timer_id = 0;
00995
00996
00997
00998 return FALSE;
00999 }
01005 static gboolean wlan_scan_cb(void* data)
01006 {
01007
01008 wlan_status.scan_id = 0;
01009
01010 DLOG_ERR("Scan failed, should not happen!");
01011
01012 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, FORCE_YES);
01013
01014 return FALSE;
01015 }
01021 static gboolean wlan_if_down_cb(void* data)
01022 {
01023
01024 wlan_if_down_timer_id = 0;
01025
01026 if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
01027 DLOG_DEBUG("Delayed shutdown occurred");
01028 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
01029 return FALSE;
01030 }
01031
01032
01033
01034 return FALSE;
01035 }
01043 int mlme_command(guchar* addr, guint16 cmd, guint16 reason_code)
01044 {
01045 struct iwreq req;
01046 struct iw_mlme mlme;
01047
01048 init_iwreq(&req);
01049
01050 DLOG_INFO("%s", cmd==IW_MLME_DEAUTH?"Deauthenticating":
01051 "Disassociating");
01052
01053 memset(&mlme, 0, sizeof(mlme));
01054
01055 mlme.cmd = cmd;
01056 mlme.reason_code = reason_code;
01057 mlme.addr.sa_family = ARPHRD_ETHER;
01058 memcpy(mlme.addr.sa_data, addr, ETH_ALEN);
01059
01060 req.u.data.pointer = (caddr_t) &mlme;
01061 req.u.data.length = sizeof(mlme);
01062
01063 if (ioctl(socket_open(), SIOCSIWMLME, &req) < 0) {
01064 DLOG_ERR("Failed to run MLME command");
01065 return -1;
01066 }
01067
01068 return 0;
01069 }
01073 static int set_mode(guint32 mode)
01074 {
01075 struct iwreq req;
01076
01077 init_iwreq(&req);
01078
01079 switch (mode) {
01080 case WLANCOND_ADHOC:
01081 req.u.mode = IW_MODE_ADHOC;
01082 DLOG_DEBUG("Setting mode: adhoc");
01083 break;
01084 case WLANCOND_INFRA:
01085 req.u.mode = IW_MODE_INFRA;
01086 DLOG_DEBUG("Setting mode: infra");
01087 break;
01088 default:
01089 DLOG_ERR("Operating mode undefined\n");
01090 return -1;
01091 }
01092
01093 if (ioctl(socket_open(), SIOCSIWMODE, &req) < 0) {
01094 DLOG_ERR("Operating mode setting failed\n");
01095 return -1;
01096 }
01097 return 0;
01098 }
01104 static int set_wep_keys(struct connect_params_t *conn)
01105 {
01106 struct iwreq req;
01107 guint nbr_of_keys = 0;
01108 int sock;
01109 guint i;
01110
01111 sock = socket_open();
01112
01113
01114 for (i=0;i<4;i++) {
01115 if(conn->key_len[i] == 0) {
01116 continue;
01117 } else {
01118 if (conn->key_len[i] < WLANCOND_MIN_KEY_LEN ||
01119 conn->key_len[i] > WLANCOND_MAX_KEY_LEN) {
01120 return -1;
01121 }
01122
01123 init_iwreq(&req);
01124 req.u.data.length = conn->key_len[i];
01125 req.u.data.pointer = (caddr_t) &conn->key[i][0];
01126 req.u.data.flags |= IW_ENCODE_RESTRICTED;
01127 req.u.encoding.flags = i+1;
01128 nbr_of_keys++;
01129 }
01130
01131 #ifdef DEBUG_KEY
01132 int k;
01133 unsigned char* p = &conn->key[i][0];
01134 for (k=0;k<conn->key_len[i];k++) {
01135 DLOG_DEBUG("Key %d, 0x%02x\n", i, *(p+k));
01136 }
01137 #endif
01138 if (ioctl(sock, SIOCSIWENCODE, &req) < 0) {
01139 DLOG_ERR("Set encode failed\n");
01140 return -1;
01141 }
01142
01143 }
01144
01145 if (nbr_of_keys) {
01146
01147 DLOG_DEBUG("Default key: %d\n", conn->default_key);
01148
01149 init_iwreq(&req);
01150
01151
01152 req.u.encoding.flags = conn->default_key;
01153
01154 if (ioctl(sock, SIOCSIWENCODE, &req) < 0) {
01155 DLOG_ERR("Set encode failed\n");
01156 return -1;
01157 }
01158 }
01159
01160 return 0;
01161 }
01162
01169 int set_essid(char* essid, int essid_len)
01170 {
01171 struct iwreq req;
01172
01173 DLOG_INFO("Setting SSID: %s", essid);
01174
01175 init_iwreq(&req);
01176
01177 req.u.essid.pointer = (caddr_t)essid;
01178 req.u.essid.length = essid_len -1;
01179 req.u.essid.flags = 1;
01180
01181 if (ioctl(socket_open(), SIOCSIWESSID, &req) < 0) {
01182 DLOG_ERR("set ESSID failed");
01183 return -1;
01184 }
01185 return 0;
01186 }
01192 int set_bssid(unsigned char *bssid)
01193 {
01194 struct iwreq req;
01195
01196 print_mac(WLANCOND_PRIO_HIGH, "Setting BSSID", bssid);
01197
01198 init_iwreq(&req);
01199
01200 req.u.ap_addr.sa_family = ARPHRD_ETHER;
01201
01202 memcpy(req.u.ap_addr.sa_data, bssid, ETH_ALEN);
01203
01204 if (ioctl(socket_open(), SIOCSIWAP, &req) < 0) {
01205 DLOG_ERR("Failed to set BSSID");
01206 return -1;
01207 }
01208 return 0;
01209 }
01210
01217 void set_wlan_state(int new_state, int send_signal, force_t force)
01218 {
01219 const char *status_table[] =
01220 {
01221 (char*)"WLAN_NOT_INITIALIZED",
01222 (char*)"WLAN_INITIALIZED",
01223 (char*)"WLAN_INITIALIZED_FOR_SCAN",
01224 (char*)"WLAN_INITIALIZED_FOR_CONNECTION",
01225 (char*)"WLAN_NO_ADDRESS",
01226 (char*)"WLAN_CONNECTED"
01227 };
01228
01229 switch (new_state) {
01230
01231 case WLAN_NOT_INITIALIZED:
01232
01233 if (wlan_status.state == WLAN_CONNECTED ||
01234 wlan_status.state == WLAN_NO_ADDRESS) {
01235
01236 mlme_command(wlan_status.conn.bssid,
01237 IW_MLME_DEAUTH,
01238 WLANCOND_REASON_LEAVING);
01239 set_bssid(NULL_BSSID);
01240 set_essid((char*)"", 1);
01241 }
01242
01243 set_scan_state(SCAN_NOT_ACTIVE);
01244
01245 if (get_wlan_state() != WLAN_NOT_INITIALIZED &&
01246 get_wlan_state() != WLAN_INITIALIZED_FOR_SCAN)
01247 clear_wpa_mode();
01248
01249 wlan_status.retry_count = 0;
01250 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
01251 wlan_status.ip_ok = FALSE;
01252 wlan_status.last_scan = 0;
01253
01254
01255 remove_connect_timer();
01256
01257
01258 remove_scan_timer();
01259
01260 set_wlan_signal(WLANCOND_HIGH);
01261
01262
01263 remove_wlan_if_timer();
01264
01265 if (force == FORCE_YES) {
01266
01267 clean_roam_cache();
01268
01269 if (set_interface_state(socket_open(), CLEAR,
01270 IFF_UP)<0) {
01271 DLOG_ERR("Could not set interface down");
01272 }
01273
01274 } else {
01275
01276 DLOG_DEBUG("Delaying interface shutdown");
01277
01278
01279
01280
01281
01282 wlan_if_down_timer_id = g_timeout_add_seconds(
01283 WLANCOND_SHUTDOWN_DELAY,
01284 wlan_if_down_cb,
01285 NULL);
01286
01287 }
01288
01289 if (send_signal == DISCONNECTED_SIGNAL)
01290 disconnected_signal();
01291
01292 break;
01293 case WLAN_INITIALIZED_FOR_CONNECTION:
01294
01295
01296
01297
01298 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
01299
01300
01301 remove_connect_timer();
01302
01303 set_power_state(WLANCOND_POWER_ON, socket_open());
01304
01305 break;
01306 case WLAN_CONNECTED:
01307
01308
01309 if (get_wpa_mode() == FALSE)
01310 set_power_state(powersave, socket_open());
01311
01312 wlan_status.ip_ok = TRUE;
01313 break;
01314 default:
01315 break;
01316 }
01317 DLOG_DEBUG("Wlancond state change, old_state: %s, new_state: %s",
01318 status_table[wlan_status.state], status_table[new_state]);
01319 wlan_status.state = new_state;
01320 }
01321
01326 guint get_wlan_state(void)
01327 {
01328 return wlan_status.state;
01329 }
01330
01335 void set_scan_state(guint new_state)
01336 {
01337 if (wlan_status.scan == new_state) {
01338 return;
01339 }
01340 if (new_state == SCAN_NOT_ACTIVE && wlan_status.scan == SCAN_ACTIVE &&
01341 scan_name_cache != NULL) {
01342 remove_scan_timer();
01343 DLOG_DEBUG("Sending empty results");
01344 send_dbus_scan_results(NULL, scan_name_cache, 0);
01345 g_free(scan_name_cache);
01346 scan_name_cache = NULL;
01347 }
01348
01349 DLOG_DEBUG("Wlancond scan change, old_state: %s, new_state: %s",
01350 wlan_status.scan==SCAN_NOT_ACTIVE ? "SCAN_IDLE":"SCANNING",
01351 new_state == SCAN_NOT_ACTIVE ? "SCAN_IDLE":"SCANNING");
01352 wlan_status.scan = new_state;
01353 }
01354
01359 guint get_scan_state(void)
01360 {
01361 return wlan_status.scan;
01362 }
01367 guint get_mode(void)
01368 {
01369 return wlan_status.conn.mode;
01370 }
01371
01378 gboolean set_real_power_state(guint new_state, int sock)
01379 {
01380 struct iwreq req;
01381 gint sleep_timeout;
01382
01383 if (wlan_status.real_power == new_state) {
01384 return TRUE;
01385 }
01386
01387 init_iwreq(&req);
01388
01389 switch (new_state) {
01390 case WLANCOND_POWER_ON:
01391 req.u.power.disabled = 1;
01392 break;
01393 case WLANCOND_LONG_CAM:
01394 req.u.power.flags = IW_POWER_TIMEOUT | IW_POWER_ALL_R;
01395 req.u.power.value = WLANCOND_LONG_CAM_TIMEOUT;
01396 break;
01397 case WLANCOND_SHORT_CAM:
01398 req.u.power.flags = IW_POWER_TIMEOUT | IW_POWER_ALL_R;
01399 sleep_timeout = get_gconf_int(SLEEP_GCONF_PATH);
01400 if (sleep_timeout < 0)
01401 sleep_timeout = WLANCOND_DEFAULT_SLEEP_TIMEOUT;
01402 req.u.power.value = sleep_timeout;
01403 break;
01404 case WLANCOND_VERY_SHORT_CAM:
01405 req.u.power.flags = IW_POWER_TIMEOUT | IW_POWER_ALL_R ;
01406 sleep_timeout = get_gconf_int(INACTIVE_SLEEP_GCONF_PATH);
01407 if (sleep_timeout < 0)
01408 sleep_timeout = WLANCOND_VERY_SHORT_CAM_TIMEOUT;
01409 req.u.power.value = sleep_timeout;
01410 break;
01411 case WLANCOND_FULL_POWERSAVE:
01412 req.u.power.flags = IW_POWER_TIMEOUT | IW_POWER_ALL_R;
01413 req.u.power.value = 0;
01414 default:
01415 req.u.power.flags = IW_POWER_ALL_R;
01416 break;
01417 }
01418
01419 if (ioctl(sock, SIOCSIWPOWER, &req) < 0) {
01420 DLOG_ERR("set power failed, state:%d", new_state);
01421 return FALSE;
01422 }
01423
01424 if (req.u.power.value) {
01425 DLOG_DEBUG("CAM timeout: %d ms", req.u.power.value / 1000);
01426 }
01427
01428 wlan_status.real_power = new_state;
01429 DLOG_DEBUG("New power state set: %i", new_state);
01430
01431 return TRUE;
01432 }
01433
01440 gboolean set_power_state(guint new_state, int sock)
01441 {
01442 gboolean status;
01443
01444 if (new_state == WLANCOND_SHORT_CAM && get_inactivity_status() == TRUE)
01445 new_state = WLANCOND_VERY_SHORT_CAM;
01446
01447
01448 if (wlan_status.coex_state == WLANCOND_BT_COEX_MONOAUDIO &&
01449 wlan_status.call_state != WLANCOND_CALL_VOIP) {
01450 DLOG_DEBUG("Overriding power state with full power save.");
01451 new_state = WLANCOND_FULL_POWERSAVE;
01452 }
01453
01454 status = set_real_power_state(new_state, sock);
01455
01456
01457
01458 if (status && wlan_status.coex_state != WLANCOND_BT_COEX_MONOAUDIO)
01459 wlan_status.requested_power = new_state;
01460
01461 return status;
01462 }
01463
01469 static int init_if(int sock)
01470 {
01471 int previous_state = get_wlan_state();
01472
01473 if (previous_state == WLAN_NOT_INITIALIZED) {
01474
01475 if (wlan_if_down_timer_id == 0) {
01476
01477
01478 if (handle_country() < 0)
01479 return -1;
01480
01481 if (set_interface_state(sock, SET,
01482 IFF_UP | IFF_RUNNING) < 0) {
01483 return -1;
01484 }
01485 }
01486 set_power_state(WLANCOND_POWER_ON, sock);
01487 set_wlan_state(WLAN_INITIALIZED, NO_SIGNAL, FORCE_YES);
01488 }
01489
01490 return previous_state;
01491 }
01492
01501 static int set_we_name(int sock, char *name, char *args[], int count)
01502 {
01503 struct iwreq req;
01504
01505 memset(&req, 0, sizeof(req));
01506 strncpy(req.ifr_name, name, IFNAMSIZ);
01507
01508 if (ioctl(sock, SIOCGIWNAME, &req) < 0) {
01509
01510 } else {
01511
01512 if (g_str_has_prefix(name, WLAN_PREFIX_STR)) {
01513 DLOG_DEBUG("Found WLAN interface %s", name);
01514 memcpy(&wlan_status.ifname, name, IFNAMSIZ);
01515 wlan_status.ifname[IFNAMSIZ] = '\0';
01516 }
01517 }
01518
01519 return 0;
01520 }
01526 int get_we_device_name(void)
01527 {
01528 memset(&wlan_status, 0, sizeof(wlan_status));
01529
01530 wlan_status.country_code = -1;
01531
01532 iw_enum_devices(socket_open(), &set_we_name, NULL, 0);
01533
01534 if (strnlen(wlan_status.ifname, IFNAMSIZ) < 2)
01535 return -1;
01536
01537 return 0;
01538 }
01546 int set_interface_state(int sock, int dir, short flags)
01547 {
01548 struct ifreq ifr;
01549
01550 memset(&ifr, 0, sizeof(ifr));
01551
01552 strncpy(ifr.ifr_name, wlan_status.ifname, IFNAMSIZ);
01553
01554 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
01555 DLOG_ERR("Could not get interface %s flags\n",
01556 wlan_status.ifname);
01557 return -1;
01558 }
01559 if (dir == SET) {
01560 ifr.ifr_flags |= flags;
01561 } else {
01562 ifr.ifr_flags &= ~flags;
01563 }
01564
01565 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
01566 DLOG_ERR("Could not set interface %s flags\n",
01567 wlan_status.ifname);
01568 return -1;
01569 }
01570
01571 DLOG_DEBUG("%s is %s", wlan_status.ifname, dir == SET ? "UP":"DOWN");
01572
01573 return 0;
01574 }
01575
01582 static gboolean set_tx_power(guint power, int sock)
01583 {
01584 struct iwreq req;
01585 init_iwreq(&req);
01586
01587 req.u.txpower.fixed = 1;
01588 req.u.txpower.disabled = 0;
01589 req.u.txpower.flags = IW_TXPOW_DBM;
01590
01591 if (power == WLANCOND_TX_POWER10) {
01592 req.u.txpower.value = WLANCOND_TX_POWER10DBM;
01593 } else if (power == WLANCOND_TX_POWER100) {
01594 req.u.txpower.value = WLANCOND_TX_POWER100DBM;
01595 } else {
01596 return FALSE;
01597 }
01598
01599 if (ioctl(sock, SIOCSIWTXPOW, &req) < 0) {
01600 DLOG_ERR("set power failed\n");
01601 return FALSE;
01602 }
01603 return TRUE;
01604
01605 }
01611 static int update_algorithms(guint32 encryption)
01612 {
01613 wlan_status.group_cipher = 0;
01614 wlan_status.pairwise_cipher = 0;
01615
01616
01617 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_OPEN) {
01618 DLOG_DEBUG("Open mode");
01619 wlan_status.pairwise_cipher = CIPHER_SUITE_NONE;
01620 return 0;
01621 }
01622
01623
01624 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP) {
01625 DLOG_DEBUG("WEP enabled");
01626 wlan_status.pairwise_cipher = CIPHER_SUITE_WEP40;
01627 return 0;
01628 }
01629
01630
01631 if ((encryption & WLANCOND_ENCRYPT_ALG_MASK)
01632 == WLANCOND_WPA_TKIP) {
01633 DLOG_DEBUG("TKIP Selected for unicast");
01634 wlan_status.pairwise_cipher = CIPHER_SUITE_TKIP;
01635 } else if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) ==
01636 WLANCOND_WPA_AES) {
01637 DLOG_DEBUG("AES selected for unicast");
01638 wlan_status.pairwise_cipher = CIPHER_SUITE_CCMP;
01639
01640 } else {
01641 DLOG_ERR("Not supported encryption %08x", encryption);
01642 return -1;
01643 }
01644
01645 if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
01646 WLANCOND_WPA_TKIP_GROUP) {
01647 DLOG_DEBUG("TKIP Selected for multicast");
01648 wlan_status.group_cipher = CIPHER_SUITE_TKIP;
01649 } else if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
01650 (unsigned int)WLANCOND_WPA_AES_GROUP) {
01651 DLOG_DEBUG("AES Selected for multicast");
01652 wlan_status.group_cipher = CIPHER_SUITE_CCMP;
01653 } else {
01654 DLOG_ERR("Not supported encryption %08x", encryption);
01655 return -1;
01656 }
01657
01658 return 0;
01659 }
01663 void clean_roam_cache(void)
01664 {
01665 clean_scan_results(&wlan_status.roam_cache);
01666 }
01670 void clear_wpa_mode(void)
01671 {
01672 g_free(wlan_status.wpa_ie.ie);
01673 wlan_status.wpa_ie.ie_len = 0;
01674 wlan_status.wpa_ie.ie = NULL;
01675
01676 wlan_status.pairwise_cipher = CIPHER_SUITE_NONE;
01677 wlan_status.group_cipher = CIPHER_SUITE_NONE;
01678
01679
01680 clear_wpa_keys(NULL);
01681
01682 g_slist_foreach(wlan_status.pmk_cache, (GFunc)g_free, NULL);
01683 g_slist_free(wlan_status.pmk_cache);
01684 wlan_status.pmk_cache = NULL;
01685 }
01690 gboolean get_wpa_mode(void)
01691 {
01692 if (wlan_status.pairwise_cipher & CIPHER_SUITE_TKIP ||
01693 wlan_status.pairwise_cipher & CIPHER_SUITE_CCMP) {
01694 return TRUE;
01695 }
01696 return FALSE;
01697 }
01698
01699 static gint compare_pmk_entry(gconstpointer a, gconstpointer b)
01700 {
01701 const struct pmksa_cache_t *pmk_cache = a;
01702
01703 return memcmp(pmk_cache->mac, b, ETH_ALEN);
01704 }
01705
01711 static void add_to_pmksa_cache(unsigned char* pmkid, unsigned char* mac)
01712 {
01713 guint i = 0;
01714 GSList *list;
01715 gboolean entry_found = FALSE;
01716
01717 for (list = wlan_status.pmk_cache; list != NULL &&
01718 entry_found == FALSE; list = list->next) {
01719 struct pmksa_cache_t *pmk_cache = list->data;
01720
01721 if (memcmp(pmk_cache->mac, mac, ETH_ALEN) == 0) {
01722 DLOG_DEBUG("Found old entry: %i", i);
01723
01724 wlan_status.pmk_cache = g_slist_remove(
01725 wlan_status.pmk_cache, pmk_cache);
01726 g_free(pmk_cache);
01727
01728 entry_found = TRUE;
01729 } else {
01730 i++;
01731 }
01732 }
01733
01734 if (i == PMK_CACHE_SIZE) {
01735 DLOG_DEBUG("Cache full, remove oldest");
01736 GSList *last_entry = g_slist_last(wlan_status.pmk_cache);
01737 wlan_status.pmk_cache = g_slist_remove(wlan_status.pmk_cache,
01738 last_entry->data);
01739 g_free(last_entry->data);
01740 }
01741 print_mac(WLANCOND_PRIO_LOW, "Adding new entry:", mac);
01742
01743 struct pmksa_cache_t *new_entry = g_malloc(sizeof(*new_entry));
01744 memcpy(new_entry->mac, mac, ETH_ALEN);
01745 memcpy(new_entry->pmkid, pmkid, IW_PMKID_LEN);
01746
01747 wlan_status.pmk_cache = g_slist_prepend(wlan_status.pmk_cache,
01748 new_entry);
01749 return;
01750 }
01751
01758 gboolean remove_from_pmksa_cache(unsigned char* mac)
01759 {
01760 GSList *list = g_slist_find_custom(wlan_status.pmk_cache, mac,
01761 &compare_pmk_entry);
01762 if(!list)
01763 return FALSE;
01764
01765 struct pmksa_cache_t *entry = list->data;
01766
01767 print_mac(WLANCOND_PRIO_MEDIUM, "Removing PMKSA entry for:", mac);
01768
01769 wlan_status.pmk_cache = g_slist_remove(wlan_status.pmk_cache,
01770 entry);
01771
01772 g_free(entry);
01773
01774 return TRUE;
01775 }
01776
01784 int find_pmkid_from_pmk_cache(unsigned char* mac,
01785 unsigned char **pmkid)
01786 {
01787 GSList *list;
01788 int pmksa_found;
01789
01790 if (check_pmksa_cache((unsigned char *)wlan_status.own_mac, ETH_ALEN,
01791 mac, ETH_ALEN,
01792 wlan_status.conn.authentication_type,
01793 wlan_status.pairwise_cipher,
01794 wlan_status.group_cipher,
01795 &pmksa_found))
01796 {
01797 DLOG_ERR("Error while querying the pmksa cache status "
01798 "from eapd");
01799 return -1;
01800 }
01801
01802 if(!pmksa_found) {
01803 DLOG_DEBUG("No cached pmksa found from eapd");
01804
01805 remove_from_pmksa_cache(mac);
01806 *pmkid = NULL;
01807
01808 return 0;
01809 }
01810
01811 list = g_slist_find_custom(wlan_status.pmk_cache, mac, &compare_pmk_entry);
01812 if (list != NULL) {
01813 struct pmksa_cache_t *pmk_cache = list->data;
01814 print_mac(WLANCOND_PRIO_MEDIUM, "Found PMKSA entry for:", mac);
01815 *pmkid = pmk_cache->pmkid;
01816 return 0;
01817 }
01818
01819 DLOG_DEBUG("No cached pmksa found from eapd");
01820 *pmkid = NULL;
01821
01822 return 0;
01823 }
01824
01831 int scan(gchar *ssid, int ssid_len, gboolean add_timer)
01832 {
01833 struct iwreq req;
01834 struct iw_scan_req scan_req;
01835
01836 if (get_scan_state() == SCAN_ACTIVE)
01837 return 0;
01838
01839 set_scan_state(SCAN_ACTIVE);
01840
01841 init_iwreq(&req);
01842
01843 memset(&scan_req, 0, sizeof(scan_req));
01844
01845 if (ssid_len > 1 && ssid != NULL) {
01846
01847 scan_req.essid_len = ssid_len -1;
01848 scan_req.bssid.sa_family = ARPHRD_ETHER;
01849 memset(scan_req.bssid.sa_data, 0xff, ETH_ALEN);
01850 memcpy(scan_req.essid, ssid, ssid_len -1);
01851 req.u.data.pointer = (caddr_t) &scan_req;
01852 req.u.data.length = sizeof(scan_req);
01853 req.u.data.flags = IW_SCAN_THIS_ESSID;
01854 }
01855
01856 if (ioctl(socket_open(), SIOCSIWSCAN, &req) < 0) {
01857 DLOG_ERR("Scan failed");
01858 return -1;
01859 }
01860
01861 if (add_timer == TRUE) {
01862 wlan_status.scan_id = g_timeout_add_seconds(
01863 WLANCOND_SCAN_TIMEOUT,
01864 wlan_scan_cb,
01865 NULL);
01866 }
01867
01868 DLOG_INFO("Scan issued");
01869
01870 return 0;
01871 }
01877 static int set_freq(int channel)
01878 {
01879 struct iwreq req;
01880
01881 DLOG_DEBUG("Setting channel: %d", channel);
01882
01883 init_iwreq(&req);
01884
01885 req.u.freq.m = channel;
01886
01887 if (ioctl(socket_open(), SIOCSIWFREQ, &req) < 0) {
01888 DLOG_ERR("Freq failed");
01889 return -1;
01890 }
01891
01892 return 0;
01893 }
01894 static void init_conn_params(struct connect_params_t *conn_params)
01895 {
01896 memset(conn_params, 0, sizeof(*conn_params));
01897 }
01902 void clear_wpa_keys(unsigned char* bssid)
01903 {
01904 struct iwreq req;
01905 struct iw_encode_ext ext;
01906 int sock;
01907 guint i;
01908
01909 init_iwreq(&req);
01910
01911 sock = socket_open();
01912
01913 for (i=0;i<4;i++) {
01914
01915 memset(&ext, 0, sizeof(ext));
01916
01917 req.u.encoding.flags = i + 1;
01918 req.u.encoding.flags |= IW_ENCODE_DISABLED;
01919 req.u.encoding.pointer = (caddr_t) &ext;
01920 req.u.encoding.length = sizeof(ext);
01921
01922 ext.ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
01923 ext.addr.sa_family = ARPHRD_ETHER;
01924
01925 memset(ext.addr.sa_data, 0xff, ETH_ALEN);
01926 ext.alg = IW_ENCODE_ALG_NONE;
01927
01928 if (ioctl(sock, SIOCSIWENCODEEXT, &req) < 0) {
01929 DLOG_ERR("Key %i clearing failed", i);
01930 }
01931 }
01932 if (bssid != NULL) {
01933
01934 memset(&ext, 0, sizeof(ext));
01935
01936 req.u.encoding.flags = 1;
01937 req.u.encoding.flags |= IW_ENCODE_DISABLED;
01938 req.u.encoding.pointer = (caddr_t) &ext;
01939 req.u.encoding.length = sizeof(ext);
01940
01941 ext.addr.sa_family = ARPHRD_ETHER;
01942
01943 memcpy(ext.addr.sa_data, bssid, ETH_ALEN);
01944 ext.alg = IW_ENCODE_ALG_NONE;
01945
01946 if (ioctl(sock, SIOCSIWENCODEEXT, &req) < 0) {
01947 DLOG_ERR("Key clearing failed");
01948 }
01949 }
01950
01951 return;
01952 }
01960 static int check_connect_arguments(struct connect_params_t *conn, char* ssid,
01961 unsigned char** key)
01962 {
01963 guint i;
01964
01965 if (conn->flags & WLANCOND_DISABLE_POWERSAVE) {
01966 DLOG_DEBUG("Powersave disabled");
01967 powersave = WLANCOND_POWER_ON;
01968 } else if (conn->flags & WLANCOND_MINIMUM_POWERSAVE) {
01969 DLOG_DEBUG("Powersave minimum");
01970 powersave = WLANCOND_LONG_CAM;
01971 } else if (conn->flags & WLANCOND_MAXIMUM_POWERSAVE) {
01972 DLOG_DEBUG("Powersave maximum");
01973 powersave = WLANCOND_SHORT_CAM;
01974 } else {
01975 powersave = WLANCOND_SHORT_CAM;
01976 }
01977
01978 if (conn->power_level != WLANCOND_TX_POWER10 &&
01979 conn->power_level != WLANCOND_TX_POWER100) {
01980 DLOG_ERR("Invalid power level");
01981 return -1;
01982 }
01983
01984 switch (conn->mode) {
01985 case WLANCOND_ADHOC:
01986 case WLANCOND_INFRA:
01987 break;
01988 default:
01989 DLOG_ERR("Operating mode undefined\n");
01990 return -1;
01991 }
01992
01993 guint32 wpa2_mode = conn->encryption & WLANCOND_ENCRYPT_WPA2_MASK;
01994
01995 DLOG_DEBUG("Encryption setting: %08x", conn->encryption);
01996
01997 switch (conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) {
01998 case WLANCOND_OPEN:
01999 break;
02000 case WLANCOND_WEP:
02001 break;
02002 case WLANCOND_WPA_PSK:
02003 DLOG_DEBUG("%s PSK selected",
02004 wpa2_mode!=0?"WPA2":"WPA");
02005 if (wpa2_mode != 0)
02006 conn->authentication_type = EAP_AUTH_TYPE_WPA2_PSK;
02007 else
02008 conn->authentication_type = EAP_AUTH_TYPE_WPA_PSK;
02009 break;
02010 case WLANCOND_WPA_EAP:
02011 DLOG_DEBUG("%s EAP selected", wpa2_mode!=0?"WPA2":"WPA");
02012 if (wpa2_mode != 0)
02013 conn->authentication_type = EAP_AUTH_TYPE_WPA2_EAP;
02014 else
02015 conn->authentication_type = EAP_AUTH_TYPE_WPA_EAP;
02016 break;
02017 default:
02018 DLOG_DEBUG("Unsupported encryption mode");
02019 return -1;
02020 }
02021 if ((conn->encryption & WLANCOND_WPS_MASK) != 0) {
02022 DLOG_DEBUG("WPS selected");
02023 conn->authentication_type = EAP_AUTH_TYPE_WFA_SC;
02024 }
02025
02026 if (!ssid || conn->ssid_len == 0 ||
02027 conn->ssid_len > WLANCOND_MAX_SSID_SIZE + 1) {
02028 DLOG_DEBUG("Invalid SSID");
02029 return -1;
02030 }
02031 for (i=0;i<4;i++) {
02032 if (conn->key_len[i] != 0) {
02033 DLOG_DEBUG("Found key %d", i);
02034 memcpy(&conn->key[i][0], key[i], conn->key_len[i]);
02035 }
02036 }
02037 return 0;
02038 }
02039
02046 static DBusHandlerResult settings_and_connect_request(
02047 DBusMessage *message,
02048 DBusConnection *connection) {
02049
02050 DBusMessage *reply = NULL;
02051 DBusError derror;
02052 struct connect_params_t *conn;
02053 char *ssid;
02054 unsigned char* key[4];
02055 dbus_int32_t old_mode;
02056 int res;
02057 gboolean autoconnect = FALSE;
02058
02059 dbus_error_init(&derror);
02060
02061 if (in_flight_mode()) {
02062 reply = new_dbus_error(message, WLANCOND_ERROR_WLAN_DISABLED);
02063 send_and_unref(connection, reply);
02064 return DBUS_HANDLER_RESULT_HANDLED;
02065 }
02066
02067 remove_wlan_if_timer();
02068
02069 conn = &wlan_status.conn;
02070
02071 old_mode = conn->mode;
02072 init_conn_params(conn);
02073
02074 if (dbus_message_get_args(
02075 message, NULL,
02076 DBUS_TYPE_INT32, &conn->power_level,
02077 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid, &conn->ssid_len,
02078 DBUS_TYPE_INT32, &conn->mode,
02079 DBUS_TYPE_INT32, &conn->encryption,
02080 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[0], &conn->key_len[0],
02081 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[1], &conn->key_len[1],
02082 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[2], &conn->key_len[2],
02083 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[3], &conn->key_len[3],
02084 DBUS_TYPE_INT32, &conn->default_key,
02085 DBUS_TYPE_UINT32, &conn->adhoc_channel,
02086 DBUS_TYPE_UINT32, &conn->flags,
02087 DBUS_TYPE_INVALID) == FALSE)
02088 {
02089
02090 if (dbus_message_get_args(
02091 message, &derror,
02092 DBUS_TYPE_INT32, &conn->power_level,
02093 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid,
02094 &conn->ssid_len,
02095 DBUS_TYPE_INT32, &conn->mode,
02096 DBUS_TYPE_INT32, &conn->encryption,
02097 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02098 &key[0], &conn->key_len[0],
02099 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02100 &key[1], &conn->key_len[1],
02101 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02102 &key[2], &conn->key_len[2],
02103 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02104 &key[3], &conn->key_len[3],
02105 DBUS_TYPE_INT32, &conn->default_key,
02106 DBUS_TYPE_UINT32, &conn->adhoc_channel,
02107 DBUS_TYPE_INVALID) == FALSE) {
02108
02109 DLOG_ERR("Failed to parse setting_and_connect: %s",
02110 derror.message);
02111 dbus_error_free(&derror);
02112 goto param_err;
02113 }
02114 }
02115
02116 if (check_connect_arguments(conn, ssid, key) < 0)
02117 goto param_err;
02118
02119 set_power_state(WLANCOND_POWER_ON, socket_open());
02120
02121
02122
02123
02124
02125 if (old_mode != conn->mode ||
02126 conn->encryption & WLANCOND_WPS_PUSH_BUTTON) {
02127 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
02128 }
02129
02130
02131 if (set_mode(conn->mode) < 0) {
02132 goto param_err;
02133 }
02134
02135 if (init_if(socket_open()) < 0) {
02136 reply = new_dbus_error(message, WLANCOND_ERROR_INIT_FAILED);
02137 goto param_err;
02138 }
02139
02140 if (set_tx_power(conn->power_level, socket_open()) != TRUE) {
02141 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02142 goto param_err;
02143 }
02144
02145 if (conn->flags & WLANCOND_AUTOCONNECT) {
02146 DLOG_DEBUG("Autoconnect attempt");
02147 autoconnect = TRUE;
02148 }
02149
02150 memcpy(conn->ssid, ssid, conn->ssid_len);
02151
02152 set_scan_state(SCAN_NOT_ACTIVE);
02153 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL, FORCE_NO);
02154
02155
02156 if (conn->encryption & WLANCOND_WPS_PUSH_BUTTON) {
02157 DLOG_DEBUG("Broadcast scan for WPS");
02158 if (scan(NULL, 0, TRUE) < 0) {
02159 goto param_err;
02160 }
02161 } else {
02162
02163 if ((res = find_connection_and_associate(
02164 wlan_status.roam_cache,
02165 FALSE, FALSE, autoconnect)) != 0) {
02166
02167
02168
02169 if (res == ETOOWEAKAP)
02170 goto param_err;
02171
02172
02173 DLOG_DEBUG("Checking mac80211 cache...");
02174
02175 GSList *scan_results = NULL;
02176 scan_results_ioctl(0, &scan_results);
02177
02178 if (find_connection_and_associate(
02179 scan_results,
02180 TRUE, FALSE, autoconnect) != 0) {
02181
02182
02183
02184 if (res == ETOOWEAKAP)
02185 goto param_err;
02186
02187 clean_scan_results(&scan_results);
02188 if (scan(conn->ssid, conn->ssid_len, TRUE)
02189 < 0) {
02190 goto param_err;
02191 }
02192 } else {
02193 clean_scan_results(&scan_results);
02194 }
02195 }
02196 }
02197
02198 g_free(connect_name_cache);
02199 connect_name_cache = g_strdup(dbus_message_get_sender(message));
02200
02201 reply = new_dbus_method_return(message);
02202
02203 gchar* ifname = wlan_status.ifname;
02204
02205 append_dbus_args(reply,
02206 DBUS_TYPE_STRING, &ifname,
02207 DBUS_TYPE_INVALID);
02208
02209 send_and_unref(connection, reply);
02210
02211 return DBUS_HANDLER_RESULT_HANDLED;
02212
02213 param_err:
02214 if (reply == NULL) {
02215 DLOG_DEBUG("Parameter error in settings_and_connect\n");
02216 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
02217 }
02218 send_and_unref(connection, reply);
02219 return DBUS_HANDLER_RESULT_HANDLED;
02220 }
02226 int associate(struct scan_results_t *scan_results)
02227 {
02228 struct connect_params_t *conn = &wlan_status.conn;
02229 gint ret;
02230
02231 DLOG_INFO("Starting to associate");
02232
02233 if (memcmp(conn->bssid, "\0\0\0\0\0\0", ETH_ALEN)) {
02234 clear_wpa_keys(conn->bssid);
02235 }
02236
02237 if (update_algorithms(conn->encryption) < 0) {
02238 return -1;
02239 }
02240
02241
02242 if ((conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP){
02243 if (set_wep_keys(conn) < 0) {
02244 return -1;
02245 }
02246 }
02247
02248 memcpy(conn->bssid, scan_results->bssid, ETH_ALEN);
02249
02250 if ((ret = set_encryption_method(conn->encryption, &wlan_status)) < 0) {
02251 return ret;
02252 }
02253
02254 if (get_wpa_mode() == TRUE ||
02255 conn->authentication_type == EAP_AUTH_TYPE_WFA_SC) {
02256
02257
02258 if (wpa_ie_push(scan_results->bssid,
02259 scan_results->wpa_ie,
02260 scan_results->wpa_ie_len,
02261 scan_results->ssid,
02262 scan_results->ssid_len -1,
02263 conn->authentication_type) < 0)
02264 return -1;
02265 }
02266
02267
02268
02269 if (conn->adhoc_channel != 0 && (conn->mode & WLANCOND_ADHOC)) {
02270 if (conn->adhoc_channel < WLANCOND_MIN_WLAN_CHANNEL ||
02271 conn->adhoc_channel > WLANCOND_MAX_WLAN_CHANNEL) {
02272 DLOG_ERR("Invalid ad-hoc channel: %d",
02273 conn->adhoc_channel);
02274 return -1;
02275 }
02276
02277 scan_results->channel = conn->adhoc_channel;
02278 }
02279
02280 set_freq(scan_results->channel);
02281
02282
02283 if (conn->mode != WLANCOND_ADHOC &&
02284 memcmp(scan_results->bssid, "\0\0\0\0\0\0", ETH_ALEN)) {
02285 if (set_bssid(scan_results->bssid) < 0) {
02286 return -1;
02287 }
02288 }
02289
02290 if (set_essid(conn->ssid, conn->ssid_len) < 0) {
02291 return -1;
02292 }
02293
02294
02295 wlan_connect_timer_id = g_timeout_add_seconds(
02296 WLANCOND_CONNECT_TIMEOUT,
02297 wlan_connect_timer_cb, NULL);
02298
02299 return 0;
02300 }
02301
02308 static DBusHandlerResult scan_request(DBusMessage *message,
02309 DBusConnection *connection) {
02310
02311 DBusMessage *reply = NULL;
02312 DBusMessageIter iter, array_iter;
02313 char *ssid;
02314 const char* sender;
02315 dbus_int32_t power_level;
02316 dbus_int32_t flags;
02317 gint previous_state = 0;
02318
02319 if (in_flight_mode()) {
02320 reply = new_dbus_error(message, WLANCOND_ERROR_WLAN_DISABLED);
02321 send_and_unref(connection, reply);
02322 return DBUS_HANDLER_RESULT_HANDLED;
02323 }
02324
02325 sender = dbus_message_get_sender(message);
02326 if (sender == NULL) {
02327 goto param_err;
02328 }
02329
02330 DLOG_DEBUG("Got scan request from %s", sender);
02331
02332
02333 if (get_scan_state() == SCAN_ACTIVE || wlan_connect_timer_id != 0) {
02334 reply = new_dbus_error(message, WLANCOND_ERROR_ALREADY_ACTIVE);
02335 send_and_unref(connection, reply);
02336 return DBUS_HANDLER_RESULT_HANDLED;
02337 }
02338
02339 if ((previous_state = init_if(socket_open())) < 0) {
02340 reply = new_dbus_error(message, WLANCOND_ERROR_INIT_FAILED);
02341 goto param_err;
02342 }
02343
02344 if (previous_state == WLAN_NOT_INITIALIZED) {
02345 set_wlan_state(WLAN_INITIALIZED_FOR_SCAN, NO_SIGNAL, FORCE_NO);
02346 }
02347
02348 dbus_message_iter_init(message, &iter);
02349
02350 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
02351 goto param_err;
02352 dbus_message_iter_get_basic(&iter, &power_level);
02353
02354 dbus_message_iter_next(&iter);
02355
02356 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
02357 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
02358 goto param_err;
02359 dbus_message_iter_recurse(&iter, &array_iter);
02360 dbus_message_iter_get_fixed_array(&array_iter, &ssid,
02361 &wlan_status.scan_ssid_len);
02362
02363 if (wlan_status.scan_ssid_len > WLANCOND_MAX_SSID_SIZE+1)
02364 goto param_err;
02365
02366 dbus_message_iter_next(&iter);
02367
02368 power_down_after_scan = FALSE;
02369
02370 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32) {
02371 dbus_message_iter_get_basic(&iter, &flags);
02372 DLOG_DEBUG("Found flags: %08x", flags);
02373
02374 if (flags & WLANCOND_NO_DELAYED_SHUTDOWN)
02375 power_down_after_scan = TRUE;
02376 }
02377
02378 if (power_level != WLANCOND_TX_POWER10 &&
02379 power_level != WLANCOND_TX_POWER100) {
02380 DLOG_ERR("Invalid power level");
02381 goto param_err;
02382 }
02383
02384 if (set_tx_power(power_level, socket_open()) != TRUE) {
02385 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02386 goto param_err;
02387 }
02388
02389 memset(wlan_status.scan_ssid, 0, sizeof(wlan_status.scan_ssid));
02390
02391 if (ssid != NULL && wlan_status.scan_ssid_len > 1) {
02392 memcpy(wlan_status.scan_ssid, ssid, wlan_status.scan_ssid_len);
02393 }
02394
02395 if (scan(wlan_status.scan_ssid, wlan_status.scan_ssid_len, TRUE) < 0) {
02396 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02397 goto param_err;
02398 }
02399
02400 g_free(scan_name_cache);
02401 scan_name_cache = g_strdup(sender);
02402
02403 reply = new_dbus_method_return(message);
02404 send_and_unref(connection, reply);
02405
02406 return DBUS_HANDLER_RESULT_HANDLED;
02407
02408 param_err:
02409 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
02410 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
02411 }
02412 if (reply == NULL) {
02413 DLOG_DEBUG("Parameter error in scan request");
02414 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
02415 }
02416 send_and_unref(connection, reply);
02417 return DBUS_HANDLER_RESULT_HANDLED;
02418 }
02425 static int network_compare(gconstpointer a, gconstpointer b)
02426 {
02427 const struct scan_results_t *results_a = a;
02428 const struct scan_results_t *results_b = b;
02429
02430 if (wlan_status.scan_ssid_len > 1) {
02431
02432
02433
02434 gint a_eq = strncmp(wlan_status.scan_ssid,
02435 results_a->ssid, WLANCOND_MAX_SSID_SIZE);
02436 gint b_eq = strncmp(wlan_status.scan_ssid,
02437 results_b->ssid, WLANCOND_MAX_SSID_SIZE);
02438
02439 if (!a_eq && !b_eq) {
02440
02441
02442 return 0;
02443 }
02444
02445 if (!a_eq && b_eq) {
02446
02447
02448 return -1;
02449 }
02450
02451 if (a_eq && !b_eq) {
02452
02453
02454
02455 return 1;
02456 }
02457
02458 }
02459
02460
02461 return (results_a->rssi > results_b->rssi) ?
02462 -1 : (results_a->rssi < results_b->rssi) ? 1 : 0;
02463 }
02464
02465 static gint compare_scan_entry(gconstpointer a, gconstpointer b)
02466 {
02467 const struct scan_results_t *scan_entry = a;
02468 return memcmp(scan_entry->bssid, b, ETH_ALEN);
02469 }
02474 static void add_to_roam_cache(struct scan_results_t *scan_results)
02475 {
02476 GSList *list;
02477
02478 list = g_slist_find_custom(wlan_status.roam_cache, scan_results->bssid,
02479 &compare_scan_entry);
02480
02481 if (list != NULL) {
02482 struct scan_results_t *roam_cache_entry = list->data;
02483 print_mac(WLANCOND_PRIO_LOW, "Found old entry for:",
02484 scan_results->bssid);
02485
02486
02487 wlan_status.roam_cache = g_slist_remove(
02488 wlan_status.roam_cache, roam_cache_entry);
02489
02490 clean_scan_results_item(roam_cache_entry, NULL);
02491 }
02492
02493 print_mac(WLANCOND_PRIO_LOW, "New AP to roam cache:",
02494 scan_results->bssid);
02495
02496 struct scan_results_t *results_to_list =
02497 g_slice_dup(struct scan_results_t, scan_results);
02498 results_to_list->wpa_ie = g_memdup(scan_results->wpa_ie,
02499 scan_results->wpa_ie_len);
02500 wlan_status.roam_cache = g_slist_prepend(wlan_status.roam_cache,
02501 results_to_list);
02502
02503 return;
02504 }
02510 gboolean remove_from_roam_cache(unsigned char *bssid)
02511 {
02512 GSList *list;
02513
02514 list = g_slist_find_custom(wlan_status.roam_cache, bssid,
02515 &compare_scan_entry);
02516
02517 if (list != NULL) {
02518 struct scan_results_t *roam_cache_entry = list->data;
02519 print_mac(WLANCOND_PRIO_LOW, "Found entry to be removed:",
02520 bssid);
02521
02522 wlan_status.roam_cache = g_slist_remove(
02523 wlan_status.roam_cache, roam_cache_entry);
02524
02525 clean_scan_results_item(roam_cache_entry, NULL);
02526
02527 return TRUE;
02528 }
02529
02530 return FALSE;
02531 }
02532
02538 gboolean decrease_signal_in_roam_cache(unsigned char *bssid)
02539 {
02540 GSList *list;
02541
02542 list = g_slist_find_custom(wlan_status.roam_cache, bssid,
02543 &compare_scan_entry);
02544
02545 if (list != NULL) {
02546 struct scan_results_t *roam_cache_entry = list->data;
02547 print_mac(WLANCOND_PRIO_LOW, "Found entry to be decreased:",
02548 bssid);
02549
02550 roam_cache_entry->rssi -= WLANCOND_RSSI_PENALTY;
02551
02552 return TRUE;
02553 }
02554
02555 return FALSE;
02556 }
02563 static int check_group_cipher(guint32 c1, guint32 c2)
02564 {
02565 guint32 m1 = (c1 & WLANCOND_ENCRYPT_GROUP_ALG_MASK);
02566 guint32 m2 = (c2 & WLANCOND_ENCRYPT_GROUP_ALG_MASK);
02567
02568 if (m1 == m2)
02569 return 1;
02570 if (m2 == WLANCOND_WPA_TKIP_GROUP && (m1 & WLANCOND_WPA_TKIP_GROUP))
02571 return 1;
02572 if (m2 == (unsigned int)WLANCOND_WPA_AES_GROUP &&
02573 (m1 & WLANCOND_WPA_AES_GROUP))
02574 return 1;
02575
02576 DLOG_DEBUG("Group ciphers don't match");
02577
02578 return -1;
02579 }
02586 static int check_ciphers(guint32 c1, guint32 c2)
02587 {
02588 guint32 u1 = (c1 & WLANCOND_ENCRYPT_ALG_MASK);
02589 guint32 u2 = (c2 & WLANCOND_ENCRYPT_ALG_MASK);
02590
02591 if (check_group_cipher(c1, c2) < 0)
02592 return -1;
02593
02594 if (u1 == u2)
02595 return 1;
02596 if (u2 == WLANCOND_WPA_TKIP && (u1 & WLANCOND_WPA_TKIP))
02597 return 1;
02598 if (u2 == WLANCOND_WPA_AES && (u1 & WLANCOND_WPA_AES))
02599 return 1;
02600
02601 DLOG_DEBUG("Unicast ciphers don't match");
02602
02603 return -1;
02604 }
02605
02606 static gboolean wlan_roam_scan_cb(void* data)
02607 {
02608 wlan_status.roam_scan_id = 0;
02609 struct timeval tv;
02610
02611 if (wlan_status.signal == WLANCOND_LOW &&
02612 get_wlan_state() == WLAN_CONNECTED) {
02613
02614 DLOG_DEBUG("Roam scan timeout, initiating new scan");
02615
02616 if (scan(wlan_status.conn.ssid, wlan_status.conn.ssid_len,
02617 TRUE) <0) {
02618 set_wlan_state(WLAN_NOT_INITIALIZED,
02619 DISCONNECTED_SIGNAL,
02620 FORCE_YES);
02621 return FALSE;
02622 }
02623 if (gettimeofday(&tv, NULL) >= 0)
02624 wlan_status.last_scan = tv.tv_sec;
02625 }
02626
02627 return FALSE;
02628 }
02629
02634 void schedule_scan(guint seconds) {
02635
02636
02637 remove_roam_scan_timer();
02638 wlan_status.roam_scan_id = g_timeout_add_seconds(
02639 seconds,
02640 wlan_roam_scan_cb,
02641 NULL);
02642 }
02643
02647 static void reschedule_scan(void)
02648 {
02649
02650
02651
02652
02653 if (get_inactivity_status() == TRUE) {
02654 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
02655 } else {
02656 if (wlan_status.roam_scan <= WLANCOND_MIN_ROAM_SCAN_INTERVAL) {
02657 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
02658 } else if (wlan_status.roam_scan >=
02659 WLANCOND_MAX_ROAM_SCAN_INTERVAL) {
02660 wlan_status.roam_scan = WLANCOND_MAX_ROAM_SCAN_INTERVAL;
02661 } else {
02662 wlan_status.roam_scan = wlan_status.roam_scan * 2;
02663 }
02664 }
02665
02666 schedule_scan(wlan_status.roam_scan);
02667 }
02668
02675 static gboolean check_capabilities(struct scan_results_t *scan_results,
02676 struct connect_params_t *conn)
02677 {
02678
02679 if ((scan_results->cap_bits & WLANCOND_MODE_MASK) != (guint32)conn->mode)
02680 return FALSE;
02681 if ((scan_results->cap_bits & WLANCOND_ENCRYPT_METHOD_MASK) !=
02682 (guint32)(conn->encryption &
02683 WLANCOND_ENCRYPT_METHOD_MASK))
02684 return FALSE;
02685 if ((scan_results->cap_bits & WLANCOND_ENCRYPT_WPA2_MASK) !=
02686 (guint32)(conn->encryption &
02687 WLANCOND_ENCRYPT_WPA2_MASK))
02688 return FALSE;
02689 if (check_ciphers(scan_results->cap_bits, conn->encryption) < 0)
02690 return FALSE;
02691
02692 return TRUE;
02693 }
02694
02702 struct scan_results_t* find_connection(
02703 GSList* ap_list, struct connect_params_t *conn,
02704 gboolean update_roam_cache)
02705 {
02706 GSList *list;
02707 struct scan_results_t *best_connection = NULL;
02708 gint current_rssi = 0;
02709
02710
02711 if (update_roam_cache == TRUE)
02712 clean_roam_cache();
02713
02714 for (list = ap_list; list != NULL; list = list->next) {
02715 struct scan_results_t *scan_results = list->data;
02716 if (memcmp(scan_results->ssid, conn->ssid,
02717 scan_results->ssid_len) == 0) {
02718 print_mac(WLANCOND_PRIO_LOW, "Found AP:",
02719 scan_results->bssid);
02720
02721
02722 if (memcmp(scan_results->bssid, wlan_status.conn.bssid,
02723 ETH_ALEN) == 0) {
02724 current_rssi = scan_results->rssi;
02725 DLOG_DEBUG("Current AP: %d", current_rssi);
02726 }
02727
02728 if (check_capabilities(scan_results, conn) ==
02729 FALSE)
02730 continue;
02731
02732 if (is_ap_in_black_list(scan_results->bssid) == TRUE) {
02733 DLOG_INFO("AP is in black list, discarded");
02734 continue;
02735 }
02736
02737
02738
02739
02740 if (update_roam_cache == TRUE) {
02741 add_to_roam_cache(scan_results);
02742 }
02743
02744 if (best_connection == NULL ||
02745 best_connection->rssi < scan_results->rssi) {
02746 DLOG_DEBUG("Best connection: %d (old %d)",
02747 scan_results->rssi,
02748 best_connection == NULL ?
02749 WLANCOND_MINIMUM_SIGNAL:
02750 best_connection->rssi);
02751 best_connection = scan_results;
02752 }
02753 }
02754 }
02755
02756
02757 if (best_connection == NULL)
02758 return NULL;
02759
02760
02761
02762
02763 if (current_rssi != 0) {
02764 if (best_connection->rssi < current_rssi +
02765 WLANCOND_ROAM_THRESHOLD) {
02766 DLOG_DEBUG("Best connection not good enough");
02767 return NULL;
02768 }
02769 }
02770
02771
02772 if (best_connection->rssi < WLANCOND_MINIMUM_SIGNAL)
02773 return NULL;
02774
02775 return best_connection;
02776 }
02782 static dbus_uint32_t find_adhoc_channel(GSList *ap_list) {
02783
02784 dbus_uint32_t used_channel_list = 0;
02785 dbus_uint32_t selected_channel = 0;
02786 GSList* list;
02787 guint32 i;
02788
02789
02790 for (list = ap_list; list != NULL; list = list->next) {
02791 struct scan_results_t *scan_results = list->data;
02792 used_channel_list |= 1 << scan_results->channel;
02793 }
02794
02795 for (i = 1; i <= 11; i++) {
02796 if (!(used_channel_list & (1 << i))) {
02797 selected_channel = i;
02798 break;
02799 }
02800 }
02801
02802 if (selected_channel == 0) {
02803
02804
02805 selected_channel = g_random_int_range(1, 12);
02806 }
02807
02808
02809
02810 return selected_channel;
02811 }
02817 int find_connection_and_associate(GSList *scan_results,
02818 gboolean update_roam_cache,
02819 gboolean create_new_adhoc,
02820 gboolean autoconnect)
02821 {
02822 struct scan_results_t adhoc;
02823 struct connect_params_t *conn = &wlan_status.conn;
02824 guint wps_pbc_registrars = 0;
02825 GSList* list;
02826
02827
02828
02829 if (conn->encryption & WLANCOND_WPS_PUSH_BUTTON) {
02830 for (list = scan_results; list != NULL; list = list->next) {
02831 struct scan_results_t *scan_results = list->data;
02832
02833 if (scan_results->cap_bits & WLANCOND_WPS_PUSH_BUTTON
02834 &&
02835 scan_results->cap_bits & WLANCOND_WPS_CONFIGURED) {
02836 if (++wps_pbc_registrars > 1) {
02837 DLOG_ERR("Too many WPS PBC registrars");
02838 return ETOOMANYREGISTRARS;
02839 }
02840 }
02841 }
02842 }
02843
02844 struct scan_results_t *connection = find_connection(
02845 scan_results, &wlan_status.conn, update_roam_cache);
02846
02847 if (connection == NULL && conn->mode == WLANCOND_ADHOC &&
02848 create_new_adhoc == TRUE) {
02849 DLOG_DEBUG("No existing adhoc connection");
02850 memset(&adhoc, 0, sizeof(adhoc));
02851 connection = &adhoc;
02852 memcpy(connection->ssid, conn->ssid, conn->ssid_len);
02853 connection->channel = find_adhoc_channel(scan_results);
02854 }
02855
02856 if (connection) {
02857 if (autoconnect == TRUE &&
02858 connection->rssi < WLANCOND_MINIMUM_AUTOCONNECT_RSSI) {
02859 DLOG_WARN("RSSI too low for autoconnect");
02860 return ETOOWEAKAP;
02861 }
02862 int ret = associate(connection);
02863 if (ret < 0)
02864 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
02865 return ret;
02866 }
02867 return -1;
02868 }
02872 static void registrar_error_signal(void)
02873 {
02874 DBusMessage *registrar_error;
02875
02876 registrar_error = new_dbus_signal(
02877 WLANCOND_SIG_PATH,
02878 WLANCOND_SIG_INTERFACE,
02879 WLANCOND_REGISTRAR_ERROR_SIG,
02880 NULL);
02881
02882 send_and_unref(get_dbus_connection(), registrar_error);
02883 }
02887 static gboolean rescan(void* data)
02888 {
02889 if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
02890 if (scan(wlan_status.conn.ssid,
02891 wlan_status.conn.ssid_len, TRUE) < 0) {
02892 set_wlan_state(WLAN_NOT_INITIALIZED,
02893 DISCONNECTED_SIGNAL,
02894 FORCE_YES);
02895 }
02896 }
02897 return FALSE;
02898 }
02903 static void connect_from_scan_results(GSList *scan_results)
02904 {
02905 gboolean autoconnect = !!(wlan_status.conn.flags & WLANCOND_AUTOCONNECT);
02906
02907 int status = find_connection_and_associate(
02908 scan_results, TRUE, TRUE, autoconnect);
02909
02910 clean_scan_results(&scan_results);
02911
02912 if (status == 0)
02913 return;
02914
02915 DLOG_DEBUG("Could not find suitable network");
02916
02917 if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
02918
02919 if (status != ETOOWEAKAP && status != ESUPPLICANT &&
02920 ++wlan_status.retry_count <= WLANCOND_MAX_SCAN_TRIES) {
02921 DLOG_DEBUG("Rescanning");
02922 g_timeout_add_seconds(
02923 WLANCOND_RESCAN_DELAY,
02924 rescan,
02925 NULL);
02926 } else {
02927
02928
02929
02930 if (status == ETOOMANYREGISTRARS) {
02931 set_wlan_state(WLAN_NOT_INITIALIZED,
02932 NO_SIGNAL, FORCE_YES);
02933 registrar_error_signal();
02934 } else {
02935 if (status == ESUPPLICANT) {
02936 DLOG_ERR("Supplicant error");
02937 kill_supplicant();
02938 }
02939 set_wlan_state(WLAN_NOT_INITIALIZED,
02940 DISCONNECTED_SIGNAL, FORCE_YES);
02941 }
02942 }
02943 return;
02944 }
02945
02946
02947 reschedule_scan();
02948 }
02955 int scan_results_ioctl(int ifindex, GSList** scan_results_save)
02956 {
02957 struct iwreq req;
02958 char *buffer;
02959 unsigned int buflen = IW_SCAN_MAX_DATA*2;
02960 int sock;
02961 unsigned int counter = 3;
02962
02963
02964
02965 init_iwreq(&req);
02966
02967 sock = socket_open();
02968
02969 buffer = g_malloc(buflen);
02970
02971 try_again:
02972
02973
02974 req.u.data.pointer = buffer;
02975 req.u.data.flags = 0;
02976 req.u.data.length = buflen;
02977
02978 if (ioctl(sock, SIOCGIWSCAN, &req) < 0) {
02979
02980
02981 if (errno == E2BIG && buflen != G_MAXUINT16) {
02982 DLOG_DEBUG("Too much data for buffer length %d "
02983 "needed %d\n", buflen, req.u.data.length);
02984
02985 char* new_buffer = NULL;
02986 buflen = (req.u.data.length > buflen ?
02987 req.u.data.length : buflen * 2);
02988
02989
02990 if (buflen > G_MAXUINT16)
02991 buflen = G_MAXUINT16;
02992 new_buffer = g_realloc(buffer, buflen);
02993
02994 buffer = new_buffer;
02995 goto try_again;
02996 }
02997
02998
02999 if (errno == EAGAIN)
03000 {
03001 DLOG_DEBUG("Not yet ready...");
03002 if (counter-- > 0) {
03003 sleep(1);
03004 goto try_again;
03005 }
03006 }
03007
03008 DLOG_ERR("Get scan results failed");
03009
03010 g_free(buffer);
03011 return -1;
03012 }
03013
03014 if (req.u.data.length)
03015 {
03016 struct iw_event iwe;
03017 struct stream_descr stream;
03018 struct scan_results_t *scan_results;
03019 struct wireless_iface *wireless_if;
03020 int ret;
03021 gboolean wap_handled = FALSE;
03022 int we_version;
03023
03024 scan_results = g_slice_new0(struct scan_results_t);
03025 memset(&iwe, 0, sizeof(iwe));
03026
03027 if (ifindex != 0) {
03028 wireless_if = get_interface_data(ifindex);
03029 we_version = wireless_if->range.we_version_compiled;
03030 } else {
03031 struct iw_range range;
03032 if (iw_get_range_info(socket_open(),
03033 wlan_status.ifname,
03034 &range)<0)
03035 memset(&range, 0, sizeof(range));
03036 we_version = range.we_version_compiled;
03037 }
03038
03039 iw_init_event_stream(&stream, buffer, req.u.data.length);
03040 do
03041 {
03042
03043 ret = iw_extract_event_stream(
03044 &stream, &iwe,
03045 we_version);
03046 if (ret > 0) {
03047
03048
03049
03050
03051 if (iwe.cmd == SIOCGIWAP) {
03052
03053
03054
03055 if (wap_handled == TRUE) {
03056 *scan_results_save =
03057 save_scan_results(
03058 scan_results,
03059 *scan_results_save);
03060 scan_results = g_slice_new0(
03061 struct scan_results_t);
03062 } else {
03063 wap_handled = TRUE;
03064 }
03065 }
03066 print_event_token(&iwe, scan_results, ifindex,
03067 TRUE);
03068 }
03069
03070 }
03071 while (ret > 0);
03072
03073
03074
03075 if (wap_handled == TRUE) {
03076 *scan_results_save = save_scan_results(
03077 scan_results,
03078 *scan_results_save);
03079 } else {
03080
03081 g_slice_free(struct scan_results_t, scan_results);
03082 }
03083 }
03084
03085 g_free(buffer);
03086
03087 return 0;
03088 }
03089
03090
03096 gboolean ask_scan_results(int ifindex)
03097 {
03098 GSList *scan_results_save = NULL;
03099 dbus_int32_t number_of_results;
03100
03101 if (scan_results_ioctl(ifindex, &scan_results_save) < 0)
03102 return FALSE;
03103
03104
03105 if (scan_name_cache != NULL) {
03106 number_of_results = g_slist_length(scan_results_save);
03107
03108
03109
03110 if (number_of_results > WLANCOND_MAX_NETWORKS)
03111 scan_results_save = g_slist_sort(scan_results_save,
03112 network_compare);
03113
03114 send_dbus_scan_results(scan_results_save, scan_name_cache,
03115 number_of_results);
03116 g_free(scan_name_cache);
03117 scan_name_cache = NULL;
03118 }
03119
03120
03121
03122 if ((get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION ||
03123 wlan_status.signal == WLANCOND_LOW) &&
03124 get_scan_state() == SCAN_ACTIVE) {
03125
03126 DLOG_DEBUG("Connect from scan");
03127
03128 set_scan_state(SCAN_NOT_ACTIVE);
03129
03130 connect_from_scan_results(scan_results_save);
03131
03132 return TRUE;
03133 }
03134
03135 set_scan_state(SCAN_NOT_ACTIVE);
03136
03137 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN &&
03138 power_down_after_scan == TRUE) {
03139 set_interface_state(socket_open(), CLEAR, IFF_UP);
03140 }
03141
03142 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
03143
03144 if (wlan_status.roam_cache) {
03145 clean_roam_cache();
03146 }
03147 wlan_status.roam_cache = scan_results_save;
03148 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_NO);
03149 } else {
03150 clean_scan_results(&scan_results_save);
03151 }
03152
03153 return TRUE;
03154 }
03155
03162 static DBusHandlerResult disconnect_request(DBusMessage *message,
03163 DBusConnection *connection) {
03164 DBusMessage *reply;
03165
03166 set_scan_state(SCAN_NOT_ACTIVE);
03167
03168
03169 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, FORCE_YES);
03170
03171 reply = new_dbus_method_return(message);
03172 send_and_unref(connection, reply);
03173
03174 return DBUS_HANDLER_RESULT_HANDLED;
03175 }
03182 static DBusHandlerResult disassociate_request(DBusMessage *message,
03183 DBusConnection *connection) {
03184 DBusMessage *reply;
03185
03186 if (get_wlan_state() != WLAN_CONNECTED &&
03187 get_wlan_state() != WLAN_NO_ADDRESS) {
03188 DLOG_DEBUG("Not in correct state for disassociation");
03189
03190 reply = new_dbus_method_return(message);
03191 send_and_unref(connection, reply);
03192 return DBUS_HANDLER_RESULT_HANDLED;
03193 }
03194
03195 if (get_wpa_mode() == TRUE) {
03196 clear_wpa_keys(wlan_status.conn.bssid);
03197 }
03198
03199 mlme_command(wlan_status.conn.bssid, IW_MLME_DISASSOC,
03200 WLANCOND_REASON_LEAVING);
03201
03202 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL, FORCE_NO);
03203
03204 DLOG_DEBUG("Disassociated, trying to find a new connection");
03205
03206 if (scan(wlan_status.conn.ssid, wlan_status.conn.ssid_len, TRUE) < 0) {
03207
03208 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
03209 FORCE_YES);
03210 }
03211
03212 reply = new_dbus_method_return(message);
03213 send_and_unref(connection, reply);
03214
03215 return DBUS_HANDLER_RESULT_HANDLED;
03216 }
03223 static DBusHandlerResult status_request(DBusMessage *message,
03224 DBusConnection *connection) {
03225 DBusMessage *reply = NULL;
03226 struct iwreq req;
03227 struct iw_range range;
03228 char *essid = NULL;
03229 int essid_len;
03230 dbus_uint32_t sens = 0;
03231 dbus_uint32_t security = 0;
03232 dbus_uint32_t capability = 0;
03233 dbus_uint32_t channel = 0;
03234 unsigned char *bssid = NULL;
03235
03236 int sock;
03237
03238 if (get_wlan_state() != WLAN_CONNECTED &&
03239 get_wlan_state() != WLAN_NO_ADDRESS &&
03240 get_mode() != WLANCOND_ADHOC) {
03241 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03242 send_and_unref(connection, reply);
03243 return DBUS_HANDLER_RESULT_HANDLED;
03244 }
03245
03246 sock = socket_open();
03247
03248 init_iwreq(&req);
03249
03250 essid = g_malloc0(IW_ESSID_MAX_SIZE+1);
03251 req.u.essid.pointer = (caddr_t)essid;
03252 req.u.essid.length = IW_ESSID_MAX_SIZE;
03253 req.u.essid.flags = 0;
03254
03255
03256 if (ioctl(sock, SIOCGIWESSID, &req) < 0) {
03257 DLOG_ERR("Could not get ESSID");
03258 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03259 goto param_err;
03260 }
03261 essid_len = req.u.essid.length;
03262
03263
03264 if (essid_len == 0 || essid_len == 32)
03265 essid_len++;
03266
03267 init_iwreq(&req);
03268
03269
03270 if (ioctl(sock, SIOCGIWAP, &req) < 0) {
03271 DLOG_ERR("Could not get BSSID");
03272 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03273 goto param_err;
03274 }
03275 bssid = g_malloc(ETH_ALEN);
03276 memcpy(bssid, &req.u.ap_addr.sa_data, ETH_ALEN);
03277
03278 init_iwreq(&req);
03279 struct iw_statistics stats;
03280 memset(&stats, 0, sizeof(struct iw_statistics));
03281
03282 req.u.data.pointer = (caddr_t) &stats;
03283 req.u.data.length = sizeof(struct iw_statistics);
03284 req.u.data.flags = 1;
03285
03286
03287 if (ioctl(sock, SIOCGIWSTATS, &req) < 0) {
03288 DLOG_ERR("Could not get statistics");
03289 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03290 goto param_err;
03291 }
03292 sens = stats.qual.level - 0x100;
03293
03294
03295 init_iwreq(&req);
03296
03297 if (ioctl(sock, SIOCGIWFREQ, &req) < 0) {
03298 DLOG_DEBUG("Could not get channel");
03299 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03300 goto param_err;
03301 }
03302
03303 if (iw_get_range_info(sock, wlan_status.ifname, &range) >= 0) {
03304 double freq = iw_freq2float(&(req.u.freq));
03305 channel = iw_freq_to_channel(freq, &range);
03306 }
03307
03308 if (channel < WLANCOND_MIN_WLAN_CHANNEL ||
03309 channel > WLANCOND_MAX_WLAN_CHANNEL) {
03310 channel = 0;
03311 DLOG_DEBUG("Got invalid channel\n");
03312 }
03313
03314
03315 init_iwreq(&req);
03316
03317 if (ioctl(sock, SIOCGIWMODE, &req) < 0) {
03318 DLOG_ERR("Could not get operating mode");
03319 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03320 goto param_err;
03321 }
03322
03323 if (req.u.mode == IW_MODE_ADHOC) {
03324 capability |= WLANCOND_ADHOC;
03325 } else if (req.u.mode == IW_MODE_INFRA) {
03326 capability |= WLANCOND_INFRA;
03327 }
03328
03329 init_iwreq(&req);
03330
03331
03332 security = wlan_status.conn.encryption;
03333
03334 #if 0
03335 key = g_malloc(IW_ENCODING_TOKEN_MAX);
03336 req.u.data.pointer = (caddr_t) key;
03337 req.u.data.length = IW_ENCODING_TOKEN_MAX;
03338 req.u.data.flags = 0;
03339
03340 if (ioctl(sock, SIOCGIWENCODE, &req) < 0) {
03341 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03342 goto param_err;
03343 }
03344
03345 if (req.u.data.flags & IW_ENCODE_OPEN)
03346 security |= WLANCOND_OPEN;
03347
03348 if (req.u.data.flags & IW_ENCODE_RESTRICTED)
03349 security |= WLANCOND_WEP;
03350
03351
03352 if (req.u.data.flags & IW_ENCODE_TKIP)
03353 security |= WLANCOND_WPA_PSK & WLANCOND_WPA_EAP &
03354 WLANCOND_WPA_TKIP;
03355
03356 if (req.u.data.flags & IW_ENCODE_AES)
03357 security |= WLANCOND_WPA_PSK & WLANCOND_WPA_EAP &
03358 WLANCOND_WPA_AES;
03359
03360 g_free(key);
03361 #endif
03362 init_iwreq(&req);
03363
03364
03365 if (ioctl(sock, SIOCGIWRATE, &req) < 0) {
03366 DLOG_ERR("Could not get the rate");
03367 }
03368 capability |= req.u.bitrate.value;
03369
03370 reply = new_dbus_method_return(message);
03371
03372 gchar* ifname = wlan_status.ifname;
03373
03374 append_dbus_args(reply,
03375 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03376 &essid, essid_len,
03377 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, ETH_ALEN,
03378 DBUS_TYPE_UINT32, &sens,
03379 DBUS_TYPE_UINT32, &channel,
03380 DBUS_TYPE_UINT32, &capability,
03381 DBUS_TYPE_UINT32, &security,
03382 DBUS_TYPE_STRING, &ifname,
03383 DBUS_TYPE_INVALID);
03384
03385 send_and_unref(connection, reply);
03386
03387 g_free(essid);
03388 g_free(bssid);
03389
03390 return DBUS_HANDLER_RESULT_HANDLED;
03391
03392 param_err:
03393 g_free(essid);
03394 g_free(bssid);
03395
03396 if (reply == NULL) {
03397 DLOG_DEBUG("Parameter error in status request");
03398 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
03399 }
03400 send_and_unref(connection, reply);
03401 return DBUS_HANDLER_RESULT_HANDLED;
03402 }
03403
03410 static DBusHandlerResult interface_request(DBusMessage *message,
03411 DBusConnection *connection) {
03412 DBusMessage *reply;
03413 gchar* ifname = wlan_status.ifname;
03414
03415 reply = new_dbus_method_return(message);
03416
03417 append_dbus_args(reply,
03418 DBUS_TYPE_STRING, &ifname,
03419 DBUS_TYPE_INVALID);
03420
03421 send_and_unref(connection, reply);
03422
03423 return DBUS_HANDLER_RESULT_HANDLED;
03424 }
03425
03432 static DBusHandlerResult connection_status_request(
03433 DBusMessage *message,
03434 DBusConnection *connection) {
03435
03436 DBusMessage *reply;
03437 dbus_bool_t state = FALSE;
03438
03439 guint state_v = get_wlan_state();
03440
03441 if (state_v == WLAN_INITIALIZED ||
03442 state_v == WLAN_NO_ADDRESS ||
03443 state_v == WLAN_CONNECTED)
03444 state = TRUE;
03445
03446 reply = new_dbus_method_return(message);
03447
03448 append_dbus_args(reply,
03449 DBUS_TYPE_BOOLEAN, &state,
03450 DBUS_TYPE_INVALID);
03451
03452 send_and_unref(connection, reply);
03453
03454 return DBUS_HANDLER_RESULT_HANDLED;
03455 }
03462 static DBusHandlerResult set_pmksa_request(DBusMessage *message,
03463 DBusConnection *connection) {
03464
03465 DBusMessage *reply = NULL;
03466 unsigned int pmkid_len, mac_len;
03467 unsigned char *pmkid;
03468 unsigned char *mac;
03469 dbus_uint32_t action;
03470 DBusError derror;
03471
03472 dbus_error_init(&derror);
03473
03474 if (dbus_message_get_args(
03475 message, &derror,
03476 DBUS_TYPE_UINT32, &action,
03477 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &pmkid, &pmkid_len,
03478 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &mac, &mac_len,
03479 DBUS_TYPE_INVALID) == FALSE)
03480 {
03481 DLOG_ERR("Failed to parse set_pmksa request: %s",
03482 derror.message);
03483 dbus_error_free(&derror);
03484 goto param_err;
03485 }
03486
03487 if (action != IW_PMKSA_ADD) {
03488 DLOG_ERR("Invalid action");
03489 goto param_err;
03490 }
03491
03492 if (pmkid == NULL || pmkid_len != WLANCOND_PMKID_LEN || mac == NULL
03493 || mac_len != ETH_ALEN) {
03494 DLOG_ERR("Invalid arguments");
03495 goto param_err;
03496 }
03497
03498 add_to_pmksa_cache(pmkid, mac);
03499
03500 print_mac(WLANCOND_PRIO_LOW, "PMKSA added successfully for address:",
03501 mac);
03502
03503 reply = new_dbus_method_return(message);
03504 send_and_unref(connection, reply);
03505
03506 return DBUS_HANDLER_RESULT_HANDLED;
03507
03508 param_err:
03509 if (reply == NULL) {
03510 DLOG_DEBUG("Parameter error in set_pmksa");
03511 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
03512 }
03513 send_and_unref(connection, reply);
03514 return DBUS_HANDLER_RESULT_HANDLED;
03515 }
03516
03523 static DBusHandlerResult set_powersave_request(DBusMessage *message,
03524 DBusConnection *connection) {
03525
03526 DBusMessage *reply = NULL;
03527 int sock;
03528 DBusError error;
03529 dbus_bool_t onoff;
03530
03531 sock = socket_open();
03532
03533 dbus_error_init(&error);
03534
03535 if (dbus_message_get_args(message, &error,
03536 DBUS_TYPE_BOOLEAN, &onoff,
03537 DBUS_TYPE_INVALID) == FALSE) {
03538 DLOG_ERR("Failed to parse message: %s",
03539 error.message);
03540 dbus_error_free(&error);
03541
03542 send_invalid_args(connection, message);
03543 return DBUS_HANDLER_RESULT_HANDLED;
03544 }
03545
03546
03547
03548
03549 if (onoff == TRUE) {
03550 if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
03551 set_wlan_state(WLAN_NOT_INITIALIZED,
03552 NO_SIGNAL, FORCE_YES);
03553 } else if (get_wlan_state() != WLAN_NO_ADDRESS ||
03554 (connect_name_cache != NULL &&
03555 strcmp(dbus_message_get_sender(message),
03556 connect_name_cache) == 0)) {
03557 if (set_power_state(powersave, sock) == FALSE) {
03558 DLOG_ERR("Setting powersave failed");
03559
03560 }
03561 }
03562 } else {
03563
03564 if (set_power_state(WLANCOND_POWER_ON, sock) == FALSE) {
03565 DLOG_ERR("Setting powersave failed");
03566
03567 }
03568 }
03569
03570 DLOG_DEBUG("WLAN powersave %s", onoff==TRUE?"on":"off");
03571
03572 reply = new_dbus_method_return(message);
03573 send_and_unref(connection, reply);
03574
03575 return DBUS_HANDLER_RESULT_HANDLED;
03576 }
03577
03584 static void wpa_ie_push_cb(DBusPendingCall *pending,
03585 void *user_data)
03586 {
03587 DBusMessage *reply;
03588 DBusError error;
03589
03590
03591
03592 dbus_error_init (&error);
03593
03594 reply = dbus_pending_call_steal_reply(pending);
03595
03596 if (dbus_set_error_from_message(&error, reply)) {
03597
03598 DLOG_DEBUG("EAP WPA IE push call result:%s", error.name);
03599
03600 dbus_error_free(&error);
03601
03602 set_wlan_state(WLAN_NOT_INITIALIZED,
03603 DISCONNECTED_SIGNAL,
03604 FORCE_YES);
03605 }
03606
03607 if (reply)
03608 dbus_message_unref(reply);
03609 dbus_pending_call_unref(pending);
03610 }
03611
03620 int wpa_ie_push(unsigned char* ap_mac_addr, unsigned char* ap_wpa_ie,
03621 int ap_wpa_ie_len, char* ssid, int ssid_len,
03622 unsigned int authentication_type) {
03623
03624 DBusMessage *msg;
03625 DBusPendingCall *pending;
03626
03627 if (authentication_type != EAP_AUTH_TYPE_WFA_SC) {
03628 if (wlan_status.wpa_ie.ie_len == 0 || ap_wpa_ie == NULL ||
03629 ssid == NULL) {
03630 DLOG_ERR("WPA IE / SSID (%s) not valid", ssid);
03631 return -1;
03632 }
03633 }
03634
03635 msg = dbus_message_new_method_call(
03636 EAP_SERVICE,
03637 EAP_REQ_PATH,
03638 EAP_REQ_INTERFACE,
03639 EAP_WPA_IE_PUSH_REQ);
03640
03641 if (msg == NULL) {
03642 return -1;
03643 }
03644
03645 append_dbus_args(
03646 msg,
03647 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03648 &wlan_status.wpa_ie.ie, wlan_status.wpa_ie.ie_len,
03649 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ap_wpa_ie,
03650 ap_wpa_ie_len,
03651 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03652 &ssid, ssid_len,
03653 DBUS_TYPE_UINT32, &wlan_status.pairwise_cipher,
03654 DBUS_TYPE_UINT32, &wlan_status.group_cipher,
03655 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03656 &ap_mac_addr, ETH_ALEN,
03657 DBUS_TYPE_UINT32, &authentication_type,
03658 DBUS_TYPE_INVALID);
03659
03660 if (!dbus_connection_send_with_reply(get_dbus_connection(),
03661 msg, &pending, -1))
03662 die("Out of memory");
03663
03664 if (!dbus_pending_call_set_notify (pending, wpa_ie_push_cb, NULL, NULL))
03665 die("Out of memory");
03666
03667 dbus_message_unref(msg);
03668
03669 return 0;
03670 }
03677 int wpa_mic_failure_event(dbus_bool_t key_type, dbus_bool_t is_fatal) {
03678 DBusMessage *msg;
03679 DBusMessage *reply;
03680 DBusError derr;
03681
03682 msg = dbus_message_new_method_call(
03683 EAP_SERVICE,
03684 EAP_REQ_PATH,
03685 EAP_REQ_INTERFACE,
03686 EAP_WPA_MIC_FAILURE_REQ);
03687
03688 if (msg == NULL) {
03689 return -1;
03690 }
03691
03692 append_dbus_args(msg,
03693 DBUS_TYPE_BOOLEAN, &key_type,
03694 DBUS_TYPE_BOOLEAN, &is_fatal,
03695 DBUS_TYPE_INVALID);
03696
03697 dbus_error_init(&derr);
03698
03699 reply = dbus_connection_send_with_reply_and_block(
03700 get_dbus_connection(), msg, -1, &derr);
03701
03702 dbus_message_unref(msg);
03703
03704 if (dbus_error_is_set(&derr)) {
03705 DLOG_ERR("EAP returned error: %s", derr.name);
03706
03707 dbus_error_free(&derr);
03708 if (reply)
03709 dbus_message_unref(reply);
03710 return -1;
03711 }
03712
03713 dbus_message_unref(reply);
03714
03715 return 0;
03716 }
03721 int associate_supplicant(void) {
03722 DBusMessage *msg;
03723 DBusMessage *reply;
03724 DBusError derr;
03725
03726 msg = dbus_message_new_method_call(
03727 EAP_SERVICE,
03728 EAP_REQ_PATH,
03729 EAP_REQ_INTERFACE,
03730 EAP_ASSOCIATE_REQ);
03731
03732 if (msg == NULL) {
03733 return -1;
03734 }
03735
03736 dbus_error_init(&derr);
03737
03738 reply = dbus_connection_send_with_reply_and_block(
03739 get_dbus_connection(), msg, -1, &derr);
03740
03741 dbus_message_unref(msg);
03742
03743 if (dbus_error_is_set(&derr)) {
03744 DLOG_ERR("EAP returned error: %s", derr.name);
03745
03746 dbus_error_free(&derr);
03747 if (reply)
03748 dbus_message_unref(reply);
03749 return -1;
03750 }
03751
03752 dbus_message_unref(reply);
03753
03754 return 0;
03755 }
03762 static void disassociate_cb(DBusPendingCall *pending,
03763 void *user_data)
03764 {
03765 DBusMessage *reply;
03766 DBusError error;
03767
03768 dbus_error_init (&error);
03769
03770 reply = dbus_pending_call_steal_reply(pending);
03771
03772 if (dbus_set_error_from_message(&error, reply)) {
03773
03774 DLOG_DEBUG("EAP disassociate call result:%s", error.name);
03775
03776 dbus_error_free(&error);
03777 }
03778
03779 if (reply)
03780 dbus_message_unref(reply);
03781 dbus_pending_call_unref(pending);
03782 }
03783
03788 int disassociate_eap(void) {
03789 DBusMessage *msg;
03790 DBusPendingCall *pending;
03791
03792 msg = dbus_message_new_method_call(
03793 EAP_SERVICE,
03794 EAP_REQ_PATH,
03795 EAP_REQ_INTERFACE,
03796 EAP_DISASSOCIATE_REQ);
03797
03798 if (msg == NULL) {
03799 return -1;
03800 }
03801
03802 if (!dbus_connection_send_with_reply(get_dbus_connection(),
03803 msg, &pending, -1))
03804 die("Out of memory");
03805
03806 if (!dbus_pending_call_set_notify (pending, disassociate_cb, NULL,
03807 NULL))
03808 die("Out of memory");
03809
03810 dbus_message_unref(msg);
03811
03812 return 0;
03813 }
03814
03829 int check_pmksa_cache(unsigned char* own_mac, int own_mac_len,
03830 unsigned char* bssid, int bssid_len,
03831 uint32_t authentication_type,
03832 uint32_t pairwise_key_cipher_suite,
03833 uint32_t group_key_cipher_suite,
03834 int *status)
03835 {
03836 DBusMessage *msg = NULL;
03837 DBusMessage *reply = NULL;
03838 DBusError error;
03839 dbus_bool_t found;
03840
03841 dbus_error_init (&error);
03842
03843 msg = dbus_message_new_method_call(
03844 EAP_SERVICE,
03845 EAP_REQ_PATH,
03846 EAP_REQ_INTERFACE,
03847 EAP_CHECK_PMKSA_CACHE_REQ);
03848
03849 if (msg == NULL)
03850 return -1;
03851
03852 if (dbus_message_append_args(
03853 msg,
03854 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &own_mac, own_mac_len,
03855 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, bssid_len,
03856 DBUS_TYPE_UINT32, &authentication_type,
03857 DBUS_TYPE_UINT32, &pairwise_key_cipher_suite,
03858 DBUS_TYPE_UINT32, &group_key_cipher_suite,
03859 DBUS_TYPE_INVALID) == FALSE)
03860 {
03861 DLOG_ERR("Unable to add args to dbus method call.");
03862 dbus_message_unref(msg);
03863 return -1;
03864 }
03865
03866 reply = dbus_connection_send_with_reply_and_block(
03867 get_dbus_connection(), msg, -1, &error);
03868
03869 dbus_message_unref(msg);
03870
03871 if (dbus_error_is_set(&error)) {
03872 DLOG_ERR("EAP returned error: %s", error.message);
03873 dbus_error_free(&error);
03874
03875 goto error;
03876 }
03877
03878 if (!dbus_message_get_args(reply, &error,
03879 DBUS_TYPE_BOOLEAN, &found,
03880 DBUS_TYPE_INVALID))
03881 {
03882 DLOG_ERR("Error parsing the return value: %s", error.message);
03883 if (dbus_error_is_set(&error))
03884 dbus_error_free(&error);
03885
03886 goto error;
03887 }
03888
03889 dbus_message_unref(reply);
03890
03891 *status = found;
03892
03893 return 0;
03894
03895 error:
03896 if(reply)
03897 dbus_message_unref(reply);
03898
03899 return -1;
03900 }
03901
03902 #ifdef ENABLE_CALL_TYPE_CHECKING
03903
03908 void set_call_type(const char *type)
03909 {
03910 guint new_type;
03911
03912 if (!type || !strcmp(type, "none"))
03913 new_type = WLANCOND_CALL_NONE;
03914 else if (!strcmp(type, "skype"))
03915 new_type = WLANCOND_CALL_VOIP;
03916 else if (!strcmp(type, "cellular"))
03917 new_type = WLANCOND_CALL_CELL;
03918 else {
03919 DLOG_DEBUG("Unknown call type: %s", type);
03920 new_type = WLANCOND_CALL_UNKNOWN;
03921 }
03922
03923 if (new_type == wlan_status.call_state)
03924 return;
03925
03926 DLOG_DEBUG("Switching call type to %i (%s)", new_type, type);
03927
03928 wlan_status.call_state = new_type;
03929
03930
03931 set_power_state(wlan_status.requested_power, socket_open());
03932 }
03933
03941 int context_parser(DBusMessageIter *actit)
03942 {
03943 DBusMessageIter cmdit;
03944 DBusMessageIter argit;
03945 DBusMessageIter valit;
03946 char *argname;
03947 char *argval;
03948 char *variable;
03949 char *value;
03950
03951 do {
03952 variable = value = NULL;
03953
03954 dbus_message_iter_recurse(actit, &cmdit);
03955
03956 do {
03957 if (dbus_message_iter_get_arg_type(&cmdit) !=
03958 DBUS_TYPE_STRUCT)
03959 return FALSE;
03960
03961 dbus_message_iter_recurse(&cmdit, &argit);
03962
03963 if (dbus_message_iter_get_arg_type(&argit) !=
03964 DBUS_TYPE_STRING)
03965 return FALSE;
03966
03967 dbus_message_iter_get_basic(&argit, (void *)&argname);
03968
03969 if (!dbus_message_iter_next(&argit))
03970 return FALSE;
03971
03972 if (dbus_message_iter_get_arg_type(&argit) !=
03973 DBUS_TYPE_VARIANT)
03974 return FALSE;
03975
03976 dbus_message_iter_recurse(&argit, &valit);
03977
03978 if (dbus_message_iter_get_arg_type(&valit) !=
03979 DBUS_TYPE_STRING)
03980 return FALSE;
03981
03982 dbus_message_iter_get_basic(&valit, (void *)&argval);
03983
03984 if (!strcmp(argname, "variable")) {
03985 variable = argval;
03986 }
03987 else if (!strcmp(argname, "value")) {
03988 value = argval;
03989 }
03990
03991 if (!strcmp(variable, "call_audio_type"))
03992 set_call_type(value);
03993
03994 } while (dbus_message_iter_next(&cmdit));
03995
03996 } while (dbus_message_iter_next(actit));
03997
03998 return TRUE;
03999 }
04000
04005 void handle_policy_actions(DBusMessage *msg)
04006 {
04007 dbus_uint32_t txid;
04008 char *actname;
04009 DBusMessageIter msgit;
04010 DBusMessageIter arrit;
04011 DBusMessageIter entit;
04012 DBusMessageIter actit;
04013 int success = TRUE;
04014
04015 dbus_message_iter_init(msg, &msgit);
04016
04017 if (dbus_message_iter_get_arg_type(&msgit) != DBUS_TYPE_UINT32)
04018 return;
04019
04020 dbus_message_iter_get_basic(&msgit, (void *)&txid);
04021
04022 if (!dbus_message_iter_next(&msgit) ||
04023 dbus_message_iter_get_arg_type(&msgit) !=
04024 DBUS_TYPE_ARRAY) {
04025 success = FALSE;
04026 goto out;
04027 }
04028
04029 dbus_message_iter_recurse(&msgit, &arrit);
04030
04031 do {
04032 if (dbus_message_iter_get_arg_type(&arrit) !=
04033 DBUS_TYPE_DICT_ENTRY) {
04034 success = FALSE;
04035 continue;
04036 }
04037
04038 dbus_message_iter_recurse(&arrit, &entit);
04039
04040 do {
04041 if (dbus_message_iter_get_arg_type(&entit) !=
04042 DBUS_TYPE_STRING) {
04043 success = FALSE;
04044 continue;
04045 }
04046
04047 dbus_message_iter_get_basic(&entit, (void *)&actname);
04048
04049 if (!dbus_message_iter_next(&entit) ||
04050 dbus_message_iter_get_arg_type(&entit)
04051 != DBUS_TYPE_ARRAY) {
04052 success = FALSE;
04053 continue;
04054 }
04055
04056 dbus_message_iter_recurse(&entit, &actit);
04057
04058 if (dbus_message_iter_get_arg_type(&actit) !=
04059 DBUS_TYPE_ARRAY) {
04060 success = FALSE;
04061 continue;
04062 }
04063
04064 if (!strcmp(actname, "com.nokia.policy.context"))
04065 success &= context_parser(&actit);
04066
04067 } while (dbus_message_iter_next(&entit));
04068
04069 } while (dbus_message_iter_next(&arrit));
04070
04071 out:
04072 if (!success)
04073 DLOG_DEBUG("Failed to parse the policy actions message.");
04074 }
04075 #endif
04076
04077
04078 typedef DBusHandlerResult (*handler_func)(DBusMessage *message,
04079 DBusConnection *connection);
04080
04081 typedef struct {
04082 const char *interface;
04083 const char *name;
04084 handler_func func;
04085 } method_handler_t;
04086
04087 static method_handler_t handlers[] = {
04088 { WLANCOND_REQ_INTERFACE, WLANCOND_SETTINGS_AND_CONNECT_REQ,
04089 settings_and_connect_request},
04090 { WLANCOND_REQ_INTERFACE, WLANCOND_SCAN_REQ, scan_request},
04091 { WLANCOND_REQ_INTERFACE, WLANCOND_STATUS_REQ, status_request},
04092 { WLANCOND_REQ_INTERFACE, WLANCOND_INTERFACE_REQ, interface_request},
04093 { WLANCOND_REQ_INTERFACE, WLANCOND_CONNECTION_STATUS_REQ,
04094 connection_status_request},
04095 { WLANCOND_REQ_INTERFACE, WLANCOND_SET_PMKSA_REQ, set_pmksa_request},
04096 { WLANCOND_REQ_INTERFACE, WLANCOND_SET_POWERSAVE_REQ,
04097 set_powersave_request},
04098 { WLANCOND_REQ_INTERFACE, WLANCOND_DISCONNECT_REQ, disconnect_request},
04099 { WLANCOND_REQ_INTERFACE, WLANCOND_DISASSOCIATE_REQ,
04100 disassociate_request},
04101 { NULL }
04102 };
04103
04110 DBusHandlerResult wlancond_req_handler(DBusConnection *connection,
04111 DBusMessage *message,
04112 void *user_data)
04113 {
04114 method_handler_t *handler;
04115
04116 DLOG_DEBUG("Received %s.%s",
04117 dbus_message_get_interface(message),
04118 dbus_message_get_member(message));
04119
04120
04121 #ifdef USE_MCE_MODE
04122 if (dbus_message_is_signal(message,
04123 MCE_SIGNAL_IF,
04124 MCE_DEVICE_MODE_SIG)) {
04125 return mode_change_dbus(message);
04126 }
04127 #ifdef ACTIVITY_CHECK
04128 if (dbus_message_is_signal(message,
04129 MCE_SIGNAL_IF,
04130 MCE_INACTIVITY_SIG)) {
04131 return activity_check_dbus(message);
04132 }
04133 #endif
04134 #endif
04135 if (dbus_message_is_signal(message,
04136 ICD_DBUS_INTERFACE,
04137 ICD_STATUS_CHANGED_SIG))
04138 return icd_check_signal_dbus(message);
04139
04140 if (dbus_message_is_signal(message,
04141 PHONE_NET_DBUS_INTERFACE,
04142 PHONE_REGISTRATION_STATUS_CHANGE_SIG))
04143 return csd_check_signal_dbus(message);
04144
04145 if (dbus_message_is_signal (message,
04146 BLUEZ_ADAPTER_SERVICE_NAME,
04147 BLUEZ_ADAPTER_PROPERTY_CHANGED_SIG))
04148 return bluez_check_adapter_signal_dbus(message);
04149
04150 if (dbus_message_is_signal (message,
04151 BLUEZ_HEADSET_SERVICE_NAME,
04152 BLUEZ_HEADSET_PROPERTY_CHANGED_SIG))
04153 return bluez_check_headset_signal_dbus(message);
04154
04155 if (dbus_message_is_signal (message,
04156 BLUEZ_AUDIOSINK_SERVICE_NAME,
04157 BLUEZ_AUDIOSINK_PROPERTY_CHANGED_SIG))
04158 return bluez_check_headset_signal_dbus(message);
04159
04160 #ifdef ENABLE_CALL_TYPE_CHECKING
04161 if (dbus_message_is_signal(message, POLICY_SERVICE_NAME,
04162 POLICY_ACTIONS_SIG)) {
04163 handle_policy_actions(message);
04164 return DBUS_HANDLER_RESULT_HANDLED;
04165 }
04166 #endif
04167
04168
04169 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
04170 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04171 }
04172
04173 for (handler = handlers; handler->interface != NULL; handler++) {
04174 if (dbus_message_is_method_call(message,
04175 handler->interface,
04176 handler->name)) {
04177 DLOG_DEBUG("Received %s", handler->name);
04178 return handler->func(message, connection);
04179 }
04180 }
04181 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04182 }
04183
04184 static DBusObjectPathVTable wlancond_req_vtable = {
04185 .message_function = wlancond_req_handler,
04186 .unregister_function = NULL
04187 };
04188
04189
04194 void init_dbus_handlers(DBusConnection *connection) {
04195 dbus_bool_t ret;
04196 ret = dbus_connection_register_object_path(connection,
04197 WLANCOND_REQ_PATH,
04198 &wlancond_req_vtable,
04199 NULL);
04200 if (ret == FALSE) {
04201 DLOG_ERR("dbus_connection_register_object_path failed");
04202 }
04203 #ifdef USE_MCE_MODE
04204 if (!add_mode_listener(connection)) {
04205 DLOG_ERR("Adding mode listener failed");
04206 }
04207 #endif
04208 if (!add_icd_listener(connection)) {
04209 DLOG_ERR("Adding icd listener failed");
04210 }
04211
04212 if (!add_csd_listener(connection)) {
04213 DLOG_ERR("Adding csd listener failed");
04214 }
04215 if (!add_bluez_listener(connection)) {
04216 DLOG_ERR("Adding Bluez listener failed");
04217 }
04218 }
04219
04224 void destroy_dbus_handlers(DBusConnection *connection) {
04225 dbus_connection_unregister_object_path(connection, WLANCOND_REQ_PATH);
04226 }