00001
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <stdint.h>
00030 #include <string.h>
00031 #include <glib.h>
00032 #include <glib-object.h>
00033 #include <errno.h>
00034 #include <unistd.h>
00035 #include <sys/types.h>
00036 #include <sys/socket.h>
00037 #include <linux/types.h>
00038 #include <wlancond-dbus.h>
00039 #include <eap-dbus.h>
00040
00041 #include "common.h"
00042 #include "daemon.h"
00043 #include "dbus.h"
00044 #include "dbus-handler.h"
00045 #include "log.h"
00046 #include "dbus-helper.h"
00047 #include "wpa.h"
00048
00049 #define DBUS_API_SUBJECT_TO_CHANGE
00050 #include <dbus/dbus.h>
00051
00052
00053 static struct wireless_iface *interface_cache = NULL;
00054
00055 extern struct wlan_status_t wlan_status;
00056
00057 struct rtnl_handle
00058 {
00059 int fd;
00060 struct sockaddr_nl local;
00061 };
00062
00063
00064 static void handle_custom_event(char* event_pointer, int len,
00065 struct scan_results_t *scan_results);
00066 static int handle_wpa_ie_event_binary(unsigned char* p, unsigned int length,
00067 struct scan_results_t *scan_results);
00068
00069 void print_mac(guint priority, const char *message, guchar* mac)
00070 {
00071 if (priority > WLANCOND_PRIO_MEDIUM)
00072 DLOG_INFO("%s %02x:%02x:%02x:%02x:%02x:%02x", message, mac[0],
00073 mac[1], mac[2], mac[3], mac[4], mac[5]);
00074 else {
00075 DLOG_DEBUG("%s %02x:%02x:%02x:%02x:%02x:%02x", message, mac[0],
00076 mac[1], mac[2], mac[3], mac[4], mac[5]);
00077 }
00078 }
00079 void clean_scan_results_item(gpointer data, gpointer user_data)
00080 {
00081 struct scan_results_t *scan_results = data;
00082 g_free(scan_results->wpa_ie);
00083 g_slice_free(struct scan_results_t, scan_results);
00084 }
00085
00090 void clean_scan_results(GSList **scan_results_save)
00091 {
00092
00093
00094 g_slist_foreach(*scan_results_save, clean_scan_results_item, NULL);
00095 g_slist_free(*scan_results_save);
00096
00097 *scan_results_save = NULL;
00098
00099 }
00100
00106 GSList *save_scan_results(struct scan_results_t *scan_results,
00107 GSList *scan_results_save)
00108 {
00109
00110 g_assert(scan_results != NULL);
00111
00112
00113
00114 scan_results_save = g_slist_prepend(scan_results_save, scan_results);
00115
00116 return scan_results_save;
00117 }
00123 void send_dbus_scan_results(GSList *scan_results_save, const char* sender,
00124 dbus_int32_t number_of_results)
00125 {
00126 DBusMessage *results;
00127 DBusMessageIter iter, sub;
00128 GSList *list;
00129 int list_count = 0;
00130 unsigned char* v;
00131 char* p;
00132
00133 if (sender == NULL || strnlen(sender, 5) == 0)
00134 return;
00135
00136 DLOG_INFO("Scan results (%d APs) to %s", number_of_results, sender);
00137
00138 results = new_dbus_signal(WLANCOND_SIG_PATH,
00139 WLANCOND_SIG_INTERFACE,
00140 WLANCOND_SCAN_RESULTS_SIG,
00141 sender);
00142
00143 dbus_message_iter_init_append(results, &iter);
00144
00145 if (number_of_results > WLANCOND_MAX_NETWORKS) {
00146 DLOG_DEBUG("Limiting result %d to %d", number_of_results,
00147 WLANCOND_MAX_NETWORKS);
00148 number_of_results = WLANCOND_MAX_NETWORKS;
00149 }
00150 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32,
00151 &number_of_results))
00152 die("Out of memory");
00153
00154 for (list = scan_results_save; list != NULL && list_count++ <=
00155 number_of_results; list = list->next) {
00156 struct scan_results_t *scan_results = list->data;
00157 DLOG_DEBUG("AP (%d) is %s, rssi:%d channel:%d cap:%08x",
00158 list_count,
00159 scan_results->ssid,
00160 scan_results->rssi, scan_results->channel,
00161 scan_results->cap_bits);
00162
00163 p = scan_results->ssid;
00164
00165 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
00166 "y", &sub))
00167 die("Out of memory");
00168 if (!dbus_message_iter_append_fixed_array(
00169 &sub, DBUS_TYPE_BYTE, &p,
00170 scan_results->ssid_len))
00171 die("Out of memory");
00172 if (!dbus_message_iter_close_container(&iter, &sub))
00173 die("Out of memory");
00174
00175 v = scan_results->bssid;
00176 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
00177 "y", &sub))
00178 die("Out of memory");
00179 if (!dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE,
00180 &v, ETH_ALEN))
00181 die("Out of memory");
00182 if (!dbus_message_iter_close_container(&iter, &sub))
00183 die("Out of memory");
00184 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32,
00185 &scan_results->rssi))
00186 die("Out of memory");
00187 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32,
00188 &scan_results->channel))
00189 die("Out of memory");
00190 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32,
00191 &scan_results->cap_bits))
00192 die("Out of memory");
00193 }
00194
00195 send_and_unref(get_dbus_connection(), results);
00196 }
00197
00201 void disconnected_signal(void)
00202 {
00203 DBusMessage *disconnected;
00204
00205 disconnected = new_dbus_signal(
00206 WLANCOND_SIG_PATH,
00207 WLANCOND_SIG_INTERFACE,
00208 WLANCOND_DISCONNECTED_SIG,
00209 NULL);
00210
00211 gchar* ifname = wlan_status.ifname;
00212
00213 append_dbus_args(disconnected,
00214 DBUS_TYPE_STRING, &ifname,
00215 DBUS_TYPE_INVALID);
00216
00217 send_and_unref(get_dbus_connection(), disconnected);
00218 }
00219
00225 static void connected_signal(char* bssid, dbus_int32_t auth_status)
00226 {
00227 DBusMessage *connected;
00228
00229 connected = new_dbus_signal(
00230 WLANCOND_SIG_PATH,
00231 WLANCOND_SIG_INTERFACE,
00232 WLANCOND_CONNECTED_SIG,
00233 NULL);
00234
00235 gchar* ifname = wlan_status.ifname;
00236
00237 append_dbus_args(connected,
00238 DBUS_TYPE_STRING, &ifname,
00239 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, ETH_ALEN,
00240 DBUS_TYPE_INT32, &auth_status,
00241 DBUS_TYPE_INVALID);
00242
00243 send_and_unref(get_dbus_connection(), connected);
00244 }
00245
00252 static void handle_wap_event(struct scan_results_t *scan_results,
00253 struct iw_event *event, gboolean scan_event)
00254 {
00255
00256
00257 if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
00258 return;
00259 }
00260
00261 if (scan_event == TRUE) {
00262 print_mac(WLANCOND_PRIO_LOW, "SIOCGIWAP:",
00263 (guchar*)event->u.ap_addr.sa_data);
00264 memcpy(scan_results->bssid, event->u.ap_addr.sa_data, ETH_ALEN);
00265 return;
00266 }
00267
00268 print_mac(WLANCOND_PRIO_HIGH, "SIOCGIWAP:",
00269 (guchar*)event->u.ap_addr.sa_data);
00270
00271
00272 if (memcmp(event->u.ap_addr.sa_data, "\0\0\0\0\0\0", ETH_ALEN)) {
00273
00274 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
00275 DLOG_ERR("Should not happen");
00276 return;
00277 }
00278
00279
00280 remove_connect_timer();
00281 wlan_status.retry_count = 0;
00282
00283 set_wlan_signal(WLANCOND_HIGH);
00284
00285 if (get_wpa_mode() == TRUE ||
00286 wlan_status.conn.authentication_type ==
00287 EAP_AUTH_TYPE_WFA_SC) {
00288 if (associate_supplicant() < 0) {
00289 set_wlan_state(WLAN_NOT_INITIALIZED,
00290 DISCONNECTED_SIGNAL,
00291 FORCE_YES);
00292 return;
00293 }
00294 }
00295
00296 dbus_int32_t auth_status = get_encryption_info();
00297
00298 connected_signal(event->u.ap_addr.sa_data, auth_status);
00299
00300 if (wlan_status.ip_ok == FALSE) {
00301 set_wlan_state(WLAN_NO_ADDRESS, NO_SIGNAL, FORCE_NO);
00302 } else {
00303 set_wlan_state(WLAN_CONNECTED, NO_SIGNAL, FORCE_NO);
00304 }
00305
00306
00307 wlan_status.conn.flags &= ~WLANCOND_AUTOCONNECT;
00308 } else {
00309 if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION &&
00310 get_scan_state() == SCAN_ACTIVE) {
00311
00312 return;
00313 }
00314 if (get_wlan_state() != WLAN_CONNECTED &&
00315 get_wlan_state() != WLAN_NO_ADDRESS &&
00316 get_wlan_state() !=
00317 WLAN_INITIALIZED_FOR_CONNECTION) {
00318 DLOG_ERR("Not even connected?!?");
00319 return;
00320 }
00321
00322 if (wlan_status.conn.authentication_type ==
00323 EAP_AUTH_TYPE_WFA_SC) {
00324 return;
00325 }
00326
00327
00328 if (get_wpa_mode() == TRUE &&
00329 (get_wlan_state() == WLAN_CONNECTED ||
00330 get_wlan_state() == WLAN_NO_ADDRESS)) {
00331 disassociate_eap();
00332 clear_wpa_keys(wlan_status.conn.bssid);
00333 }
00334
00335
00336 set_bssid(NULL_BSSID);
00337 set_essid((char*)"", 1);
00338 set_wpa_ie(&wlan_status);
00339
00340 DLOG_DEBUG("Trying to find a new connection");
00341
00342
00343 decrease_signal_in_roam_cache(wlan_status.conn.bssid);
00344
00345 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL,
00346 FORCE_NO);
00347
00348 if (find_connection_and_associate(wlan_status.roam_cache,
00349 FALSE, FALSE, FALSE) == 0)
00350 return;
00351
00352
00353 if (++wlan_status.retry_count > WLANCOND_MAX_SCAN_TRIES) {
00354 DLOG_ERR("Too many failures: %d",
00355 wlan_status.retry_count);
00356 set_wlan_state(WLAN_NOT_INITIALIZED,
00357 DISCONNECTED_SIGNAL,
00358 FORCE_YES);
00359 return;
00360 }
00361
00362
00363 if (scan(wlan_status.conn.ssid,
00364 wlan_status.conn.ssid_len, TRUE) < 0) {
00365
00366 set_wlan_state(WLAN_NOT_INITIALIZED,
00367 DISCONNECTED_SIGNAL,
00368 FORCE_YES);
00369 }
00370 }
00371 }
00372
00380 int print_event_token(struct iw_event *event,
00381 struct scan_results_t *scan_results,
00382 int ifindex, gboolean scan_event)
00383 {
00384
00385
00386 switch(event->cmd)
00387 {
00388 case SIOCGIWESSID:
00389 {
00390 int len = event->u.essid.length;
00391 if (len > WLANCOND_MAX_SSID_SIZE) {
00392
00393 len = WLANCOND_MAX_SSID_SIZE;
00394 }
00395
00396 if ((event->u.essid.pointer) && len) {
00397 memcpy(scan_results->ssid,
00398 event->u.essid.pointer, len);
00399 }
00400
00401
00402 len++;
00403
00404 scan_results->ssid_len = len;
00405
00406 if (event->u.essid.flags)
00407 {
00408
00409 if((event->u.essid.flags & IW_ENCODE_INDEX) >
00410 1) {
00411
00412 #ifdef DEBUG
00413 DLOG_DEBUG("ESSID:\"%s\" [%d]\n",
00414 scan_results->ssid,
00415 (event->u.essid.flags &
00416 IW_ENCODE_INDEX));
00417 } else {
00418 DLOG_DEBUG("ESSID:\"%s\"\n",
00419 scan_results->ssid);
00420 #endif
00421 }
00422 } else {
00423 #ifdef DEBUG
00424 DLOG_DEBUG("ESSID:off/any");
00425 #endif
00426 }
00427 }
00428 break;
00429 case SIOCGIWAP:
00430 handle_wap_event(scan_results, event, scan_event);
00431 break;
00432 case IWEVQUAL:
00433
00434 scan_results->rssi = (signed char)event->u.qual.level;
00435 break;
00436 case SIOCGIWFREQ:
00437 {
00438 if (event->u.freq.e == 0) {
00439 scan_results->channel = event->u.freq.m;
00440 DLOG_DEBUG("Channel: %d", scan_results->channel);
00441 }
00442 }
00443 break;
00444 case SIOCGIWMODE:
00445 if (event->u.mode == IW_MODE_ADHOC) {
00446 DLOG_DEBUG("Adhoc network");
00447 scan_results->cap_bits |= WLANCOND_ADHOC;
00448 } else {
00449 scan_results->cap_bits |= WLANCOND_INFRA;
00450 }
00451 break;
00452 case SIOCGIWRATE:
00453 switch (event->u.bitrate.value) {
00454 case 2*500000:
00455 scan_results->cap_bits |= WLANCOND_RATE_10;
00456 break;
00457 case 4*500000:
00458 scan_results->cap_bits |= WLANCOND_RATE_20;
00459 break;
00460 case 11*500000:
00461 scan_results->cap_bits |= WLANCOND_RATE_55;
00462 break;
00463 case 12*500000:
00464 scan_results->cap_bits |= WLANCOND_RATE_60;
00465 break;
00466 case 18*500000:
00467 scan_results->cap_bits |= WLANCOND_RATE_90;
00468 break;
00469 case 22*500000:
00470 scan_results->cap_bits |= WLANCOND_RATE_110;
00471 break;
00472 case 24*500000:
00473 scan_results->cap_bits |= WLANCOND_RATE_120;
00474 break;
00475 case 36*500000:
00476 scan_results->cap_bits |= WLANCOND_RATE_180;
00477 break;
00478 case 48*500000:
00479 scan_results->cap_bits |= WLANCOND_RATE_240;
00480 break;
00481 case 52*500000:
00482 scan_results->cap_bits |= WLANCOND_RATE_260;
00483 break;
00484 case 72*500000:
00485 scan_results->cap_bits |= WLANCOND_RATE_360;
00486 break;
00487 case 96*500000:
00488 scan_results->cap_bits |= WLANCOND_RATE_480;
00489 break;
00490 case 108*500000:
00491 scan_results->cap_bits |= WLANCOND_RATE_540;
00492 break;
00493 #ifdef DEBUG
00494 default:
00495
00496 DLOG_DEBUG("Unknown rate %04x",
00497 (int)event->u.bitrate.value);
00498 break;
00499 #endif
00500 }
00501 break;
00502 case SIOCGIWENCODE:
00503
00504 if (event->u.data.flags & ~IW_ENCODE_DISABLED) {
00505 DLOG_DEBUG("Encrypted network");
00506 scan_results->cap_bits |= WLANCOND_WEP;
00507 } else {
00508 scan_results->cap_bits |= WLANCOND_OPEN;
00509 }
00510
00511 break;
00512 case SIOCGIWSCAN:
00513 {
00514 remove_scan_timer();
00515
00516 if (get_scan_state() == SCAN_ACTIVE) {
00517 DLOG_INFO("Scan results ready -- scan active");
00518 if (ask_scan_results(ifindex) == FALSE) {
00519 DLOG_ERR("Getting scan results failed");
00520
00521 set_wlan_state(WLAN_NOT_INITIALIZED,
00522 DISCONNECTED_SIGNAL,
00523 FORCE_YES);
00524 }
00525 #ifdef DEBUG
00526 } else {
00527 DLOG_DEBUG("Scan results ready -- "
00528 "not requested");
00529 #endif
00530 }
00531 }
00532 break;
00533
00534 case IWEVCUSTOM:
00535 {
00536
00537
00538 handle_custom_event(event->u.data.pointer,
00539 event->u.data.length, scan_results);
00540 }
00541 break;
00542
00543 case IWEVGENIE:
00544 {
00545 if (handle_wpa_ie_event_binary(event->u.data.pointer,
00546 event->u.data.length,
00547 scan_results) < 0) {
00548 DLOG_ERR("Error in IE handling");
00549 }
00550
00551 }
00552 break;
00553 #if 0
00554 case IWEVASSOCRESPIE:
00555 case IWEVASSOCREQIE:
00556 {
00557 if (handle_wpa_ie_assoc_event_binary(
00558 event->u.data.pointer,
00559 event->u.data.length) < 0) {
00560
00561
00562 set_wlan_state(WLAN_NOT_INITIALIZED,
00563 DISCONNECTED_SIGNAL,
00564 FORCE_YES);
00565 }
00566 }
00567 #endif
00568 break;
00569 case SIOCSIWFREQ:
00570 case SIOCSIWENCODE:
00571 case SIOCSIWMODE:
00572 case SIOCSIWESSID:
00573 break;
00574
00575 default:
00576 DLOG_DEBUG("Unknown Wireless event 0x%04X", event->cmd);
00577 }
00578
00579 return 0;
00580 }
00588 static void save_caps(struct scan_results_t *scan_results,
00589 struct ap_info_t *ap_info, unsigned char *p,
00590 unsigned int length)
00591 {
00592 gboolean no_wep = FALSE;
00593
00594 scan_results->wpa_ie = g_memdup(p, length);
00595 scan_results->wpa_ie_len = length;
00596
00597
00598 if (ap_info->key_mgmt & WPA_PSK) {
00599 scan_results->cap_bits |= WLANCOND_WPA_PSK;
00600 no_wep = TRUE;
00601 }
00602 if (ap_info->key_mgmt & WPA_802_1X) {
00603 scan_results->cap_bits |= WLANCOND_WPA_EAP;
00604
00605 scan_results->cap_bits &= ~WLANCOND_WPS_MASK;
00606 no_wep = TRUE;
00607 }
00608 DLOG_DEBUG("%s %s supported",
00609 (scan_results->cap_bits & WLANCOND_WPA2) ? "WPA2":"WPA",
00610 (ap_info->key_mgmt & WPA_PSK) ? "PSK":"EAP");
00611
00612
00613
00614 if (ap_info->pairwise_cipher & CIPHER_SUITE_CCMP) {
00615 scan_results->cap_bits |= WLANCOND_WPA_AES;
00616 }
00617 if (ap_info->pairwise_cipher & CIPHER_SUITE_TKIP) {
00618 scan_results->cap_bits |= WLANCOND_WPA_TKIP;
00619 }
00620 if (ap_info->pairwise_cipher & CIPHER_SUITE_WEP40 ||
00621 ap_info->pairwise_cipher & CIPHER_SUITE_WEP104) {
00622
00623 if (no_wep == TRUE) {
00624 DLOG_DEBUG("In WPA mode WEP is not allowed");
00625 scan_results->cap_bits |= WLANCOND_UNSUPPORTED_NETWORK;
00626 }
00627 }
00628 DLOG_DEBUG("%s/%s/%s/%s for unicast",
00629 (ap_info->pairwise_cipher & CIPHER_SUITE_CCMP)?
00630 "AES":"-",
00631 (ap_info->pairwise_cipher & CIPHER_SUITE_TKIP)?
00632 "TKIP":"-",
00633 (ap_info->pairwise_cipher & CIPHER_SUITE_WEP104)?
00634 "WEP104":"-",
00635 (ap_info->pairwise_cipher & CIPHER_SUITE_WEP40)?
00636 "WEP40":"-");
00637
00638 if (ap_info->group_cipher & CIPHER_SUITE_CCMP) {
00639 scan_results->cap_bits |= WLANCOND_WPA_AES_GROUP;
00640 }
00641 if (ap_info->group_cipher & CIPHER_SUITE_TKIP) {
00642 scan_results->cap_bits |= WLANCOND_WPA_TKIP_GROUP;
00643 }
00644 if (ap_info->group_cipher & CIPHER_SUITE_WEP40 ||
00645 ap_info->group_cipher & CIPHER_SUITE_WEP104) {
00646
00647 if (no_wep == TRUE) {
00648 DLOG_DEBUG("In WPA mode WEP is not allowed");
00649 scan_results->cap_bits |= WLANCOND_UNSUPPORTED_NETWORK;
00650 }
00651 }
00652 DLOG_DEBUG("%s/%s/%s/%s for multicast",
00653 (ap_info->group_cipher & CIPHER_SUITE_CCMP)?"AES":"-",
00654 (ap_info->group_cipher & CIPHER_SUITE_TKIP)?"TKIP":"-",
00655 (ap_info->group_cipher & CIPHER_SUITE_WEP104)?
00656 "WEP104":"-",
00657 (ap_info->group_cipher & CIPHER_SUITE_WEP40)?
00658 "WEP40":"-");
00659
00660 if (no_wep == TRUE) {
00661 scan_results->cap_bits &= ~WLANCOND_WEP;
00662 }
00663
00664
00665 }
00666
00673 static int handle_wpa_ie_event_binary(unsigned char* p, unsigned int length,
00674 struct scan_results_t *scan_results)
00675 {
00676 struct ap_info_t ap_info;
00677 const guint8 WPA1_OUI[] = { 0x00, 0x50, 0xf2, 0x01 };
00678 const guint8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
00679 guchar* ie_pos = NULL;
00680 guint ie_len = 0;
00681 guint index = 0;
00682
00683 while(index <= (length - 2))
00684 {
00685
00686 if (p[index] == RSN_ELEMENT && length-index > 3) {
00687
00688 guint len = p[index+1]+2;
00689
00690 if (len > length-index) {
00691 DLOG_ERR("Too long IE");
00692 return -1;
00693 }
00694
00695
00696 scan_results->cap_bits |= WLANCOND_WPA2;
00697
00698 ie_pos = &p[index];
00699 ie_len = len;
00700 }
00701
00702 else if (p[index] == WPA_ELEMENT && length-index > 7 &&
00703 memcmp(&p[index + 2], WPA1_OUI,
00704 sizeof(WPA1_OUI)) == 0)
00705 {
00706 guint len = p[index+1]+2;
00707
00708 if (len > length-index) {
00709 DLOG_ERR("Too long IE");
00710 return -1;
00711 }
00712
00713 if (!(scan_results->cap_bits &
00714 WLANCOND_ENCRYPT_WPA2_MASK)) {
00715 ie_pos = &p[index];
00716 ie_len = len;
00717 } else {
00718 DLOG_DEBUG("Ignoring WPA IE");
00719 }
00720 }
00721
00722 else if (p[index] == WPA_ELEMENT && length-index > 3 &&
00723 memcmp(&p[index + 2], WPS_OUI,
00724 sizeof(WPS_OUI)) == 0)
00725 {
00726 guint len = p[index+1]+2;
00727
00728 if (len > length-index) {
00729 DLOG_ERR("Too long IE");
00730 return -1;
00731 }
00732 if (handle_wps_ie(&p[index+6], scan_results, len) < 0) {
00733 return -1;
00734 }
00735 }
00736
00737 index +=p[index+1]+2;
00738 }
00739
00740 if (ie_pos != NULL) {
00741
00742 memset(&ap_info, 0, sizeof(ap_info));
00743 if (scan_results->cap_bits & WLANCOND_ENCRYPT_WPA2_MASK) {
00744 if (parse_rsn_ie(ie_pos, ie_len, &ap_info) < 0) {
00745 return -1;
00746 }
00747 } else {
00748 if (parse_wpa_ie(ie_pos, ie_len, &ap_info) < 0) {
00749 return -1;
00750 }
00751 }
00752
00753 save_caps(scan_results, &ap_info, ie_pos, ie_len);
00754 }
00755
00756 return 0;
00757 }
00762 static gboolean roam_scanning(void) {
00763 struct timeval tv;
00764
00765 if (gettimeofday(&tv, NULL) <0)
00766 return FALSE;
00767
00768 if (tv.tv_sec > wlan_status.last_scan + WLANCOND_MIN_ROAM_SCAN_INTERVAL)
00769 return FALSE;
00770
00771 DLOG_DEBUG("Already roam scanning");
00772 return TRUE;
00773 }
00774
00781 static void handle_custom_event(char* event_pointer, int length,
00782 struct scan_results_t *scan_results)
00783 {
00784
00785 if (length < 5 || length > IW_GENERIC_IE_MAX) {
00786 DLOG_DEBUG("Invalid length event");
00787 return;
00788 }
00789 if (strncmp(event_pointer, "tsf=", 4) == 0) {
00790
00791 } else if (strncmp(event_pointer, "LOWSIGNAL", 10) == 0) {
00792 DLOG_INFO("Low signal");
00793 set_wlan_signal(WLANCOND_LOW);
00794 if (get_wlan_state() == WLAN_CONNECTED) {
00795 if (roam_scanning())
00796
00797 schedule_scan(WLANCOND_MIN_ROAM_SCAN_INTERVAL);
00798 else
00799 schedule_scan(WLANCOND_INITIAL_ROAM_SCAN_DELAY);
00800 }
00801 } else if (strncmp(event_pointer, "HIGHSIGNAL", 11) == 0) {
00802 DLOG_INFO("High signal");
00803 set_wlan_signal(WLANCOND_HIGH);
00804 } else if (strncmp(event_pointer, "MLME-MICHAELMICFAILURE.indication",
00805 33) == 0) {
00806 dbus_bool_t key_type = TRUE;
00807
00808 if (strstr(event_pointer, "unicast") != NULL)
00809 key_type = FALSE;
00810
00811 DLOG_INFO("MIC failure event for %s key",
00812 key_type==FALSE?"unicast":"group");
00813 handle_mic_failure(key_type, wlan_status.conn.bssid);
00814 } else {
00815
00816
00817 }
00818 }
00819
00827 static int index2name(int skfd, int ifindex, char *name)
00828 {
00829 struct ifreq irq;
00830 int ret = 0;
00831
00832 memset(name, 0, IFNAMSIZ + 1);
00833 memset(&irq, 0, sizeof(irq));
00834
00835
00836 irq.ifr_ifindex = ifindex;
00837
00838 if (ioctl(skfd, SIOCGIFNAME, &irq) < 0)
00839 ret = -1;
00840 else
00841 strncpy(name, irq.ifr_name, IFNAMSIZ);
00842
00843 return ret;
00844 }
00845
00851 struct wireless_iface *get_interface_data(int ifindex)
00852 {
00853 struct wireless_iface *curr;
00854 int skfd;
00855
00856
00857 curr = interface_cache;
00858
00859 while(curr != NULL)
00860 {
00861
00862 if (curr->ifindex == ifindex)
00863 {
00864
00865
00866
00867
00868 return(curr);
00869 }
00870
00871 curr = curr->next;
00872 }
00873
00874 skfd = socket_open();
00875
00876 curr = g_new(struct wireless_iface, 1);
00877
00878 curr->ifindex = ifindex;
00879
00880
00881 if (index2name(skfd, ifindex, curr->ifname) < 0)
00882 {
00883 perror("index2name");
00884 g_free(curr);
00885 return NULL;
00886 }
00887 curr->has_range = (iw_get_range_info(skfd, curr->ifname,
00888 &curr->range) >= 0);
00889
00890 curr->next = interface_cache;
00891 interface_cache = curr;
00892
00893 return(curr);
00894 }
00895
00903 static int print_event_stream(int ifindex, char *data, int len)
00904 {
00905 struct iw_event iwe;
00906 struct stream_descr stream;
00907 struct wireless_iface *wireless_if;
00908 struct scan_results_t scan_results;
00909 int ret;
00910
00911 wireless_if = get_interface_data(ifindex);
00912
00913 if (wireless_if == NULL)
00914 return (-1);
00915
00916 memset(&scan_results, 0, sizeof(struct scan_results_t));
00917 memset(&iwe, 0, sizeof(iwe));
00918
00919
00920
00921
00922 iw_init_event_stream(&stream, data, len);
00923 do {
00924 ret = iw_extract_event_stream(&stream, &iwe,
00925 wireless_if->range.we_version_compiled);
00926 if (ret != 0)
00927 {
00928 if (ret > 0)
00929 print_event_token(&iwe, &scan_results, ifindex,
00930 FALSE);
00931 else
00932 die("Invalid event");
00933 }
00934 } while (ret > 0);
00935
00936 return 0;
00937 }
00941 void del_all_interface_data(void)
00942 {
00943 struct wireless_iface *curr;
00944 struct wireless_iface *next;
00945
00946 curr = interface_cache;
00947
00948 while(curr)
00949 {
00950 next = curr->next;
00951
00952 g_free(curr);
00953
00954 curr = next;
00955 }
00956 }
00957
00962 static void del_interface_data(int ifindex)
00963 {
00964 struct wireless_iface * curr;
00965 struct wireless_iface * prev = NULL;
00966 struct wireless_iface * next;
00967
00968
00969 curr = interface_cache;
00970 while(curr)
00971 {
00972 next = curr->next;
00973
00974 DLOG_DEBUG("Removing interface %s.", curr->ifname);
00975
00976
00977 if(curr->ifindex == ifindex)
00978 {
00979
00980 if(!prev)
00981 interface_cache = next;
00982 else
00983 prev->next = next;
00984
00985
00986
00987 if( !strcmp(wlan_status.ifname, curr->ifname) ) {
00988 DLOG_DEBUG("Current interface in use, "
00989 "disconnecting...");
00990 set_scan_state(SCAN_NOT_ACTIVE);
00991
00992
00993 set_wlan_state(WLAN_NOT_INITIALIZED,
00994 DISCONNECTED_SIGNAL,
00995 FORCE_YES);
00996 }
00997
00998
00999 g_free(curr);
01000 }
01001 else
01002 {
01003
01004 prev = curr;
01005 }
01006
01007
01008 curr = next;
01009 }
01010 }
01015 static void handle_message(struct nlmsghdr *hdr)
01016 {
01017 struct ifinfomsg *infomsg;
01018 int attrlen;
01019 struct rtattr *rtattr;
01020
01021 infomsg = NLMSG_DATA(hdr);
01022
01023
01024 if(hdr->nlmsg_type == RTM_DELLINK)
01025 {
01026
01027 del_interface_data(infomsg->ifi_index);
01028 return;
01029 }
01030
01031 if(hdr->nlmsg_type != RTM_NEWLINK)
01032 return;
01033
01034 if(hdr->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg))) {
01035 attrlen = hdr->nlmsg_len-NLMSG_ALIGN(sizeof(struct ifinfomsg));
01036 rtattr = (void *) ((char *) infomsg +
01037 NLMSG_ALIGN(sizeof(struct ifinfomsg)));
01038 while (RTA_OK(rtattr, attrlen)) {
01039
01040 if (rtattr->rta_type == IFLA_WIRELESS) {
01041
01042 print_event_stream(infomsg->ifi_index,
01043 (char *)rtattr +
01044 RTA_ALIGN(sizeof(struct rtattr)),
01045 rtattr->rta_len -
01046 RTA_ALIGN(sizeof(struct rtattr)));
01047 }
01048 rtattr = RTA_NEXT(rtattr, attrlen);
01049 }
01050 }
01051 }
01056 static void handle_netlink_event(int fd)
01057 {
01058 char buf[1024];
01059 struct sockaddr_nl nl;
01060 socklen_t nl_len = sizeof(struct sockaddr_nl);
01061 int res;
01062
01063 while (1) {
01064 res = recvfrom (fd, buf, sizeof(buf), MSG_DONTWAIT,
01065 (struct sockaddr*)&nl, &nl_len);
01066
01067
01068 if (res < 0) {
01069 if (errno != EINTR && errno != EAGAIN) {
01070 DLOG_ERR("Error reading netlink socket");
01071 }
01072
01073 return;
01074 }
01075
01076
01077 if (res == 0) {
01078 return;
01079 }
01080 int len;
01081 struct nlmsghdr *hdr = (struct nlmsghdr*)buf;
01082
01083 while (res >= (int)sizeof(*hdr))
01084 {
01085 len = hdr->nlmsg_len;
01086
01087 if ((len - (int)sizeof(*hdr) < 0) || len > res) {
01088 DLOG_ERR("Error in netlink message length");
01089 break;
01090 }
01091
01092 if (hdr->nlmsg_type == RTM_NEWLINK ||
01093 hdr->nlmsg_type == RTM_DELLINK) {
01094 handle_message(hdr);
01095 }
01096
01097
01098 len = NLMSG_ALIGN(len);
01099 res -= len;
01100 hdr = (struct nlmsghdr*)((char*)hdr+len);
01101 }
01102 }
01103 }
01104
01110 static int init_wi (struct rtnl_handle *rth)
01111 {
01112 unsigned int addr_len;
01113
01114 memset(rth, 0, sizeof(struct rtnl_handle));
01115
01116 rth->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
01117 if (rth->fd < 0) {
01118 DLOG_ERR("socket()");
01119 return -1;
01120 }
01121 memset(&rth->local, 0, sizeof(rth->local));
01122 rth->local.nl_family = AF_NETLINK;
01123 rth->local.nl_groups = RTMGRP_LINK;
01124
01125 if (bind(rth->fd, (struct sockaddr*)&rth->local,
01126 sizeof(rth->local)) < 0) {
01127 DLOG_ERR("bind()");
01128 return -1;
01129 }
01130 addr_len = sizeof(rth->local);
01131 if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
01132 DLOG_ERR("Cannot getsockname");
01133 return -1;
01134 }
01135 if (addr_len != sizeof(rth->local)) {
01136 DLOG_ERR("Wrong address length %d", addr_len);
01137 return -1;
01138 }
01139 if (rth->local.nl_family != AF_NETLINK) {
01140 DLOG_ERR("Wrong address family %d", rth->local.nl_family);
01141 return -1;
01142 }
01143
01144 return 0;
01145 }
01146
01154 static gboolean _monitor_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
01155 {
01156 int fd;
01157
01158 if (cond != G_IO_IN) {
01159 guint watch_id = *((guint *)data);
01160 DLOG_ERR("Error message from wireless interface");
01161 g_source_remove(watch_id);
01162 g_io_channel_unref(chan);
01163 return FALSE;
01164 }
01165
01166 fd = g_io_channel_unix_get_fd(chan);
01167 if (fd >= 0) {
01168 handle_netlink_event(fd);
01169 }
01170
01171 return TRUE;
01172 }
01173
01178 gboolean monitor_wi(void) {
01179 static guint watch_id = 0;
01180 GIOChannel *gio;
01181 struct rtnl_handle rth;
01182
01183 if (init_wi(&rth) < 0)
01184 return FALSE;
01185
01186 gio = g_io_channel_unix_new(rth.fd);
01187 g_io_channel_set_close_on_unref(gio, TRUE);
01188 watch_id = g_io_add_watch(gio, G_IO_IN | G_IO_PRI | G_IO_ERR |
01189 G_IO_HUP, _monitor_cb, &watch_id);
01190 return TRUE;
01191 }