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