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 (wlan_status.allow_all_ciphers == TRUE) {
00621 if (ap_info->pairwise_cipher & CIPHER_SUITE_WEP40) {
00622 scan_results->extra_cap_bits |= WLANCOND_WEP40;
00623 }
00624 if (ap_info->pairwise_cipher & CIPHER_SUITE_WEP104) {
00625 scan_results->extra_cap_bits |= WLANCOND_WEP104;
00626 }
00627 if (ap_info->group_cipher & CIPHER_SUITE_WEP40) {
00628 scan_results->extra_cap_bits |= WLANCOND_WEP40_GROUP;
00629 }
00630 if (ap_info->group_cipher & CIPHER_SUITE_WEP104) {
00631 scan_results->extra_cap_bits |= WLANCOND_WEP104_GROUP;
00632 }
00633 } else {
00634 if (ap_info->pairwise_cipher & CIPHER_SUITE_WEP40 ||
00635 ap_info->pairwise_cipher & CIPHER_SUITE_WEP104 ||
00636 ap_info->group_cipher & CIPHER_SUITE_WEP40 ||
00637 ap_info->group_cipher & CIPHER_SUITE_WEP104) {
00638 DLOG_DEBUG("In WPA mode WEP is not allowed");
00639 scan_results->cap_bits |=
00640 WLANCOND_UNSUPPORTED_NETWORK;
00641 }
00642 }
00643
00644 DLOG_DEBUG("%s/%s/%s/%s for unicast",
00645 (ap_info->pairwise_cipher & CIPHER_SUITE_CCMP)?
00646 "AES":"-",
00647 (ap_info->pairwise_cipher & CIPHER_SUITE_TKIP)?
00648 "TKIP":"-",
00649 (ap_info->pairwise_cipher & CIPHER_SUITE_WEP104)?
00650 "WEP104":"-",
00651 (ap_info->pairwise_cipher & CIPHER_SUITE_WEP40)?
00652 "WEP40":"-");
00653
00654 if (ap_info->group_cipher & CIPHER_SUITE_CCMP) {
00655 scan_results->cap_bits |= WLANCOND_WPA_AES_GROUP;
00656 }
00657 if (ap_info->group_cipher & CIPHER_SUITE_TKIP) {
00658 scan_results->cap_bits |= WLANCOND_WPA_TKIP_GROUP;
00659 }
00660 if (ap_info->group_cipher & CIPHER_SUITE_WEP40 ||
00661 ap_info->group_cipher & CIPHER_SUITE_WEP104) {
00662
00663 if (no_wep == TRUE && wlan_status.allow_all_ciphers == FALSE) {
00664 DLOG_DEBUG("In WPA mode WEP is not allowed");
00665 scan_results->cap_bits |= WLANCOND_UNSUPPORTED_NETWORK;
00666 }
00667 }
00668 DLOG_DEBUG("%s/%s/%s/%s for multicast",
00669 (ap_info->group_cipher & CIPHER_SUITE_CCMP)?"AES":"-",
00670 (ap_info->group_cipher & CIPHER_SUITE_TKIP)?"TKIP":"-",
00671 (ap_info->group_cipher & CIPHER_SUITE_WEP104)?
00672 "WEP104":"-",
00673 (ap_info->group_cipher & CIPHER_SUITE_WEP40)?
00674 "WEP40":"-");
00675
00676 if (no_wep == TRUE) {
00677 scan_results->cap_bits &= ~WLANCOND_WEP;
00678 }
00679
00680
00681 }
00682
00689 static int handle_wpa_ie_event_binary(unsigned char* p, unsigned int length,
00690 struct scan_results_t *scan_results)
00691 {
00692 struct ap_info_t ap_info;
00693 const guint8 WPA1_OUI[] = { 0x00, 0x50, 0xf2, 0x01 };
00694 const guint8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
00695 guchar* ie_pos = NULL;
00696 guint ie_len = 0;
00697 guint index = 0;
00698
00699 while(index <= (length - 2))
00700 {
00701
00702 if (p[index] == RSN_ELEMENT && length-index > 3) {
00703
00704 guint len = p[index+1]+2;
00705
00706 if (len > length-index) {
00707 DLOG_ERR("Too long IE");
00708 return -1;
00709 }
00710
00711
00712 scan_results->cap_bits |= WLANCOND_WPA2;
00713
00714 ie_pos = &p[index];
00715 ie_len = len;
00716 }
00717
00718 else if (p[index] == WPA_ELEMENT && length-index > 7 &&
00719 memcmp(&p[index + 2], WPA1_OUI,
00720 sizeof(WPA1_OUI)) == 0)
00721 {
00722 guint len = p[index+1]+2;
00723
00724 if (len > length-index) {
00725 DLOG_ERR("Too long IE");
00726 return -1;
00727 }
00728
00729 if (!(scan_results->cap_bits &
00730 WLANCOND_ENCRYPT_WPA2_MASK)) {
00731 ie_pos = &p[index];
00732 ie_len = len;
00733 } else {
00734 DLOG_DEBUG("Ignoring WPA IE");
00735 }
00736 }
00737
00738 else if (p[index] == WPA_ELEMENT && length-index > 3 &&
00739 memcmp(&p[index + 2], WPS_OUI,
00740 sizeof(WPS_OUI)) == 0)
00741 {
00742 guint len = p[index+1]+2;
00743
00744 if (len > length-index) {
00745 DLOG_ERR("Too long IE");
00746 return -1;
00747 }
00748 if (handle_wps_ie(&p[index+6], scan_results, len) < 0) {
00749 return -1;
00750 }
00751 }
00752
00753 index +=p[index+1]+2;
00754 }
00755
00756 if (ie_pos != NULL) {
00757
00758 memset(&ap_info, 0, sizeof(ap_info));
00759 if (scan_results->cap_bits & WLANCOND_ENCRYPT_WPA2_MASK) {
00760 if (parse_rsn_ie(ie_pos, ie_len, &ap_info) < 0) {
00761 return -1;
00762 }
00763 } else {
00764 if (parse_wpa_ie(ie_pos, ie_len, &ap_info) < 0) {
00765 return -1;
00766 }
00767 }
00768
00769 save_caps(scan_results, &ap_info, ie_pos, ie_len);
00770 }
00771
00772 return 0;
00773 }
00778 static gboolean roam_scanning(void) {
00779 struct timeval tv;
00780
00781 if (gettimeofday(&tv, NULL) <0)
00782 return FALSE;
00783
00784 if (tv.tv_sec > wlan_status.last_scan + WLANCOND_MIN_ROAM_SCAN_INTERVAL)
00785 return FALSE;
00786
00787 DLOG_DEBUG("Already roam scanning");
00788 return TRUE;
00789 }
00790
00797 static void handle_custom_event(char* event_pointer, int length,
00798 struct scan_results_t *scan_results)
00799 {
00800
00801 if (length < 5 || length > IW_GENERIC_IE_MAX) {
00802 DLOG_DEBUG("Invalid length event");
00803 return;
00804 }
00805 if (strncmp(event_pointer, "tsf=", 4) == 0) {
00806
00807 } else if (strncmp(event_pointer, "LOWSIGNAL", 10) == 0) {
00808 DLOG_INFO("Low signal");
00809 set_wlan_signal(WLANCOND_LOW);
00810 if (get_wlan_state() == WLAN_CONNECTED) {
00811 if (roam_scanning())
00812
00813 schedule_scan(WLANCOND_MIN_ROAM_SCAN_INTERVAL);
00814 else
00815 schedule_scan(WLANCOND_INITIAL_ROAM_SCAN_DELAY);
00816 }
00817 } else if (strncmp(event_pointer, "HIGHSIGNAL", 11) == 0) {
00818 DLOG_INFO("High signal");
00819 set_wlan_signal(WLANCOND_HIGH);
00820 } else if (strncmp(event_pointer, "MLME-MICHAELMICFAILURE.indication",
00821 33) == 0) {
00822 dbus_bool_t key_type = TRUE;
00823
00824 if (strstr(event_pointer, "unicast") != NULL)
00825 key_type = FALSE;
00826
00827 DLOG_INFO("MIC failure event for %s key",
00828 key_type==FALSE?"unicast":"group");
00829 handle_mic_failure(key_type, wlan_status.conn.bssid);
00830 } else {
00831
00832
00833 }
00834 }
00835
00843 static int index2name(int skfd, int ifindex, char *name)
00844 {
00845 struct ifreq irq;
00846 int ret = 0;
00847
00848 memset(name, 0, IFNAMSIZ + 1);
00849 memset(&irq, 0, sizeof(irq));
00850
00851
00852 irq.ifr_ifindex = ifindex;
00853
00854 if (ioctl(skfd, SIOCGIFNAME, &irq) < 0)
00855 ret = -1;
00856 else
00857 strncpy(name, irq.ifr_name, IFNAMSIZ);
00858
00859 return ret;
00860 }
00861
00867 struct wireless_iface *get_interface_data(int ifindex)
00868 {
00869 struct wireless_iface *curr;
00870 int skfd;
00871
00872
00873 curr = interface_cache;
00874
00875 while(curr != NULL)
00876 {
00877
00878 if (curr->ifindex == ifindex)
00879 {
00880
00881
00882
00883
00884 return(curr);
00885 }
00886
00887 curr = curr->next;
00888 }
00889
00890 skfd = socket_open();
00891
00892 curr = g_new(struct wireless_iface, 1);
00893
00894 curr->ifindex = ifindex;
00895
00896
00897 if (index2name(skfd, ifindex, curr->ifname) < 0)
00898 {
00899 perror("index2name");
00900 g_free(curr);
00901 return NULL;
00902 }
00903 curr->has_range = (iw_get_range_info(skfd, curr->ifname,
00904 &curr->range) >= 0);
00905
00906 curr->next = interface_cache;
00907 interface_cache = curr;
00908
00909 return(curr);
00910 }
00911
00919 static int print_event_stream(int ifindex, char *data, int len)
00920 {
00921 struct iw_event iwe;
00922 struct stream_descr stream;
00923 struct wireless_iface *wireless_if;
00924 struct scan_results_t scan_results;
00925 int ret;
00926
00927 wireless_if = get_interface_data(ifindex);
00928
00929 if (wireless_if == NULL)
00930 return (-1);
00931
00932 memset(&scan_results, 0, sizeof(struct scan_results_t));
00933 memset(&iwe, 0, sizeof(iwe));
00934
00935
00936
00937
00938 iw_init_event_stream(&stream, data, len);
00939 do {
00940 ret = iw_extract_event_stream(&stream, &iwe,
00941 wireless_if->range.we_version_compiled);
00942 if (ret != 0)
00943 {
00944 if (ret > 0)
00945 print_event_token(&iwe, &scan_results, ifindex,
00946 FALSE);
00947 else
00948 die("Invalid event");
00949 }
00950 } while (ret > 0);
00951
00952 return 0;
00953 }
00957 void del_all_interface_data(void)
00958 {
00959 struct wireless_iface *curr;
00960 struct wireless_iface *next;
00961
00962 curr = interface_cache;
00963
00964 while(curr)
00965 {
00966 next = curr->next;
00967
00968 g_free(curr);
00969
00970 curr = next;
00971 }
00972 }
00973
00978 static void del_interface_data(int ifindex)
00979 {
00980 struct wireless_iface * curr;
00981 struct wireless_iface * prev = NULL;
00982 struct wireless_iface * next;
00983
00984
00985 curr = interface_cache;
00986 while(curr)
00987 {
00988 next = curr->next;
00989
00990 DLOG_DEBUG("Removing interface %s.", curr->ifname);
00991
00992
00993 if(curr->ifindex == ifindex)
00994 {
00995
00996 if(!prev)
00997 interface_cache = next;
00998 else
00999 prev->next = next;
01000
01001
01002
01003 if( !strcmp(wlan_status.ifname, curr->ifname) ) {
01004 DLOG_DEBUG("Current interface in use, "
01005 "disconnecting...");
01006 set_scan_state(SCAN_NOT_ACTIVE);
01007
01008
01009 set_wlan_state(WLAN_NOT_INITIALIZED,
01010 DISCONNECTED_SIGNAL,
01011 FORCE_YES);
01012 }
01013
01014
01015 g_free(curr);
01016 }
01017 else
01018 {
01019
01020 prev = curr;
01021 }
01022
01023
01024 curr = next;
01025 }
01026 }
01031 static void handle_message(struct nlmsghdr *hdr)
01032 {
01033 struct ifinfomsg *infomsg;
01034 int attrlen;
01035 struct rtattr *rtattr;
01036
01037 infomsg = NLMSG_DATA(hdr);
01038
01039
01040 if(hdr->nlmsg_type == RTM_DELLINK)
01041 {
01042
01043 del_interface_data(infomsg->ifi_index);
01044 return;
01045 }
01046
01047 if(hdr->nlmsg_type != RTM_NEWLINK)
01048 return;
01049
01050 if(hdr->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg))) {
01051 attrlen = hdr->nlmsg_len-NLMSG_ALIGN(sizeof(struct ifinfomsg));
01052 rtattr = (void *) ((char *) infomsg +
01053 NLMSG_ALIGN(sizeof(struct ifinfomsg)));
01054 while (RTA_OK(rtattr, attrlen)) {
01055
01056 if (rtattr->rta_type == IFLA_WIRELESS) {
01057
01058 print_event_stream(infomsg->ifi_index,
01059 (char *)rtattr +
01060 RTA_ALIGN(sizeof(struct rtattr)),
01061 rtattr->rta_len -
01062 RTA_ALIGN(sizeof(struct rtattr)));
01063 }
01064 rtattr = RTA_NEXT(rtattr, attrlen);
01065 }
01066 }
01067 }
01072 static void handle_netlink_event(int fd)
01073 {
01074 char buf[1024];
01075 struct sockaddr_nl nl;
01076 socklen_t nl_len = sizeof(struct sockaddr_nl);
01077 int res;
01078
01079 while (1) {
01080 res = recvfrom (fd, buf, sizeof(buf), MSG_DONTWAIT,
01081 (struct sockaddr*)&nl, &nl_len);
01082
01083
01084 if (res < 0) {
01085 if (errno != EINTR && errno != EAGAIN) {
01086 DLOG_ERR("Error reading netlink socket");
01087 }
01088
01089 return;
01090 }
01091
01092
01093 if (res == 0) {
01094 return;
01095 }
01096 int len;
01097 struct nlmsghdr *hdr = (struct nlmsghdr*)buf;
01098
01099 while (res >= (int)sizeof(*hdr))
01100 {
01101 len = hdr->nlmsg_len;
01102
01103 if ((len - (int)sizeof(*hdr) < 0) || len > res) {
01104 DLOG_ERR("Error in netlink message length");
01105 break;
01106 }
01107
01108 if (hdr->nlmsg_type == RTM_NEWLINK ||
01109 hdr->nlmsg_type == RTM_DELLINK) {
01110 handle_message(hdr);
01111 }
01112
01113
01114 len = NLMSG_ALIGN(len);
01115 res -= len;
01116 hdr = (struct nlmsghdr*)((char*)hdr+len);
01117 }
01118 }
01119 }
01120
01126 static int init_wi (struct rtnl_handle *rth)
01127 {
01128 unsigned int addr_len;
01129
01130 memset(rth, 0, sizeof(struct rtnl_handle));
01131
01132 rth->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
01133 if (rth->fd < 0) {
01134 DLOG_ERR("socket()");
01135 return -1;
01136 }
01137 memset(&rth->local, 0, sizeof(rth->local));
01138 rth->local.nl_family = AF_NETLINK;
01139 rth->local.nl_groups = RTMGRP_LINK;
01140
01141 if (bind(rth->fd, (struct sockaddr*)&rth->local,
01142 sizeof(rth->local)) < 0) {
01143 DLOG_ERR("bind()");
01144 return -1;
01145 }
01146 addr_len = sizeof(rth->local);
01147 if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
01148 DLOG_ERR("Cannot getsockname");
01149 return -1;
01150 }
01151 if (addr_len != sizeof(rth->local)) {
01152 DLOG_ERR("Wrong address length %d", addr_len);
01153 return -1;
01154 }
01155 if (rth->local.nl_family != AF_NETLINK) {
01156 DLOG_ERR("Wrong address family %d", rth->local.nl_family);
01157 return -1;
01158 }
01159
01160 return 0;
01161 }
01162
01170 static gboolean _monitor_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
01171 {
01172 int fd;
01173
01174 if (cond != G_IO_IN) {
01175 guint watch_id = *((guint *)data);
01176 DLOG_ERR("Error message from wireless interface");
01177 g_source_remove(watch_id);
01178 g_io_channel_unref(chan);
01179 return FALSE;
01180 }
01181
01182 fd = g_io_channel_unix_get_fd(chan);
01183 if (fd >= 0) {
01184 handle_netlink_event(fd);
01185 }
01186
01187 return TRUE;
01188 }
01189
01194 gboolean monitor_wi(void) {
01195 static guint watch_id = 0;
01196 GIOChannel *gio;
01197 struct rtnl_handle rth;
01198
01199 if (init_wi(&rth) < 0)
01200 return FALSE;
01201
01202 gio = g_io_channel_unix_new(rth.fd);
01203 g_io_channel_set_close_on_unref(gio, TRUE);
01204 watch_id = g_io_add_watch(gio, G_IO_IN | G_IO_PRI | G_IO_ERR |
01205 G_IO_HUP, _monitor_cb, &watch_id);
01206 return TRUE;
01207 }