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