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