00001
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <glib.h>
00030 #include <net/ethernet.h>
00031 #include <linux/socket.h>
00032 #include <gconf/gconf-client.h>
00033 #include <osso-ic-dbus.h>
00034
00035 #define DBUS_API_SUBJECT_TO_CHANGE
00036 #include <dbus/dbus.h>
00037 #include <eap-dbus.h>
00038 #include <wlancond-dbus.h>
00039 #ifdef USE_MCE_MODE
00040 #include <mce/dbus-names.h>
00041 #endif
00042 #include "log.h"
00043 #include "dbus.h"
00044 #include "dbus-helper.h"
00045 #include "dbus-handler.h"
00046 #include "common.h"
00047 #include "wpa.h"
00048
00049 #define WLANCOND_SHUTDOWN_DELAY 4000 //4s
00050
00051 #define WLANCOND_CONNECT_TIMEOUT 15000 //15s
00052 #define WLANCOND_SCAN_TIMEOUT 12000 //12s
00053
00054
00055 static char *scan_name_cache = NULL;
00056 static char *connect_name_cache = NULL;
00057
00058 static int wlan_socket = -1;
00059
00060 struct wlan_status_t wlan_status;
00061
00062 static gboolean _flight_mode = FALSE;
00063 static gboolean power_down_after_scan = FALSE;
00064 static dbus_bool_t saved_inactivity = FALSE;
00065
00066
00067 static guint wlan_if_down_timer_id = 0;
00068 static guint wlan_connect_timer_id = 0;
00069
00070
00071 static guint powersave = WLANCOND_SHORT_CAM;
00072
00073 #define WLAN_PREFIX_STR "wlan"
00074
00078 int socket_open(void)
00079 {
00080 if (wlan_socket > 0)
00081 return wlan_socket;
00082
00083 wlan_socket = socket(AF_INET, SOCK_DGRAM, 0);
00084
00085 if (wlan_socket < 0)
00086 die("socket() failed");
00087
00088 return wlan_socket;
00089 }
00093 void init_iwreq(struct iwreq* req)
00094 {
00095 memset(req, 0, sizeof(struct iwreq));
00096 strncpy(req->ifr_name, wlan_status.ifname, IFNAMSIZ);
00097 }
00101 static int get_own_mac(void)
00102 {
00103 struct ifreq req;
00104
00105 memset(&req , 0, sizeof(req));
00106 memcpy(req.ifr_name, wlan_status.ifname, IFNAMSIZ);
00107
00108 if (ioctl(socket_open(), SIOCGIFHWADDR, &req) < 0)
00109 {
00110 return -1;
00111 }
00112
00113 memcpy(wlan_status.own_mac, req.ifr_hwaddr.sa_data, ETH_ALEN);
00114
00115 return 0;
00116 }
00117
00123 static gint get_gconf_int(const gchar* path)
00124 {
00125 GConfClient *client;
00126 GConfValue *gconf_value;
00127 GError *error = NULL;
00128
00129 client = gconf_client_get_default();
00130 if (client == NULL) {
00131 return -1;
00132 }
00133
00134 gconf_value = gconf_client_get(client, path, &error);
00135
00136 g_object_unref(client);
00137
00138 if (error != NULL) {
00139 DLOG_ERR("Could not get setting:%s, error:%s", path,
00140 error->message);
00141
00142 g_clear_error(&error);
00143 return -1;
00144 }
00145
00146 if (gconf_value == NULL) {
00147 return -1;
00148 }
00149 if (gconf_value->type == GCONF_VALUE_INT) {
00150 gint value = gconf_value_get_int(gconf_value);
00151 DLOG_DEBUG("User selected value: %d", value);
00152 gconf_value_free(gconf_value);
00153 return value;
00154 }
00155
00156 gconf_value_free(gconf_value);
00157 return -1;
00158 }
00164 void update_own_ie(unsigned char* wpa_ie, guint wpa_ie_len)
00165 {
00166 g_free(wlan_status.wpa_ie.ie);
00167 wlan_status.wpa_ie.ie = wpa_ie;
00168 wlan_status.wpa_ie.ie_len = wpa_ie_len;
00169 }
00174 guint get_encryption_info(void)
00175 {
00176 guint auth_status = 0;
00177
00178 if (wlan_status.pairwise_cipher & CIPHER_SUITE_CCMP) {
00179 auth_status |= WLANCOND_WPA_AES;
00180 } else if (wlan_status.pairwise_cipher & CIPHER_SUITE_TKIP) {
00181 auth_status |= WLANCOND_WPA_TKIP;
00182 } else if (wlan_status.pairwise_cipher & CIPHER_SUITE_WEP40 ||
00183 wlan_status.pairwise_cipher & CIPHER_SUITE_WEP104) {
00184 auth_status |= WLANCOND_WEP;
00185 } else {
00186 auth_status |= WLANCOND_OPEN;
00187 }
00188 return auth_status;
00189 }
00190
00194 int init_dbus_handler(void)
00195 {
00196 if (get_own_mac() < 0) {
00197 DLOG_ERR("Could not get own MAC address");
00198 return -1;
00199 }
00200
00201 return 0;
00202 }
00206 int clean_dbus_handler(void)
00207 {
00208 if (wlan_socket > 0)
00209 close(wlan_socket);
00210 return 0;
00211 }
00216 void mode_change(const char *mode) {
00217
00218 DLOG_DEBUG("WLAN flight mode changed to \"%s\"", mode);
00219
00220 if (g_str_equal(mode, "flight")) {
00221 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, FORCE_YES);
00222 _flight_mode = TRUE;
00223 }
00224 else if (g_str_equal(mode, "normal")) {
00225 _flight_mode = FALSE;
00226 }
00227 else {
00228 DLOG_ERR("Invalid mode \"%s\" passed to mode_change()", mode);
00229 }
00230 }
00235 #ifdef USE_MCE_MODE
00236 static DBusHandlerResult mode_change_dbus(DBusMessage *message) {
00237
00238 char *mode;
00239
00240 if (!dbus_message_get_args(message, NULL,
00241 DBUS_TYPE_STRING, &mode,
00242 DBUS_TYPE_INVALID)) {
00243 DLOG_ERR("Invalid arguments for device_mode_ind signal");
00244 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00245 }
00246
00247 mode_change(mode);
00248
00249 return DBUS_HANDLER_RESULT_HANDLED;
00250 }
00251 #ifdef ACTIVITY_CHECK
00252 static DBusHandlerResult activity_check_dbus(DBusMessage *message) {
00253
00254 if (!dbus_message_get_args(message, NULL,
00255 DBUS_TYPE_BOOLEAN, &saved_inactivity,
00256 DBUS_TYPE_INVALID)) {
00257 DLOG_ERR("Invalid arguments for device_activity signal");
00258 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00259 }
00260 activity_check(saved_inactivity);
00261
00262 return DBUS_HANDLER_RESULT_HANDLED;
00263 }
00264 #endif
00265 #endif
00266
00267 #ifdef ACTIVITY_CHECK
00268
00271 void activity_check(dbus_bool_t inactivity) {
00272
00273 int sock;
00274
00275 if (get_wlan_state() != WLAN_CONNECTED) {
00276 return;
00277 }
00278
00279 sock = socket_open();
00280
00281 if (inactivity == FALSE) {
00282
00283 } else {
00284
00285 }
00286
00287 set_power_state(powersave, sock);
00288 }
00289
00293 static gboolean get_inactivity_status(void)
00294 {
00295 return saved_inactivity;
00296 }
00297 #endif
00298
00303 static DBusHandlerResult icd_check_signal_dbus(DBusMessage *message) {
00304
00305 char *icd_name;
00306 char *icd_type;
00307 char *icd_state;
00308 char *icd_disconnect_reason;
00309 DBusError dbus_error;
00310
00311 if ((get_wlan_state() != WLAN_CONNECTED &&
00312 get_wlan_state() != WLAN_NO_ADDRESS) ||
00313 get_mode() != WLANCOND_INFRA) {
00314 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00315 }
00316
00317 dbus_error_init(&dbus_error);
00318 if (!dbus_message_get_args(message, &dbus_error,
00319 DBUS_TYPE_STRING, &icd_name,
00320 DBUS_TYPE_STRING, &icd_type,
00321 DBUS_TYPE_STRING, &icd_state,
00322 DBUS_TYPE_STRING, &icd_disconnect_reason,
00323 DBUS_TYPE_INVALID ) )
00324 {
00325 DLOG_ERR("Could not get args from signal, '%s'",
00326 dbus_error.message);
00327 dbus_error_free(&dbus_error);
00328 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00329 }
00330
00331 if (icd_state != NULL && strncmp(icd_state, "CONNECTED", 9) == 0) {
00332
00333 set_wlan_state(WLAN_CONNECTED, NO_SIGNAL, FORCE_NO);
00334
00335 DLOG_DEBUG("Going to power save");
00336
00337 if (set_power_state(powersave, socket_open()) == FALSE) {
00338 DLOG_ERR("Failed to set power save");
00339 }
00340
00341 }
00342
00343
00344
00345 return DBUS_HANDLER_RESULT_HANDLED;
00346 }
00347
00348 static gboolean in_flight_mode(void) {
00349 return _flight_mode;
00350 }
00351
00352 void set_wlan_signal(gboolean high_or_low)
00353 {
00354 if (high_or_low == WLANCOND_HIGH) {
00355 wlan_status.signal = WLANCOND_HIGH;
00356 remove_roam_scan_timer();
00357 } else {
00358 wlan_status.signal = WLANCOND_LOW;
00359 }
00360 }
00361
00362 void remove_roam_scan_timer(void)
00363 {
00364 if (wlan_status.roam_scan_id) {
00365 g_source_remove(wlan_status.roam_scan_id);
00366 wlan_status.roam_scan_id = 0;
00367 }
00368 }
00369
00370 void remove_connect_timer(void)
00371 {
00372 if (wlan_connect_timer_id) {
00373 g_source_remove(wlan_connect_timer_id);
00374 wlan_connect_timer_id = 0;
00375 }
00376 }
00377
00378 static void remove_wlan_if_timer(void)
00379 {
00380
00381 if (wlan_if_down_timer_id) {
00382 g_source_remove(wlan_if_down_timer_id);
00383 wlan_if_down_timer_id = 0;
00384 }
00385 }
00386
00387 void remove_scan_timer(void)
00388 {
00389 if (wlan_status.scan_id) {
00390 g_source_remove(wlan_status.scan_id);
00391 wlan_status.scan_id = 0;
00392 }
00393 }
00399 static gboolean wlan_connect_timer_cb(void* data)
00400 {
00401 wlan_connect_timer_id = 0;
00402
00403 if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
00404
00405 DLOG_DEBUG("Association timeout, try: %d",
00406 wlan_status.retry_count);
00407
00408
00409 remove_from_roam_cache(wlan_status.conn.bssid);
00410
00411
00412 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
00413
00414 if (find_connection_and_associate(wlan_status.roam_cache, FALSE) == 0)
00415 return FALSE;
00416
00417
00418 if (++wlan_status.retry_count < WLANCOND_MAX_SCAN_TRIES) {
00419 if (scan(wlan_status.conn.ssid,
00420 wlan_status.conn.ssid_len, FALSE) == 0) {
00421 return FALSE;
00422 }
00423 }
00424
00425 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
00426 FORCE_YES);
00427 return FALSE;
00428 }
00429
00430
00431
00432 return FALSE;
00433 }
00439 static gboolean wlan_scan_cb(void* data)
00440 {
00441
00442 wlan_status.scan_id = 0;
00443
00444 DLOG_ERR("Scan failed, should not happen!");
00445
00446 if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
00447 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
00448 FORCE_YES);
00449 }
00450
00451 return FALSE;
00452 }
00458 static gboolean wlan_if_down_cb(void* data)
00459 {
00460
00461 wlan_if_down_timer_id = 0;
00462
00463 if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
00464 DLOG_DEBUG("Delayed shutdown occurred");
00465 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
00466 return FALSE;
00467 }
00468
00469
00470
00471 return FALSE;
00472 }
00480 int mlme_command(guchar* addr, guint16 cmd, guint16 reason_code)
00481 {
00482 struct iwreq req;
00483 struct iw_mlme mlme;
00484
00485 init_iwreq(&req);
00486
00487 DLOG_DEBUG("%s", cmd==IW_MLME_DEAUTH?"Deauthenticating":
00488 "Disassociating");
00489
00490 memset(&mlme, 0, sizeof(mlme));
00491
00492 mlme.cmd = cmd;
00493 mlme.reason_code = reason_code;
00494 mlme.addr.sa_family = ARPHRD_ETHER;
00495 memcpy(mlme.addr.sa_data, addr, ETH_ALEN);
00496
00497 req.u.data.pointer = (caddr_t) &mlme;
00498 req.u.data.length = sizeof(mlme);
00499
00500 if (ioctl(socket_open(), SIOCSIWMLME, &req) < 0) {
00501 DLOG_ERR("Failed to run MLME command");
00502 return -1;
00503 }
00504
00505 return 0;
00506 }
00510 static int set_mode(guint32 mode)
00511 {
00512 struct iwreq req;
00513
00514 init_iwreq(&req);
00515
00516 switch (mode) {
00517 case WLANCOND_ADHOC:
00518 req.u.mode = IW_MODE_ADHOC;
00519 DLOG_DEBUG("Setting mode: adhoc");
00520 break;
00521 case WLANCOND_INFRA:
00522 req.u.mode = IW_MODE_INFRA;
00523 DLOG_DEBUG("Setting mode: infra");
00524 break;
00525 default:
00526 DLOG_ERR("Operating mode undefined\n");
00527 return -1;
00528 }
00529
00530 if (ioctl(socket_open(), SIOCSIWMODE, &req) < 0) {
00531 DLOG_ERR("Operating mode setting failed\n");
00532 return -1;
00533 }
00534 return 0;
00535 }
00541 static int set_wep_keys(struct connect_params_t *conn)
00542 {
00543 struct iwreq req;
00544 guint nbr_of_keys = 0;
00545 int sock;
00546 guint i;
00547
00548 sock = socket_open();
00549
00550
00551 for (i=0;i<4;i++) {
00552 if(conn->key_len[i] == 0) {
00553 continue;
00554 } else {
00555 if (conn->key_len[i] < WLANCOND_MIN_KEY_LEN ||
00556 conn->key_len[i] > WLANCOND_MAX_KEY_LEN) {
00557 return -1;
00558 }
00559
00560 init_iwreq(&req);
00561 req.u.data.length = conn->key_len[i];
00562 req.u.data.pointer = (caddr_t) &conn->key[i][0];
00563 req.u.data.flags |= IW_ENCODE_RESTRICTED;
00564 req.u.encoding.flags = i+1;
00565 nbr_of_keys++;
00566 }
00567 #define DEBUG_KEY
00568 #ifdef DEBUG_KEY
00569 int k;
00570 unsigned char* p = &conn->key[i][0];
00571 for (k=0;k<conn->key_len[i];k++) {
00572 DLOG_DEBUG("Key %d, 0x%02x\n", i, *(p+k));
00573 }
00574 #endif
00575 if (ioctl(sock, SIOCSIWENCODE, &req) < 0) {
00576 DLOG_ERR("Set encode failed\n");
00577 return -1;
00578 }
00579
00580 }
00581
00582 if (nbr_of_keys) {
00583
00584 DLOG_DEBUG("Default key: %d\n", conn->default_key);
00585
00586 init_iwreq(&req);
00587
00588
00589 req.u.encoding.flags = conn->default_key;
00590
00591 if (ioctl(sock, SIOCSIWENCODE, &req) < 0) {
00592 DLOG_ERR("Set encode failed\n");
00593 return -1;
00594 }
00595 }
00596
00597 return 0;
00598 }
00599
00606 static int set_essid(char* essid, int essid_len)
00607 {
00608 struct iwreq req;
00609
00610 DLOG_DEBUG("Setting SSID: %s", essid);
00611
00612 init_iwreq(&req);
00613
00614 req.u.essid.pointer = (caddr_t)essid;
00615 req.u.essid.length = essid_len -1;
00616 req.u.essid.flags = 1;
00617
00618 if (ioctl(socket_open(), SIOCSIWESSID, &req) < 0) {
00619 DLOG_ERR("set ESSID failed");
00620 return -1;
00621 }
00622 return 0;
00623 }
00629 int set_bssid(unsigned char *bssid)
00630 {
00631 struct iwreq req;
00632
00633 print_mac("Setting BSSID", bssid);
00634
00635 init_iwreq(&req);
00636
00637 req.u.ap_addr.sa_family = ARPHRD_ETHER;
00638
00639 memcpy(req.u.ap_addr.sa_data, bssid, ETH_ALEN);
00640
00641 if (ioctl(socket_open(), SIOCSIWAP, &req) < 0) {
00642 DLOG_ERR("Failed to set BSSID");
00643 return -1;
00644 }
00645 return 0;
00646 }
00647
00654 void set_wlan_state(int new_state, int send_signal, force_t force)
00655 {
00656 char *status_table[] =
00657 {
00658 (char*)"WLAN_NOT_INITIALIZED",
00659 (char*)"WLAN_INITIALIZED",
00660 (char*)"WLAN_INITIALIZED_FOR_SCAN",
00661 (char*)"WLAN_INITIALIZED_FOR_CONNECTION",
00662 (char*)"WLAN_NO_ADDRESS",
00663 (char*)"WLAN_CONNECTED"
00664 };
00665
00666 switch (new_state) {
00667
00668 case WLAN_NOT_INITIALIZED:
00669
00670 if (wlan_status.state == WLAN_CONNECTED ||
00671 wlan_status.state == WLAN_NO_ADDRESS) {
00672
00673 mlme_command(wlan_status.conn.bssid,
00674 IW_MLME_DEAUTH,
00675 WLANCOND_REASON_LEAVING);
00676 set_bssid(NULL_BSSID);
00677 }
00678
00679 set_scan_state(SCAN_NOT_ACTIVE);
00680
00681 if (get_wlan_state() != WLAN_NOT_INITIALIZED &&
00682 get_wlan_state() != WLAN_INITIALIZED_FOR_SCAN)
00683 clear_wpa_mode();
00684
00685 wlan_status.retry_count = 0;
00686
00687
00688 remove_connect_timer();
00689
00690
00691 remove_scan_timer();
00692
00693 set_wlan_signal(WLANCOND_HIGH);
00694
00695
00696 remove_wlan_if_timer();
00697
00698 if (force == FORCE_YES) {
00699
00700 clean_roam_cache();
00701
00702 if (set_interface_state(socket_open(), CLEAR,
00703 IFF_UP)<0) {
00704 DLOG_ERR("Could not set interface down");
00705 return;
00706 }
00707
00708 } else {
00709
00710 DLOG_DEBUG("Delaying interface shutdown");
00711
00712
00713
00714
00715
00716 wlan_if_down_timer_id = g_timeout_add(
00717 WLANCOND_SHUTDOWN_DELAY,
00718 wlan_if_down_cb,
00719 NULL);
00720
00721 }
00722
00723 if (send_signal == DISCONNECTED_SIGNAL)
00724 disconnected_signal();
00725
00726 break;
00727 case WLAN_INITIALIZED_FOR_CONNECTION:
00728
00729
00730
00731
00732 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
00733 break;
00734 default:
00735 break;
00736 }
00737 DLOG_DEBUG("Wlancond state change, old_state: %s, new_state: %s",
00738 status_table[wlan_status.state], status_table[new_state]);
00739 wlan_status.state = new_state;
00740 }
00741
00746 guint get_wlan_state(void)
00747 {
00748 return wlan_status.state;
00749 }
00750
00755 void set_scan_state(guint new_state)
00756 {
00757 if (wlan_status.scan == new_state) {
00758 return;
00759 }
00760 if (new_state == SCAN_NOT_ACTIVE && wlan_status.scan == SCAN_ACTIVE &&
00761 scan_name_cache != NULL) {
00762 DLOG_DEBUG("Sending empty results");
00763 send_dbus_scan_results(NULL, scan_name_cache, 0);
00764 g_free(scan_name_cache);
00765 scan_name_cache = NULL;
00766 }
00767
00768 DLOG_DEBUG("Wlancond scan change, old_state: %s, new_state: %s",
00769 wlan_status.scan==SCAN_NOT_ACTIVE ? "SCAN_IDLE":"SCANNING",
00770 new_state == SCAN_NOT_ACTIVE ? "SCAN_IDLE":"SCANNING");
00771 wlan_status.scan = new_state;
00772 }
00773
00778 guint get_scan_state(void)
00779 {
00780 return wlan_status.scan;
00781 }
00786 guint get_mode(void)
00787 {
00788 return wlan_status.conn.mode;
00789 }
00790
00797 gboolean set_power_state(guint new_state, int sock)
00798 {
00799 #if 0
00800 struct iwreq req;
00801 gint sleep_timeout;
00802
00803 if (new_state == WLANCOND_SHORT_CAM && get_inactivity_status() == TRUE)
00804 new_state = WLANCOND_VERY_SHORT_CAM;
00805
00806 if (wlan_status.power == new_state) {
00807 return TRUE;
00808 }
00809
00810 init_iwreq(&req);
00811
00812 switch (new_state) {
00813 case WLANCOND_POWER_ON:
00814 req.u.power.disabled = 1;
00815 break;
00816 case WLANCOND_LONG_CAM:
00817 req.u.power.flags = IW_POWER_MULTICAST_R;
00818 req.u.power.value = WLANCOND_LONG_CAM_TIMEOUT;
00819 break;
00820 case WLANCOND_SHORT_CAM:
00821 req.u.power.flags = IW_POWER_MULTICAST_R;
00822 sleep_timeout = get_gconf_int(SLEEP_GCONF_PATH);
00823 if (sleep_timeout < 0)
00824 sleep_timeout = WLANCOND_DEFAULT_SLEEP_TIMEOUT;
00825 req.u.power.value = sleep_timeout;
00826 break;
00827 case WLANCOND_VERY_SHORT_CAM:
00828 req.u.power.flags = IW_POWER_MULTICAST_R;
00829 sleep_timeout = get_gconf_int(INACTIVE_SLEEP_GCONF_PATH);
00830 if (sleep_timeout < 0)
00831 sleep_timeout = WLANCOND_VERY_SHORT_CAM_TIMEOUT;
00832 req.u.power.value = sleep_timeout;
00833 break;
00834 default:
00835 req.u.power.flags = IW_POWER_ALL_R;
00836 break;
00837 }
00838
00839 if (ioctl(sock, SIOCSIWPOWER, &req) < 0) {
00840 DLOG_ERR("set power failed, state:%d", new_state);
00841 return FALSE;
00842 }
00843 #endif
00844
00845
00846 wlan_status.power = new_state;
00847
00848 return TRUE;
00849 }
00850
00851
00857 static int init_if(int sock)
00858 {
00859 int previous_state = get_wlan_state();
00860
00861 if (previous_state == WLAN_NOT_INITIALIZED) {
00862
00863 if (wlan_if_down_timer_id == 0) {
00864 if (set_interface_state(sock, SET,
00865 IFF_UP | IFF_RUNNING) < 0) {
00866 return -1;
00867 }
00868 }
00869 set_power_state(WLANCOND_POWER_ON, sock);
00870 set_wlan_state(WLAN_INITIALIZED, NO_SIGNAL, FORCE_YES);
00871 }
00872
00873 return previous_state;
00874 }
00875
00884 static int set_we_name(int sock, char *name, char *args[], int count)
00885 {
00886 struct iwreq req;
00887
00888 memset(&req, 0, sizeof(req));
00889 strncpy(req.ifr_name, name, IFNAMSIZ);
00890
00891 if (ioctl(sock, SIOCGIWNAME, &req) < 0) {
00892
00893 } else {
00894
00895 if (g_str_has_prefix(name, WLAN_PREFIX_STR)) {
00896 DLOG_DEBUG("Found WLAN interface %s", name);
00897 memcpy(&wlan_status.ifname, name, IFNAMSIZ);
00898 wlan_status.ifname[IFNAMSIZ] = '\0';
00899 }
00900 }
00901
00902 return 0;
00903 }
00909 int get_we_device_name(void)
00910 {
00911 memset(&wlan_status, 0, sizeof(wlan_status));
00912
00913 iw_enum_devices(socket_open(), &set_we_name, NULL, 0);
00914
00915 if (strnlen(wlan_status.ifname, IFNAMSIZ) < 2)
00916 return -1;
00917
00918 return 0;
00919 }
00927 int set_interface_state(int sock, int dir, short flags)
00928 {
00929 struct ifreq ifr;
00930
00931 memset(&ifr, 0, sizeof(ifr));
00932
00933 strncpy(ifr.ifr_name, wlan_status.ifname, IFNAMSIZ);
00934
00935 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
00936 DLOG_ERR("Could not get interface %s flags\n",
00937 wlan_status.ifname);
00938 return -1;
00939 }
00940 if (dir == SET) {
00941 ifr.ifr_flags |= flags;
00942 } else {
00943 ifr.ifr_flags &= ~flags;
00944 }
00945
00946 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
00947 DLOG_ERR("Could not set interface %s flags\n",
00948 wlan_status.ifname);
00949 return -1;
00950 }
00951
00952 DLOG_DEBUG("%s is %s", wlan_status.ifname, dir == SET ? "UP":"DOWN");
00953
00954 return 0;
00955 }
00956
00963 static gboolean set_tx_power(guint power, int sock)
00964 {
00965 struct iwreq req;
00966 init_iwreq(&req);
00967
00968 req.u.txpower.fixed = 1;
00969 req.u.txpower.disabled = 0;
00970 req.u.txpower.flags = IW_TXPOW_DBM;
00971
00972 if (power == WLANCOND_TX_POWER10) {
00973 req.u.txpower.value = WLANCOND_TX_POWER10DBM;
00974 } else if (power == WLANCOND_TX_POWER100) {
00975 req.u.txpower.value = WLANCOND_TX_POWER100DBM;
00976 } else {
00977 return FALSE;
00978 }
00979
00980 if (ioctl(sock, SIOCSIWTXPOW, &req) < 0) {
00981 DLOG_ERR("set power failed\n");
00982 return FALSE;
00983 }
00984 return TRUE;
00985
00986 }
00992 static int update_algorithms(guint32 encryption)
00993 {
00994 wlan_status.group_cipher = 0;
00995 wlan_status.pairwise_cipher = 0;
00996
00997
00998 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_OPEN) {
00999 DLOG_DEBUG("Open mode");
01000 wlan_status.pairwise_cipher = CIPHER_SUITE_NONE;
01001 return 0;
01002 }
01003
01004
01005 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP) {
01006 DLOG_DEBUG("WEP enabled");
01007 wlan_status.pairwise_cipher = CIPHER_SUITE_WEP40;
01008 return 0;
01009 }
01010
01011
01012 if ((encryption & WLANCOND_ENCRYPT_ALG_MASK)
01013 == WLANCOND_WPA_TKIP) {
01014 DLOG_DEBUG("TKIP Selected for unicast");
01015 wlan_status.pairwise_cipher = CIPHER_SUITE_TKIP;
01016 } else if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) ==
01017 WLANCOND_WPA_AES) {
01018 DLOG_DEBUG("AES selected for unicast");
01019 wlan_status.pairwise_cipher = CIPHER_SUITE_CCMP;
01020
01021 } else {
01022 DLOG_ERR("Not supported encryption %08x", encryption);
01023 return -1;
01024 }
01025
01026 if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
01027 WLANCOND_WPA_TKIP_GROUP) {
01028 DLOG_DEBUG("TKIP Selected for multicast");
01029 wlan_status.group_cipher = CIPHER_SUITE_TKIP;
01030 } else if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) ==
01031 (unsigned int)WLANCOND_WPA_AES_GROUP) {
01032 DLOG_DEBUG("AES Selected for multicast");
01033 wlan_status.group_cipher = CIPHER_SUITE_CCMP;
01034 } else {
01035 DLOG_ERR("Not supported encryption %08x", encryption);
01036 return -1;
01037 }
01038
01039 return 0;
01040 }
01044 void clean_roam_cache(void)
01045 {
01046 clean_scan_results(&wlan_status.roam_cache);
01047 }
01051 void clear_wpa_mode(void)
01052 {
01053 g_free(wlan_status.wpa_ie.ie);
01054 wlan_status.wpa_ie.ie_len = 0;
01055 wlan_status.wpa_ie.ie = NULL;
01056
01057 wlan_status.pairwise_cipher = CIPHER_SUITE_NONE;
01058 wlan_status.group_cipher = CIPHER_SUITE_NONE;
01059
01060
01061 clear_wpa_keys(NULL);
01062
01063 g_slist_foreach(wlan_status.pmk_cache, (GFunc)g_free, NULL);
01064 g_slist_free(wlan_status.pmk_cache);
01065 wlan_status.pmk_cache = NULL;
01066 }
01071 gboolean get_wpa_mode(void)
01072 {
01073 if (wlan_status.pairwise_cipher & CIPHER_SUITE_TKIP ||
01074 wlan_status.pairwise_cipher & CIPHER_SUITE_CCMP) {
01075 return TRUE;
01076 }
01077 return FALSE;
01078 }
01079
01080 static gint compare_pmk_entry(gconstpointer a, gconstpointer b)
01081 {
01082 struct pmksa_cache_t *pmk_cache = (struct pmksa_cache_t*)a;
01083
01084 return memcmp(pmk_cache->mac, b, ETH_ALEN);
01085 }
01086
01092 static void add_to_pmksa_cache(unsigned char* pmkid, unsigned char* mac)
01093 {
01094 guint i = 0;
01095 GSList *list;
01096 gboolean entry_found = FALSE;
01097
01098 for (list = wlan_status.pmk_cache; list != NULL && entry_found == FALSE; list = list->next) {
01099 struct pmksa_cache_t *pmk_cache = (struct pmksa_cache_t*)list->data;
01100
01101 if (memcmp(pmk_cache->mac, mac, ETH_ALEN) == 0) {
01102 DLOG_DEBUG("Found old entry: %i", i);
01103
01104 wlan_status.pmk_cache = g_slist_remove(wlan_status.pmk_cache, pmk_cache);
01105 g_free(pmk_cache);
01106
01107 entry_found = TRUE;
01108 } else {
01109 i++;
01110 }
01111 }
01112
01113 if (i == PMK_CACHE_SIZE) {
01114 DLOG_DEBUG("Cache full, remove oldest");
01115 GSList *last_entry = g_slist_last(wlan_status.pmk_cache);
01116 wlan_status.pmk_cache = g_slist_remove(wlan_status.pmk_cache, last_entry->data);
01117 g_free(last_entry->data);
01118 }
01119 print_mac("Adding new entry:", mac);
01120
01121 struct pmksa_cache_t *new_entry = g_malloc(sizeof(*new_entry));
01122 memcpy(new_entry->mac, mac, ETH_ALEN);
01123 memcpy(new_entry->pmkid, pmkid, IW_PMKID_LEN);
01124
01125 wlan_status.pmk_cache = g_slist_prepend(wlan_status.pmk_cache, new_entry);
01126 return;
01127 }
01133 unsigned char* find_pmkid_from_pmk_cache(unsigned char* mac)
01134 {
01135 GSList *list;
01136
01137 list = g_slist_find_custom(wlan_status.pmk_cache, mac, &compare_pmk_entry);
01138 if (list != NULL) {
01139 struct pmksa_cache_t *pmk_cache = (struct pmksa_cache_t*)list->data;
01140 print_mac("Found PMKSA entry for:", mac);
01141 return pmk_cache->pmkid;
01142 }
01143 return NULL;
01144 }
01145
01152 int scan(gchar *ssid, int ssid_len, gboolean add_timer)
01153 {
01154 struct iwreq req;
01155 struct iw_scan_req scan_req;
01156
01157 if (get_scan_state() == SCAN_ACTIVE)
01158 return 0;
01159
01160 set_scan_state(SCAN_ACTIVE);
01161
01162 init_iwreq(&req);
01163
01164 memset(&scan_req, 0, sizeof(scan_req));
01165
01166 if (ssid_len > 1 && ssid != NULL) {
01167 scan_req.essid_len = ssid_len -1;
01168 scan_req.bssid.sa_family = ARPHRD_ETHER;
01169 memset(scan_req.bssid.sa_data, 0xff, ETH_ALEN);
01170 memcpy(scan_req.essid, ssid, ssid_len -1);
01171 req.u.data.pointer = (caddr_t) &scan_req;
01172 req.u.data.length = sizeof(scan_req);
01173 req.u.data.flags = IW_SCAN_THIS_ESSID;
01174 }
01175
01176 if (ioctl(socket_open(), SIOCSIWSCAN, &req) < 0) {
01177 DLOG_ERR("Scan failed");
01178 return -1;
01179 }
01180
01181 if (add_timer == TRUE) {
01182 wlan_status.scan_id = g_timeout_add(
01183 WLANCOND_SCAN_TIMEOUT,
01184 wlan_scan_cb,
01185 NULL);
01186 }
01187
01188 DLOG_DEBUG("Scan issued");
01189
01190 return 0;
01191 }
01197 static int set_freq(int channel)
01198 {
01199 struct iwreq req;
01200
01201 DLOG_DEBUG("Setting channel: %d", channel);
01202
01203 init_iwreq(&req);
01204
01205 req.u.freq.m = channel;
01206
01207 if (ioctl(socket_open(), SIOCSIWFREQ, &req) < 0) {
01208 DLOG_ERR("Freq failed");
01209 return -1;
01210 }
01211
01212 return 0;
01213 }
01214 static void init_conn_params(struct connect_params_t *conn_params)
01215 {
01216 memset(conn_params, 0, sizeof(*conn_params));
01217 }
01222 void clear_wpa_keys(unsigned char* bssid)
01223 {
01224 struct iwreq req;
01225 struct iw_encode_ext ext;
01226 int sock;
01227 guint i;
01228
01229 init_iwreq(&req);
01230
01231 sock = socket_open();
01232
01233 for (i=0;i<4;i++) {
01234
01235 memset(&ext, 0, sizeof(ext));
01236
01237 req.u.encoding.flags = i + 1;
01238 req.u.encoding.flags |= IW_ENCODE_DISABLED;
01239 req.u.encoding.pointer = (caddr_t) &ext;
01240 req.u.encoding.length = sizeof(ext);
01241
01242 ext.ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
01243 ext.addr.sa_family = ARPHRD_ETHER;
01244
01245 memset(ext.addr.sa_data, 0xff, ETH_ALEN);
01246 ext.alg = IW_ENCODE_ALG_NONE;
01247
01248 if (ioctl(sock, SIOCSIWENCODEEXT, &req) < 0) {
01249 DLOG_ERR("Key clearing failed");
01250 }
01251 }
01252 if (bssid != NULL) {
01253
01254 memset(&ext, 0, sizeof(ext));
01255
01256 req.u.encoding.flags = 1;
01257 req.u.encoding.flags |= IW_ENCODE_DISABLED;
01258 req.u.encoding.pointer = (caddr_t) &ext;
01259 req.u.encoding.length = sizeof(ext);
01260
01261 ext.addr.sa_family = ARPHRD_ETHER;
01262
01263 memcpy(ext.addr.sa_data, bssid, ETH_ALEN);
01264 ext.alg = IW_ENCODE_ALG_NONE;
01265
01266 if (ioctl(sock, SIOCSIWENCODEEXT, &req) < 0) {
01267 DLOG_ERR("Key clearing failed");
01268 }
01269 }
01270
01271 return;
01272 }
01280 static int check_connect_arguments(struct connect_params_t *conn, char* ssid,
01281 unsigned char** key)
01282 {
01283 guint i;
01284
01285 if (conn->flags & WLANCOND_DISABLE_POWERSAVE) {
01286 DLOG_DEBUG("Powersave disabled");
01287 powersave = WLANCOND_POWER_ON;
01288 } else if (conn->flags & WLANCOND_MINIMUM_POWERSAVE) {
01289 DLOG_DEBUG("Powersave minimum");
01290 powersave = WLANCOND_LONG_CAM;
01291 } else if (conn->flags & WLANCOND_MAXIMUM_POWERSAVE) {
01292 DLOG_DEBUG("Powersave maximum");
01293 powersave = WLANCOND_SHORT_CAM;
01294 } else {
01295 powersave = WLANCOND_SHORT_CAM;
01296 }
01297
01298 if (conn->power_level != WLANCOND_TX_POWER10 &&
01299 conn->power_level != WLANCOND_TX_POWER100) {
01300 DLOG_ERR("Invalid power level");
01301 return -1;
01302 }
01303
01304 switch (conn->mode) {
01305 case WLANCOND_ADHOC:
01306 case WLANCOND_INFRA:
01307 break;
01308 default:
01309 DLOG_ERR("Operating mode undefined\n");
01310 return -1;
01311 }
01312
01313 guint32 wpa2_mode = conn->encryption & WLANCOND_ENCRYPT_WPA2_MASK;
01314
01315 DLOG_DEBUG("Encryption setting: %08x", conn->encryption);
01316
01317 switch (conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) {
01318 case WLANCOND_OPEN:
01319 break;
01320 case WLANCOND_WEP:
01321 break;
01322 case WLANCOND_WPA_PSK:
01323 DLOG_DEBUG("%s PSK selected", wpa2_mode!=0?"WPA2":"WPA");
01324 if (wpa2_mode != 0)
01325 conn->authentication_type = EAP_AUTH_TYPE_WPA2_PSK;
01326 else
01327 conn->authentication_type = EAP_AUTH_TYPE_WPA_PSK;
01328 break;
01329 case WLANCOND_WPA_EAP:
01330 DLOG_DEBUG("%s EAP selected", wpa2_mode!=0?"WPA2":"WPA");
01331 if (wpa2_mode != 0)
01332 conn->authentication_type = EAP_AUTH_TYPE_WPA2_EAP;
01333 else
01334 conn->authentication_type = EAP_AUTH_TYPE_WPA_EAP;
01335 break;
01336 default:
01337 DLOG_DEBUG("Unsupported encryption mode");
01338 return -1;
01339 }
01340 if ((conn->encryption & WLANCOND_WPS_MASK) != 0) {
01341 DLOG_DEBUG("WPS selected");
01342 conn->authentication_type = EAP_AUTH_TYPE_WFA_SC;
01343 }
01344
01345 if (!ssid || conn->ssid_len == 0 ||
01346 conn->ssid_len > WLANCOND_MAX_SSID_SIZE + 1) {
01347 DLOG_DEBUG("Invalid SSID");
01348 return -1;
01349 }
01350 for (i=0;i<4;i++) {
01351 if (conn->key_len[i] != 0) {
01352 DLOG_DEBUG("Found key %d", i);
01353 memcpy(&conn->key[i][0], key[i], conn->key_len[i]);
01354 }
01355 }
01356 return 0;
01357 }
01358
01365 static DBusHandlerResult settings_and_connect_request(
01366 DBusMessage *message,
01367 DBusConnection *connection) {
01368
01369 DBusMessage *reply = NULL;
01370 DBusError derror;
01371 struct connect_params_t *conn;
01372 char *ssid;
01373 unsigned char* key[4];
01374 dbus_int32_t old_mode;
01375
01376 dbus_error_init(&derror);
01377
01378 if (in_flight_mode()) {
01379 reply = new_dbus_error(message, WLANCOND_ERROR_WLAN_DISABLED);
01380 send_and_unref(connection, reply);
01381 return DBUS_HANDLER_RESULT_HANDLED;
01382 }
01383
01384 remove_connect_timer();
01385 remove_wlan_if_timer();
01386
01387 conn = &wlan_status.conn;
01388
01389 old_mode = conn->mode;
01390 init_conn_params(conn);
01391
01392 if (dbus_message_get_args(
01393 message, NULL,
01394 DBUS_TYPE_INT32, &conn->power_level,
01395 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid, &conn->ssid_len,
01396 DBUS_TYPE_INT32, &conn->mode,
01397 DBUS_TYPE_INT32, &conn->encryption,
01398 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[0], &conn->key_len[0],
01399 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[1], &conn->key_len[1],
01400 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[2], &conn->key_len[2],
01401 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[3], &conn->key_len[3],
01402 DBUS_TYPE_INT32, &conn->default_key,
01403 DBUS_TYPE_UINT32, &conn->adhoc_channel,
01404 DBUS_TYPE_UINT32, &conn->flags,
01405 DBUS_TYPE_INVALID) == FALSE)
01406 {
01407
01408 if (dbus_message_get_args(
01409 message, &derror,
01410 DBUS_TYPE_INT32, &conn->power_level,
01411 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid,
01412 &conn->ssid_len,
01413 DBUS_TYPE_INT32, &conn->mode,
01414 DBUS_TYPE_INT32, &conn->encryption,
01415 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
01416 &key[0], &conn->key_len[0],
01417 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
01418 &key[1], &conn->key_len[1],
01419 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
01420 &key[2], &conn->key_len[2],
01421 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
01422 &key[3], &conn->key_len[3],
01423 DBUS_TYPE_INT32, &conn->default_key,
01424 DBUS_TYPE_UINT32, &conn->adhoc_channel,
01425 DBUS_TYPE_INVALID) == FALSE) {
01426
01427 DLOG_ERR("Failed to parse setting_and_connect: %s",
01428 derror.message);
01429 dbus_error_free(&derror);
01430 goto param_err;
01431 }
01432 }
01433
01434 if (check_connect_arguments(conn, ssid, key) < 0)
01435 goto param_err;
01436
01437
01438 if (old_mode != conn->mode) {
01439 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
01440 }
01441
01442
01443 if (set_mode(conn->mode) < 0) {
01444 goto param_err;
01445 }
01446
01447 if (init_if(socket_open()) < 0) {
01448 reply = new_dbus_error(message, WLANCOND_ERROR_INIT_FAILED);
01449 goto param_err;
01450 }
01451
01452 set_power_state(WLANCOND_POWER_ON, socket_open());
01453
01454 if (set_tx_power(conn->power_level, socket_open()) != TRUE) {
01455 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
01456 goto param_err;
01457 }
01458
01459 memcpy(conn->ssid, ssid, conn->ssid_len);
01460
01461 set_scan_state(SCAN_NOT_ACTIVE);
01462 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL, FORCE_NO);
01463
01464
01465 if (find_connection_and_associate(wlan_status.roam_cache, FALSE) != 0) {
01466
01467 DLOG_DEBUG("Checking mac80211 cache...");
01468
01469 GSList *scan_results = NULL;
01470 scan_results_ioctl(0, &scan_results);
01471
01472 if (find_connection_and_associate(scan_results, TRUE) != 0) {
01473 clean_scan_results(&scan_results);
01474 if (scan(conn->ssid, conn->ssid_len, TRUE) < 0) {
01475 goto param_err;
01476 }
01477 } else {
01478 clean_scan_results(&scan_results);
01479 }
01480 }
01481
01482 g_free(connect_name_cache);
01483 connect_name_cache = g_strdup(dbus_message_get_sender(message));
01484
01485 reply = new_dbus_method_return(message);
01486
01487 gchar* ifname = wlan_status.ifname;
01488
01489 append_dbus_args(reply,
01490 DBUS_TYPE_STRING, &ifname,
01491 DBUS_TYPE_INVALID);
01492
01493 send_and_unref(connection, reply);
01494
01495 return DBUS_HANDLER_RESULT_HANDLED;
01496
01497 param_err:
01498 if (reply == NULL) {
01499 DLOG_DEBUG("Parameter error in settings_and_connect\n");
01500 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
01501 }
01502 send_and_unref(connection, reply);
01503 return DBUS_HANDLER_RESULT_HANDLED;
01504 }
01510 int associate(struct scan_results_t *scan_results)
01511 {
01512 struct connect_params_t *conn = &wlan_status.conn;
01513
01514 DLOG_DEBUG("Starting associate...");
01515
01516 if (memcmp(conn->bssid, "\0\0\0\0\0\0", ETH_ALEN)) {
01517 clear_wpa_keys(conn->bssid);
01518 }
01519
01520 if (update_algorithms(conn->encryption) < 0) {
01521 return -1;
01522 }
01523
01524
01525 if ((conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP){
01526 if (set_wep_keys(conn) < 0) {
01527 return -1;
01528 }
01529 }
01530
01531 memcpy(conn->bssid, scan_results->bssid, ETH_ALEN);
01532
01533 if (set_encryption_method(conn->encryption, &wlan_status) == FALSE) {
01534 return -1;
01535 }
01536
01537 if (get_wpa_mode() == TRUE ||
01538 conn->authentication_type == EAP_AUTH_TYPE_WFA_SC) {
01539
01540
01541 if (wpa_ie_push(scan_results->bssid,
01542 scan_results->wpa_ie,
01543 scan_results->wpa_ie_len,
01544 scan_results->ssid,
01545 scan_results->ssid_len -1,
01546 conn->authentication_type) < 0)
01547 return -1;
01548 }
01549
01550
01551
01552 if (conn->adhoc_channel != 0 && (conn->mode & WLANCOND_ADHOC)) {
01553 if (conn->adhoc_channel < WLANCOND_MIN_WLAN_CHANNEL ||
01554 conn->adhoc_channel > WLANCOND_MAX_WLAN_CHANNEL) {
01555 DLOG_ERR("Invalid ad-hoc channel: %d",
01556 conn->adhoc_channel);
01557 return -1;
01558 }
01559
01560 scan_results->channel = conn->adhoc_channel;
01561 }
01562
01563 set_freq(scan_results->channel);
01564
01565
01566 if (set_essid(conn->ssid, conn->ssid_len) < 0) {
01567 return -1;
01568 }
01569
01570
01571 if (memcmp(scan_results->bssid, "\0\0\0\0\0\0", ETH_ALEN)) {
01572 if (set_bssid(scan_results->bssid) < 0) {
01573 return -1;
01574 }
01575 }
01576
01577
01578 if (conn->mode == WLANCOND_INFRA) {
01579 wlan_connect_timer_id = g_timeout_add(
01580 WLANCOND_CONNECT_TIMEOUT,
01581 wlan_connect_timer_cb, NULL);
01582 }
01583
01584 return 0;
01585 }
01586
01593 static DBusHandlerResult scan_request(DBusMessage *message,
01594 DBusConnection *connection) {
01595
01596 DBusMessage *reply = NULL;
01597 DBusMessageIter iter, array_iter;
01598 char *ssid;
01599 const char* sender;
01600 dbus_int32_t power_level;
01601 dbus_int32_t flags;
01602 guint previous_state = 0;
01603
01604 if (in_flight_mode()) {
01605 reply = new_dbus_error(message, WLANCOND_ERROR_WLAN_DISABLED);
01606 send_and_unref(connection, reply);
01607 return DBUS_HANDLER_RESULT_HANDLED;
01608 }
01609
01610 sender = dbus_message_get_sender(message);
01611 if (sender == NULL) {
01612 goto param_err;
01613 }
01614
01615 DLOG_DEBUG("Got scan request from %s", sender);
01616
01617 if (get_scan_state() == SCAN_ACTIVE) {
01618 reply = new_dbus_error(message, WLANCOND_ERROR_ALREADY_ACTIVE);
01619 send_and_unref(connection, reply);
01620 return DBUS_HANDLER_RESULT_HANDLED;
01621 }
01622
01623 if ((previous_state = init_if(socket_open())) < 0) {
01624 reply = new_dbus_error(message, WLANCOND_ERROR_INIT_FAILED);
01625 goto param_err;
01626 }
01627 if (previous_state == WLAN_NOT_INITIALIZED) {
01628 set_wlan_state(WLAN_INITIALIZED_FOR_SCAN, NO_SIGNAL, FORCE_NO);
01629 }
01630
01631 dbus_message_iter_init(message, &iter);
01632
01633 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
01634 goto param_err;
01635 dbus_message_iter_get_basic(&iter, &power_level);
01636
01637 dbus_message_iter_next(&iter);
01638
01639 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
01640 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
01641 goto param_err;
01642 dbus_message_iter_recurse(&iter, &array_iter);
01643 dbus_message_iter_get_fixed_array(&array_iter, &ssid,
01644 &wlan_status.scan_ssid_len);
01645 dbus_message_iter_next(&iter);
01646
01647 power_down_after_scan = FALSE;
01648
01649 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32) {
01650 dbus_message_iter_get_basic(&iter, &flags);
01651 DLOG_DEBUG("Found flags: %08x", flags);
01652
01653 if (flags & WLANCOND_NO_DELAYED_SHUTDOWN)
01654 power_down_after_scan = TRUE;
01655 }
01656
01657 if (power_level != WLANCOND_TX_POWER10 &&
01658 power_level != WLANCOND_TX_POWER100) {
01659 DLOG_ERR("Invalid power level");
01660 goto param_err;
01661 }
01662
01663 if (set_tx_power(power_level, socket_open()) != TRUE) {
01664 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
01665 goto param_err;
01666 }
01667
01668 if (ssid != NULL && wlan_status.scan_ssid_len > 1 &&
01669 wlan_status.scan_ssid_len < WLANCOND_MAX_SSID_SIZE +1) {
01670 memcpy(wlan_status.scan_ssid, ssid, wlan_status.scan_ssid_len);
01671 }
01672
01673 if (scan(wlan_status.scan_ssid, wlan_status.scan_ssid_len, FALSE) < 0) {
01674 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
01675 goto param_err;
01676 }
01677
01678 g_free(scan_name_cache);
01679 scan_name_cache = g_strdup(sender);
01680
01681 reply = new_dbus_method_return(message);
01682 send_and_unref(connection, reply);
01683
01684 return DBUS_HANDLER_RESULT_HANDLED;
01685
01686 param_err:
01687 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
01688 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
01689 }
01690 if (reply == NULL) {
01691 DLOG_DEBUG("Parameter error in scan request");
01692 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
01693 }
01694 send_and_unref(connection, reply);
01695 return DBUS_HANDLER_RESULT_HANDLED;
01696 }
01703 static int network_compare(gconstpointer a, gconstpointer b)
01704 {
01705 struct scan_results_t *results_a = (struct scan_results_t*)a;
01706 struct scan_results_t *results_b = (struct scan_results_t*)b;
01707
01708 if (wlan_status.scan_ssid_len > 1) {
01709
01710
01711
01712 gint a_eq = strncmp(wlan_status.scan_ssid, results_a->ssid, WLANCOND_MAX_SSID_SIZE);
01713 gint b_eq = strncmp(wlan_status.scan_ssid, results_b->ssid, WLANCOND_MAX_SSID_SIZE);
01714
01715 if (!a_eq && !b_eq) {
01716
01717 return 0;
01718 }
01719
01720 if (!a_eq && b_eq) {
01721
01722 return -1;
01723 }
01724
01725 if (a_eq && !b_eq) {
01726
01727
01728 return 1;
01729 }
01730
01731 }
01732
01733
01734 return (results_a->rssi > results_b->rssi) ? -1 : (results_a->rssi < results_b->rssi) ? 1 : 0;
01735 }
01736
01737 static gint compare_scan_entry(gconstpointer a, gconstpointer b)
01738 {
01739 struct scan_results_t *scan_entry = (struct scan_results_t*)a;
01740 return memcmp(scan_entry->bssid, b, ETH_ALEN);
01741 }
01746 static void add_to_roam_cache(struct scan_results_t *scan_results)
01747 {
01748 GSList *list;
01749
01750 list = g_slist_find_custom(wlan_status.roam_cache, scan_results->bssid,
01751 &compare_scan_entry);
01752
01753 if (list != NULL) {
01754 struct scan_results_t *roam_cache_entry = (struct scan_results_t*)list->data;
01755 print_mac("Found old entry for:", scan_results->bssid);
01756
01757
01758 wlan_status.roam_cache = g_slist_remove(
01759 wlan_status.roam_cache, roam_cache_entry);
01760
01761 clean_scan_results_item(roam_cache_entry, NULL);
01762 }
01763
01764 print_mac("New AP to roam cache:", scan_results->bssid);
01765
01766 struct scan_results_t *results_to_list = g_slice_dup(struct scan_results_t, scan_results);
01767 results_to_list->wpa_ie = g_memdup(scan_results->wpa_ie,
01768 scan_results->wpa_ie_len);
01769 wlan_status.roam_cache = g_slist_prepend(wlan_status.roam_cache,
01770 results_to_list);
01771
01772 return;
01773 }
01779 gboolean remove_from_roam_cache(unsigned char *bssid)
01780 {
01781 GSList *list;
01782
01783 list = g_slist_find_custom(wlan_status.roam_cache, bssid,
01784 &compare_scan_entry);
01785
01786 if (list != NULL) {
01787 struct scan_results_t *roam_cache_entry = (struct scan_results_t*)list->data;
01788 print_mac("Found entry to be removed:", bssid);
01789
01790 wlan_status.roam_cache = g_slist_remove(
01791 wlan_status.roam_cache, roam_cache_entry);
01792
01793 clean_scan_results_item(roam_cache_entry, NULL);
01794
01795 return TRUE;
01796 }
01797
01798 return FALSE;
01799 }
01800
01806 gboolean decrease_signal_in_roam_cache(unsigned char *bssid)
01807 {
01808 GSList *list;
01809
01810 list = g_slist_find_custom(wlan_status.roam_cache, bssid,
01811 &compare_scan_entry);
01812
01813 if (list != NULL) {
01814 struct scan_results_t *roam_cache_entry = (struct scan_results_t*)list->data;
01815 print_mac("Found entry to be decreased:", bssid);
01816
01817 roam_cache_entry->rssi -= WLANCOND_RSSI_PENALTY;
01818
01819 return TRUE;
01820 }
01821
01822 return FALSE;
01823 }
01830 static int check_group_cipher(guint32 c1, guint32 c2)
01831 {
01832 guint32 m1 = (c1 & WLANCOND_ENCRYPT_GROUP_ALG_MASK);
01833 guint32 m2 = (c2 & WLANCOND_ENCRYPT_GROUP_ALG_MASK);
01834
01835 if (m1 == m2)
01836 return 1;
01837 if (m2 == WLANCOND_WPA_TKIP_GROUP && (m1 & WLANCOND_WPA_TKIP_GROUP))
01838 return 1;
01839 if (m2 == (unsigned int)WLANCOND_WPA_AES_GROUP &&
01840 (m1 & WLANCOND_WPA_AES_GROUP))
01841 return 1;
01842
01843 DLOG_DEBUG("Group ciphers don't match");
01844
01845 return -1;
01846 }
01853 static int check_ciphers(guint32 c1, guint32 c2)
01854 {
01855 guint32 u1 = (c1 & WLANCOND_ENCRYPT_ALG_MASK);
01856 guint32 u2 = (c2 & WLANCOND_ENCRYPT_ALG_MASK);
01857
01858 if (check_group_cipher(c1, c2) < 0)
01859 return -1;
01860
01861 if (u1 == u2)
01862 return 1;
01863 if (u2 == WLANCOND_WPA_TKIP && (u1 & WLANCOND_WPA_TKIP))
01864 return 1;
01865 if (u2 == WLANCOND_WPA_AES && (u1 & WLANCOND_WPA_AES))
01866 return 1;
01867
01868 DLOG_DEBUG("Unicast ciphers don't match");
01869
01870 return -1;
01871 }
01872 static gboolean wlan_roam_scan_cb(void* data)
01873 {
01874 wlan_status.roam_scan_id = 0;
01875
01876 if (wlan_status.signal == WLANCOND_LOW &&
01877 get_wlan_state() == WLAN_CONNECTED) {
01878
01879 DLOG_DEBUG("Roam scan timeout, initiating new scan");
01880
01881
01882 scan(wlan_status.conn.ssid, wlan_status.conn.ssid_len, FALSE);
01883 }
01884
01885 return FALSE;
01886 }
01890 static void reschedule_scan(void)
01891 {
01892
01893
01894
01895
01896 if (get_inactivity_status() == TRUE) {
01897 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
01898 } else {
01899 if (wlan_status.roam_scan <= WLANCOND_MIN_ROAM_SCAN_INTERVAL) {
01900 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
01901 } else if (wlan_status.roam_scan >= WLANCOND_MAX_ROAM_SCAN_INTERVAL) {
01902 wlan_status.roam_scan = WLANCOND_MAX_ROAM_SCAN_INTERVAL;
01903 } else {
01904 wlan_status.roam_scan = wlan_status.roam_scan * 2;
01905 }
01906 }
01907
01908 wlan_status.roam_scan_id = g_timeout_add(
01909 wlan_status.roam_scan,
01910 wlan_roam_scan_cb,
01911 NULL);
01912 }
01919 static gboolean check_capabilities(struct scan_results_t *scan_results,
01920 struct connect_params_t *conn)
01921 {
01922
01923 if ((scan_results->cap_bits & WLANCOND_MODE_MASK) != (guint32)conn->mode)
01924 return FALSE;
01925 if ((scan_results->cap_bits & WLANCOND_ENCRYPT_METHOD_MASK) != (guint32)(conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK))
01926 return FALSE;
01927 if ((scan_results->cap_bits & WLANCOND_ENCRYPT_WPA2_MASK) != (guint32)(conn->encryption & WLANCOND_ENCRYPT_WPA2_MASK))
01928 return FALSE;
01929 if (check_ciphers(scan_results->cap_bits, conn->encryption) < 0)
01930 return FALSE;
01931
01932 return TRUE;
01933 }
01934
01942 struct scan_results_t* find_connection(
01943 GSList* ap_list, struct connect_params_t *conn,
01944 gboolean update_roam_cache)
01945 {
01946 GSList *list;
01947 struct scan_results_t *best_connection = NULL;
01948 gint current_rssi = 0;
01949
01950
01951 if (update_roam_cache == TRUE)
01952 clean_roam_cache();
01953
01954 for (list = ap_list; list != NULL; list = list->next) {
01955 struct scan_results_t *scan_results = (struct scan_results_t*)list->data;
01956 if (memcmp(scan_results->ssid, conn->ssid, scan_results->ssid_len) == 0) {
01957 print_mac("Found AP:", scan_results->bssid);
01958
01959
01960 if (memcmp(scan_results->bssid, wlan_status.conn.bssid,
01961 ETH_ALEN) == 0) {
01962 current_rssi = scan_results->rssi;
01963 DLOG_DEBUG("Current AP: %d", current_rssi);
01964 }
01965
01966 if (check_capabilities(scan_results, conn) ==
01967 FALSE)
01968 continue;
01969
01970 if (is_ap_in_black_list(scan_results->bssid) == TRUE) {
01971 DLOG_DEBUG("AP is in black list, discarded");
01972 continue;
01973 }
01974
01975
01976
01977
01978 if (update_roam_cache == TRUE) {
01979 add_to_roam_cache(scan_results);
01980 }
01981
01982 if (best_connection == NULL ||
01983 best_connection->rssi < scan_results->rssi) {
01984 DLOG_DEBUG("Best connection: %d (old %d)",
01985 scan_results->rssi,
01986 best_connection == NULL ?
01987 WLANCOND_MINIMUM_SIGNAL:
01988 best_connection->rssi);
01989 best_connection = scan_results;
01990 }
01991 }
01992 }
01993
01994
01995 if (best_connection == NULL)
01996 return NULL;
01997
01998
01999
02000
02001 if (current_rssi != 0) {
02002 if (best_connection->rssi < current_rssi +
02003 WLANCOND_ROAM_THRESHOLD) {
02004 DLOG_DEBUG("Best connection not good enough");
02005 return NULL;
02006 }
02007 }
02008
02009
02010 if (best_connection->rssi < WLANCOND_MINIMUM_SIGNAL)
02011 return NULL;
02012
02013 return best_connection;
02014 }
02015
02021 int find_connection_and_associate(GSList *scan_results, gboolean update_roam_cache)
02022 {
02023 struct scan_results_t adhoc;
02024 struct connect_params_t *conn = &wlan_status.conn;
02025
02026 struct scan_results_t *connection = find_connection(
02027 scan_results, &wlan_status.conn, update_roam_cache);
02028
02029 if (connection == NULL && conn->mode == WLANCOND_ADHOC) {
02030 DLOG_DEBUG("No existing adhoc connection");
02031 memset(&adhoc, 0, sizeof(adhoc));
02032 connection = &adhoc;
02033 memcpy(connection->ssid, conn->ssid, conn->ssid_len);
02034 }
02035
02036 if (connection) {
02037 int ret = associate(connection);
02038 if (ret < 0)
02039 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
02040 return ret;
02041 }
02042 return -1;
02043 }
02044
02049 static void connect_from_scan_results(GSList *scan_results)
02050 {
02051 int status = find_connection_and_associate(scan_results, TRUE);
02052
02053 clean_scan_results(&scan_results);
02054
02055 if (status == 0)
02056 return;
02057
02058 DLOG_DEBUG("Could not find suitable network");
02059
02060 if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
02061 set_wlan_state(WLAN_NOT_INITIALIZED,
02062 DISCONNECTED_SIGNAL, FORCE_YES);
02063 return;
02064 }
02065
02066
02067 reschedule_scan();
02068 }
02075 int scan_results_ioctl(int ifindex, GSList** scan_results_save)
02076 {
02077 struct iwreq req;
02078 char *buffer;
02079 unsigned int buflen = IW_SCAN_MAX_DATA*2;
02080 int sock;
02081 unsigned int counter = 3;
02082
02083
02084
02085 init_iwreq(&req);
02086
02087 sock = socket_open();
02088
02089 buffer = g_malloc(buflen);
02090
02091 try_again:
02092
02093
02094 req.u.data.pointer = buffer;
02095 req.u.data.flags = 0;
02096 req.u.data.length = buflen;
02097
02098 if (ioctl(sock, SIOCGIWSCAN, &req) < 0) {
02099
02100
02101 if (errno == E2BIG) {
02102 DLOG_DEBUG("Too much data for buffer length %d "
02103 "needed %d\n", buflen, req.u.data.length);
02104
02105 char* new_buffer = NULL;
02106 buflen = (req.u.data.length > buflen ?
02107 req.u.data.length : buflen * 2);
02108 new_buffer = g_realloc(buffer, buflen);
02109
02110 buffer = new_buffer;
02111 goto try_again;
02112 }
02113
02114
02115 if (errno == EAGAIN)
02116 {
02117 DLOG_DEBUG("Not yet ready...");
02118 if (counter-- > 0) {
02119 sleep(1);
02120 goto try_again;
02121 }
02122 }
02123
02124 DLOG_ERR("Get scan results failed");
02125
02126 g_free(buffer);
02127 return -1;
02128 }
02129
02130 if (req.u.data.length)
02131 {
02132 struct iw_event iwe;
02133 struct stream_descr stream;
02134 struct scan_results_t *scan_results;
02135 struct wireless_iface *wireless_if;
02136 int ret;
02137 gboolean wap_handled = FALSE;
02138 int we_version;
02139
02140 scan_results = g_slice_new0(struct scan_results_t);
02141 memset(&iwe, 0, sizeof(iwe));
02142
02143 if (ifindex != 0) {
02144 wireless_if = get_interface_data(ifindex);
02145 we_version = wireless_if->range.we_version_compiled;
02146 } else {
02147 struct iw_range range;
02148 iw_get_range_info(socket_open(), wlan_status.ifname,
02149 &range);
02150 we_version = range.we_version_compiled;
02151 }
02152
02153 iw_init_event_stream(&stream, buffer, req.u.data.length);
02154 do
02155 {
02156
02157 ret = iw_extract_event_stream(
02158 &stream, &iwe,
02159 we_version);
02160 if (ret > 0) {
02161
02162
02163
02164
02165 if (iwe.cmd == SIOCGIWAP) {
02166
02167
02168
02169 if (wap_handled == TRUE) {
02170 *scan_results_save = save_scan_results(scan_results, *scan_results_save);
02171 scan_results = g_slice_new0(struct scan_results_t);
02172 } else {
02173 wap_handled = TRUE;
02174 }
02175 }
02176 print_event_token(&iwe, scan_results, ifindex,
02177 TRUE);
02178 }
02179
02180 }
02181 while (ret > 0);
02182
02183
02184
02185 if (wap_handled == TRUE) {
02186 *scan_results_save = save_scan_results(
02187 scan_results,
02188 *scan_results_save);
02189 } else {
02190
02191 g_slice_free(struct scan_results_t, scan_results);
02192 }
02193 }
02194
02195 g_free(buffer);
02196
02197 return 0;
02198 }
02199
02200
02206 gboolean ask_scan_results(int ifindex)
02207 {
02208 GSList *scan_results_save = NULL;
02209 dbus_int32_t number_of_results;
02210
02211 if (scan_results_ioctl(ifindex, &scan_results_save) < 0)
02212 return FALSE;
02213
02214
02215 if (scan_name_cache != NULL) {
02216 number_of_results = g_slist_length(scan_results_save);
02217
02218
02219
02220 if (number_of_results > WLANCOND_MAX_NETWORKS)
02221 scan_results_save = g_slist_sort(scan_results_save,
02222 network_compare);
02223
02224 send_dbus_scan_results(scan_results_save, scan_name_cache,
02225 number_of_results);
02226 g_free(scan_name_cache);
02227 scan_name_cache = NULL;
02228 }
02229
02230
02231
02232 if ((get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION ||
02233 wlan_status.signal == WLANCOND_LOW) &&
02234 get_scan_state() == SCAN_ACTIVE) {
02235
02236 DLOG_DEBUG("Connect from scan");
02237
02238 set_scan_state(SCAN_NOT_ACTIVE);
02239
02240 connect_from_scan_results(scan_results_save);
02241
02242 return TRUE;
02243 }
02244
02245 set_scan_state(SCAN_NOT_ACTIVE);
02246
02247 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN &&
02248 power_down_after_scan == TRUE) {
02249 set_interface_state(socket_open(), CLEAR, IFF_UP);
02250 }
02251
02252 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
02253
02254 if (wlan_status.roam_cache) {
02255 clean_roam_cache();
02256 }
02257 wlan_status.roam_cache = scan_results_save;
02258 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_NO);
02259 } else {
02260 clean_scan_results(&scan_results_save);
02261 }
02262
02263 return TRUE;
02264 }
02265
02272 static DBusHandlerResult disconnect_request(DBusMessage *message,
02273 DBusConnection *connection) {
02274 DBusMessage *reply;
02275
02276 set_scan_state(SCAN_NOT_ACTIVE);
02277
02278
02279 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, FORCE_YES);
02280
02281 reply = new_dbus_method_return(message);
02282 send_and_unref(connection, reply);
02283
02284 return DBUS_HANDLER_RESULT_HANDLED;
02285 }
02292 static DBusHandlerResult disassociate_request(DBusMessage *message,
02293 DBusConnection *connection) {
02294 DBusMessage *reply;
02295
02296 if (get_wlan_state() != WLAN_CONNECTED &&
02297 get_wlan_state() != WLAN_NO_ADDRESS) {
02298 DLOG_ERR("Not in correct state for disassociation");
02299
02300 reply = new_dbus_method_return(message);
02301 send_and_unref(connection, reply);
02302 return DBUS_HANDLER_RESULT_HANDLED;
02303 }
02304
02305 if (get_wpa_mode() == TRUE) {
02306 clear_wpa_keys(wlan_status.conn.bssid);
02307 }
02308
02309 mlme_command(wlan_status.conn.bssid, IW_MLME_DISASSOC,
02310 WLANCOND_REASON_LEAVING);
02311
02312 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL, FORCE_NO);
02313
02314 DLOG_DEBUG("Disassociated, trying to find a new connection");
02315
02316 if (scan(wlan_status.conn.ssid, wlan_status.conn.ssid_len, TRUE) < 0) {
02317
02318 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
02319 FORCE_YES);
02320 }
02321
02322 reply = new_dbus_method_return(message);
02323 send_and_unref(connection, reply);
02324
02325 return DBUS_HANDLER_RESULT_HANDLED;
02326 }
02333 static DBusHandlerResult status_request(DBusMessage *message,
02334 DBusConnection *connection) {
02335 DBusMessage *reply = NULL;
02336 struct iwreq req;
02337 struct iw_range range;
02338 char *essid = NULL;
02339 int essid_len;
02340 dbus_uint32_t sens = 0;
02341 dbus_uint32_t security = 0;
02342 dbus_uint32_t capability = 0;
02343 dbus_uint32_t channel = 0;
02344 unsigned char *bssid = NULL;
02345
02346 int sock;
02347
02348 if (get_wlan_state() != WLAN_CONNECTED &&
02349 get_wlan_state() != WLAN_NO_ADDRESS &&
02350 get_mode() != WLANCOND_ADHOC) {
02351 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02352 send_and_unref(connection, reply);
02353 return DBUS_HANDLER_RESULT_HANDLED;
02354 }
02355
02356 sock = socket_open();
02357
02358 init_iwreq(&req);
02359
02360 essid = g_malloc0(IW_ESSID_MAX_SIZE+1);
02361 req.u.essid.pointer = (caddr_t)essid;
02362 req.u.essid.length = IW_ESSID_MAX_SIZE;
02363 req.u.essid.flags = 0;
02364
02365
02366 if (ioctl(sock, SIOCGIWESSID, &req) < 0) {
02367 DLOG_ERR("Could not get ESSID");
02368 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02369 goto param_err;
02370 }
02371 essid_len = req.u.essid.length;
02372
02373
02374 if (essid_len == 0 || essid_len == 32)
02375 essid_len++;
02376
02377 init_iwreq(&req);
02378
02379
02380 if (ioctl(sock, SIOCGIWAP, &req) < 0) {
02381 DLOG_ERR("Could not get BSSID");
02382 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02383 goto param_err;
02384 }
02385 bssid = g_malloc(ETH_ALEN);
02386 memcpy(bssid, &req.u.ap_addr.sa_data, ETH_ALEN);
02387
02388 init_iwreq(&req);
02389 struct iw_statistics stats;
02390 memset(&stats, 0, sizeof(struct iw_statistics));
02391
02392 req.u.data.pointer = (caddr_t) &stats;
02393 req.u.data.length = sizeof(struct iw_statistics);
02394 req.u.data.flags = 1;
02395
02396
02397 if (ioctl(sock, SIOCGIWSTATS, &req) < 0) {
02398 DLOG_ERR("Could not get statistics");
02399 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02400 goto param_err;
02401 }
02402 sens = stats.qual.level - 0x100;
02403
02404
02405 init_iwreq(&req);
02406
02407 if (ioctl(sock, SIOCGIWFREQ, &req) < 0) {
02408 DLOG_DEBUG("Could not get channel");
02409 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02410 goto param_err;
02411 }
02412
02413 if (iw_get_range_info(sock, wlan_status.ifname, &range) >= 0) {
02414 double freq = iw_freq2float(&(req.u.freq));
02415 channel = iw_freq_to_channel(freq, &range);
02416 }
02417
02418 if (channel < WLANCOND_MIN_WLAN_CHANNEL ||
02419 channel > WLANCOND_MAX_WLAN_CHANNEL) {
02420 channel = 0;
02421 DLOG_DEBUG("Got invalid channel\n");
02422 }
02423
02424
02425 init_iwreq(&req);
02426
02427 if (ioctl(sock, SIOCGIWMODE, &req) < 0) {
02428 DLOG_ERR("Could not get operating mode");
02429 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02430 goto param_err;
02431 }
02432
02433 if (req.u.mode == IW_MODE_ADHOC) {
02434 capability |= WLANCOND_ADHOC;
02435 } else if (req.u.mode == IW_MODE_INFRA) {
02436 capability |= WLANCOND_INFRA;
02437 }
02438
02439 init_iwreq(&req);
02440
02441
02442 security = wlan_status.conn.encryption;
02443
02444 #if 0
02445 key = g_malloc(IW_ENCODING_TOKEN_MAX);
02446 req.u.data.pointer = (caddr_t) key;
02447 req.u.data.length = IW_ENCODING_TOKEN_MAX;
02448 req.u.data.flags = 0;
02449
02450 if (ioctl(sock, SIOCGIWENCODE, &req) < 0) {
02451 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02452 goto param_err;
02453 }
02454
02455 if (req.u.data.flags & IW_ENCODE_OPEN)
02456 security |= WLANCOND_OPEN;
02457
02458 if (req.u.data.flags & IW_ENCODE_RESTRICTED)
02459 security |= WLANCOND_WEP;
02460
02461
02462 if (req.u.data.flags & IW_ENCODE_TKIP)
02463 security |= WLANCOND_WPA_PSK & WLANCOND_WPA_EAP &
02464 WLANCOND_WPA_TKIP;
02465
02466 if (req.u.data.flags & IW_ENCODE_AES)
02467 security |= WLANCOND_WPA_PSK & WLANCOND_WPA_EAP &
02468 WLANCOND_WPA_AES;
02469
02470 g_free(key);
02471 #endif
02472 init_iwreq(&req);
02473
02474
02475 if (ioctl(sock, SIOCGIWRATE, &req) < 0) {
02476 DLOG_ERR("Could not get the rate");
02477 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02478 goto param_err;
02479 }
02480 capability |= req.u.bitrate.value;
02481
02482 reply = new_dbus_method_return(message);
02483
02484 gchar* ifname = wlan_status.ifname;
02485
02486 append_dbus_args(reply,
02487 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02488 &essid, essid_len,
02489 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, ETH_ALEN,
02490 DBUS_TYPE_UINT32, &sens,
02491 DBUS_TYPE_UINT32, &channel,
02492 DBUS_TYPE_UINT32, &capability,
02493 DBUS_TYPE_UINT32, &security,
02494 DBUS_TYPE_STRING, &ifname,
02495 DBUS_TYPE_INVALID);
02496
02497 send_and_unref(connection, reply);
02498
02499 g_free(essid);
02500 g_free(bssid);
02501
02502 return DBUS_HANDLER_RESULT_HANDLED;
02503
02504 param_err:
02505 g_free(essid);
02506 g_free(bssid);
02507
02508 if (reply == NULL) {
02509 DLOG_DEBUG("Parameter error in status request");
02510 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
02511 }
02512 send_and_unref(connection, reply);
02513 return DBUS_HANDLER_RESULT_HANDLED;
02514 }
02515
02522 static DBusHandlerResult interface_request(DBusMessage *message,
02523 DBusConnection *connection) {
02524 DBusMessage *reply;
02525 gchar* ifname = wlan_status.ifname;
02526
02527 reply = new_dbus_method_return(message);
02528
02529 append_dbus_args(reply,
02530 DBUS_TYPE_STRING, &ifname,
02531 DBUS_TYPE_INVALID);
02532
02533 send_and_unref(connection, reply);
02534
02535 return DBUS_HANDLER_RESULT_HANDLED;
02536 }
02537
02544 static DBusHandlerResult connection_status_request(
02545 DBusMessage *message,
02546 DBusConnection *connection) {
02547
02548 DBusMessage *reply;
02549 dbus_bool_t state = FALSE;
02550
02551 guint state_v = get_wlan_state();
02552
02553 if (state_v == WLAN_INITIALIZED ||
02554 state_v == WLAN_NO_ADDRESS ||
02555 state_v == WLAN_CONNECTED)
02556 state = TRUE;
02557
02558 reply = new_dbus_method_return(message);
02559
02560 append_dbus_args(reply,
02561 DBUS_TYPE_BOOLEAN, &state,
02562 DBUS_TYPE_INVALID);
02563
02564 send_and_unref(connection, reply);
02565
02566 return DBUS_HANDLER_RESULT_HANDLED;
02567 }
02574 static DBusHandlerResult set_pmksa_request(DBusMessage *message,
02575 DBusConnection *connection) {
02576
02577 DBusMessage *reply = NULL;
02578 unsigned int pmkid_len, mac_len;
02579 unsigned char *pmkid;
02580 unsigned char *mac;
02581 dbus_uint32_t action;
02582 DBusError derror;
02583
02584 dbus_error_init(&derror);
02585
02586 if (dbus_message_get_args(
02587 message, &derror,
02588 DBUS_TYPE_UINT32, &action,
02589 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &pmkid, &pmkid_len,
02590 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &mac, &mac_len,
02591 DBUS_TYPE_INVALID) == FALSE)
02592 {
02593 DLOG_ERR("Failed to parse set_pmksa request: %s",
02594 derror.message);
02595 dbus_error_free(&derror);
02596 goto param_err;
02597 }
02598
02599 if (action != IW_PMKSA_ADD) {
02600 DLOG_ERR("Invalid action");
02601 goto param_err;
02602 }
02603
02604 if (pmkid == NULL || pmkid_len != WLANCOND_PMKID_LEN || mac == NULL
02605 || mac_len != ETH_ALEN) {
02606 DLOG_ERR("Invalid arguments");
02607 goto param_err;
02608 }
02609
02610 add_to_pmksa_cache(pmkid, mac);
02611
02612 print_mac("PMKSA added successfully for address:", mac);
02613
02614 reply = new_dbus_method_return(message);
02615 send_and_unref(connection, reply);
02616
02617 return DBUS_HANDLER_RESULT_HANDLED;
02618
02619 param_err:
02620 if (reply == NULL) {
02621 DLOG_DEBUG("Parameter error in set_pmksa");
02622 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
02623 }
02624 send_and_unref(connection, reply);
02625 return DBUS_HANDLER_RESULT_HANDLED;
02626 }
02627
02634 static DBusHandlerResult set_powersave_request(DBusMessage *message,
02635 DBusConnection *connection) {
02636
02637 DBusMessage *reply = NULL;
02638 int sock;
02639 DBusError error;
02640 dbus_bool_t onoff;
02641
02642 sock = socket_open();
02643
02644 dbus_error_init(&error);
02645
02646 if (dbus_message_get_args(message, &error,
02647 DBUS_TYPE_BOOLEAN, &onoff,
02648 DBUS_TYPE_INVALID) == FALSE) {
02649 DLOG_ERR("Failed to parse message: %s",
02650 error.message);
02651 dbus_error_free(&error);
02652
02653 send_invalid_args(connection, message);
02654 return DBUS_HANDLER_RESULT_HANDLED;
02655 }
02656
02657
02658
02659
02660 if (onoff == TRUE) {
02661 if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
02662 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
02663 } else if (get_wlan_state() != WLAN_NO_ADDRESS ||
02664 (connect_name_cache != NULL &&
02665 strcmp(dbus_message_get_sender(message),
02666 connect_name_cache) == 0)) {
02667 if (set_power_state(powersave, sock) == FALSE) {
02668 DLOG_ERR("Setting powersave failed");
02669
02670 }
02671 }
02672 } else {
02673
02674 if (set_power_state(WLANCOND_POWER_ON, sock) == FALSE) {
02675 DLOG_ERR("Setting powersave failed");
02676
02677 }
02678 }
02679
02680 DLOG_DEBUG("WLAN powersave %s", onoff==TRUE?"on":"off");
02681
02682 reply = new_dbus_method_return(message);
02683 send_and_unref(connection, reply);
02684
02685 return DBUS_HANDLER_RESULT_HANDLED;
02686 }
02687
02694 static void wpa_ie_push_cb(DBusPendingCall *pending,
02695 void *user_data)
02696 {
02697 DBusMessage *reply;
02698 DBusError error;
02699
02700
02701
02702 dbus_error_init (&error);
02703
02704 reply = dbus_pending_call_steal_reply(pending);
02705
02706 if (dbus_set_error_from_message(&error, reply)) {
02707
02708 DLOG_DEBUG("EAP WPA IE push call result:%s", error.name);
02709
02710 dbus_error_free(&error);
02711
02712 set_wlan_state(WLAN_NOT_INITIALIZED,
02713 DISCONNECTED_SIGNAL,
02714 FORCE_YES);
02715 }
02716
02717 if (reply)
02718 dbus_message_unref(reply);
02719 dbus_pending_call_unref(pending);
02720 }
02721
02730 int wpa_ie_push(unsigned char* ap_mac_addr, unsigned char* ap_wpa_ie,
02731 int ap_wpa_ie_len, char* ssid, int ssid_len,
02732 unsigned int authentication_type) {
02733
02734 DBusMessage *msg;
02735 DBusPendingCall *pending;
02736
02737 if (authentication_type != EAP_AUTH_TYPE_WFA_SC) {
02738 if (wlan_status.wpa_ie.ie_len == 0 || ap_wpa_ie == NULL ||
02739 ssid == NULL) {
02740 DLOG_ERR("WPA IE / SSID (%s) not valid", ssid);
02741 return -1;
02742 }
02743 }
02744
02745 msg = dbus_message_new_method_call(
02746 EAP_SERVICE,
02747 EAP_REQ_PATH,
02748 EAP_REQ_INTERFACE,
02749 EAP_WPA_IE_PUSH_REQ);
02750
02751 if (msg == NULL) {
02752 return -1;
02753 }
02754
02755 append_dbus_args(
02756 msg,
02757 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02758 &wlan_status.wpa_ie.ie, wlan_status.wpa_ie.ie_len,
02759 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ap_wpa_ie,
02760 ap_wpa_ie_len,
02761 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02762 &ssid, ssid_len,
02763 DBUS_TYPE_UINT32, &wlan_status.pairwise_cipher,
02764 DBUS_TYPE_UINT32, &wlan_status.group_cipher,
02765 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
02766 &ap_mac_addr, ETH_ALEN,
02767 DBUS_TYPE_UINT32, &authentication_type,
02768 DBUS_TYPE_INVALID);
02769
02770 if (!dbus_connection_send_with_reply(get_dbus_connection(),
02771 msg, &pending, -1))
02772 die("Out of memory");
02773
02774 if (!dbus_pending_call_set_notify (pending, wpa_ie_push_cb, NULL, NULL))
02775 die("Out of memory");
02776
02777 dbus_message_unref(msg);
02778
02779 return 0;
02780 }
02787 int wpa_mic_failure_event(dbus_bool_t key_type, dbus_bool_t is_fatal) {
02788 DBusMessage *msg;
02789 DBusMessage *reply;
02790 DBusError derr;
02791
02792 msg = dbus_message_new_method_call(
02793 EAP_SERVICE,
02794 EAP_REQ_PATH,
02795 EAP_REQ_INTERFACE,
02796 EAP_WPA_MIC_FAILURE_REQ);
02797
02798 if (msg == NULL) {
02799 return -1;
02800 }
02801
02802 append_dbus_args(msg,
02803 DBUS_TYPE_BOOLEAN, &key_type,
02804 DBUS_TYPE_BOOLEAN, &is_fatal,
02805 DBUS_TYPE_INVALID);
02806
02807 dbus_error_init(&derr);
02808
02809 reply = dbus_connection_send_with_reply_and_block(
02810 get_dbus_connection(), msg, -1, &derr);
02811
02812 dbus_message_unref(msg);
02813
02814 if (dbus_error_is_set(&derr)) {
02815 DLOG_ERR("EAP returned error: %s", derr.name);
02816
02817 dbus_error_free(&derr);
02818 if (reply)
02819 dbus_message_unref(reply);
02820 return -1;
02821 }
02822
02823 dbus_message_unref(reply);
02824
02825 return 0;
02826 }
02831 int associate_supplicant(void) {
02832 DBusMessage *msg;
02833 DBusMessage *reply;
02834 DBusError derr;
02835
02836 msg = dbus_message_new_method_call(
02837 EAP_SERVICE,
02838 EAP_REQ_PATH,
02839 EAP_REQ_INTERFACE,
02840 EAP_ASSOCIATE_REQ);
02841
02842 if (msg == NULL) {
02843 return -1;
02844 }
02845
02846 dbus_error_init(&derr);
02847
02848 reply = dbus_connection_send_with_reply_and_block(
02849 get_dbus_connection(), msg, -1, &derr);
02850
02851 dbus_message_unref(msg);
02852
02853 if (dbus_error_is_set(&derr)) {
02854 DLOG_ERR("EAP returned error: %s", derr.name);
02855
02856 dbus_error_free(&derr);
02857 if (reply)
02858 dbus_message_unref(reply);
02859 return -1;
02860 }
02861
02862 dbus_message_unref(reply);
02863
02864 return 0;
02865 }
02872 static void disassociate_cb(DBusPendingCall *pending,
02873 void *user_data)
02874 {
02875 DBusMessage *reply;
02876 DBusError error;
02877
02878 dbus_error_init (&error);
02879
02880 reply = dbus_pending_call_steal_reply(pending);
02881
02882 if (dbus_set_error_from_message(&error, reply)) {
02883
02884 DLOG_DEBUG("EAP disassociate call result:%s", error.name);
02885
02886 dbus_error_free(&error);
02887 }
02888
02889 if (reply)
02890 dbus_message_unref(reply);
02891 dbus_pending_call_unref(pending);
02892 }
02893
02898 int disassociate_eap(void) {
02899 DBusMessage *msg;
02900 DBusPendingCall *pending;
02901
02902 msg = dbus_message_new_method_call(
02903 EAP_SERVICE,
02904 EAP_REQ_PATH,
02905 EAP_REQ_INTERFACE,
02906 EAP_DISASSOCIATE_REQ);
02907
02908 if (msg == NULL) {
02909 return -1;
02910 }
02911
02912 if (!dbus_connection_send_with_reply(get_dbus_connection(),
02913 msg, &pending, -1))
02914 die("Out of memory");
02915
02916 if (!dbus_pending_call_set_notify (pending, disassociate_cb, NULL,
02917 NULL))
02918 die("Out of memory");
02919
02920 dbus_message_unref(msg);
02921
02922 return 0;
02923 }
02924
02925 typedef DBusHandlerResult (*handler_func)(DBusMessage *message,
02926 DBusConnection *connection);
02927
02928 typedef struct {
02929 const char *interface;
02930 const char *name;
02931 handler_func func;
02932 } method_handler_t;
02933
02934 static method_handler_t handlers[] = {
02935 { WLANCOND_REQ_INTERFACE, WLANCOND_SETTINGS_AND_CONNECT_REQ, settings_and_connect_request},
02936 { WLANCOND_REQ_INTERFACE, WLANCOND_SCAN_REQ, scan_request},
02937 { WLANCOND_REQ_INTERFACE, WLANCOND_STATUS_REQ, status_request},
02938 { WLANCOND_REQ_INTERFACE, WLANCOND_INTERFACE_REQ, interface_request},
02939 { WLANCOND_REQ_INTERFACE, WLANCOND_CONNECTION_STATUS_REQ, connection_status_request},
02940 { WLANCOND_REQ_INTERFACE, WLANCOND_SET_PMKSA_REQ, set_pmksa_request},
02941 { WLANCOND_REQ_INTERFACE, WLANCOND_SET_POWERSAVE_REQ, set_powersave_request},
02942 { WLANCOND_REQ_INTERFACE, WLANCOND_DISCONNECT_REQ, disconnect_request},
02943 { WLANCOND_REQ_INTERFACE, WLANCOND_DISASSOCIATE_REQ, disassociate_request},
02944 { NULL }
02945 };
02946
02953 DBusHandlerResult wlancond_req_handler(DBusConnection *connection,
02954 DBusMessage *message,
02955 void *user_data) {
02956 method_handler_t *handler;
02957 const char *dest;
02958
02959
02960
02961
02962
02963 #ifdef USE_MCE_MODE
02964 if (dbus_message_is_signal(message,
02965 MCE_SIGNAL_IF,
02966 MCE_DEVICE_MODE_SIG)) {
02967 return mode_change_dbus(message);
02968 }
02969 #ifdef ACTIVITY_CHECK
02970 if (dbus_message_is_signal(message,
02971 MCE_SIGNAL_IF,
02972 MCE_INACTIVITY_SIG)) {
02973 return activity_check_dbus(message);
02974 }
02975 #endif
02976 #endif
02977 if (dbus_message_is_signal(message,
02978 ICD_DBUS_INTERFACE,
02979 ICD_STATUS_CHANGED_SIG))
02980 return icd_check_signal_dbus(message);
02981
02982
02983 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
02984 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
02985 }
02986
02987 dest = dbus_message_get_destination(message);
02988 if (!g_str_equal(dest, WLANCOND_SERVICE)) {
02989 DLOG_DEBUG("Received D-Bus message not addressed to me.");
02990 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
02991 }
02992
02993 for (handler = handlers; handler->interface != NULL; handler++) {
02994 if (dbus_message_is_method_call(message,
02995 handler->interface,
02996 handler->name)) {
02997 DLOG_DEBUG("Received %s", handler->name);
02998 return handler->func(message, connection);
02999 }
03000 }
03001 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03002 }
03003
03004 static DBusObjectPathVTable wlancond_req_vtable = {
03005 .message_function = wlancond_req_handler,
03006 .unregister_function = NULL
03007 };
03008
03009
03014 void init_dbus_handlers(DBusConnection *connection) {
03015 dbus_bool_t ret;
03016 ret = dbus_connection_register_object_path(connection,
03017 WLANCOND_REQ_PATH,
03018 &wlancond_req_vtable,
03019 NULL);
03020 if (ret == FALSE) {
03021 DLOG_ERR("dbus_connection_register_object_path failed");
03022 }
03023 #ifdef USE_MCE_MODE
03024 if (!add_mode_listener(connection)) {
03025 DLOG_ERR("Adding mode listener failed");
03026 }
03027 #endif
03028 if (!add_icd_listener(connection)) {
03029 DLOG_ERR("Adding icd listener failed");
03030 }
03031 }
03032
03037 void destroy_dbus_handlers(DBusConnection *connection) {
03038 dbus_connection_unregister_object_path(connection, WLANCOND_REQ_PATH);
03039 }