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(const char *message, guchar* mac)
00070 {
00071 DLOG_DEBUG("%s %02x:%02x:%02x:%02x:%02x:%02x", message, mac[0],
00072 mac[1], mac[2], mac[3], mac[4], mac[5]);
00073 }
00074 void clean_scan_results_item(gpointer data, gpointer user_data)
00075 {
00076 struct scan_results_t *scan_results = data;
00077 g_free(scan_results->wpa_ie);
00078 g_slice_free(struct scan_results_t, scan_results);
00079 }
00080
00085 void clean_scan_results(GSList **scan_results_save)
00086 {
00087
00088
00089 g_slist_foreach(*scan_results_save, clean_scan_results_item, NULL);
00090 g_slist_free(*scan_results_save);
00091
00092 *scan_results_save = NULL;
00093
00094 }
00095
00101 GSList *save_scan_results(struct scan_results_t *scan_results,
00102 GSList *scan_results_save)
00103 {
00104
00105 g_assert(scan_results != NULL);
00106
00107
00108
00109 scan_results_save = g_slist_prepend(scan_results_save, scan_results);
00110
00111 return scan_results_save;
00112 }
00118 void send_dbus_scan_results(GSList *scan_results_save, const char* sender,
00119 dbus_int32_t number_of_results)
00120 {
00121 DBusMessage *results;
00122 DBusMessageIter iter, sub;
00123 GSList *list;
00124 int list_count = 0;
00125 unsigned char* v;
00126 char* p;
00127
00128 if (sender == NULL || strnlen(sender, 5) == 0)
00129 return;
00130
00131 DLOG_DEBUG("Sending scan results to %s", sender);
00132
00133 results = new_dbus_signal(WLANCOND_SIG_PATH,
00134 WLANCOND_SIG_INTERFACE,
00135 WLANCOND_SCAN_RESULTS_SIG,
00136 sender);
00137
00138 dbus_message_iter_init_append(results, &iter);
00139
00140 if (number_of_results > WLANCOND_MAX_NETWORKS) {
00141 DLOG_DEBUG("Limiting result %d to %d", number_of_results,
00142 WLANCOND_MAX_NETWORKS);
00143 number_of_results = WLANCOND_MAX_NETWORKS;
00144 }
00145 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32,
00146 &number_of_results))
00147 die("Out of memory");
00148
00149 for (list = scan_results_save; list != NULL && list_count++ <= number_of_results; list = list->next) {
00150 struct scan_results_t *scan_results = list->data;
00151 DLOG_DEBUG("AP (%d) is %s, rssi:%d channel:%d cap:%08x",
00152 list_count,
00153 scan_results->ssid,
00154 scan_results->rssi, scan_results->channel,
00155 scan_results->cap_bits);
00156
00157 p = scan_results->ssid;
00158
00159 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "y", &sub))
00160 die("Out of memory");
00161 if (!dbus_message_iter_append_fixed_array(
00162 &sub, DBUS_TYPE_BYTE, &p, scan_results->ssid_len))
00163 die("Out of memory");
00164 if (!dbus_message_iter_close_container(&iter, &sub))
00165 die("Out of memory");
00166
00167 v = scan_results->bssid;
00168 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "y", &sub))
00169 die("Out of memory");
00170 if (!dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE,
00171 &v, ETH_ALEN))
00172 die("Out of memory");
00173 if (!dbus_message_iter_close_container(&iter, &sub))
00174 die("Out of memory");
00175 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32,
00176 &scan_results->rssi))
00177 die("Out of memory");
00178 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32,
00179 &scan_results->channel))
00180 die("Out of memory");
00181 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32,
00182 &scan_results->cap_bits))
00183 die("Out of memory");
00184 }
00185
00186 send_and_unref(get_dbus_connection(), results);
00187 }
00188
00192 void disconnected_signal(void)
00193 {
00194 DBusMessage *disconnected;
00195
00196 disconnected = new_dbus_signal(
00197 WLANCOND_SIG_PATH,
00198 WLANCOND_SIG_INTERFACE,
00199 WLANCOND_DISCONNECTED_SIG,
00200 NULL);
00201
00202 gchar* ifname = wlan_status.ifname;
00203
00204 append_dbus_args(disconnected,
00205 DBUS_TYPE_STRING, &ifname,
00206 DBUS_TYPE_INVALID);
00207
00208 send_and_unref(get_dbus_connection(), disconnected);
00209 }
00210
00216 static void connected_signal(char* bssid, dbus_int32_t auth_status)
00217 {
00218 DBusMessage *connected;
00219
00220 connected = new_dbus_signal(
00221 WLANCOND_SIG_PATH,
00222 WLANCOND_SIG_INTERFACE,
00223 WLANCOND_CONNECTED_SIG,
00224 NULL);
00225
00226 gchar* ifname = wlan_status.ifname;
00227
00228 append_dbus_args(connected,
00229 DBUS_TYPE_STRING, &ifname,
00230 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, ETH_ALEN,
00231 DBUS_TYPE_INT32, &auth_status,
00232 DBUS_TYPE_INVALID);
00233
00234 send_and_unref(get_dbus_connection(), connected);
00235 }
00236
00243 static void handle_wap_event(struct scan_results_t *scan_results,
00244 struct iw_event *event, gboolean scan_event)
00245 {
00246
00247
00248 if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
00249 return;
00250 }
00251
00252 print_mac("SIOCGIWAP:", (guchar*)event->u.ap_addr.sa_data);
00253
00254 if (scan_event == TRUE) {
00255 memcpy(scan_results->bssid, event->u.ap_addr.sa_data, ETH_ALEN);
00256 return;
00257 }
00258
00259
00260 if (memcmp(event->u.ap_addr.sa_data, "\0\0\0\0\0\0", ETH_ALEN)) {
00261
00262 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
00263 DLOG_ERR("Should not happen");
00264 return;
00265 }
00266
00267
00268 remove_connect_timer();
00269 wlan_status.retry_count = 0;
00270
00271 set_wlan_signal(WLANCOND_HIGH);
00272
00273 if (get_wpa_mode() == TRUE ||
00274 wlan_status.conn.authentication_type ==
00275 EAP_AUTH_TYPE_WFA_SC) {
00276 if (associate_supplicant() < 0)
00277 set_wlan_state(WLAN_NOT_INITIALIZED,
00278 DISCONNECTED_SIGNAL,
00279 FORCE_YES);
00280 }
00281
00282 dbus_int32_t auth_status = get_encryption_info();
00283
00284 connected_signal(event->u.ap_addr.sa_data, auth_status);
00285
00286 if (wlan_status.ip_ok == FALSE) {
00287 set_wlan_state(WLAN_NO_ADDRESS, NO_SIGNAL, FORCE_NO);
00288 } else {
00289 set_wlan_state(WLAN_CONNECTED, NO_SIGNAL, FORCE_NO);
00290 }
00291 } else {
00292 if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION &&
00293 get_scan_state() == SCAN_ACTIVE) {
00294
00295 return;
00296 }
00297 if (get_wlan_state() != WLAN_CONNECTED &&
00298 get_wlan_state() != WLAN_NO_ADDRESS &&
00299 get_wlan_state() != WLAN_INITIALIZED_FOR_CONNECTION) {
00300 DLOG_ERR("Not even connected?!?");
00301 return;
00302 }
00303
00304 if (wlan_status.conn.authentication_type ==
00305 EAP_AUTH_TYPE_WFA_SC) {
00306 return;
00307 }
00308
00309
00310 if (get_wpa_mode() == TRUE &&
00311 (get_wlan_state() == WLAN_CONNECTED ||
00312 get_wlan_state() == WLAN_NO_ADDRESS)) {
00313 disassociate_eap();
00314 clear_wpa_keys(wlan_status.conn.bssid);
00315 }
00316
00317
00318 set_bssid(NULL_BSSID);
00319 set_essid((char*)"", 1);
00320 set_wpa_ie(&wlan_status);
00321
00322 DLOG_DEBUG("Trying to find a new connection");
00323
00324
00325 decrease_signal_in_roam_cache(wlan_status.conn.bssid);
00326
00327 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL,
00328 FORCE_NO);
00329
00330 if (find_connection_and_associate(wlan_status.roam_cache,
00331 FALSE, FALSE) == 0)
00332 return;
00333
00334
00335 if (++wlan_status.retry_count > WLANCOND_MAX_SCAN_TRIES) {
00336 DLOG_ERR("Too many failures: %d",
00337 wlan_status.retry_count);
00338 set_wlan_state(WLAN_NOT_INITIALIZED,
00339 DISCONNECTED_SIGNAL,
00340 FORCE_YES);
00341 return;
00342 }
00343
00344
00345 if (scan(wlan_status.conn.ssid,
00346 wlan_status.conn.ssid_len, TRUE) < 0) {
00347
00348 set_wlan_state(WLAN_NOT_INITIALIZED,
00349 DISCONNECTED_SIGNAL,
00350 FORCE_YES);
00351 }
00352 }
00353 }
00354
00362 int print_event_token(struct iw_event *event,
00363 struct scan_results_t *scan_results,
00364 int ifindex, gboolean scan_event)
00365 {
00366
00367
00368 switch(event->cmd)
00369 {
00370 case SIOCGIWESSID:
00371 {
00372 int len = event->u.essid.length;
00373 if (len > WLANCOND_MAX_SSID_SIZE) {
00374
00375 len = WLANCOND_MAX_SSID_SIZE;
00376 }
00377
00378 if ((event->u.essid.pointer) && len) {
00379 memcpy(scan_results->ssid, event->u.essid.pointer,
00380 len);
00381 }
00382
00383
00384 len++;
00385
00386 scan_results->ssid_len = len;
00387
00388 if (event->u.essid.flags)
00389 {
00390
00391 if((event->u.essid.flags & IW_ENCODE_INDEX) > 1) {
00392
00393 #ifdef DEBUG
00394 DLOG_DEBUG("ESSID:\"%s\" [%d]\n",
00395 scan_results->ssid,
00396 (event->u.essid.flags &
00397 IW_ENCODE_INDEX));
00398 } else {
00399 DLOG_DEBUG("ESSID:\"%s\"\n",
00400 scan_results->ssid);
00401 #endif
00402 }
00403 } else {
00404 #ifdef DEBUG
00405 DLOG_DEBUG("ESSID:off/any");
00406 #endif
00407 }
00408 }
00409 break;
00410 case SIOCGIWAP:
00411 handle_wap_event(scan_results, event, scan_event);
00412 break;
00413 case IWEVQUAL:
00414
00415 scan_results->rssi = (signed char)event->u.qual.level;
00416 break;
00417 case SIOCGIWFREQ:
00418 {
00419 if (event->u.freq.e == 0) {
00420 scan_results->channel = event->u.freq.m;
00421 DLOG_DEBUG("Channel: %d", scan_results->channel);
00422 }
00423 }
00424 break;
00425 case SIOCGIWMODE:
00426 if (event->u.mode == IW_MODE_ADHOC) {
00427 DLOG_DEBUG("Adhoc network");
00428 scan_results->cap_bits |= WLANCOND_ADHOC;
00429 } else {
00430 scan_results->cap_bits |= WLANCOND_INFRA;
00431 }
00432 break;
00433 case SIOCGIWRATE:
00434 switch (event->u.bitrate.value) {
00435 case 2*500000:
00436 scan_results->cap_bits |= WLANCOND_RATE_10;
00437 break;
00438 case 4*500000:
00439 scan_results->cap_bits |= WLANCOND_RATE_20;
00440 break;
00441 case 11*500000:
00442 scan_results->cap_bits |= WLANCOND_RATE_55;
00443 break;
00444 case 12*500000:
00445 scan_results->cap_bits |= WLANCOND_RATE_60;
00446 break;
00447 case 18*500000:
00448 scan_results->cap_bits |= WLANCOND_RATE_90;
00449 break;
00450 case 22*500000:
00451 scan_results->cap_bits |= WLANCOND_RATE_110;
00452 break;
00453 case 24*500000:
00454 scan_results->cap_bits |= WLANCOND_RATE_120;
00455 break;
00456 case 36*500000:
00457 scan_results->cap_bits |= WLANCOND_RATE_180;
00458 break;
00459 case 48*500000:
00460 scan_results->cap_bits |= WLANCOND_RATE_240;
00461 break;
00462 case 52*500000:
00463 scan_results->cap_bits |= WLANCOND_RATE_260;
00464 break;
00465 case 72*500000:
00466 scan_results->cap_bits |= WLANCOND_RATE_360;
00467 break;
00468 case 96*500000:
00469 scan_results->cap_bits |= WLANCOND_RATE_480;
00470 break;
00471 case 108*500000:
00472 scan_results->cap_bits |= WLANCOND_RATE_540;
00473 break;
00474 #ifdef DEBUG
00475 default:
00476
00477 DLOG_DEBUG("Unknown rate %04x",
00478 (int)event->u.bitrate.value);
00479 break;
00480 #endif
00481 }
00482 break;
00483 case SIOCGIWENCODE:
00484
00485 if (event->u.data.flags & ~IW_ENCODE_DISABLED) {
00486 DLOG_DEBUG("Encrypted network");
00487 scan_results->cap_bits |= WLANCOND_WEP;
00488 } else {
00489 scan_results->cap_bits |= WLANCOND_OPEN;
00490 }
00491
00492 break;
00493 case SIOCGIWSCAN:
00494 {
00495 remove_scan_timer();
00496
00497 if (get_scan_state() == SCAN_ACTIVE) {
00498 DLOG_DEBUG("Scan results ready -- scan active");
00499 if (ask_scan_results(ifindex) == FALSE) {
00500 DLOG_ERR("Getting scan results failed");
00501
00502 set_wlan_state(WLAN_NOT_INITIALIZED,
00503 DISCONNECTED_SIGNAL,
00504 FORCE_YES);
00505 }
00506 #ifdef DEBUG
00507 } else {
00508 DLOG_DEBUG("Scan results ready -- not requested");
00509 #endif
00510 }
00511 }
00512 break;
00513
00514 case IWEVCUSTOM:
00515 {
00516
00517
00518 handle_custom_event(event->u.data.pointer,
00519 event->u.data.length, scan_results);
00520 }
00521 break;
00522
00523 case IWEVGENIE:
00524 {
00525 if (handle_wpa_ie_event_binary(event->u.data.pointer,
00526 event->u.data.length,
00527 scan_results) < 0) {
00528 DLOG_ERR("Error in IE handling");
00529 }
00530
00531 }
00532 break;
00533 #if 0
00534 case IWEVASSOCRESPIE:
00535 case IWEVASSOCREQIE:
00536 {
00537 if (handle_wpa_ie_assoc_event_binary(
00538 event->u.data.pointer,
00539 event->u.data.length) < 0) {
00540
00541
00542 set_wlan_state(WLAN_NOT_INITIALIZED,
00543 DISCONNECTED_SIGNAL,
00544 FORCE_YES);
00545 }
00546 }
00547 #endif
00548 break;
00549 case SIOCSIWFREQ:
00550 case SIOCSIWENCODE:
00551 case SIOCSIWMODE:
00552 case SIOCSIWESSID:
00553 break;
00554
00555 default:
00556 DLOG_DEBUG("Unknown Wireless event 0x%04X", event->cmd);
00557 }
00558
00559 return 0;
00560 }
00568 static void save_caps(struct scan_results_t *scan_results,
00569 struct ap_info_t *ap_info, unsigned char *p,
00570 unsigned int length)
00571 {
00572 gboolean no_wep = FALSE;
00573
00574 scan_results->wpa_ie = g_memdup(p, length);
00575 scan_results->wpa_ie_len = length;
00576
00577
00578 if (ap_info->key_mgmt & WPA_PSK) {
00579 scan_results->cap_bits |= WLANCOND_WPA_PSK;
00580 no_wep = TRUE;
00581 }
00582 if (ap_info->key_mgmt & WPA_802_1X) {
00583 scan_results->cap_bits |= WLANCOND_WPA_EAP;
00584
00585 scan_results->cap_bits &= ~WLANCOND_WPS_MASK;
00586 no_wep = TRUE;
00587 }
00588 DLOG_DEBUG("%s %s supported",
00589 (scan_results->cap_bits & WLANCOND_WPA2) ? "WPA2":"WPA",
00590 (ap_info->key_mgmt & WPA_PSK) ? "PSK":"EAP");
00591
00592
00593
00594 if (ap_info->pairwise_cipher & CIPHER_SUITE_CCMP) {
00595 scan_results->cap_bits |= WLANCOND_WPA_AES;
00596 }
00597 if (ap_info->pairwise_cipher & CIPHER_SUITE_TKIP) {
00598 scan_results->cap_bits |= WLANCOND_WPA_TKIP;
00599 }
00600 if (ap_info->pairwise_cipher & CIPHER_SUITE_WEP40 ||
00601 ap_info->pairwise_cipher & CIPHER_SUITE_WEP104) {
00602
00603 if (no_wep == TRUE) {
00604 DLOG_DEBUG("In WPA mode WEP is not allowed");
00605 scan_results->cap_bits |= WLANCOND_UNSUPPORTED_NETWORK;
00606 }
00607 }
00608 DLOG_DEBUG("%s/%s/%s/%s for unicast",
00609 (ap_info->pairwise_cipher & CIPHER_SUITE_CCMP)?"AES":"-",
00610 (ap_info->pairwise_cipher & CIPHER_SUITE_TKIP)?"TKIP":"-",
00611 (ap_info->pairwise_cipher & CIPHER_SUITE_WEP104)?"WEP104":"-",
00612 (ap_info->pairwise_cipher & CIPHER_SUITE_WEP40)?"WEP40":"-");
00613
00614 if (ap_info->group_cipher & CIPHER_SUITE_CCMP) {
00615 scan_results->cap_bits |= WLANCOND_WPA_AES_GROUP;
00616 }
00617 if (ap_info->group_cipher & CIPHER_SUITE_TKIP) {
00618 scan_results->cap_bits |= WLANCOND_WPA_TKIP_GROUP;
00619 }
00620 if (ap_info->group_cipher & CIPHER_SUITE_WEP40 ||
00621 ap_info->group_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 multicast",
00629 (ap_info->group_cipher & CIPHER_SUITE_CCMP)?"AES":"-",
00630 (ap_info->group_cipher & CIPHER_SUITE_TKIP)?"TKIP":"-",
00631 (ap_info->group_cipher & CIPHER_SUITE_WEP104)?"WEP104":"-",
00632 (ap_info->group_cipher & CIPHER_SUITE_WEP40)?"WEP40":"-");
00633
00634 if (no_wep == TRUE) {
00635 scan_results->cap_bits &= ~WLANCOND_WEP;
00636 }
00637
00638
00639 }
00640
00647 static int handle_wpa_ie_event_binary(unsigned char* p, unsigned int length,
00648 struct scan_results_t *scan_results)
00649 {
00650 struct ap_info_t ap_info;
00651 const guint8 WPA1_OUI[] = { 0x00, 0x50, 0xf2, 0x01 };
00652 const guint8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
00653 guchar* ie_pos = NULL;
00654 guint ie_len = 0;
00655 guint index = 0;
00656
00657 while(index <= (length - 2))
00658 {
00659
00660 if (p[index] == RSN_ELEMENT && length-index > 3) {
00661
00662 guint len = p[index+1]+2;
00663
00664 if (len > length-index) {
00665 DLOG_ERR("Too long IE");
00666 return -1;
00667 }
00668
00669
00670 scan_results->cap_bits |= WLANCOND_WPA2;
00671
00672 ie_pos = &p[index];
00673 ie_len = len;
00674 }
00675
00676 else if (p[index] == WPA_ELEMENT && length-index > 7 &&
00677 memcmp(&p[index + 2], WPA1_OUI, sizeof(WPA1_OUI)) == 0)
00678 {
00679 guint len = p[index+1]+2;
00680
00681 if (len > length-index) {
00682 DLOG_ERR("Too long IE");
00683 return -1;
00684 }
00685
00686 if (!(scan_results->cap_bits & WLANCOND_ENCRYPT_WPA2_MASK)) {
00687 ie_pos = &p[index];
00688 ie_len = len;
00689 } else {
00690 DLOG_DEBUG("Ignoring WPA IE");
00691 }
00692 }
00693
00694 else if (p[index] == WPA_ELEMENT && length-index > 3 &&
00695 memcmp(&p[index + 2], WPS_OUI, sizeof(WPS_OUI)) == 0)
00696 {
00697 guint len = p[index+1]+2;
00698
00699 if (len > length-index) {
00700 DLOG_ERR("Too long IE");
00701 return -1;
00702 }
00703 if (handle_wps_ie(&p[index+6], scan_results, len) < 0) {
00704 return -1;
00705 }
00706 }
00707
00708 index +=p[index+1]+2;
00709 }
00710
00711 if (ie_pos != NULL) {
00712
00713 memset(&ap_info, 0, sizeof(ap_info));
00714 if (scan_results->cap_bits & WLANCOND_ENCRYPT_WPA2_MASK) {
00715 if (parse_rsn_ie(ie_pos, ie_len, &ap_info) < 0) {
00716 return -1;
00717 }
00718 } else {
00719 if (parse_wpa_ie(ie_pos, ie_len, &ap_info) < 0) {
00720 return -1;
00721 }
00722 }
00723
00724 save_caps(scan_results, &ap_info, ie_pos, ie_len);
00725 }
00726
00727 return 0;
00728 }
00729
00736 static void handle_custom_event(char* event_pointer, int length,
00737 struct scan_results_t *scan_results)
00738 {
00739
00740 if (length < 5 || length > IW_GENERIC_IE_MAX) {
00741 DLOG_DEBUG("Invalid length event");
00742 return;
00743 }
00744 if (strncmp(event_pointer, "tsf=", 4) == 0) {
00745
00746 } else if (strncmp(event_pointer, "LOWSIGNAL", 10) == 0) {
00747 DLOG_DEBUG("Low signal");
00748 set_wlan_signal(WLANCOND_LOW);
00749 if (get_wlan_state() == WLAN_CONNECTED)
00750 schedule_scan(WLANCOND_INITIAL_ROAM_SCAN_DELAY);
00751 } else if (strncmp(event_pointer, "HIGHSIGNAL", 11) == 0) {
00752 DLOG_DEBUG("High signal");
00753 set_wlan_signal(WLANCOND_HIGH);
00754 } else if (strncmp(event_pointer, "MLME-MICHAELMICFAILURE.indication",
00755 33) == 0) {
00756 dbus_bool_t key_type = TRUE;
00757
00758 if (strstr(event_pointer, "unicast") != NULL)
00759 key_type = FALSE;
00760
00761 DLOG_DEBUG("MIC failure event for %s key",
00762 key_type==FALSE?"unicast":"group");
00763 handle_mic_failure(key_type, wlan_status.conn.bssid);
00764 } else {
00765
00766
00767 }
00768 }
00769
00777 static int index2name(int skfd, int ifindex, char *name)
00778 {
00779 struct ifreq irq;
00780 int ret = 0;
00781
00782 memset(name, 0, IFNAMSIZ + 1);
00783 memset(&irq, 0, sizeof(irq));
00784
00785
00786 irq.ifr_ifindex = ifindex;
00787
00788 if (ioctl(skfd, SIOCGIFNAME, &irq) < 0)
00789 ret = -1;
00790 else
00791 strncpy(name, irq.ifr_name, IFNAMSIZ);
00792
00793 return ret;
00794 }
00795
00801 struct wireless_iface *get_interface_data(int ifindex)
00802 {
00803 struct wireless_iface *curr;
00804 int skfd;
00805
00806
00807 curr = interface_cache;
00808
00809 while(curr != NULL)
00810 {
00811
00812 if (curr->ifindex == ifindex)
00813 {
00814
00815
00816
00817 return(curr);
00818 }
00819
00820 curr = curr->next;
00821 }
00822
00823 skfd = socket_open();
00824
00825 curr = g_new(struct wireless_iface, 1);
00826
00827 curr->ifindex = ifindex;
00828
00829
00830 if (index2name(skfd, ifindex, curr->ifname) < 0)
00831 {
00832 perror("index2name");
00833 g_free(curr);
00834 return NULL;
00835 }
00836 curr->has_range = (iw_get_range_info(skfd, curr->ifname, &curr->range) >= 0);
00837
00838 curr->next = interface_cache;
00839 interface_cache = curr;
00840
00841 return(curr);
00842 }
00843
00851 static int print_event_stream(int ifindex, char *data, int len)
00852 {
00853 struct iw_event iwe;
00854 struct stream_descr stream;
00855 struct wireless_iface *wireless_if;
00856 struct scan_results_t scan_results;
00857 int ret;
00858
00859 wireless_if = get_interface_data(ifindex);
00860
00861 if (wireless_if == NULL)
00862 return (-1);
00863
00864 memset(&scan_results, 0, sizeof(struct scan_results_t));
00865 memset(&iwe, 0, sizeof(iwe));
00866
00867
00868
00869
00870 iw_init_event_stream(&stream, data, len);
00871 do {
00872 ret = iw_extract_event_stream(&stream, &iwe, wireless_if->range.we_version_compiled);
00873 if (ret != 0)
00874 {
00875 if (ret > 0)
00876 print_event_token(&iwe, &scan_results, ifindex,
00877 FALSE);
00878 else
00879 die("Invalid event");
00880 }
00881 } while (ret > 0);
00882
00883 return 0;
00884 }
00888 void del_all_interface_data(void)
00889 {
00890 struct wireless_iface *curr;
00891 struct wireless_iface *next;
00892
00893 curr = interface_cache;
00894
00895 while(curr)
00896 {
00897 next = curr->next;
00898
00899 g_free(curr);
00900
00901 curr = next;
00902 }
00903 }
00904
00909 static void del_interface_data(int ifindex)
00910 {
00911 struct wireless_iface * curr;
00912 struct wireless_iface * prev = NULL;
00913 struct wireless_iface * next;
00914
00915
00916 curr = interface_cache;
00917 while(curr)
00918 {
00919 next = curr->next;
00920
00921
00922 if(curr->ifindex == ifindex)
00923 {
00924
00925 if(!prev)
00926 interface_cache = next;
00927 else
00928 prev->next = next;
00929
00930
00931
00932 g_free(curr);
00933 }
00934 else
00935 {
00936
00937 prev = curr;
00938 }
00939
00940
00941 curr = next;
00942 }
00943 }
00948 static void handle_message(struct nlmsghdr *hdr)
00949 {
00950 struct ifinfomsg *infomsg;
00951 int attrlen;
00952 struct rtattr *rtattr;
00953
00954 infomsg = NLMSG_DATA(hdr);
00955
00956
00957 if(hdr->nlmsg_type == RTM_DELLINK)
00958 {
00959
00960 del_interface_data(infomsg->ifi_index);
00961 return;
00962 }
00963
00964 if(hdr->nlmsg_type != RTM_NEWLINK)
00965 return;
00966
00967 if(hdr->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg))) {
00968 attrlen = hdr->nlmsg_len-NLMSG_ALIGN(sizeof(struct ifinfomsg));
00969 rtattr = (void *) ((char *) infomsg +
00970 NLMSG_ALIGN(sizeof(struct ifinfomsg)));
00971 while (RTA_OK(rtattr, attrlen)) {
00972
00973 if (rtattr->rta_type == IFLA_WIRELESS) {
00974
00975 print_event_stream(infomsg->ifi_index,
00976 (char *)rtattr + RTA_ALIGN(sizeof(struct rtattr)),
00977 rtattr->rta_len - RTA_ALIGN(sizeof(struct rtattr)));
00978 }
00979 rtattr = RTA_NEXT(rtattr, attrlen);
00980 }
00981 }
00982 }
00987 static void handle_netlink_event(int fd)
00988 {
00989 char buf[1024];
00990 struct sockaddr_nl nl;
00991 socklen_t nl_len = sizeof(struct sockaddr_nl);
00992 int res;
00993
00994 while (1) {
00995 res = recvfrom (fd, buf, sizeof(buf), MSG_DONTWAIT,
00996 (struct sockaddr*)&nl, &nl_len);
00997
00998
00999 if (res < 0) {
01000 if (errno != EINTR && errno != EAGAIN) {
01001 DLOG_ERR("Error reading netlink socket");
01002 }
01003
01004 return;
01005 }
01006
01007
01008 if (res == 0) {
01009 return;
01010 }
01011 int len;
01012 struct nlmsghdr *hdr = (struct nlmsghdr*)buf;
01013
01014 while (res >= (int)sizeof(*hdr))
01015 {
01016 len = hdr->nlmsg_len;
01017
01018 if ((len - (int)sizeof(*hdr) < 0) || len > res) {
01019 DLOG_ERR("Error in netlink message length");
01020 break;
01021 }
01022
01023 if (hdr->nlmsg_type == RTM_NEWLINK ||
01024 hdr->nlmsg_type == RTM_DELLINK) {
01025 handle_message(hdr);
01026 }
01027
01028
01029 len = NLMSG_ALIGN(len);
01030 res -= len;
01031 hdr = (struct nlmsghdr*)((char*)hdr+len);
01032 }
01033 }
01034 }
01035
01041 static int init_wi (struct rtnl_handle *rth)
01042 {
01043 unsigned int addr_len;
01044
01045 memset(rth, 0, sizeof(struct rtnl_handle));
01046
01047 rth->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
01048 if (rth->fd < 0) {
01049 DLOG_ERR("socket()");
01050 return -1;
01051 }
01052 memset(&rth->local, 0, sizeof(rth->local));
01053 rth->local.nl_family = AF_NETLINK;
01054 rth->local.nl_groups = RTMGRP_LINK;
01055
01056 if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
01057 DLOG_ERR("bind()");
01058 return -1;
01059 }
01060 addr_len = sizeof(rth->local);
01061 if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
01062 DLOG_ERR("Cannot getsockname");
01063 return -1;
01064 }
01065 if (addr_len != sizeof(rth->local)) {
01066 DLOG_ERR("Wrong address length %d", addr_len);
01067 return -1;
01068 }
01069 if (rth->local.nl_family != AF_NETLINK) {
01070 DLOG_ERR("Wrong address family %d", rth->local.nl_family);
01071 return -1;
01072 }
01073
01074 return 0;
01075 }
01076
01084 static gboolean _monitor_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
01085 {
01086 int fd;
01087
01088 if (cond != G_IO_IN) {
01089 guint watch_id = *((guint *)data);
01090 DLOG_ERR("Error message from wireless interface");
01091 g_source_remove(watch_id);
01092 g_io_channel_unref(chan);
01093 return FALSE;
01094 }
01095
01096 fd = g_io_channel_unix_get_fd(chan);
01097 if (fd >= 0) {
01098 handle_netlink_event(fd);
01099 }
01100
01101 return TRUE;
01102 }
01103
01108 gboolean monitor_wi(void) {
01109 static guint watch_id = 0;
01110 GIOChannel *gio;
01111 struct rtnl_handle rth;
01112
01113 if (init_wi(&rth) < 0)
01114 return FALSE;
01115
01116 gio = g_io_channel_unix_new(rth.fd);
01117 g_io_channel_set_close_on_unref(gio, TRUE);
01118 watch_id = g_io_add_watch(gio, G_IO_IN | G_IO_PRI | G_IO_ERR |
01119 G_IO_HUP, _monitor_cb, &watch_id);
01120 return TRUE;
01121 }