dbus-signal.c

Go to the documentation of this file.
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 /* Cache of wireless interfaces */
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 /* Local functions */
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         //DLOG_DEBUG("Cleaning scan results");
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         //DLOG_DEBUG("\nScan results to save\n");
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         // Spurious event
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         // Check if the address is valid
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                 // If not roaming, set NO_ADDRESS state
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                         /* We are alredy searching for better connection */
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                 // Disconnect supplicant
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                 /* Decrese failed AP signal */
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                 /* No luck, start scanning */
00325                 if (scan(wlan_status.conn.ssid, 
00326                          wlan_status.conn.ssid_len, TRUE) < 0) {
00327                         /* Set_wlan_state puts IF down */
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         /* Now, let's decode the event */
00348         switch(event->cmd)
00349         {
00350             case SIOCGIWESSID:
00351             {
00352                     int len = event->u.essid.length;
00353                     if (len > WLANCOND_MAX_SSID_SIZE) {
00354                             //DLOG_ERR("Invalid length SSID (%d)", len);
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                     // Keep the API the same i.e. add Null termination
00364                     len++;
00365 
00366                     scan_results->ssid_len = len;
00367                     
00368                     if (event->u.essid.flags)
00369                     {
00370                             /* Does it have an ESSID index ? */
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                     /* WPA encryption is handled by a custom event */
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                     //DLOG_DEBUG("Custom driver event");
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                             /* Set_wlan_state puts IF down */
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         // event is MAC:IE, do minimal sanity checking
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                 //DLOG_DEBUG("Own WPA IE found");
00570                 update_own_ie(g_memdup(p + ETH_ALEN + 1, ie_len), ie_len);
00571         } else {
00572                 /* Push WPA IEs to security SW */
00573                 status = wpa_ie_push(p, p + ETH_ALEN + 1, ie_len);
00574                 
00575                 /* Check if we are roaming */
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         /* Key mgmt */
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                 /* No WPS in EAP mode */
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         /* Algorithms */
00618         /* Pairwise */
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         /* Group */
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         /* Remove WEP bit to make UI show correct dialogs */
00659         if (no_wep == TRUE) {
00660                 scan_results->cap_bits &= ~WLANCOND_WEP;
00661         }
00662 
00663         //DLOG_DEBUG("Cap bits: 0x%08x", scan_results->cap_bits);
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                 // WPA2
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                         /* Add WPA2 */
00695                         scan_results->cap_bits |= WLANCOND_WPA2;
00696                         
00697                         ie_pos = &p[index];
00698                         ie_len = len;
00699                 }
00700                 // WPA1
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                 // Protected setup
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                 /* Do nothing for now */
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                 //DLOG_DEBUG("Unknown custom event");
00792                 //DLOG_DEBUG("%s\n", event_pointer);
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         /* Get interface name */
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         /* Search for it in the database */
00833         curr = interface_cache;
00834         
00835         while(curr != NULL)
00836         {
00837                 /* Match ? */
00838                 if (curr->ifindex == ifindex)
00839                 {
00840                         //printf("Cache : found %d-%s\n", curr->ifindex, curr->ifname);
00841 
00842                         /* Return */
00843                         return(curr);
00844                 }
00845                 /* Next entry */
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         /* Extract static data */
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         /* Link it */
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         /* We don't send scan_results at this point, 
00894            only some events are sent */
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         /* Go through the list, find the interface, kills it */
00942         curr = interface_cache;
00943         while(curr)
00944         {
00945                 next = curr->next;
00946                 
00947                 /* Got a match ? */
00948                 if(curr->ifindex == ifindex)
00949                 {
00950                         /* Unlink. Root ? */
00951                         if(!prev)
00952                                 interface_cache = next;
00953                         else
00954                                 prev->next = next;
00955                         //printf("Cache : purge %d-%s\n", curr->ifindex, curr->ifname);
00956                         
00957                         /* Destroy */
00958                         g_free(curr);
00959                 }
00960                 else
00961                 {
00962                         /* Keep as previous */
00963                         prev = curr;
00964                 }
00965                 
00966                 /* Next entry */
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         /* If interface is getting destoyed */
00983         if(hdr->nlmsg_type == RTM_DELLINK)
00984         {
00985                 /* Remove from cache (if in cache) */
00986                 del_interface_data(infomsg->ifi_index);
00987                 return;
00988         }
00989         /* Only keep add/change events */
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                                 /* Go to display it */
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                 /* Error */
01024                 if (res < 0) {
01025                         if (errno != EINTR && errno != EAGAIN) {
01026                                 DLOG_ERR("Error reading netlink socket");
01027                         }
01028                         /* Don't do anything */
01029                         return;
01030                 }
01031 
01032                 /* EOF */
01033                 if (res == 0) {
01034                         return;
01035                 }
01036                 int len;
01037                 struct nlmsghdr *hdr = (struct nlmsghdr*)buf;
01038                 /* real handling in this loop */
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                         /* Ok, we have good message */
01048                         if (hdr->nlmsg_type == RTM_NEWLINK ||
01049                             hdr->nlmsg_type == RTM_DELLINK) {
01050                                 handle_message(hdr);
01051                         }
01052                         
01053                         /* Get ready for next message */
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 }

Generated on Sat Dec 6 22:17:00 2008 for WLAN Connection Daemon by  doxygen 1.5.1