00001
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <unistd.h>
00030 #include <glib.h>
00031 #include <errno.h>
00032 #include <net/if.h>
00033 #include <net/ethernet.h>
00034 #include <linux/socket.h>
00035 #include <sys/ioctl.h>
00036 #include <osso-ic-dbus.h>
00037 #include <syslog.h>
00038
00039 #define DBUS_API_SUBJECT_TO_CHANGE
00040 #include <dbus/dbus.h>
00041 #include <eap-dbus.h>
00042 #include <wlancond-dbus.h>
00043 #include <mce/mode-names.h>
00044 #ifdef USE_MCE_MODE
00045 #include <mce/dbus-names.h>
00046 #endif
00047 #include "log.h"
00048 #include "dbus.h"
00049 #include "dbus-helper.h"
00050 #include "dbus-handler.h"
00051 #include "common.h"
00052 #include "wpa.h"
00053 #include "wps.h"
00054 #include "wapi.h"
00055
00056 #define WLANCOND_SHUTDOWN_DELAY 12 //12s
00057 #define WLANCOND_CONNECT_TIMEOUT 14 //14s
00058 #define WLANCOND_SCAN_TIMEOUT 8 //8s
00059 #define WLANCOND_RESCAN_DELAY 1
00060 #define WLANCOND_GPRS_TIMEOUT 2 //2s
00061
00062 #define CALIBRATION_APPLICATION "/usr/bin/wl1271-cal"
00063
00065 static char *scan_name_cache = NULL;
00067 static char *connect_name_cache = NULL;
00068
00070 static int wlan_socket = -1;
00071
00073 struct wlan_status_t wlan_status;
00074
00075 static gboolean _flight_mode = FALSE;
00076 static gboolean power_down_after_scan = FALSE;
00077 static dbus_bool_t saved_inactivity = FALSE;
00078
00080 static guint wlan_if_down_timer_id = 0;
00081 static guint wlan_connect_timer_id = 0;
00082 static guint wlan_gprs_timer_id = 0;
00083
00085 gint debug_level = 0;
00086
00087 #define WLAN_PREFIX_STR "wlan"
00088
00091 void wlancond_print(guint priority, const char *debug, ...) {
00092 va_list args;
00093 char buffer[200];
00094
00095 switch (debug_level) {
00096
00097 case 0:
00098 if (priority > WLANCOND_PRIO_MEDIUM) {
00099 va_start(args, debug);
00100 vsnprintf(buffer, sizeof(buffer), debug, args);
00101 va_end(args);
00102
00103 syslog(LOG_INFO | LOG_DAEMON, "%s", buffer);
00104 return;
00105 }
00106 break;
00107 case 1:
00108 if (priority > WLANCOND_PRIO_LOW) {
00109 va_start(args, debug);
00110 vsnprintf(buffer, sizeof(buffer), debug, args);
00111 va_end(args);
00112
00113 syslog(LOG_INFO | LOG_DAEMON, "%s", buffer);
00114 return;
00115 }
00116 break;
00117
00118 default:
00119 va_start(args, debug);
00120 vsnprintf(buffer, sizeof(buffer), debug, args);
00121 va_end(args);
00122
00123 syslog(LOG_INFO | LOG_DAEMON, "%s", buffer);
00124 return;
00125 }
00126 }
00130 int socket_open(void)
00131 {
00132 if (wlan_socket > 0)
00133 return wlan_socket;
00134
00135 wlan_socket = socket(AF_INET, SOCK_DGRAM, 0);
00136
00137 if (wlan_socket < 0)
00138 die("socket() failed");
00139
00140 return wlan_socket;
00141 }
00142
00143 static int get_own_mac(void)
00144 {
00145 struct ifreq req;
00146
00147 memset(&req , 0, sizeof(req));
00148 memcpy(req.ifr_name, wlan_status.ifname, IFNAMSIZ);
00149
00150 if (ioctl(socket_open(), SIOCGIFHWADDR, &req) < 0)
00151 {
00152 return -1;
00153 }
00154
00155 memcpy(wlan_status.own_mac, req.ifr_hwaddr.sa_data, ETH_ALEN);
00156
00157 print_mac(WLANCOND_PRIO_LOW, "MAC:", (guchar*) wlan_status.own_mac);
00158
00159 return 0;
00160 }
00161
00167 static gint get_setting_int(const gchar* path)
00168 {
00169 gint value = -1;
00170 ConnSettingsValue *conn_setting_value;
00171
00172 conn_setting_value = conn_settings_get(wlan_status.setting, path);
00173 if (conn_setting_value == NULL) {
00174 return -1;
00175 }
00176
00177 if (conn_setting_value->type == CONN_SETTINGS_VALUE_INT) {
00178 value = conn_setting_value->value.int_val;
00179 DLOG_DEBUG("User selected value %d for %s", value, path);
00180
00181 }
00182
00183 conn_settings_value_destroy(conn_setting_value);
00184
00185 return value;
00186 }
00193 gboolean get_setting_bool(const gchar* path, gboolean *error)
00194 {
00195 gboolean value = FALSE;
00196 ConnSettingsValue *conn_setting_value;
00197
00198 *error = TRUE;
00199
00200 conn_setting_value = conn_settings_get(wlan_status.setting, path);
00201 if (conn_setting_value == NULL) {
00202 return value;
00203 }
00204
00205 if (conn_setting_value->type == CONN_SETTINGS_VALUE_BOOL) {
00206 value = conn_setting_value->value.bool_val;
00207 DLOG_DEBUG("User selected %s for %s", value==TRUE?
00208 "true":"false", path);
00209 *error = FALSE;
00210 }
00211
00212 conn_settings_value_destroy(conn_setting_value);
00213
00214 return value;
00215 }
00219 void init_logging(void) {
00220
00221 wlan_status.setting = conn_settings_open(CONN_SETTINGS_CONNECTION,
00222 NULL);
00223
00224 if (wlan_status.setting == NULL ) {
00225 DLOG_ERR("Opening connection settings failed");
00226 return;
00227 }
00228 debug_level = get_setting_int(WLANCOND_DEBUG_LEVEL);
00229 if (debug_level < 0)
00230 debug_level = 0;
00231
00232 if (debug_level > 0) {
00233 DLOG_DEBUG("Debug level increased to %d", debug_level);
00234 }
00235 }
00236
00242 void update_own_ie(unsigned char* wpa_ie, guint wpa_ie_len)
00243 {
00244 g_free(wlan_status.wpa_ie.ie);
00245 wlan_status.wpa_ie.ie = wpa_ie;
00246 wlan_status.wpa_ie.ie_len = wpa_ie_len;
00247 }
00248
00253 guint get_encryption_info(void)
00254 {
00255 guint auth_status = 0;
00256
00257 if (wlan_status.pairwise_cipher & CIPHER_SUITE_CCMP) {
00258 auth_status |= WLANCOND_WPA_AES;
00259 } else if (wlan_status.pairwise_cipher & CIPHER_SUITE_TKIP) {
00260 auth_status |= WLANCOND_WPA_TKIP;
00261 } else if (wlan_status.pairwise_cipher & CIPHER_SUITE_SMS4) {
00262 auth_status |= WLANCOND_WAPI_SMS4;
00263 } else if (wlan_status.pairwise_cipher & CIPHER_SUITE_WEP40 ||
00264 wlan_status.pairwise_cipher & CIPHER_SUITE_WEP104) {
00265 auth_status |= WLANCOND_WEP;
00266 } else {
00267 auth_status |= WLANCOND_OPEN;
00268 }
00269 return auth_status;
00270 }
00271
00275 int clean_dbus_handler(void)
00276 {
00277 if (wlan_socket > 0) {
00278 close(wlan_socket);
00279 wlan_socket = -1;
00280 }
00281 return 0;
00282 }
00287 void mode_change(dbus_uint32_t radio_mode) {
00288
00289 gboolean mode = !!(radio_mode & MCE_RADIO_STATE_WLAN);
00290
00291 DLOG_INFO("WLAN flight mode changed to \"%s\"",
00292 mode?"Normal":"Flight");
00293
00294 if (!mode) {
00295 int signal = NO_SIGNAL;
00296 if (is_connected_state() == TRUE)
00297 signal = DISCONNECTED_SIGNAL;
00298 set_wlan_state(WLAN_NOT_INITIALIZED, signal, FALSE);
00299 _flight_mode = TRUE;
00300 }
00301 else {
00302 _flight_mode = FALSE;
00303 }
00304 }
00309 #ifdef USE_MCE_MODE
00310 static DBusHandlerResult mode_change_dbus(DBusMessage *message) {
00311
00312 dbus_uint32_t mode;
00313
00314 if (!dbus_message_get_args(message, NULL,
00315 DBUS_TYPE_UINT32, &mode,
00316 DBUS_TYPE_INVALID)) {
00317 DLOG_ERR("Invalid arguments for device_mode_ind signal");
00318 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00319 }
00320
00321 mode_change(mode);
00322
00323 return DBUS_HANDLER_RESULT_HANDLED;
00324 }
00325 #ifdef ACTIVITY_CHECK
00326 static DBusHandlerResult activity_check_dbus(DBusMessage *message) {
00327
00328 if (!dbus_message_get_args(message, NULL,
00329 DBUS_TYPE_BOOLEAN, &saved_inactivity,
00330 DBUS_TYPE_INVALID)) {
00331 DLOG_ERR("Invalid arguments for device_activity signal");
00332 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00333 }
00334 activity_check(saved_inactivity);
00335
00336 return DBUS_HANDLER_RESULT_HANDLED;
00337 }
00338 #endif
00339 #endif
00340
00341 #ifdef ACTIVITY_CHECK
00342
00345 void activity_check(dbus_bool_t inactivity) {
00346
00347 if (get_wlan_state() != WLAN_CONNECTED) {
00348 return;
00349 }
00350
00351 if (inactivity == FALSE) {
00352
00353 if (nl80211_set_cqm(WLANCOND_CQM_THRESHOLD_ACTIVE,
00354 WLANCOND_CQM_HYSTERESIS))
00355 DLOG_ERR("nl80211 - CQM monitor setting failed");
00356
00357
00358 remove_iptables();
00359 } else {
00360
00361 if (nl80211_set_cqm(WLANCOND_CQM_THRESHOLD_IDLE,
00362 WLANCOND_CQM_HYSTERESIS))
00363 DLOG_ERR("nl80211 - CQM monitor setting failed");
00364
00365 if (set_iptables() < 0)
00366 DLOG_ERR("Setting iptables failed");
00367 }
00368 set_power_state(wlan_status.powersave);
00369 }
00370
00374 gboolean get_inactivity_status(void)
00375 {
00376 return saved_inactivity;
00377 }
00378 #endif
00379
00384 static DBusHandlerResult icd_check_signal_dbus(DBusMessage *message) {
00385
00386 char *icd_name;
00387 char *icd_type;
00388 char *icd_state;
00389 DBusError dbus_error;
00390
00391 if ((get_wlan_state() != WLAN_CONNECTED &&
00392 get_wlan_state() != WLAN_NO_ADDRESS) ||
00393 get_mode() != WLANCOND_INFRA) {
00394 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00395 }
00396
00397 dbus_error_init(&dbus_error);
00398 if (!dbus_message_get_args(message, &dbus_error,
00399 DBUS_TYPE_STRING, &icd_name,
00400 DBUS_TYPE_STRING, &icd_type,
00401 DBUS_TYPE_STRING, &icd_state,
00402 DBUS_TYPE_INVALID ) )
00403 {
00404 DLOG_ERR("Could not get args from signal, '%s'",
00405 dbus_error.message);
00406 dbus_error_free(&dbus_error);
00407 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00408 }
00409
00410 if (icd_state != NULL && strncmp(icd_state, "CONNECTED", 9) == 0) {
00411
00412 set_wlan_state(WLAN_CONNECTED, NO_SIGNAL, TRUE);
00413
00414 DLOG_DEBUG("Going to power save");
00415
00416 if (set_power_state(wlan_status.powersave) == FALSE) {
00417 DLOG_ERR("Failed to set power save");
00418 }
00419
00420 }
00421
00422
00423
00424 return DBUS_HANDLER_RESULT_HANDLED;
00425 }
00426
00432 static DBusHandlerResult eap_check_signal_dbus(DBusMessage *message) {
00433
00434 DBusError dbus_error;
00435 dbus_uint32_t status;
00436
00437 dbus_error_init(&dbus_error);
00438 if (!dbus_message_get_args(message, &dbus_error,
00439 DBUS_TYPE_UINT32, &status,
00440 DBUS_TYPE_INVALID ) )
00441 {
00442 DLOG_ERR("Could not get args from signal, '%s'",
00443 dbus_error.message);
00444 dbus_error_free(&dbus_error);
00445 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00446 }
00447
00448 if (status == EAP_SUCCESS)
00449 {
00450
00451 if (get_wlan_state() != WLAN_NO_ADDRESS)
00452 if (set_power_state(wlan_status.powersave) == FALSE)
00453 DLOG_ERR("Setting powersave failed (wpa)");
00454
00455 if (netlink_send_linkmode(WLANCOND_IF_READY) != 0)
00456 DLOG_ERR("Setting oper state to ready failed");
00457
00458
00459 wlan_status.retry_count = 0;
00460 }
00461
00462 return DBUS_HANDLER_RESULT_HANDLED;
00463 }
00464
00468 gint run_calibration(void) {
00469 gchar *args[2];
00470 gint count = 0;
00471 args[count++] = (gchar*) CALIBRATION_APPLICATION;
00472 args[count++] = NULL;
00473
00474 DLOG_DEBUG("Running calibration");
00475
00476 if (!g_spawn_sync (NULL, args, NULL, G_SPAWN_STDOUT_TO_DEV_NULL |
00477 G_SPAWN_STDERR_TO_DEV_NULL,
00478 NULL, NULL, NULL, NULL, NULL, NULL)) {
00479 return -1;
00480 }
00481
00482 return 0;
00483 }
00487 #define KILL_SUPPLICANT "/usr/bin/killall"
00488 #define SUPPLICANT_NAME "eapd.real"
00489 void kill_supplicant(void) {
00490
00491 DLOG_ERR("Supplicant error");
00492
00493 system(KILL_SUPPLICANT " -9 " SUPPLICANT_NAME);
00494 }
00495 static void remove_wlan_gprs_timer(void)
00496 {
00497 if (wlan_gprs_timer_id) {
00498 g_source_remove(wlan_gprs_timer_id);
00499 wlan_gprs_timer_id = 0;
00500 }
00501 }
00507 static gboolean wlan_gprs_cb(void* data) {
00508
00509 if (wlan_gprs_timer_id) {
00510 wlan_gprs_timer_id = 0;
00511
00512 DLOG_DEBUG("GPRS became idle");
00513 wlan_status.call_type &= ~CALL_GPRS;
00514 set_tx_power(wlan_status.conn.power_level);
00515 }
00516 return FALSE;
00517 }
00523 static DBusHandlerResult gprs_datacounters_signal(DBusMessage *message) {
00524
00525 if (!(wlan_status.call_type & CALL_GPRS)) {
00526 DLOG_DEBUG("GPRS is active");
00527 wlan_status.call_type |= CALL_GPRS;
00528 set_tx_power(wlan_status.conn.power_level);
00529 }
00530
00531 remove_wlan_gprs_timer();
00532
00533 wlan_gprs_timer_id = g_timeout_add_seconds(
00534 WLANCOND_GPRS_TIMEOUT,
00535 wlan_gprs_cb,
00536 NULL);
00537
00538 return DBUS_HANDLER_RESULT_HANDLED;
00539 }
00545 static DBusHandlerResult csd_check_signal_dbus(DBusMessage *message) {
00546
00547 DBusError error;
00548 char* network_code;
00549 char* country_code;
00550 struct timeval tv;
00551
00552 dbus_error_init(&error);
00553
00554 if (!dbus_message_get_args(message, &error,
00555 DBUS_TYPE_STRING, &network_code,
00556 DBUS_TYPE_STRING, &country_code,
00557 DBUS_TYPE_INVALID))
00558 {
00559 DLOG_ERR("Could not get args from signal, '%s'",
00560 error.message);
00561 dbus_error_free(&error);
00562 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00563 }
00564
00565 DLOG_DEBUG("Handled csd signal, country code: %s", country_code);
00566
00567 if (country_code == NULL || strlen(country_code) == 0) {
00568 if (wlan_status.country_code != NULL &&
00569 strlen(wlan_status.country_code) != 0) {
00570
00571
00572 if (wlan_status.calibration_needed == FALSE) {
00573 if (gettimeofday(&tv, NULL) <0)
00574 wlan_status.last_code = 0;
00575 else
00576 wlan_status.last_code = tv.tv_sec;
00577 }
00578 g_free(wlan_status.country_code);
00579 wlan_status.country_code = NULL;
00580 wlan_status.calibration_needed = TRUE;
00581 DLOG_INFO("Country information lost");
00582 }
00583 } else if (wlan_status.country_code == NULL ||
00584 strcmp(country_code, wlan_status.country_code)) {
00585
00586
00587
00588
00589 if (wlan_status.last_calibrated_code && country_code &&
00590 strcmp(wlan_status.last_calibrated_code,
00591 country_code) == 0) {
00592 DLOG_DEBUG("Calibration is not needed");
00593 wlan_status.calibration_needed = FALSE;
00594 } else {
00595 DLOG_DEBUG("Calibration is needed");
00596 wlan_status.calibration_needed = TRUE;
00597 }
00598 g_free(wlan_status.country_code);
00599 wlan_status.country_code = g_strdup(country_code);
00600
00601
00602 wlan_status.last_code = 0;
00603 DLOG_INFO("Country code changed to: %s", country_code);
00604 }
00605
00606 return DBUS_HANDLER_RESULT_HANDLED;
00607 }
00612 static gboolean check_country_timeout(void) {
00613 struct timeval tv;
00614
00615
00616 if (wlan_status.last_code == 0)
00617 return FALSE;
00618
00619 if (gettimeofday(&tv, NULL) <0)
00620 return FALSE;
00621
00622 if (tv.tv_sec > wlan_status.last_code + WLANCOND_COUNTRY_CACHE_TIME)
00623 return FALSE;
00624
00625 return TRUE;
00626 }
00627
00632 static gint handle_country(void) {
00633 if (wlan_status.calibration_needed ||
00634 wlan_status.country_code == NULL) {
00635
00636 if (wlan_status.country_code == NULL ||
00637 strlen(wlan_status.country_code) == 0) {
00638
00639 if (check_country_timeout() == TRUE) {
00640 DLOG_DEBUG("Cached code in use");
00641 return 0;
00642 } else {
00643 DLOG_DEBUG("Cannot use cached code");
00644 }
00645 }
00646
00647
00648
00649
00650 char* code = check_country_code();
00651
00652
00653 if (code != NULL)
00654 if (run_calibration() < 0)
00655 DLOG_ERR("Fatal: Could not calibrate");
00656
00657 g_free(wlan_status.country_code);
00658 wlan_status.country_code = code;
00659 g_free(wlan_status.last_calibrated_code);
00660 wlan_status.last_calibrated_code = g_strdup(code);
00661 wlan_status.calibration_needed = FALSE;
00662 }
00663 return 0;
00664 }
00668 int init_dbus_handler(void)
00669 {
00670 gboolean error;
00671
00672 handle_country();
00673
00674 if (get_own_mac() < 0) {
00675 DLOG_ERR("Could not get own MAC address");
00676 return -1;
00677 }
00678
00679 wlan_status.allow_all_ciphers = get_setting_bool(
00680 WLANCOND_ALLOW_ALL_CIPHERS, &error);
00681
00682 return 0;
00683 }
00684
00685 static gboolean in_flight_mode(void) {
00686 return _flight_mode;
00687 }
00688
00689 void set_wlan_signal(gboolean high_or_low)
00690 {
00691 if (high_or_low == WLANCOND_HIGH) {
00692 wlan_status.signal = WLANCOND_HIGH;
00693 remove_roam_scan_timer();
00694 } else {
00695 wlan_status.signal = WLANCOND_LOW;
00696 }
00697 }
00698
00699 void remove_roam_scan_timer(void)
00700 {
00701 if (wlan_status.roam_scan_id) {
00702 g_source_remove(wlan_status.roam_scan_id);
00703 wlan_status.roam_scan_id = 0;
00704 }
00705 }
00706
00707 void remove_connect_timer(void)
00708 {
00709 if (wlan_connect_timer_id) {
00710 g_source_remove(wlan_connect_timer_id);
00711 wlan_connect_timer_id = 0;
00712 }
00713 }
00714
00715 static void remove_wlan_if_timer(void)
00716 {
00717
00718 if (wlan_if_down_timer_id) {
00719 g_source_remove(wlan_if_down_timer_id);
00720 wlan_if_down_timer_id = 0;
00721 }
00722 }
00723
00724 void remove_scan_timer(void)
00725 {
00726 if (wlan_status.scan_id) {
00727 g_source_remove(wlan_status.scan_id);
00728 wlan_status.scan_id = 0;
00729 }
00730 }
00731 static void remove_rescan_timer(void)
00732 {
00733 if (wlan_status.rescan_id) {
00734 g_source_remove(wlan_status.rescan_id);
00735 wlan_status.rescan_id = 0;
00736 }
00737 }
00741 gboolean scan_retries_left(void) {
00742 guint scan_tries = WLANCOND_MAX_SCAN_TRIES;
00743
00744
00745
00746
00747
00748
00749
00750
00751 if ((wlan_status.conn.encryption & WLANCOND_ENCRYPT_METHOD_MASK) ==
00752 WLANCOND_WEP)
00753 scan_tries = WLANCOND_MAX_SCAN_TRIES*2;
00754
00755 if (++wlan_status.retry_count <= scan_tries)
00756 return TRUE;
00757 else
00758 return FALSE;
00759 }
00763 static gboolean no_connection_and_scan_retries_left(void) {
00764 guint scan_tries = WLANCOND_MAX_SCAN_TRIES*2;
00765
00766 if (++wlan_status.retry_count <= scan_tries)
00767 return TRUE;
00768 else
00769 return FALSE;
00770 }
00776 static gboolean wlan_connect_timer_cb(void* data)
00777 {
00778 if (wlan_connect_timer_id && get_wlan_state() ==
00779 WLAN_INITIALIZED_FOR_CONNECTION) {
00780
00781 wlan_connect_timer_id = 0;
00782
00783 DLOG_DEBUG("Association timeout, try: %d",
00784 wlan_status.retry_count);
00785
00786 DLOG_DEBUG("Disconnecting previous connection");
00787 mlme_command(wlan_status.conn.bssid,
00788 WLANCOND_NL80211_MLME_DISCONNECT,
00789 WLANCOND_REASON_LEAVING);
00790
00791
00792 roam_cache_key_t key = { wlan_status.conn.bssid,
00793 wlan_status.conn.channel };
00794 remove_from_roam_cache(&key);
00795
00796
00797 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
00798
00799
00800 wlan_status.conn.channel = 0;
00801
00802 if (find_connection_and_associate(wlan_status.roam_cache,
00803 FALSE, FALSE, FALSE) == 0)
00804 return FALSE;
00805
00806
00807 if (scan_retries_left()) {
00808 if (scan(wlan_status.conn.ssid,
00809 wlan_status.conn.ssid_len, TRUE) == 0) {
00810 return FALSE;
00811 }
00812 }
00813
00814 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
00815 FALSE);
00816 return FALSE;
00817 }
00818
00819 wlan_connect_timer_id = 0;
00820
00821
00822
00823 return FALSE;
00824 }
00825
00831 static gboolean wlan_scan_cb(void* data)
00832 {
00833
00834 wlan_status.scan_id = 0;
00835
00836 DLOG_ERR("Scan failed, should not happen!");
00837
00838 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, FALSE);
00839
00840 return FALSE;
00841 }
00847 static gboolean wlan_if_down_cb(void* data)
00848 {
00849
00850 wlan_if_down_timer_id = 0;
00851
00852 if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
00853 DLOG_DEBUG("Delayed shutdown occurred");
00854 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FALSE);
00855 return FALSE;
00856 }
00857
00858
00859
00860 return FALSE;
00861 }
00869 int mlme_command(guchar* addr, guint16 cmd, guint16 reason_code)
00870 {
00871 gint ret;
00872
00873 if (!wlan_status.ifindex)
00874 return -2;
00875
00876
00877
00878
00879
00880 if (wlan_status.conn.mode & WLANCOND_ADHOC) {
00881 ret = nl80211_leave_adhoc(wlan_status.ifindex);
00882 if (ret) {
00883 DLOG_ERR("nl80211: Failed to Leave IBSS");
00884 return -1;
00885 }
00886 } else {
00887 ret = nl80211_mlme_command(addr, cmd, reason_code,
00888 wlan_status.ifindex);
00889 if (ret) {
00890 DLOG_ERR("nl80211: Failed to run MLME command, ret=%d",
00891 ret);
00892 return -1;
00893 }
00894 }
00895
00896 return 0;
00897 }
00903 static int set_mode(guint32 mode)
00904 {
00905 int ret;
00906 guint32 threshold;
00907
00908 ret = nl80211_set_op_mode(wlan_status.ifindex, mode);
00909
00910 if (ret) {
00911 DLOG_ERR("nl80211 - Operating mode setting failed");
00912 return -1;
00913 }
00914
00915 if (get_inactivity_status() == TRUE)
00916 threshold = WLANCOND_CQM_THRESHOLD_IDLE;
00917 else
00918 threshold = WLANCOND_CQM_THRESHOLD_ACTIVE;
00919
00920 if (nl80211_set_cqm(threshold, WLANCOND_CQM_HYSTERESIS)) {
00921 DLOG_ERR("nl80211 - CQM monitor setting failed");
00922 return -1;
00923 }
00924
00925 return 0;
00926 }
00930 static void remove_timers(void) {
00931
00932 remove_connect_timer();
00933
00934
00935 remove_scan_timer();
00936
00937
00938 remove_rescan_timer();
00939
00940
00941 remove_wlan_if_timer();
00942
00943
00944 remove_wlan_gprs_timer();
00945 }
00946
00947 static void remove_connection_time_filters(void) {
00948 if (wlan_status.dbus_filters == FALSE)
00949 return;
00950
00951 remove_icd_listener(get_dbus_connection());
00952 #ifdef ACTIVITY_CHECK
00953 remove_activity_listener(get_dbus_connection());
00954 #endif
00955 if (get_wpa_mode() == TRUE)
00956 remove_eap_listener(get_dbus_connection());
00957
00958 remove_gprs_listener(get_dbus_connection());
00959
00960 wlan_status.dbus_filters = FALSE;
00961 }
00962
00969 void set_wlan_state(int new_state, int send_signal, gboolean delay_shutdown)
00970 {
00971 const char *status_table[] =
00972 {
00973 (char*)"WLAN_NOT_INITIALIZED",
00974 (char*)"WLAN_INITIALIZED",
00975 (char*)"WLAN_INITIALIZED_FOR_SCAN",
00976 (char*)"WLAN_INITIALIZED_FOR_CONNECTION",
00977 (char*)"WLAN_NO_ADDRESS",
00978 (char*)"WLAN_CONNECTED"
00979 };
00980
00981 switch (new_state) {
00982
00983 case WLAN_NOT_INITIALIZED:
00984 if (get_wlan_state() == WLAN_CONNECTED ||
00985 get_wlan_state() == WLAN_NO_ADDRESS) {
00986 mlme_command(wlan_status.conn.bssid,
00987 WLANCOND_NL80211_MLME_DISCONNECT,
00988 WLANCOND_REASON_LEAVING);
00989 }
00990
00991 remove_iptables();
00992
00993 set_scan_state(SCAN_NOT_ACTIVE);
00994
00995 if (get_wlan_state() != WLAN_NOT_INITIALIZED &&
00996 get_wlan_state() != WLAN_INITIALIZED_FOR_SCAN)
00997 clear_wpa_mode();
00998
00999 wlan_status.retry_count = 0;
01000 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
01001 wlan_status.ip_ok = FALSE;
01002 wlan_status.last_scan = 0;
01003
01004 remove_timers();
01005
01006 set_wlan_signal(WLANCOND_HIGH);
01007
01008 if (delay_shutdown == FALSE) {
01009
01010 clean_roam_cache();
01011
01012 if (set_interface_state(socket_open(), CLEAR,
01013 IFF_UP)<0) {
01014 DLOG_ERR("Could not set interface down");
01015 }
01016
01017 } else {
01018
01019 DLOG_DEBUG("Delaying interface shutdown");
01020
01021 wlan_if_down_timer_id = g_timeout_add_seconds(
01022 WLANCOND_SHUTDOWN_DELAY,
01023 wlan_if_down_cb,
01024 NULL);
01025
01026 }
01027
01028 remove_connection_time_filters();
01029
01030 if (send_signal == DISCONNECTED_SIGNAL)
01031 disconnected_signal();
01032
01033 break;
01034 case WLAN_INITIALIZED_FOR_CONNECTION:
01035
01036
01037
01038
01039 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
01040
01041
01042 wlan_status.conn.channel = 0;
01043
01044
01045 remove_connect_timer();
01046
01047 set_power_state(WLANCOND_POWER_ON);
01048
01049 break;
01050 case WLAN_CONNECTED:
01051
01052
01053 if (get_wpa_mode() == FALSE)
01054 set_power_state(wlan_status.powersave);
01055
01056 wlan_status.ip_ok = TRUE;
01057 break;
01058 default:
01059 break;
01060 }
01061 DLOG_DEBUG("Wlancond state change, old_state: %s, new_state: %s",
01062 status_table[wlan_status.state], status_table[new_state]);
01063 wlan_status.state = new_state;
01064 }
01065
01070 guint get_wlan_state(void)
01071 {
01072 return wlan_status.state;
01073 }
01074
01079 void set_scan_state(guint new_state)
01080 {
01081 if (wlan_status.scan == new_state) {
01082 return;
01083 }
01084 if (new_state == SCAN_NOT_ACTIVE) {
01085 remove_scan_timer();
01086 if (wlan_status.scan == SCAN_ACTIVE &&
01087 scan_name_cache != NULL) {
01088 DLOG_DEBUG("Sending empty results");
01089 send_dbus_scan_results(NULL, scan_name_cache, 0);
01090 g_free(scan_name_cache);
01091 scan_name_cache = NULL;
01092 }
01093 }
01094
01095 DLOG_DEBUG("Wlancond scan change, old_state: %s, new_state: %s",
01096 wlan_status.scan==SCAN_NOT_ACTIVE ? "SCAN_IDLE":"SCANNING",
01097 new_state == SCAN_NOT_ACTIVE ? "SCAN_IDLE":"SCANNING");
01098 wlan_status.scan = new_state;
01099 }
01100
01105 guint get_scan_state(void)
01106 {
01107 return wlan_status.scan;
01108 }
01113 guint get_mode(void)
01114 {
01115 return wlan_status.conn.mode;
01116 }
01117
01122 static void set_network_latency(int latency) {
01123
01124 DLOG_DEBUG("Setting network latency to %i", latency);
01125
01126 if (wlan_status.latency_file == NULL) {
01127 wlan_status.latency_file = fopen(WLANCOND_LATENCY_FILE, "w");
01128 if (wlan_status.latency_file == NULL) {
01129 DLOG_ERR("Cannot open: %s", WLANCOND_LATENCY_FILE);
01130 return;
01131 }
01132 }
01133
01134 if (fwrite(&latency, sizeof(int), 1, wlan_status.latency_file)
01135 != 1) {
01136 DLOG_ERR("Could not write to: %s", WLANCOND_LATENCY_FILE);
01137 }
01138
01139 fflush(wlan_status.latency_file);
01140
01141 return;
01142 }
01143
01144 gboolean can_adjust_psm(void) {
01145
01146
01147 if (get_wlan_state() == WLAN_CONNECTED &&
01148 wlan_status.ip_ok == TRUE &&
01149 wlan_status.retry_count == 0)
01150 return TRUE;
01151
01152 return FALSE;
01153 }
01154 static gint compare_scan_entry(gconstpointer a, gconstpointer b)
01155 {
01156 const scan_results_t *scan_entry = a;
01157 const roam_cache_key_t *key = b;
01158 int ret;
01159 if ((ret = memcmp(scan_entry->bssid, key->bssid, ETH_ALEN)))
01160 return ret;
01161 else
01162 return scan_entry->channel - key->channel;
01163 }
01164
01170 static gboolean is_uapsd_supported(unsigned char* mac) {
01171
01172 GSList *list;
01173 unsigned char *ap_mac = mac;
01174
01175
01176 if (ap_mac == NULL)
01177 ap_mac = wlan_status.conn.bssid;
01178
01179 roam_cache_key_t key = { ap_mac, wlan_status.conn.channel };
01180 list = g_slist_find_custom(wlan_status.roam_cache,
01181 &key,
01182 &compare_scan_entry);
01183 if (list == NULL)
01184 return FALSE;
01185
01186 struct scan_results_t *entry = list->data;
01187 if (entry->extra_cap_bits & WLANCOND_UAPSD_SUPPORTED)
01188 return TRUE;
01189
01190 return FALSE;
01191 }
01192
01198 gboolean set_power_state(guint new_state)
01199 {
01200 gboolean power_state;
01201
01202 if (new_state == WLANCOND_CAM_TIMEOUT) {
01203 if ((wlan_status.call_type & CALL_VOIP) &&
01204 is_uapsd_supported(NULL)) {
01205 DLOG_DEBUG("Full PSM because of VOIP and U-APSD");
01206 new_state = WLANCOND_FULL_POWERSAVE;
01207 } else if (wlan_status.full_psm_enabled) {
01208
01209 new_state = WLANCOND_FULL_POWERSAVE;
01210 } else if (wlan_status.high_traffic == FALSE &&
01211 can_adjust_psm() == TRUE &&
01212 get_inactivity_status() == TRUE) {
01213
01214
01215
01216 new_state = WLANCOND_FULL_POWERSAVE;
01217 }
01218 }
01219
01220 if (wlan_status.power == new_state)
01221 return TRUE;
01222
01223 switch (new_state) {
01224 case WLANCOND_POWER_ON:
01225 power_state = FALSE;
01226 break;
01227 case WLANCOND_CAM_TIMEOUT:
01228 set_network_latency(WLANCOND_DEFAULT_NETWORK_LATENCY);
01229 power_state = TRUE;
01230 break;
01231 case WLANCOND_FULL_POWERSAVE:
01232 set_network_latency(WLANCOND_FULL_PSM_LATENCY);
01233 power_state = TRUE;
01234 break;
01235 default:
01236 power_state = TRUE;
01237 break;
01238 }
01239
01240 if (nl80211_set_power_save(power_state, wlan_status.ifindex) != 0) {
01241 DLOG_ERR("set power failed, state: %s",
01242 power_state?"true":"false");
01243 return FALSE;
01244 }
01245
01246 wlan_status.power = new_state;
01247
01248 DLOG_DEBUG("New power state set: %i", new_state);
01249
01250 return TRUE;
01251 }
01252
01258 static int init_if(int sock)
01259 {
01260 if (!wlan_status.ifindex)
01261 return -1;
01262
01263 int previous_state = get_wlan_state();
01264
01265 if (previous_state == WLAN_NOT_INITIALIZED) {
01266
01267 if (wlan_status.interface_up == FALSE) {
01268
01269
01270 if (handle_country() < 0)
01271 return -1;
01272
01273 if (set_interface_state(sock, SET,
01274 IFF_UP | IFF_RUNNING) < 0) {
01275 return -1;
01276 }
01277 }
01278
01279 set_power_state(WLANCOND_POWER_ON);
01280 set_wlan_state(WLAN_INITIALIZED, NO_SIGNAL, FALSE);
01281 }
01282
01283 return previous_state;
01284 }
01285
01289 void save_device_interface(void)
01290 {
01291 strncpy(wlan_status.ifname, WLANCOND_IF_NAME, IFNAMSIZ);
01292 wlan_status.ifname[IFNAMSIZ] = '\0';
01293 wlan_status.ifindex = if_nametoindex(wlan_status.ifname);
01294 DLOG_DEBUG("WLAN interface Index %u", wlan_status.ifindex);
01295 }
01296
01304 int set_interface_state(int sock, int dir, short flags)
01305 {
01306 struct ifreq ifr;
01307
01308 memset(&ifr, 0, sizeof(ifr));
01309
01310 strncpy(ifr.ifr_name, wlan_status.ifname, IFNAMSIZ);
01311
01312 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
01313 DLOG_ERR("Could not get interface %s flags",
01314 wlan_status.ifname);
01315 return -1;
01316 }
01317 if (dir == SET) {
01318 if (!add_context_listener(get_dbus_connection()))
01319 DLOG_ERR("Adding context listener failed");
01320
01321 wlan_status.call_type = get_call_state();
01322
01323 ifr.ifr_flags |= flags;
01324 } else {
01325 remove_context_listener(get_dbus_connection());
01326
01327 wlan_status.if_down_self = TRUE;
01328 ifr.ifr_flags &= ~flags;
01329 }
01330
01331 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
01332 DLOG_ERR("Could not set interface %s flags",
01333 wlan_status.ifname);
01334 return -1;
01335 }
01336
01337 wlan_status.interface_up = (dir == SET ? TRUE:FALSE);
01338 DLOG_DEBUG("%s is %s", wlan_status.ifname,
01339 wlan_status.interface_up == TRUE ? "UP":"DOWN");
01340
01341 return 0;
01342 }
01343
01350 gboolean set_tx_power(guint power)
01351 {
01352 int tx_power;
01353
01354 if (wlan_status.call_type & (CALL_CELLULAR | CALL_GPRS)) {
01355 if (power == WLANCOND_TX_POWER10)
01356 tx_power = WLANCOND_TX_POWER10DBM;
01357 else
01358 tx_power = WLANCOND_TX_POWERLIMITED;
01359 } else {
01360 if (power == WLANCOND_TX_POWER10) {
01361 tx_power = WLANCOND_TX_POWER10DBM;
01362 } else if (power == WLANCOND_TX_POWER100) {
01363 tx_power = WLANCOND_TX_POWER100DBM;
01364 } else {
01365 return FALSE;
01366 }
01367 }
01368
01369 if (nl80211_set_tx_power(tx_power, wlan_status.ifindex) != 0) {
01370 DLOG_ERR("set tx power failed");
01371 return FALSE;
01372 }
01373
01374 return TRUE;
01375 }
01382 static int update_algorithms(guint32 encryption,
01383 struct scan_results_t *scan_results)
01384 {
01385 wlan_status.group_cipher = 0;
01386 wlan_status.pairwise_cipher = 0;
01387
01388
01389 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_OPEN) {
01390 DLOG_DEBUG("Open mode");
01391 wlan_status.pairwise_cipher = CIPHER_SUITE_NONE;
01392 return 0;
01393 }
01394
01395
01396 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP) {
01397 DLOG_DEBUG("WEP enabled");
01398 wlan_status.pairwise_cipher = CIPHER_SUITE_WEP40;
01399 return 0;
01400 }
01401
01402
01403 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK ||
01404 (encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_EAP) {
01405 if ((encryption & WLANCOND_ENCRYPT_ALG_MASK)
01406 == WLANCOND_WPA_TKIP) {
01407 DLOG_DEBUG("TKIP Selected for unicast");
01408 wlan_status.pairwise_cipher = CIPHER_SUITE_TKIP;
01409 } else if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) ==
01410 WLANCOND_WPA_AES) {
01411 DLOG_DEBUG("AES selected for unicast");
01412 wlan_status.pairwise_cipher = CIPHER_SUITE_CCMP;
01413 } else if (wlan_status.allow_all_ciphers == TRUE) {
01414 if (scan_results->extra_cap_bits & WLANCOND_WEP104) {
01415 DLOG_DEBUG("WEP104 selected for unicast");
01416 wlan_status.pairwise_cipher = CIPHER_SUITE_WEP104;
01417 } else if (scan_results->extra_cap_bits & WLANCOND_WEP40) {
01418 DLOG_DEBUG("WEP40 selected for unicast");
01419 wlan_status.pairwise_cipher = CIPHER_SUITE_WEP40;
01420 } else {
01421 DLOG_ERR("Not supported encryption %08x", encryption);
01422 return -1;
01423 }
01424 } else {
01425 DLOG_ERR("Not supported encryption %08x", encryption);
01426 return -1;
01427 }
01428
01429 if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
01430 WLANCOND_WPA_TKIP_GROUP) {
01431 DLOG_DEBUG("TKIP Selected for group key");
01432 wlan_status.group_cipher = CIPHER_SUITE_TKIP;
01433 } else if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
01434 (unsigned int)WLANCOND_WPA_AES_GROUP) {
01435 DLOG_DEBUG("AES Selected for group key");
01436 wlan_status.group_cipher = CIPHER_SUITE_CCMP;
01437
01438 } else if (wlan_status.allow_all_ciphers == TRUE) {
01439
01440 if (scan_results->extra_cap_bits & WLANCOND_WEP104_GROUP) {
01441 DLOG_DEBUG("WEP104 selected for group key");
01442 wlan_status.group_cipher = CIPHER_SUITE_WEP104;
01443 } else if (scan_results->extra_cap_bits & WLANCOND_WEP40_GROUP) {
01444 DLOG_DEBUG("WEP40 selected for group key");
01445 wlan_status.group_cipher = CIPHER_SUITE_WEP40;
01446 } else {
01447 DLOG_ERR("Not supported encryption %08x", encryption);
01448 return -1;
01449 }
01450 } else {
01451 DLOG_ERR("Not supported encryption %08x", encryption);
01452 return -1;
01453 }
01454 } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) ==
01455 WLANCOND_WAPI_PSK ||
01456 (encryption & WLANCOND_ENCRYPT_METHOD_MASK) ==
01457 WLANCOND_WAPI_CERT) {
01458 if ((encryption & WLANCOND_ENCRYPT_ALG_MASK)
01459 == WLANCOND_WAPI_SMS4) {
01460 DLOG_DEBUG("SMS4 Selected for unicast");
01461 wlan_status.pairwise_cipher = CIPHER_SUITE_SMS4;
01462 } else {
01463 DLOG_ERR("Not supported encryption %08x", encryption);
01464 return -1;
01465 }
01466
01467 if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
01468 WLANCOND_WAPI_SMS4_GROUP) {
01469 DLOG_DEBUG("SMS4 Selected for multicast");
01470 wlan_status.group_cipher = CIPHER_SUITE_SMS4;
01471 } else {
01472 DLOG_ERR("Not supported encryption %08x", encryption);
01473 return -1;
01474 }
01475 }
01476
01477 return 0;
01478 }
01482 void clean_roam_cache(void)
01483 {
01484 clean_scan_results(&wlan_status.roam_cache);
01485 }
01486
01490 void clear_wpa_mode(void)
01491 {
01492 update_own_ie(NULL, 0);
01493
01494 wlan_status.pairwise_cipher = CIPHER_SUITE_NONE;
01495 wlan_status.group_cipher = CIPHER_SUITE_NONE;
01496
01497
01498 g_slist_foreach(wlan_status.pmk_cache, (GFunc)g_free, NULL);
01499 g_slist_free(wlan_status.pmk_cache);
01500 wlan_status.pmk_cache = NULL;
01501 }
01506 gboolean get_wpa_mode(void)
01507 {
01508 dbus_int32_t encryption = wlan_status.conn.encryption;
01509
01510 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK ||
01511 (encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_EAP ||
01512 (encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WAPI_PSK ||
01513 (encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WAPI_CERT) {
01514 return TRUE;
01515 }
01516 return FALSE;
01517 }
01518
01519 static gint compare_pmk_entry(gconstpointer a, gconstpointer b)
01520 {
01521 const struct pmksa_cache_t *pmk_cache = a;
01522
01523 return memcmp(pmk_cache->mac, b, ETH_ALEN);
01524 }
01525
01531 static void add_to_pmksa_cache(unsigned char* pmkid, unsigned char* mac)
01532 {
01533 guint i = 0;
01534 GSList *list;
01535 gboolean entry_found = FALSE;
01536
01537 for (list = wlan_status.pmk_cache; list != NULL &&
01538 entry_found == FALSE; list = list->next) {
01539 struct pmksa_cache_t *pmk_cache = list->data;
01540
01541 if (memcmp(pmk_cache->mac, mac, ETH_ALEN) == 0) {
01542 DLOG_DEBUG("Found old entry: %i", i);
01543
01544 wlan_status.pmk_cache = g_slist_remove(
01545 wlan_status.pmk_cache, pmk_cache);
01546 g_free(pmk_cache);
01547
01548 entry_found = TRUE;
01549 } else {
01550 i++;
01551 }
01552 }
01553
01554 if (i == PMK_CACHE_SIZE) {
01555 DLOG_DEBUG("Cache full, remove oldest");
01556 GSList *last_entry = g_slist_last(wlan_status.pmk_cache);
01557 wlan_status.pmk_cache = g_slist_remove(wlan_status.pmk_cache,
01558 last_entry->data);
01559 g_free(last_entry->data);
01560 }
01561 print_mac(WLANCOND_PRIO_LOW, "Adding new entry:", mac);
01562
01563 struct pmksa_cache_t *new_entry = g_malloc(sizeof(*new_entry));
01564 memcpy(new_entry->mac, mac, ETH_ALEN);
01565 memcpy(new_entry->pmkid, pmkid, WLANCOND_PMKID_LEN);
01566
01567 wlan_status.pmk_cache = g_slist_prepend(wlan_status.pmk_cache,
01568 new_entry);
01569 return;
01570 }
01571
01578 gboolean remove_from_pmksa_cache(unsigned char* mac)
01579 {
01580 GSList *list = g_slist_find_custom(wlan_status.pmk_cache, mac,
01581 &compare_pmk_entry);
01582 if(!list)
01583 return FALSE;
01584
01585 struct pmksa_cache_t *entry = list->data;
01586
01587 print_mac(WLANCOND_PRIO_MEDIUM, "Removing PMKSA entry for:", mac);
01588
01589 wlan_status.pmk_cache = g_slist_remove(wlan_status.pmk_cache,
01590 entry);
01591
01592 g_free(entry);
01593
01594 return TRUE;
01595 }
01596
01604 int find_pmkid_from_pmk_cache(unsigned char* mac,
01605 unsigned char **pmkid)
01606 {
01607 GSList *list;
01608 int pmksa_found;
01609
01610 if (check_pmksa_cache((unsigned char *)wlan_status.own_mac, ETH_ALEN,
01611 mac, ETH_ALEN,
01612 wlan_status.conn.authentication_type,
01613 wlan_status.pairwise_cipher,
01614 wlan_status.group_cipher,
01615 &pmksa_found))
01616 {
01617 DLOG_ERR("Error while querying the pmksa cache status "
01618 "from eapd");
01619 return -1;
01620 }
01621
01622 if(!pmksa_found) {
01623 DLOG_DEBUG("No cached pmksa found from eapd");
01624
01625 remove_from_pmksa_cache(mac);
01626 *pmkid = NULL;
01627
01628 return 0;
01629 }
01630
01631 list = g_slist_find_custom(wlan_status.pmk_cache, mac, &compare_pmk_entry);
01632 if (list != NULL) {
01633 struct pmksa_cache_t *pmk_cache = list->data;
01634 print_mac(WLANCOND_PRIO_MEDIUM, "Found PMKSA entry for:", mac);
01635 *pmkid = pmk_cache->pmkid;
01636 return 0;
01637 }
01638
01639 DLOG_DEBUG("No cached pmksa found from eapd");
01640 *pmkid = NULL;
01641
01642 return 0;
01643 }
01644 static void rescan_destroy_cb(gpointer data)
01645 {
01646 g_free(data);
01647 }
01653 #define MAX_SCAN_COUNT 3
01654 static gboolean rescan(void* data)
01655 {
01656 int ret;
01657
01658 if (data) {
01659 struct scan_cb_data *scan_data = data;
01660 ret = nl80211_scan(&wlan_status, scan_data->ssid_len,
01661 scan_data->ssid);
01662 if (ret == -EBUSY) {
01663 if (scan_data->count++ >= MAX_SCAN_COUNT) {
01664 set_wlan_state(WLAN_NOT_INITIALIZED,
01665 DISCONNECTED_SIGNAL, FALSE);
01666 } else {
01667 DLOG_ERR("Scan is busy, rescanning later");
01668 return TRUE;
01669 }
01670 } else if (ret != 0) {
01671 DLOG_ERR("Scan failed in rescan");
01672 set_wlan_state(WLAN_NOT_INITIALIZED,
01673 DISCONNECTED_SIGNAL, FALSE);
01674 }
01675 } else if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
01676 scan(wlan_status.scan_ssid, wlan_status.scan_ssid_len, TRUE);
01677 }
01678 wlan_status.rescan_id = 0;
01679
01680 return FALSE;
01681 }
01688 int scan(gchar *ssid, int ssid_len, gboolean add_timer)
01689 {
01690 int ret;
01691
01692 if (get_scan_state() == SCAN_ACTIVE)
01693 return 0;
01694
01695 set_scan_state(SCAN_ACTIVE);
01696
01697 ret = nl80211_scan(&wlan_status, ssid_len - 1, ssid);
01698
01699 if (ret == -EBUSY) {
01700 DLOG_ERR("Scan is busy, rescanning later");
01701 struct scan_cb_data *scan_data = g_malloc(
01702 sizeof(struct scan_cb_data));
01703 memcpy(scan_data->ssid, ssid, ssid_len);
01704 scan_data->ssid_len = ssid_len -1;
01705 scan_data->count = 1;
01706 wlan_status.rescan_id = g_timeout_add_seconds_full(
01707 G_PRIORITY_DEFAULT,
01708 WLANCOND_RESCAN_DELAY,
01709 rescan,
01710 scan_data,
01711 rescan_destroy_cb);
01712 } else if (ret != 0) {
01713 DLOG_ERR("Scan command failed: %d", ret);
01714 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
01715 FALSE);
01716 return -1;
01717 }
01718
01719 if (ssid != wlan_status.scan_ssid) {
01720 memset(wlan_status.scan_ssid, 0, sizeof(wlan_status.scan_ssid));
01721 wlan_status.scan_ssid_len = ssid_len;
01722
01723 if (ssid && ssid_len > 1)
01724 memcpy(wlan_status.scan_ssid, ssid, ssid_len);
01725 }
01726 if (add_timer == TRUE) {
01727 wlan_status.scan_id = g_timeout_add_seconds(
01728 WLANCOND_SCAN_TIMEOUT,
01729 wlan_scan_cb,
01730 NULL);
01731 }
01732
01733 DLOG_INFO("Scan issued");
01734
01735 return 0;
01736 }
01737
01738 static void init_conn_params(struct connect_params_t *conn_params)
01739 {
01740 memset(conn_params, 0, sizeof(*conn_params));
01741 }
01742
01743 static void add_connection_time_filters(void) {
01744
01745 if (wlan_status.dbus_filters == TRUE)
01746 return;
01747
01748 if (!add_icd_listener(get_dbus_connection()))
01749 DLOG_ERR("Adding icd listener failed");
01750
01751 #ifdef ACTIVITY_CHECK
01752 if (!add_activity_listener(get_dbus_connection()))
01753 DLOG_ERR("Adding activity listener failed");
01754
01755 saved_inactivity = get_activity();
01756 #endif
01757 if (get_wpa_mode() == TRUE)
01758 if (!add_eap_listener(get_dbus_connection()))
01759 DLOG_ERR("Adding eap listener failed");
01760
01761 if (!add_gprs_listener(get_dbus_connection()))
01762 DLOG_ERR("Adding GPRS listener failed");
01763
01764 wlan_status.dbus_filters = TRUE;
01765 }
01766
01774 static int check_connect_arguments(struct connect_params_t *conn, char* ssid,
01775 unsigned char** key)
01776 {
01777 guint i;
01778
01779 if (conn->flags & WLANCOND_DISABLE_POWERSAVE) {
01780 DLOG_DEBUG("Powersave disabled");
01781 wlan_status.powersave = WLANCOND_POWER_ON;
01782 } else {
01783 wlan_status.powersave = WLANCOND_CAM_TIMEOUT;
01784 }
01785
01786 if (conn->power_level != WLANCOND_TX_POWER10 &&
01787 conn->power_level != WLANCOND_TX_POWER100) {
01788 DLOG_ERR("Invalid power level");
01789 return -1;
01790 }
01791
01792 switch (conn->mode) {
01793 case WLANCOND_ADHOC:
01794 case WLANCOND_INFRA:
01795 break;
01796 default:
01797 DLOG_ERR("Operating mode undefined");
01798 return -1;
01799 }
01800
01801 guint32 wpa2_mode = conn->encryption & WLANCOND_ENCRYPT_WPA2_MASK;
01802
01803 DLOG_DEBUG("Encryption setting: %08x", conn->encryption);
01804
01805 switch (conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) {
01806 case WLANCOND_OPEN:
01807 break;
01808 case WLANCOND_WEP:
01809 wlan_status.conn.wep_try_open_mode_first = TRUE;
01810 break;
01811 case WLANCOND_WPA_PSK:
01812 DLOG_DEBUG("%s PSK selected",
01813 wpa2_mode!=0?"WPA2":"WPA");
01814 if (wpa2_mode != 0)
01815 conn->authentication_type = EAP_AUTH_TYPE_WPA2_PSK;
01816 else
01817 conn->authentication_type = EAP_AUTH_TYPE_WPA_PSK;
01818 break;
01819 case WLANCOND_WPA_EAP:
01820 DLOG_DEBUG("%s EAP selected", wpa2_mode!=0?"WPA2":"WPA");
01821 if (wpa2_mode != 0)
01822 conn->authentication_type = EAP_AUTH_TYPE_WPA2_EAP;
01823 else
01824 conn->authentication_type = EAP_AUTH_TYPE_WPA_EAP;
01825 break;
01826 case WLANCOND_WAPI_PSK:
01827 DLOG_DEBUG("WAPI PSK selected");
01828 conn->authentication_type = EAP_AUTH_TYPE_WAPI_PSK;
01829 break;
01830 case WLANCOND_WAPI_CERT:
01831 DLOG_DEBUG("WAPI CERT selected");
01832 conn->authentication_type = EAP_AUTH_TYPE_WAPI_CERT;
01833 break;
01834 default:
01835 DLOG_DEBUG("Unsupported encryption mode");
01836 return -1;
01837 }
01838 if ((conn->encryption & WLANCOND_WPS_MASK) != 0) {
01839 DLOG_DEBUG("WPS selected");
01840 conn->authentication_type = EAP_AUTH_TYPE_WFA_SC;
01841 }
01842
01843 if (!ssid || conn->ssid_len <= 1 ||
01844 conn->ssid_len > WLANCOND_MAX_SSID_SIZE + 1) {
01845 DLOG_DEBUG("Invalid SSID");
01846 return -1;
01847 }
01848
01849 for (i = 0; i < 4; i++) {
01850
01851 if (conn->key_len[i] == WLANCOND_MIN_KEY_LEN ||
01852 conn->key_len[i] == WLANCOND_MAX_KEY_LEN) {
01853 DLOG_DEBUG("Found key %d", i);
01854 memcpy(&conn->key[i][0], key[i], conn->key_len[i]);
01855 } else {
01856 conn->key_len[i] = 0;
01857 }
01858 }
01859 return 0;
01860 }
01861
01868 static DBusHandlerResult settings_and_connect_request(
01869 DBusMessage *message,
01870 DBusConnection *connection) {
01871
01872 DBusMessage *reply = NULL;
01873 DBusError derror;
01874 struct connect_params_t *conn;
01875 char *ssid;
01876 unsigned char* key[4];
01877 dbus_int32_t old_mode;
01878 int res;
01879 gboolean autoconnect = FALSE;
01880 GSList *scan_results = NULL;
01881
01882 dbus_error_init(&derror);
01883
01884 if (in_flight_mode()) {
01885 reply = new_dbus_error(message, WLANCOND_ERROR_WLAN_DISABLED);
01886 send_and_unref(connection, reply);
01887 return DBUS_HANDLER_RESULT_HANDLED;
01888 }
01889
01890 conn = &wlan_status.conn;
01891
01892 old_mode = conn->mode;
01893 init_conn_params(conn);
01894
01895 if (dbus_message_get_args(
01896 message, NULL,
01897 DBUS_TYPE_INT32, &conn->power_level,
01898 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid, &conn->ssid_len,
01899 DBUS_TYPE_INT32, &conn->mode,
01900 DBUS_TYPE_INT32, &conn->encryption,
01901 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[0], &conn->key_len[0],
01902 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[1], &conn->key_len[1],
01903 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[2], &conn->key_len[2],
01904 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[3], &conn->key_len[3],
01905 DBUS_TYPE_INT32, &conn->default_key,
01906 DBUS_TYPE_UINT32, &conn->adhoc_channel,
01907 DBUS_TYPE_UINT32, &conn->flags,
01908 DBUS_TYPE_INVALID) == FALSE)
01909 {
01910
01911 if (dbus_message_get_args(
01912 message, &derror,
01913 DBUS_TYPE_INT32, &conn->power_level,
01914 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid,
01915 &conn->ssid_len,
01916 DBUS_TYPE_INT32, &conn->mode,
01917 DBUS_TYPE_INT32, &conn->encryption,
01918 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
01919 &key[0], &conn->key_len[0],
01920 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
01921 &key[1], &conn->key_len[1],
01922 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
01923 &key[2], &conn->key_len[2],
01924 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
01925 &key[3], &conn->key_len[3],
01926 DBUS_TYPE_INT32, &conn->default_key,
01927 DBUS_TYPE_UINT32, &conn->adhoc_channel,
01928 DBUS_TYPE_INVALID) == FALSE) {
01929
01930 DLOG_ERR("Failed to parse setting_and_connect: %s",
01931 derror.message);
01932 dbus_error_free(&derror);
01933 goto param_err;
01934 }
01935 }
01936
01937 if (check_connect_arguments(conn, ssid, key) < 0)
01938 goto param_err;
01939
01940 set_power_state(WLANCOND_POWER_ON);
01941
01942
01943
01944
01945
01946 if (old_mode != conn->mode ||
01947 conn->encryption & WLANCOND_WPS_PUSH_BUTTON) {
01948 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FALSE);
01949 }
01950 if (nl80211_set_channel(wlan_status.ifindex,
01951 WLANCOND_INITIAL_CHANNEL) < 0)
01952 DLOG_ERR("Changing channel failed");
01953
01954
01955 if (set_mode(conn->mode) < 0) {
01956
01957 conn->mode = old_mode;
01958 goto param_err;
01959 }
01960
01961 if (init_if(socket_open()) < 0) {
01962 reply = new_dbus_error(message, WLANCOND_ERROR_INIT_FAILED);
01963 goto param_err;
01964 }
01965
01966 remove_wlan_if_timer();
01967
01968 if (set_tx_power(conn->power_level) != TRUE) {
01969 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
01970 goto param_err;
01971 }
01972
01973 if (conn->flags & WLANCOND_AUTOCONNECT) {
01974 DLOG_DEBUG("Autoconnect attempt");
01975 autoconnect = TRUE;
01976 }
01977
01978 memcpy(conn->ssid, ssid, conn->ssid_len);
01979
01980 if (get_wlan_state() == WLAN_CONNECTED ||
01981 get_wlan_state() == WLAN_NO_ADDRESS) {
01982 DLOG_DEBUG("Disconnecting previous connection");
01983 mlme_command(wlan_status.conn.bssid,
01984 WLANCOND_NL80211_MLME_DISCONNECT,
01985 WLANCOND_REASON_LEAVING);
01986 }
01987
01988 set_scan_state(SCAN_NOT_ACTIVE);
01989 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL, TRUE);
01990
01991
01992 if (conn->encryption & WLANCOND_WPS_PUSH_BUTTON) {
01993 DLOG_DEBUG("Broadcast scan for WPS");
01994 if (scan(NULL, 0, TRUE) < 0) {
01995 goto param_err;
01996 }
01997 } else {
01998
01999 if ((res = find_connection_and_associate(
02000 wlan_status.roam_cache,
02001 FALSE, FALSE, autoconnect)) != 0) {
02002
02003
02004
02005 if (res == ETOOWEAKAP || res == ESUPPLICANT)
02006 goto param_err;
02007
02008
02009 DLOG_DEBUG("Checking mac80211 cache...");
02010
02011 wlan_status.scan_ssid_len = conn->ssid_len;
02012 memcpy(wlan_status.scan_ssid, ssid, conn->ssid_len);
02013
02014 if (!nl80211_send_get_scan_results(&wlan_status, &scan_results))
02015 DLOG_DEBUG("No cached scan results");
02016
02017 if ((res = find_connection_and_associate(
02018 scan_results,
02019 TRUE, FALSE, autoconnect)) != 0) {
02020
02021
02022
02023 if (res == ETOOWEAKAP || res == ESUPPLICANT)
02024 goto param_err;
02025
02026 clean_scan_results(&scan_results);
02027 if (scan(conn->ssid, conn->ssid_len, TRUE) < 0)
02028 goto param_err;
02029 }
02030 }
02031 }
02032
02033 clean_scan_results(&scan_results);
02034 g_free(connect_name_cache);
02035 connect_name_cache = g_strdup(dbus_message_get_sender(message));
02036
02037 add_connection_time_filters();
02038
02039 reply = new_dbus_method_return(message);
02040
02041 gchar* ifname = wlan_status.ifname;
02042
02043 append_dbus_args(reply,
02044 DBUS_TYPE_STRING, &ifname,
02045 DBUS_TYPE_INVALID);
02046
02047 send_and_unref(connection, reply);
02048
02049 return DBUS_HANDLER_RESULT_HANDLED;
02050
02051 param_err:
02052 clean_scan_results(&scan_results);
02053 if (reply == NULL) {
02054 DLOG_DEBUG("Parameter error in settings_and_connect");
02055 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
02056 }
02057 send_and_unref(connection, reply);
02058 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, TRUE);
02059
02060 return DBUS_HANDLER_RESULT_HANDLED;
02061 }
02067 int associate(struct scan_results_t *scan_results)
02068 {
02069 struct connect_params_t *conn = &wlan_status.conn;
02070 gint ret;
02071
02072 DLOG_INFO("Starting to associate");
02073
02074 guint connection_timeout = WLANCOND_CONNECT_TIMEOUT;
02075
02076 if (get_wlan_state() == WLAN_CONNECTED) {
02077 DLOG_DEBUG("Disconnecting previous connection");
02078 mlme_command(conn->bssid, WLANCOND_NL80211_MLME_DISCONNECT,
02079 WLANCOND_REASON_LEAVING);
02080 if (get_wpa_mode() == TRUE)
02081 disassociate_eap();
02082 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL,
02083 TRUE);
02084 }
02085
02086 if (update_algorithms(conn->encryption, scan_results) < 0) {
02087 return -1;
02088 }
02089
02090 if (netlink_send_linkmode(WLANCOND_IF_DORMANT) != 0) {
02091 DLOG_ERR("Setting oper state to dormant failed");
02092
02093 }
02094
02095 memcpy(conn->bssid, scan_results->bssid, ETH_ALEN);
02096 conn->channel = scan_results->channel;
02097
02098 if (get_wpa_mode() == TRUE) {
02099 if ((conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WAPI_PSK ||
02100 (conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WAPI_CERT) {
02101 if ((ret = generate_wapi_ie(conn->encryption, &wlan_status)) < 0) {
02102 DLOG_ERR("nl80211 - nl80211_encryption_method failed");
02103 return ret;
02104 }
02105 }
02106 else if ((ret = nl80211_encryption_method(conn->encryption,
02107 &wlan_status)) < 0) {
02108 DLOG_ERR("nl80211 - nl80211_encryption_method failed");
02109 return ret;
02110 }
02111 }
02112
02113 if (conn->mode & WLANCOND_ADHOC) {
02114 if (conn->adhoc_channel != 0 && (conn->mode & WLANCOND_ADHOC)) {
02115 if (conn->adhoc_channel < WLANCOND_MIN_WLAN_CHANNEL ||
02116 conn->adhoc_channel > WLANCOND_MAX_WLAN_CHANNEL) {
02117 DLOG_ERR("Invalid ad-hoc channel: %d",
02118 conn->adhoc_channel);
02119 return -1;
02120 }
02121 scan_results->channel = conn->adhoc_channel;
02122 }
02123 } else {
02124 if ((conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) ==
02125 WLANCOND_WEP)
02126 connection_timeout = WLANCOND_CONNECT_TIMEOUT/2;
02127 else
02128 connection_timeout = WLANCOND_CONNECT_TIMEOUT;
02129 }
02130
02131 ret = nl80211_connect(scan_results, &wlan_status);
02132 if (ret) {
02133 DLOG_ERR("nl80211 - connect returned error");
02134 return -1;
02135 }
02136
02137
02138 wlan_connect_timer_id = g_timeout_add_seconds(
02139 connection_timeout,
02140 wlan_connect_timer_cb, NULL);
02141
02142 return 0;
02143 }
02144
02151 static DBusHandlerResult scan_request(DBusMessage *message,
02152 DBusConnection *connection) {
02153
02154 DBusMessage *reply = NULL;
02155 DBusMessageIter iter, array_iter;
02156 char *ssid;
02157 gint ssid_len;
02158 const char* sender;
02159 dbus_int32_t power_level;
02160 dbus_int32_t flags;
02161 gint previous_state = 0;
02162
02163 if (in_flight_mode()) {
02164 reply = new_dbus_error(message, WLANCOND_ERROR_WLAN_DISABLED);
02165 send_and_unref(connection, reply);
02166 return DBUS_HANDLER_RESULT_HANDLED;
02167 }
02168
02169 sender = dbus_message_get_sender(message);
02170 if (sender == NULL) {
02171 goto param_err;
02172 }
02173
02174 DLOG_DEBUG("Got scan request from %s", sender);
02175
02176
02177 if (get_scan_state() == SCAN_ACTIVE || wlan_connect_timer_id != 0) {
02178 reply = new_dbus_error(message, WLANCOND_ERROR_ALREADY_ACTIVE);
02179 send_and_unref(connection, reply);
02180 return DBUS_HANDLER_RESULT_HANDLED;
02181 }
02182
02183 if ((previous_state = init_if(socket_open())) < 0) {
02184 reply = new_dbus_error(message, WLANCOND_ERROR_INIT_FAILED);
02185 goto param_err;
02186 }
02187
02188 if (previous_state == WLAN_NOT_INITIALIZED) {
02189 set_wlan_state(WLAN_INITIALIZED_FOR_SCAN, NO_SIGNAL, TRUE);
02190 }
02191
02192 dbus_message_iter_init(message, &iter);
02193
02194 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
02195 goto param_err;
02196 dbus_message_iter_get_basic(&iter, &power_level);
02197
02198 dbus_message_iter_next(&iter);
02199
02200 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
02201 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
02202 goto param_err;
02203 dbus_message_iter_recurse(&iter, &array_iter);
02204 dbus_message_iter_get_fixed_array(&array_iter, &ssid, &ssid_len);
02205
02206 if (ssid_len > WLANCOND_MAX_SSID_SIZE+1)
02207 goto param_err;
02208
02209 dbus_message_iter_next(&iter);
02210
02211 power_down_after_scan = FALSE;
02212
02213 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32) {
02214 dbus_message_iter_get_basic(&iter, &flags);
02215 DLOG_DEBUG("Found flags: %08x", flags);
02216
02217 if (flags & WLANCOND_NO_DELAYED_SHUTDOWN)
02218 power_down_after_scan = TRUE;
02219 }
02220
02221 if (power_level != WLANCOND_TX_POWER10 &&
02222 power_level != WLANCOND_TX_POWER100) {
02223 DLOG_ERR("Invalid power level");
02224 goto param_err;
02225 }
02226
02227 if (set_tx_power(power_level) != TRUE) {
02228 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02229 goto param_err;
02230 }
02231
02232 if (scan(ssid, ssid_len, TRUE) < 0) {
02233 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02234 goto param_err;
02235 }
02236
02237 g_free(scan_name_cache);
02238 scan_name_cache = g_strdup(sender);
02239
02240 reply = new_dbus_method_return(message);
02241 send_and_unref(connection, reply);
02242
02243 return DBUS_HANDLER_RESULT_HANDLED;
02244
02245 param_err:
02246 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
02247 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FALSE);
02248 }
02249 if (reply == NULL) {
02250 DLOG_DEBUG("Parameter error in scan request");
02251 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
02252 }
02253 send_and_unref(connection, reply);
02254 return DBUS_HANDLER_RESULT_HANDLED;
02255 }
02262 static int network_compare(gconstpointer a, gconstpointer b)
02263 {
02264 const struct scan_results_t *results_a = a;
02265 const struct scan_results_t *results_b = b;
02266
02267 if (wlan_status.scan_ssid_len > 1) {
02268
02269
02270
02271 gint a_eq = strncmp(wlan_status.scan_ssid,
02272 results_a->ssid, WLANCOND_MAX_SSID_SIZE);
02273 gint b_eq = strncmp(wlan_status.scan_ssid,
02274 results_b->ssid, WLANCOND_MAX_SSID_SIZE);
02275
02276 if (!a_eq && !b_eq) {
02277
02278
02279 return 0;
02280 }
02281
02282 if (!a_eq && b_eq) {
02283
02284
02285 return -1;
02286 }
02287
02288 if (a_eq && !b_eq) {
02289
02290
02291
02292 return 1;
02293 }
02294
02295 }
02296
02297
02298 return (results_a->rssi > results_b->rssi) ?
02299 -1 : (results_a->rssi < results_b->rssi) ? 1 : 0;
02300 }
02301
02306 static void add_to_roam_cache(struct scan_results_t *scan_results)
02307 {
02308 GSList *list;
02309 roam_cache_key_t key = { scan_results->bssid, scan_results->channel };
02310 list = g_slist_find_custom(wlan_status.roam_cache, &key,
02311 &compare_scan_entry);
02312
02313 if (list != NULL) {
02314 struct scan_results_t *roam_cache_entry = list->data;
02315 print_mac(WLANCOND_PRIO_LOW, "Found old entry for:",
02316 scan_results->bssid);
02317
02318
02319 wlan_status.roam_cache = g_slist_remove(
02320 wlan_status.roam_cache, roam_cache_entry);
02321
02322 clean_scan_results_item(roam_cache_entry, NULL);
02323 }
02324
02325 print_mac(WLANCOND_PRIO_LOW, "New AP to roam cache:",
02326 scan_results->bssid);
02327
02328 struct scan_results_t *results_to_list = copy_scan_results(scan_results);
02329 wlan_status.roam_cache = g_slist_prepend(wlan_status.roam_cache,
02330 results_to_list);
02331
02332 return;
02333 }
02334
02340 struct scan_results_t* copy_scan_results(struct scan_results_t *results) {
02341
02342 struct scan_results_t *copy = g_slice_dup(struct scan_results_t,
02343 results);
02344 copy->wpa_ie = g_memdup(results->wpa_ie, results->wpa_ie_len);
02345 copy->uuid_e = g_memdup(results->uuid_e, MAX_UUID_E_LEN);
02346
02347 return copy;
02348 }
02349
02355 gboolean remove_from_roam_cache(roam_cache_key_t* const key)
02356 {
02357 GSList *list;
02358
02359 list = g_slist_find_custom(wlan_status.roam_cache, key,
02360 &compare_scan_entry);
02361
02362 if (list != NULL) {
02363 struct scan_results_t *roam_cache_entry = list->data;
02364 print_mac(WLANCOND_PRIO_LOW, "Found entry to be removed:",
02365 key->bssid);
02366
02367 wlan_status.roam_cache = g_slist_remove(
02368 wlan_status.roam_cache, roam_cache_entry);
02369
02370 clean_scan_results_item(roam_cache_entry, NULL);
02371
02372 return TRUE;
02373 }
02374
02375 return FALSE;
02376 }
02377
02383 gboolean decrease_signal_in_roam_cache(roam_cache_key_t* const key)
02384 {
02385 GSList *list;
02386
02387 list = g_slist_find_custom(wlan_status.roam_cache, key,
02388 &compare_scan_entry);
02389
02390 if (list != NULL) {
02391 struct scan_results_t *roam_cache_entry = list->data;
02392 print_mac(WLANCOND_PRIO_LOW, "Found entry to be decreased:",
02393 key->bssid);
02394
02395 roam_cache_entry->rssi -= WLANCOND_RSSI_PENALTY;
02396
02397 return TRUE;
02398 }
02399
02400 return FALSE;
02401 }
02408 static int check_group_cipher(guint32 c1, guint32 c2)
02409 {
02410 guint32 m1 = (c1 & WLANCOND_ENCRYPT_GROUP_ALG_MASK);
02411 guint32 m2 = (c2 & WLANCOND_ENCRYPT_GROUP_ALG_MASK);
02412
02413 if (m1 == m2)
02414 return 1;
02415 if (m2 == WLANCOND_WPA_TKIP_GROUP && (m1 & WLANCOND_WPA_TKIP_GROUP))
02416 return 1;
02417 if (m2 == (unsigned int)WLANCOND_WPA_AES_GROUP &&
02418 (m1 & WLANCOND_WPA_AES_GROUP))
02419 return 1;
02420 if (m2 == WLANCOND_WAPI_SMS4_GROUP && (m1 & WLANCOND_WAPI_SMS4_GROUP))
02421 return 1;
02422
02423 DLOG_DEBUG("Group ciphers don't match");
02424
02425 return -1;
02426 }
02433 static int check_ciphers(guint32 c1, guint32 c2)
02434 {
02435 guint32 u1 = (c1 & WLANCOND_ENCRYPT_ALG_MASK);
02436 guint32 u2 = (c2 & WLANCOND_ENCRYPT_ALG_MASK);
02437
02438 if (check_group_cipher(c1, c2) < 0) {
02439 DLOG_DEBUG("Group cipher's don't match");
02440 return -1;
02441 }
02442
02443 if (u1 == u2)
02444 return 1;
02445 if (u2 == WLANCOND_WPA_TKIP && (u1 & WLANCOND_WPA_TKIP))
02446 return 1;
02447 if (u2 == WLANCOND_WPA_AES && (u1 & WLANCOND_WPA_AES))
02448 return 1;
02449 if (u2 == WLANCOND_WAPI_SMS4 && (u1 & WLANCOND_WAPI_SMS4))
02450 return 1;
02451
02452 DLOG_DEBUG("Unicast ciphers don't match");
02453
02454 return -1;
02455 }
02456 static gboolean wlan_roam_scan_cb(void* data)
02457 {
02458 wlan_status.roam_scan_id = 0;
02459 struct timeval tv;
02460
02461 if (wlan_status.signal == WLANCOND_LOW &&
02462 get_wlan_state() == WLAN_CONNECTED) {
02463
02464 DLOG_DEBUG("Roam scan timeout, initiating new scan");
02465
02466 if (scan(wlan_status.conn.ssid, wlan_status.conn.ssid_len,
02467 TRUE) < 0) {
02468 return FALSE;
02469 }
02470 if (gettimeofday(&tv, NULL) >= 0)
02471 wlan_status.last_scan = tv.tv_sec;
02472 }
02473
02474 return FALSE;
02475 }
02476
02481 void schedule_scan(guint seconds) {
02482
02483
02484 remove_roam_scan_timer();
02485 wlan_status.roam_scan_id = g_timeout_add_seconds(
02486 seconds,
02487 wlan_roam_scan_cb,
02488 NULL);
02489 }
02490
02494 static void reschedule_scan(void)
02495 {
02496
02497
02498
02499
02500 if (get_inactivity_status() == FALSE) {
02501 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
02502 } else {
02503 if (wlan_status.roam_scan <= WLANCOND_MIN_ROAM_SCAN_INTERVAL) {
02504 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
02505 } else if (wlan_status.roam_scan >=
02506 WLANCOND_MAX_ROAM_SCAN_INTERVAL) {
02507 wlan_status.roam_scan = WLANCOND_MAX_ROAM_SCAN_INTERVAL;
02508 } else {
02509 wlan_status.roam_scan = wlan_status.roam_scan * 2;
02510 }
02511 }
02512
02513 schedule_scan(wlan_status.roam_scan);
02514 }
02515
02522 static gboolean check_capabilities(struct scan_results_t *scan_results,
02523 struct connect_params_t *conn)
02524 {
02525
02526 if ((scan_results->cap_bits & WLANCOND_MODE_MASK) != (guint32)conn->mode)
02527 return FALSE;
02528 if ((scan_results->cap_bits & WLANCOND_ENCRYPT_METHOD_MASK) !=
02529 (guint32)(conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK))
02530 return FALSE;
02531
02532 if ((scan_results->cap_bits & WLANCOND_ENCRYPT_WPA2_MASK) !=
02533 (guint32)(conn->encryption & WLANCOND_ENCRYPT_WPA2_MASK))
02534 return FALSE;
02535
02536 if (check_ciphers(scan_results->cap_bits, conn->encryption) < 0)
02537 return FALSE;
02538
02539 return TRUE;
02540 }
02547 static gboolean better_than_current_best(struct scan_results_t *current_best,
02548 struct scan_results_t *candidate) {
02549 gint current_best_rssi;
02550 gint candidate_rssi;
02551
02552
02553 if (current_best->channel > 14)
02554 current_best_rssi = current_best->rssi + WLANCOND_5GHZ_BENEFIT;
02555 else
02556 current_best_rssi = current_best->rssi;
02557
02558 if (candidate->channel > 14)
02559 candidate_rssi = candidate->rssi + WLANCOND_5GHZ_BENEFIT;
02560 else
02561 candidate_rssi = candidate->rssi;
02562
02563 if (current_best_rssi > candidate_rssi)
02564 return FALSE;
02565
02566 return TRUE;
02567 }
02568
02576 struct scan_results_t* find_connection(
02577 GSList* ap_list, struct connect_params_t *conn,
02578 gboolean update_roam_cache)
02579 {
02580 GSList *list;
02581 struct scan_results_t *best_connection = NULL;
02582 gint current_rssi = 0;
02583
02584
02585 if (update_roam_cache == TRUE)
02586 clean_roam_cache();
02587
02588 for (list = ap_list; list != NULL; list = list->next) {
02589 struct scan_results_t *scan_results = list->data;
02590 if (scan_results->ssid_len == conn->ssid_len &&
02591 memcmp(scan_results->ssid, conn->ssid,
02592 scan_results->ssid_len) == 0) {
02593 print_mac(WLANCOND_PRIO_LOW, "Found AP:",
02594 scan_results->bssid);
02595
02596
02597 if (memcmp(scan_results->bssid, wlan_status.conn.bssid,
02598 ETH_ALEN) == 0 &&
02599 scan_results->channel == wlan_status.conn.channel) {
02600 current_rssi = scan_results->rssi;
02601 DLOG_DEBUG("Current AP: %d", current_rssi);
02602 }
02603
02604 if (check_capabilities(scan_results, conn) ==
02605 FALSE)
02606 continue;
02607
02608 if (is_ap_in_black_list(scan_results->bssid) == TRUE) {
02609 DLOG_INFO("AP is in black list, discarded");
02610 continue;
02611 }
02612
02613
02614
02615
02616 if (update_roam_cache == TRUE) {
02617 add_to_roam_cache(scan_results);
02618 }
02619
02620 if (best_connection == NULL ||
02621 better_than_current_best(best_connection,
02622 scan_results)) {
02623 DLOG_DEBUG("Best connection: %d (old %d)",
02624 scan_results->rssi,
02625 best_connection == NULL ?
02626 WLANCOND_MINIMUM_SIGNAL:
02627 best_connection->rssi);
02628 best_connection = scan_results;
02629 }
02630 }
02631 }
02632
02633
02634 if (best_connection == NULL)
02635 return NULL;
02636
02637
02638
02639
02640 if (current_rssi != 0) {
02641 if (best_connection->rssi < current_rssi +
02642 WLANCOND_ROAM_THRESHOLD) {
02643 DLOG_DEBUG("Best connection not good enough");
02644 return NULL;
02645 }
02646 }
02647
02648
02649 if (best_connection->rssi < WLANCOND_MINIMUM_SIGNAL)
02650 return NULL;
02651
02652 return best_connection;
02653 }
02659 static dbus_uint32_t find_adhoc_channel(GSList *ap_list) {
02660
02661 dbus_uint32_t used_channel_list = 0;
02662 dbus_uint32_t selected_channel = 0;
02663 GSList* list;
02664 guint32 i;
02665
02666
02667 for (list = ap_list; list != NULL; list = list->next) {
02668 struct scan_results_t *scan_results = list->data;
02669 used_channel_list |= 1 << scan_results->channel;
02670 }
02671
02672 for (i = 1; i <= 11; i++) {
02673 if (!(used_channel_list & (1 << i))) {
02674 selected_channel = i;
02675 break;
02676 }
02677 }
02678
02679 if (selected_channel == 0) {
02680
02681
02682 selected_channel = g_random_int_range(1, 12);
02683 }
02684
02685
02686
02687 return selected_channel;
02688 }
02696 static gboolean check_if_duplicate_entry(GSList *scan_results,
02697 GSList *entry) {
02698
02699 GSList *list;
02700 struct scan_results_t *entry_result = entry->data;
02701
02702 if (entry_result->uuid_e == NULL)
02703 return FALSE;
02704
02705 for (list = scan_results; list && list != entry; list = list->next) {
02706 struct scan_results_t *result = list->data;
02707 if (result->cap_bits & WLANCOND_WPS_PUSH_BUTTON &&
02708 result->cap_bits & WLANCOND_WPS_CONFIGURED &&
02709 result->uuid_e && memcmp(result->uuid_e,
02710 entry_result->uuid_e,
02711 MAX_UUID_E_LEN) == 0) {
02712 print_mac(WLANCOND_PRIO_MEDIUM,
02713 "Found matching previous entry:",
02714 result->bssid);
02715 return TRUE;
02716 }
02717 }
02718 return FALSE;
02719 }
02725 int find_connection_and_associate(GSList *scan_results,
02726 gboolean update_roam_cache,
02727 gboolean create_new_adhoc,
02728 gboolean autoconnect)
02729 {
02730 struct scan_results_t adhoc;
02731 struct connect_params_t *conn = &wlan_status.conn;
02732 guint wps_pbc_registrars = 0;
02733 GSList* list;
02734
02735
02736
02737 if (conn->encryption & WLANCOND_WPS_PUSH_BUTTON) {
02738 for (list = scan_results; list != NULL; list = list->next) {
02739 struct scan_results_t *scan_result = list->data;
02740
02741 if (scan_result->cap_bits & WLANCOND_WPS_PUSH_BUTTON
02742 &&
02743 scan_result->cap_bits & WLANCOND_WPS_CONFIGURED)
02744 {
02745 print_mac(WLANCOND_PRIO_MEDIUM,
02746 "Found active PBC session from:",
02747 scan_result->bssid);
02748
02749
02750
02751
02752 if (check_if_duplicate_entry(scan_results,
02753 list) == FALSE) {
02754 if (++wps_pbc_registrars > 1) {
02755 DLOG_ERR("Too many WPS PBC registrars");
02756 return ETOOMANYREGISTRARS;
02757 }
02758 }
02759 }
02760 }
02761
02762
02763 if (wlan_status.retry_count < 1)
02764 return ENEEDEXTRASCAN;
02765 }
02766
02767 struct scan_results_t *connection = find_connection(
02768 scan_results, &wlan_status.conn, update_roam_cache);
02769
02770 if (connection == NULL && conn->mode == WLANCOND_ADHOC &&
02771 create_new_adhoc == TRUE) {
02772 DLOG_DEBUG("No existing adhoc connection");
02773 memset(&adhoc, 0, sizeof(adhoc));
02774 connection = &adhoc;
02775 memcpy(connection->ssid, conn->ssid, conn->ssid_len);
02776 connection->channel = find_adhoc_channel(scan_results);
02777 }
02778
02779 if (connection) {
02780 if (autoconnect == TRUE &&
02781 connection->rssi < WLANCOND_MINIMUM_AUTOCONNECT_RSSI) {
02782 DLOG_WARN("RSSI too low for autoconnect");
02783 return ETOOWEAKAP;
02784 }
02785 int ret = associate(connection);
02786 if (ret < 0) {
02787 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
02788 wlan_status.conn.channel = 0;
02789 }
02790 if (ret == ESUPPLICANT)
02791 kill_supplicant();
02792 return ret;
02793 }
02794 return -1;
02795 }
02799 static void registrar_error_signal(void)
02800 {
02801 DBusMessage *registrar_error;
02802
02803 registrar_error = new_dbus_signal(
02804 WLANCOND_SIG_PATH,
02805 WLANCOND_SIG_INTERFACE,
02806 WLANCOND_REGISTRAR_ERROR_SIG,
02807 NULL);
02808
02809 send_and_unref(get_dbus_connection(), registrar_error);
02810 }
02811
02816 static void connect_from_scan_results(GSList *scan_results)
02817 {
02818 gboolean autoconnect = !!(wlan_status.conn.flags & WLANCOND_AUTOCONNECT);
02819
02820 int status = find_connection_and_associate(
02821 scan_results, TRUE, TRUE, autoconnect);
02822
02823 clean_scan_results(&scan_results);
02824
02825 if (status == 0)
02826 return;
02827
02828 DLOG_DEBUG("Could not find suitable network");
02829
02830 if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
02831
02832
02833
02834 if (status == ETOOMANYREGISTRARS) {
02835 set_wlan_state(WLAN_NOT_INITIALIZED,
02836 NO_SIGNAL, FALSE);
02837 registrar_error_signal();
02838 } else if (status != ETOOWEAKAP && status != ESUPPLICANT &&
02839
02840 no_connection_and_scan_retries_left()) {
02841 DLOG_DEBUG("Rescanning");
02842 wlan_status.rescan_id = g_timeout_add_seconds(
02843 WLANCOND_RESCAN_DELAY,
02844 rescan,
02845 NULL);
02846 } else {
02847 set_wlan_state(WLAN_NOT_INITIALIZED,
02848 DISCONNECTED_SIGNAL, FALSE);
02849 }
02850 return;
02851 }
02852
02853
02854 reschedule_scan();
02855 }
02856
02862 gboolean ask_scan_results(void)
02863 {
02864 GSList *scan_results_save = NULL;
02865 dbus_int32_t number_of_results;
02866
02867 if (nl80211_send_get_scan_results(&wlan_status, &scan_results_save)) {
02868 clean_scan_results(&scan_results_save);
02869 return FALSE;
02870 }
02871
02872 if (scan_name_cache != NULL) {
02873
02874 number_of_results = g_slist_length(scan_results_save);
02875
02876
02877
02878 if (number_of_results > WLANCOND_MAX_NETWORKS)
02879 scan_results_save = g_slist_sort(scan_results_save,
02880 network_compare);
02881
02882 send_dbus_scan_results(scan_results_save, scan_name_cache,
02883 number_of_results);
02884 g_free(scan_name_cache);
02885 scan_name_cache = NULL;
02886 }
02887
02888
02889
02890 if ((get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION ||
02891 wlan_status.signal == WLANCOND_LOW) &&
02892 get_scan_state() == SCAN_ACTIVE) {
02893
02894 DLOG_DEBUG("Connect from scan");
02895
02896 set_scan_state(SCAN_NOT_ACTIVE);
02897
02898 connect_from_scan_results(scan_results_save);
02899
02900 return TRUE;
02901 }
02902
02903 set_scan_state(SCAN_NOT_ACTIVE);
02904
02905 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN &&
02906 power_down_after_scan == TRUE) {
02907 set_interface_state(socket_open(), CLEAR, IFF_UP);
02908 }
02909
02910 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
02911
02912 if (wlan_status.roam_cache) {
02913 clean_roam_cache();
02914 }
02915 wlan_status.roam_cache = scan_results_save;
02916 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, TRUE);
02917 } else {
02918 clean_scan_results(&scan_results_save);
02919 }
02920
02921 return TRUE;
02922 }
02923
02927 void nl80211_scan_ready(void) {
02928 remove_scan_timer();
02929
02930 if (get_scan_state() == SCAN_ACTIVE) {
02931 DLOG_INFO("Scan results ready -- scan active");
02932 if (ask_scan_results() == FALSE) {
02933 DLOG_ERR("Getting scan results failed");
02934
02935 set_wlan_state(WLAN_NOT_INITIALIZED,
02936 DISCONNECTED_SIGNAL,
02937 FALSE);
02938 }
02939 } else {
02940 DLOG_DEBUG("Scan results ready -- "
02941 "not requested");
02942 }
02943 }
02944
02951 static DBusHandlerResult disconnect_request(DBusMessage *message,
02952 DBusConnection *connection) {
02953 DBusMessage *reply;
02954
02955
02956 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, FALSE);
02957
02958 reply = new_dbus_method_return(message);
02959 send_and_unref(connection, reply);
02960
02961 return DBUS_HANDLER_RESULT_HANDLED;
02962 }
02969 static DBusHandlerResult disassociate_request(DBusMessage *message,
02970 DBusConnection *connection) {
02971 DBusMessage *reply;
02972
02973 if (get_wlan_state() != WLAN_CONNECTED &&
02974 get_wlan_state() != WLAN_NO_ADDRESS) {
02975 DLOG_DEBUG("Not in correct state for disassociation");
02976
02977 reply = new_dbus_method_return(message);
02978 send_and_unref(connection, reply);
02979 return DBUS_HANDLER_RESULT_HANDLED;
02980 }
02981
02982 mlme_command(wlan_status.conn.bssid, WLANCOND_NL80211_MLME_DISCONNECT,
02983 WLANCOND_REASON_LEAVING);
02984
02985 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL, TRUE);
02986
02987 DLOG_DEBUG("Disassociated, trying to find a new connection");
02988
02989 scan(wlan_status.conn.ssid, wlan_status.conn.ssid_len, TRUE);
02990
02991 reply = new_dbus_method_return(message);
02992 send_and_unref(connection, reply);
02993
02994 return DBUS_HANDLER_RESULT_HANDLED;
02995 }
03002 static DBusHandlerResult status_request(DBusMessage *message,
03003 DBusConnection *connection) {
03004 DBusMessage *reply = NULL;
03005 dbus_uint32_t sens = 0;
03006 dbus_uint32_t security = 0;
03007 dbus_uint32_t capability = 0;
03008 dbus_uint32_t channel = 0;
03009 GSList *list;
03010 struct scan_results_t *current_conn_ap = NULL;
03011 struct connect_params_t *conn = &wlan_status.conn;
03012 char *essid = conn->ssid;
03013 unsigned char *bssid = conn->bssid;
03014 guint8 power;
03015
03016 if (get_wlan_state() != WLAN_CONNECTED &&
03017 get_wlan_state() != WLAN_NO_ADDRESS &&
03018 get_mode() != WLANCOND_ADHOC) {
03019 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
03020 send_and_unref(connection, reply);
03021 return DBUS_HANDLER_RESULT_HANDLED;
03022 }
03023
03024 roam_cache_key_t key = { conn->bssid, conn->channel };
03025 list = g_slist_find_custom(wlan_status.roam_cache, &key,
03026 &compare_scan_entry);
03027 if (list == NULL) {
03028 if (get_mode() != WLANCOND_ADHOC) {
03029 DLOG_ERR("nl80211: MAC entry not found");
03030 reply = new_dbus_error(message, WLANCOND_ERROR_FATAL);
03031 goto param_err;
03032 }
03033 } else {
03034 current_conn_ap = list->data;
03035 }
03036
03037
03038 if (nl80211_get_signal_info(&power, &wlan_status) !=0) {
03039 if (get_mode() != WLANCOND_ADHOC) {
03040 DLOG_ERR("Could not get statistics");
03041 reply = new_dbus_error(message,
03042 WLANCOND_ERROR_IOCTL_FAILED);
03043 goto param_err;
03044 }
03045 } else {
03046 sens = power - 0x100;
03047 }
03048
03049
03050 channel = conn->channel;
03051
03052 if (channel < WLANCOND_MIN_WLAN_CHANNEL ||
03053 channel > WLANCOND_MAX_WLAN_CHANNEL) {
03054 channel = 0;
03055 DLOG_DEBUG("Got invalid channel");
03056 }
03057
03058
03059 if (conn->mode == WLANCOND_ADHOC) {
03060 capability |= WLANCOND_ADHOC;
03061 } else if (conn->mode == WLANCOND_INFRA) {
03062 capability |= WLANCOND_INFRA;
03063 }
03064
03065
03066 security = wlan_status.conn.encryption;
03067
03068
03069 if (current_conn_ap != NULL)
03070 capability |= current_conn_ap->cap_bits & WLANCOND_RATE_MASK;
03071
03072 reply = new_dbus_method_return(message);
03073
03074 gchar* ifname = wlan_status.ifname;
03075
03076 append_dbus_args(reply,
03077 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03078 &essid, conn->ssid_len-1,
03079 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, ETH_ALEN,
03080 DBUS_TYPE_UINT32, &sens,
03081 DBUS_TYPE_UINT32, &channel,
03082 DBUS_TYPE_UINT32, &capability,
03083 DBUS_TYPE_UINT32, &security,
03084 DBUS_TYPE_STRING, &ifname,
03085 DBUS_TYPE_INVALID);
03086
03087 send_and_unref(connection, reply);
03088
03089 return DBUS_HANDLER_RESULT_HANDLED;
03090
03091 param_err:
03092 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, FALSE);
03093
03094 if (reply == NULL) {
03095 DLOG_DEBUG("Parameter error in status request");
03096 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
03097 }
03098
03099 send_and_unref(connection, reply);
03100
03101 return DBUS_HANDLER_RESULT_HANDLED;
03102 }
03103
03110 static DBusHandlerResult interface_request(DBusMessage *message,
03111 DBusConnection *connection) {
03112 DBusMessage *reply;
03113 gchar* ifname = wlan_status.ifname;
03114
03115 reply = new_dbus_method_return(message);
03116
03117 append_dbus_args(reply,
03118 DBUS_TYPE_STRING, &ifname,
03119 DBUS_TYPE_INVALID);
03120
03121 send_and_unref(connection, reply);
03122
03123 return DBUS_HANDLER_RESULT_HANDLED;
03124 }
03125
03132 static DBusHandlerResult connection_status_request(
03133 DBusMessage *message,
03134 DBusConnection *connection) {
03135
03136 DBusMessage *reply;
03137 dbus_bool_t state = FALSE;
03138
03139 guint state_v = get_wlan_state();
03140
03141 if (state_v == WLAN_INITIALIZED ||
03142 state_v == WLAN_INITIALIZED_FOR_CONNECTION ||
03143 state_v == WLAN_NO_ADDRESS ||
03144 state_v == WLAN_CONNECTED)
03145 state = TRUE;
03146
03147 reply = new_dbus_method_return(message);
03148
03149 append_dbus_args(reply,
03150 DBUS_TYPE_BOOLEAN, &state,
03151 DBUS_TYPE_INVALID);
03152
03153 send_and_unref(connection, reply);
03154
03155 return DBUS_HANDLER_RESULT_HANDLED;
03156 }
03163 static DBusHandlerResult set_pmksa_request(DBusMessage *message,
03164 DBusConnection *connection) {
03165
03166 DBusMessage *reply = NULL;
03167 unsigned int pmkid_len, mac_len;
03168 unsigned char *pmkid;
03169 unsigned char *mac;
03170 dbus_uint32_t action;
03171 DBusError derror;
03172
03173 dbus_error_init(&derror);
03174
03175 if (dbus_message_get_args(
03176 message, &derror,
03177 DBUS_TYPE_UINT32, &action,
03178 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &pmkid, &pmkid_len,
03179 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &mac, &mac_len,
03180 DBUS_TYPE_INVALID) == FALSE)
03181 {
03182 DLOG_ERR("Failed to parse set_pmksa request: %s",
03183 derror.message);
03184 dbus_error_free(&derror);
03185 goto param_err;
03186 }
03187
03188 if (action != WLANCOND_PMKSA_ADD) {
03189 DLOG_ERR("Invalid action");
03190 goto param_err;
03191 }
03192
03193 if (pmkid == NULL || pmkid_len != WLANCOND_PMKID_LEN || mac == NULL
03194 || mac_len != ETH_ALEN) {
03195 DLOG_ERR("Invalid arguments");
03196 goto param_err;
03197 }
03198
03199 add_to_pmksa_cache(pmkid, mac);
03200
03201 print_mac(WLANCOND_PRIO_LOW, "PMKSA added successfully for address:",
03202 mac);
03203
03204 reply = new_dbus_method_return(message);
03205 send_and_unref(connection, reply);
03206
03207 return DBUS_HANDLER_RESULT_HANDLED;
03208
03209 param_err:
03210 if (reply == NULL) {
03211 DLOG_DEBUG("Parameter error in set_pmksa");
03212 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
03213 }
03214 send_and_unref(connection, reply);
03215 return DBUS_HANDLER_RESULT_HANDLED;
03216 }
03217
03224 static DBusHandlerResult set_powersave_request(DBusMessage *message,
03225 DBusConnection *connection) {
03226
03227 DBusMessage *reply = NULL;
03228 DBusError error;
03229 dbus_bool_t onoff;
03230
03231 dbus_error_init(&error);
03232
03233 if (dbus_message_get_args(message, &error,
03234 DBUS_TYPE_BOOLEAN, &onoff,
03235 DBUS_TYPE_INVALID) == FALSE) {
03236 DLOG_ERR("Failed to parse message: %s",
03237 error.message);
03238 dbus_error_free(&error);
03239
03240 send_invalid_args(connection, message);
03241 return DBUS_HANDLER_RESULT_HANDLED;
03242 }
03243
03244
03245
03246
03247 if (onoff == TRUE) {
03248 if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
03249 set_wlan_state(WLAN_NOT_INITIALIZED,
03250 NO_SIGNAL, TRUE);
03251 } else if (get_wlan_state() != WLAN_NO_ADDRESS ||
03252 (connect_name_cache != NULL &&
03253 strcmp(dbus_message_get_sender(message),
03254 connect_name_cache) == 0)) {
03255 if (set_power_state(wlan_status.powersave) == FALSE) {
03256 DLOG_ERR("Setting powersave failed");
03257
03258 }
03259 }
03260 } else {
03261
03262 if (set_power_state(WLANCOND_POWER_ON) == FALSE) {
03263 DLOG_ERR("Setting powersave failed");
03264
03265 }
03266 }
03267
03268 DLOG_DEBUG("WLAN powersave %s", onoff==TRUE?"on":"off");
03269
03270 reply = new_dbus_method_return(message);
03271 send_and_unref(connection, reply);
03272
03273 return DBUS_HANDLER_RESULT_HANDLED;
03274 }
03275
03281 int wpa_ie_push(char* ap_mac_addr) {
03282
03283 DBusMessage *msg;
03284 DBusMessage *reply;
03285 DBusError derr;
03286 struct connect_params_t *conn = &wlan_status.conn;
03287 dbus_bool_t autoconnect = !!(conn->flags & WLANCOND_AUTOCONNECT);
03288 char *ssid = conn->ssid;
03289 unsigned char *ap_wpa_ie;
03290 guint32 ap_wpa_ie_len;
03291 GSList *list;
03292
03293 if (conn->authentication_type != EAP_AUTH_TYPE_WFA_SC) {
03294 if (wlan_status.wpa_ie.ie_len == 0 ||
03295 conn->ssid_len == 0) {
03296 DLOG_ERR("WPA IE / SSID not valid");
03297 return -1;
03298 }
03299 }
03300
03301 roam_cache_key_t key = { (unsigned char*) ap_mac_addr, conn->channel };
03302 list = g_slist_find_custom(wlan_status.roam_cache, &key,
03303 &compare_scan_entry);
03304
03305 if (list == NULL)
03306 return -1;
03307
03308 struct scan_results_t *current_ap_entry = list->data;
03309 ap_wpa_ie = current_ap_entry->wpa_ie;
03310 ap_wpa_ie_len = current_ap_entry->wpa_ie_len;
03311
03312 dbus_error_init(&derr);
03313
03314 msg = dbus_message_new_method_call(
03315 EAP_SERVICE,
03316 EAP_REQ_PATH,
03317 EAP_REQ_INTERFACE,
03318 EAP_WPA_IE_PUSH_REQ);
03319
03320 if (msg == NULL) {
03321 return -1;
03322 }
03323
03324 dbus_message_set_auto_start(msg, FALSE);
03325
03326 append_dbus_args(
03327 msg,
03328 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03329 &wlan_status.wpa_ie.ie, wlan_status.wpa_ie.ie_len,
03330 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ap_wpa_ie,
03331 ap_wpa_ie_len,
03332 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03333 &ssid, conn->ssid_len -1,
03334 DBUS_TYPE_UINT32, &wlan_status.pairwise_cipher,
03335 DBUS_TYPE_UINT32, &wlan_status.group_cipher,
03336 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
03337 &ap_mac_addr, ETH_ALEN,
03338 DBUS_TYPE_UINT32, &conn->authentication_type,
03339 DBUS_TYPE_BOOLEAN, &autoconnect,
03340 DBUS_TYPE_INVALID);
03341
03342 reply = dbus_connection_send_with_reply_and_block(
03343 get_dbus_connection(), msg, -1, &derr);
03344
03345 dbus_message_unref(msg);
03346
03347 if (dbus_error_is_set(&derr)) {
03348 DLOG_ERR("EAP returned error: %s", derr.name);
03349
03350 dbus_error_free(&derr);
03351 if (reply)
03352 dbus_message_unref(reply);
03353 return -1;
03354 }
03355
03356 dbus_message_unref(reply);
03357
03358 return 0;
03359 }
03366 int wpa_mic_failure_event(dbus_bool_t key_type, dbus_bool_t is_fatal) {
03367 DBusMessage *msg;
03368 DBusMessage *reply;
03369 DBusError derr;
03370
03371 msg = dbus_message_new_method_call(
03372 EAP_SERVICE,
03373 EAP_REQ_PATH,
03374 EAP_REQ_INTERFACE,
03375 EAP_WPA_MIC_FAILURE_REQ);
03376
03377 if (msg == NULL) {
03378 return -1;
03379 }
03380
03381 append_dbus_args(msg,
03382 DBUS_TYPE_BOOLEAN, &key_type,
03383 DBUS_TYPE_BOOLEAN, &is_fatal,
03384 DBUS_TYPE_INVALID);
03385
03386 dbus_error_init(&derr);
03387
03388 reply = dbus_connection_send_with_reply_and_block(
03389 get_dbus_connection(), msg, -1, &derr);
03390
03391 dbus_message_unref(msg);
03392
03393 if (dbus_error_is_set(&derr)) {
03394 DLOG_ERR("EAP returned error: %s", derr.name);
03395
03396 dbus_error_free(&derr);
03397 if (reply)
03398 dbus_message_unref(reply);
03399 return -1;
03400 }
03401
03402 dbus_message_unref(reply);
03403
03404 return 0;
03405 }
03412 static void disassociate_cb(DBusPendingCall *pending,
03413 void *user_data)
03414 {
03415 DBusMessage *reply;
03416 DBusError error;
03417
03418 dbus_error_init (&error);
03419
03420 reply = dbus_pending_call_steal_reply(pending);
03421
03422 if (dbus_set_error_from_message(&error, reply)) {
03423
03424 DLOG_DEBUG("EAP disassociate call result:%s", error.name);
03425
03426 dbus_error_free(&error);
03427 }
03428
03429 if (reply)
03430 dbus_message_unref(reply);
03431 dbus_pending_call_unref(pending);
03432 }
03433
03438 int disassociate_eap(void) {
03439 DBusMessage *msg;
03440 DBusPendingCall *pending;
03441
03442 msg = dbus_message_new_method_call(
03443 EAP_SERVICE,
03444 EAP_REQ_PATH,
03445 EAP_REQ_INTERFACE,
03446 EAP_DISASSOCIATE_REQ);
03447
03448 if (msg == NULL) {
03449 return -1;
03450 }
03451
03452 dbus_message_set_auto_start(msg, FALSE);
03453
03454 if (!dbus_connection_send_with_reply(get_dbus_connection(),
03455 msg, &pending, -1))
03456 die("Out of memory");
03457
03458 if (!dbus_pending_call_set_notify (pending, disassociate_cb, NULL,
03459 NULL))
03460 die("Out of memory");
03461
03462 dbus_message_unref(msg);
03463
03464 return 0;
03465 }
03466
03481 int check_pmksa_cache(unsigned char* own_mac, int own_mac_len,
03482 unsigned char* bssid, int bssid_len,
03483 uint32_t authentication_type,
03484 uint32_t pairwise_key_cipher_suite,
03485 uint32_t group_key_cipher_suite,
03486 int *status)
03487 {
03488 DBusMessage *msg = NULL;
03489 DBusMessage *reply = NULL;
03490 DBusError error;
03491 dbus_bool_t found;
03492
03493 dbus_error_init (&error);
03494
03495 msg = dbus_message_new_method_call(
03496 EAP_SERVICE,
03497 EAP_REQ_PATH,
03498 EAP_REQ_INTERFACE,
03499 EAP_CHECK_PMKSA_CACHE_REQ);
03500
03501 if (msg == NULL)
03502 return -1;
03503
03504 dbus_message_set_auto_start(msg, FALSE);
03505
03506 if (dbus_message_append_args(
03507 msg,
03508 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &own_mac, own_mac_len,
03509 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, bssid_len,
03510 DBUS_TYPE_UINT32, &authentication_type,
03511 DBUS_TYPE_UINT32, &pairwise_key_cipher_suite,
03512 DBUS_TYPE_UINT32, &group_key_cipher_suite,
03513 DBUS_TYPE_INVALID) == FALSE)
03514 {
03515 DLOG_ERR("Unable to add args to dbus method call.");
03516 dbus_message_unref(msg);
03517 return -1;
03518 }
03519
03520 reply = dbus_connection_send_with_reply_and_block(
03521 get_dbus_connection(), msg, -1, &error);
03522
03523 dbus_message_unref(msg);
03524
03525 if (dbus_error_is_set(&error)) {
03526 DLOG_ERR("EAP returned error: %s", error.message);
03527 dbus_error_free(&error);
03528
03529 goto error;
03530 }
03531
03532 if (!dbus_message_get_args(reply, &error,
03533 DBUS_TYPE_BOOLEAN, &found,
03534 DBUS_TYPE_INVALID))
03535 {
03536 DLOG_ERR("Error parsing the return value: %s", error.message);
03537 if (dbus_error_is_set(&error))
03538 dbus_error_free(&error);
03539
03540 goto error;
03541 }
03542
03543 dbus_message_unref(reply);
03544
03545 *status = found;
03546
03547 return 0;
03548
03549 error:
03550 if (reply)
03551 dbus_message_unref(reply);
03552
03553 return -1;
03554 }
03560 static void write_file(const char* file, guint value) {
03561 char buf[4];
03562 FILE *sysfsfile;
03563
03564 sysfsfile = fopen(file, "w");
03565 if (sysfsfile == NULL)
03566 return;
03567 snprintf(buf, 3, "%d", value);
03568 if (fwrite(buf, 3, 1, sysfsfile) != 1) {
03569 DLOG_ERR("Could not write to: %s", file);
03570 }
03571 fclose(sysfsfile);
03572 return;
03573 }
03578 static void set_scan_params(guint scan_mode) {
03579 static guint current_scan_mode = 0;
03580
03581 if (current_scan_mode == scan_mode)
03582 return;
03583
03584 current_scan_mode = scan_mode;
03585
03586 if (scan_mode == SCAN_SPLIT) {
03587
03588 write_file(SCAN_SIZE_FILE, SCAN_SIZE_SPLIT);
03589
03590 write_file(SCAN_DELAY_FILE, SCAN_DELAY_SPLIT);
03591 } else {
03592
03593 write_file(SCAN_SIZE_FILE, SCAN_SIZE_NORMAL);
03594
03595 write_file(SCAN_DELAY_FILE, SCAN_DELAY_NORMAL);
03596 }
03597 return;
03598 }
03604 void set_call_type(const char *type)
03605 {
03606 guint previous_call_type;
03607
03608 if (!type)
03609 return;
03610
03611 previous_call_type = wlan_status.call_type;
03612
03613 wlan_status.call_type &= ~CALL_CELLULAR;
03614 wlan_status.call_type &= ~CALL_VOIP;
03615
03616 if (!strcmp(type, "none")) {
03617 set_scan_params(SCAN_NORMAL);
03618 DLOG_DEBUG("Call cleared");
03619 } else if (!strcmp(type, "cellular")) {
03620 wlan_status.call_type |= CALL_CELLULAR;
03621 set_tx_power(wlan_status.conn.power_level);
03622 set_scan_params(SCAN_NORMAL);
03623 DLOG_DEBUG("Reduced power level");
03624 } else {
03625 wlan_status.call_type |= CALL_VOIP;
03626 set_scan_params(SCAN_SPLIT);
03627 DLOG_DEBUG("VOIP call");
03628 }
03629
03630
03631
03632
03633 if ((previous_call_type & CALL_CELLULAR) &&
03634 (!strcmp(type, "none") ||
03635 (wlan_status.call_type & CALL_VOIP))) {
03636 if (wlan_status.conn.power_level) {
03637 set_tx_power(wlan_status.conn.power_level);
03638 DLOG_DEBUG("Restored power level");
03639 }
03640 }
03641 if (can_adjust_psm())
03642 set_power_state(wlan_status.powersave);
03643 }
03651 int context_parser(DBusMessageIter *actit)
03652 {
03653 DBusMessageIter cmdit;
03654 DBusMessageIter argit;
03655 DBusMessageIter valit;
03656 char *argname;
03657 char *argval;
03658 char *variable;
03659 char *value;
03660
03661 do {
03662 variable = value = NULL;
03663
03664 dbus_message_iter_recurse(actit, &cmdit);
03665
03666 do {
03667 if (dbus_message_iter_get_arg_type(&cmdit) !=
03668 DBUS_TYPE_STRUCT)
03669 return FALSE;
03670
03671 dbus_message_iter_recurse(&cmdit, &argit);
03672
03673 if (dbus_message_iter_get_arg_type(&argit) !=
03674 DBUS_TYPE_STRING)
03675 return FALSE;
03676
03677 dbus_message_iter_get_basic(&argit, (void *)&argname);
03678
03679 if (!dbus_message_iter_next(&argit))
03680 return FALSE;
03681
03682 if (dbus_message_iter_get_arg_type(&argit) !=
03683 DBUS_TYPE_VARIANT)
03684 return FALSE;
03685
03686 dbus_message_iter_recurse(&argit, &valit);
03687
03688 if (dbus_message_iter_get_arg_type(&valit) !=
03689 DBUS_TYPE_STRING)
03690 return FALSE;
03691
03692 dbus_message_iter_get_basic(&valit, (void *)&argval);
03693
03694 if (!strcmp(argname, "variable")) {
03695 variable = argval;
03696 }
03697 else if (!strcmp(argname, "value")) {
03698 value = argval;
03699 }
03700
03701 if (variable && !strcmp(variable, "call_audio_type"))
03702 set_call_type(value);
03703
03704 } while (dbus_message_iter_next(&cmdit));
03705
03706 } while (dbus_message_iter_next(actit));
03707
03708 return TRUE;
03709 }
03710
03716 static DBusHandlerResult handle_policy_actions(DBusMessage *msg)
03717 {
03718 dbus_uint32_t txid;
03719 char *actname;
03720 DBusMessageIter msgit;
03721 DBusMessageIter arrit;
03722 DBusMessageIter entit;
03723 DBusMessageIter actit;
03724 int success = TRUE;
03725
03726 dbus_message_iter_init(msg, &msgit);
03727
03728 if (dbus_message_iter_get_arg_type(&msgit) != DBUS_TYPE_UINT32)
03729 return DBUS_HANDLER_RESULT_HANDLED;
03730
03731 dbus_message_iter_get_basic(&msgit, (void *)&txid);
03732
03733 if (!dbus_message_iter_next(&msgit) ||
03734 dbus_message_iter_get_arg_type(&msgit) !=
03735 DBUS_TYPE_ARRAY) {
03736 success = FALSE;
03737 goto out;
03738 }
03739
03740 dbus_message_iter_recurse(&msgit, &arrit);
03741
03742 do {
03743 if (dbus_message_iter_get_arg_type(&arrit) !=
03744 DBUS_TYPE_DICT_ENTRY) {
03745 success = FALSE;
03746 continue;
03747 }
03748
03749 dbus_message_iter_recurse(&arrit, &entit);
03750
03751 do {
03752 if (dbus_message_iter_get_arg_type(&entit) !=
03753 DBUS_TYPE_STRING) {
03754 success = FALSE;
03755 continue;
03756 }
03757
03758 dbus_message_iter_get_basic(&entit, (void *)&actname);
03759
03760 if (!dbus_message_iter_next(&entit) ||
03761 dbus_message_iter_get_arg_type(&entit)
03762 != DBUS_TYPE_ARRAY) {
03763 success = FALSE;
03764 continue;
03765 }
03766
03767 dbus_message_iter_recurse(&entit, &actit);
03768
03769 if (dbus_message_iter_get_arg_type(&actit) !=
03770 DBUS_TYPE_ARRAY) {
03771 success = FALSE;
03772 continue;
03773 }
03774
03775 if (!strcmp(actname, "com.nokia.policy.context"))
03776 success &= context_parser(&actit);
03777
03778 } while (dbus_message_iter_next(&entit));
03779
03780 } while (dbus_message_iter_next(&arrit));
03781
03782 out:
03783 if (!success)
03784 DLOG_DEBUG("Failed to parse the policy actions message.");
03785
03786 return DBUS_HANDLER_RESULT_HANDLED;
03787 }
03788
03789 typedef DBusHandlerResult (*handler_func)(DBusMessage *message,
03790 DBusConnection *connection);
03791
03792 typedef struct {
03793 const char *interface;
03794 const char *name;
03795 handler_func func;
03796 } method_handler_t;
03797
03798 static method_handler_t handlers[] = {
03799 { WLANCOND_REQ_INTERFACE, WLANCOND_SETTINGS_AND_CONNECT_REQ,
03800 settings_and_connect_request},
03801 { WLANCOND_REQ_INTERFACE, WLANCOND_SCAN_REQ, scan_request},
03802 { WLANCOND_REQ_INTERFACE, WLANCOND_STATUS_REQ, status_request},
03803 { WLANCOND_REQ_INTERFACE, WLANCOND_INTERFACE_REQ, interface_request},
03804 { WLANCOND_REQ_INTERFACE, WLANCOND_CONNECTION_STATUS_REQ,
03805 connection_status_request},
03806 { WLANCOND_REQ_INTERFACE, WLANCOND_SET_PMKSA_REQ, set_pmksa_request},
03807 { WLANCOND_REQ_INTERFACE, WLANCOND_SET_POWERSAVE_REQ,
03808 set_powersave_request},
03809 { WLANCOND_REQ_INTERFACE, WLANCOND_DISCONNECT_REQ, disconnect_request},
03810 { WLANCOND_REQ_INTERFACE, WLANCOND_DISASSOCIATE_REQ,
03811 disassociate_request},
03812 { NULL }
03813 };
03814
03821 DBusHandlerResult wlancond_req_handler(DBusConnection *connection,
03822 DBusMessage *message,
03823 void *user_data)
03824 {
03825 method_handler_t *handler;
03826
03827 DLOG_DEBUG("Received %s.%s",
03828 dbus_message_get_interface(message),
03829 dbus_message_get_member(message));
03830
03831 if (dbus_message_is_signal(message,
03832 ICD_DBUS_INTERFACE,
03833 ICD_STATUS_CHANGED_SIG))
03834 return icd_check_signal_dbus(message);
03835
03836 else if (dbus_message_is_signal(message,
03837 CSNET_OPER_IFACE,
03838 CSNET_OPERATOR_CHANGED_SIG))
03839 return csd_check_signal_dbus(message);
03840
03841 else if (dbus_message_is_signal(message,
03842 EAP_SIG_INTERFACE,
03843 EAP_AUTH_STATUS_SIG))
03844 return eap_check_signal_dbus(message);
03845 else if (dbus_message_is_signal(message,
03846 POLICY_SERVICE_NAME,
03847 POLICY_ACTIONS_SIG))
03848 return handle_policy_actions(message);
03849 else if (dbus_message_is_signal(message,
03850 GPRS_DBUS_INTERFACE,
03851 GPRS_DBUS_DATACOUNTERS_SIG)) {
03852 return gprs_datacounters_signal(message);
03853 }
03854 #ifdef USE_MCE_MODE
03855 else if (dbus_message_is_signal(message,
03856 MCE_SIGNAL_IF,
03857 MCE_RADIO_STATES_SIG)) {
03858 return mode_change_dbus(message);
03859 }
03860 #ifdef ACTIVITY_CHECK
03861 else if (dbus_message_is_signal(message,
03862 MCE_SIGNAL_IF,
03863 MCE_INACTIVITY_SIG)) {
03864 return activity_check_dbus(message);
03865 }
03866 #endif
03867 #endif
03868
03869 else if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
03870 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03871 }
03872
03873 for (handler = handlers; handler->interface != NULL; handler++) {
03874 if (dbus_message_is_method_call(message,
03875 handler->interface,
03876 handler->name)) {
03877 DLOG_DEBUG("Received %s", handler->name);
03878 return handler->func(message, connection);
03879 }
03880 }
03881 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03882 }
03883
03884 static DBusObjectPathVTable wlancond_req_vtable = {
03885 .message_function = wlancond_req_handler,
03886 .unregister_function = NULL
03887 };
03888
03889
03894 void init_dbus_handlers(DBusConnection *connection) {
03895 dbus_bool_t ret;
03896 ret = dbus_connection_register_object_path(connection,
03897 WLANCOND_REQ_PATH,
03898 &wlancond_req_vtable,
03899 NULL);
03900 if (ret == FALSE)
03901 DLOG_ERR("dbus_connection_register_object_path failed");
03902
03903 #ifdef USE_MCE_MODE
03904 if (!add_mode_listener(connection))
03905 DLOG_ERR("Adding mode listener failed");
03906 #endif
03907 if (!add_csd_listener(connection))
03908 DLOG_ERR("Adding csd listener failed");
03909 }
03910
03915 void destroy_dbus_handlers(DBusConnection *connection) {
03916 dbus_connection_unregister_object_path(connection, WLANCOND_REQ_PATH);
03917 }