dbus-handler.c

Go to the documentation of this file.
00001 
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <glib.h>
00030 #include <net/ethernet.h>
00031 #include <linux/socket.h>
00032 #include <gconf/gconf-client.h>
00033 #include <osso-ic-dbus.h>
00034 
00035 #define DBUS_API_SUBJECT_TO_CHANGE
00036 #include <dbus/dbus.h>
00037 #include <eap-dbus.h>
00038 #include <wlancond-dbus.h>
00039 #ifdef USE_MCE_MODE
00040 #include <mce/dbus-names.h>
00041 #endif
00042 #include "log.h"
00043 #include "dbus.h"
00044 #include "dbus-helper.h"
00045 #include "dbus-handler.h"
00046 #include "common.h"
00047 #include "wpa.h"
00048 
00049 #define WLANCOND_SHUTDOWN_DELAY 4000 //4s
00050 //FIXME, make these smaller
00051 #define WLANCOND_CONNECT_TIMEOUT 15000 //15s
00052 #define WLANCOND_SCAN_TIMEOUT 12000 //12s
00053 
00054 /* Saved DBUS names */
00055 static char *scan_name_cache = NULL;
00056 static char *connect_name_cache = NULL;
00057 
00058 static int wlan_socket = -1;
00059 
00060 struct wlan_status_t wlan_status;
00061 
00062 static gboolean _flight_mode = FALSE;
00063 static gboolean power_down_after_scan = FALSE;
00064 static dbus_bool_t saved_inactivity = FALSE;
00065 
00066 /* Timer IDs */
00067 static guint wlan_if_down_timer_id = 0;
00068 static guint wlan_connect_timer_id = 0;
00069 
00070 /* This is the desired powersave and can be set from DBUS when connecting */
00071 static guint powersave = WLANCOND_SHORT_CAM;
00072 
00073 #define WLAN_PREFIX_STR "wlan"
00074 
00078 int socket_open(void) 
00079 {
00080         if (wlan_socket > 0)
00081                 return wlan_socket;
00082         
00083         wlan_socket = socket(AF_INET, SOCK_DGRAM, 0);
00084 
00085         if (wlan_socket < 0)
00086                 die("socket() failed");
00087         
00088         return wlan_socket;
00089 }
00093 void init_iwreq(struct iwreq* req) 
00094 {
00095         memset(req, 0, sizeof(struct iwreq));
00096         strncpy(req->ifr_name, wlan_status.ifname, IFNAMSIZ);
00097 }
00101 static int get_own_mac(void) 
00102 {
00103         struct ifreq req;
00104         
00105         memset(&req , 0, sizeof(req));
00106         memcpy(req.ifr_name, wlan_status.ifname, IFNAMSIZ);
00107         
00108         if (ioctl(socket_open(), SIOCGIFHWADDR, &req) < 0)
00109         {
00110                 return -1;
00111         }
00112         
00113         memcpy(wlan_status.own_mac, req.ifr_hwaddr.sa_data, ETH_ALEN);
00114         
00115         return 0;
00116 }
00117 
00123 static gint get_gconf_int(const gchar* path) 
00124 {
00125         GConfClient *client;
00126         GConfValue *gconf_value;
00127         GError *error = NULL;
00128  
00129         client = gconf_client_get_default();
00130         if (client == NULL) {
00131                 return -1;
00132         }
00133 
00134         gconf_value = gconf_client_get(client, path, &error); 
00135 
00136         g_object_unref(client);
00137 
00138         if (error != NULL) {
00139                 DLOG_ERR("Could not get setting:%s, error:%s", path, 
00140                          error->message);
00141                 
00142                 g_clear_error(&error);
00143                 return -1;
00144         }
00145         
00146         if (gconf_value == NULL) {
00147                 return -1;
00148         }
00149         if (gconf_value->type == GCONF_VALUE_INT) {
00150                 gint value = gconf_value_get_int(gconf_value);
00151                 DLOG_DEBUG("User selected value: %d", value);
00152                 gconf_value_free(gconf_value);
00153                 return value;
00154         }
00155         
00156         gconf_value_free(gconf_value);
00157         return -1;
00158 }
00164 void update_own_ie(unsigned char* wpa_ie, guint wpa_ie_len) 
00165 {
00166         g_free(wlan_status.wpa_ie.ie);
00167         wlan_status.wpa_ie.ie = wpa_ie;
00168         wlan_status.wpa_ie.ie_len =  wpa_ie_len;
00169 }
00174 guint get_encryption_info(void) 
00175 {
00176         guint auth_status = 0;
00177 
00178         if (wlan_status.pairwise_cipher & CIPHER_SUITE_CCMP) {
00179                 auth_status |= WLANCOND_WPA_AES;
00180         } else if (wlan_status.pairwise_cipher & CIPHER_SUITE_TKIP) {
00181                 auth_status |= WLANCOND_WPA_TKIP;
00182         } else if (wlan_status.pairwise_cipher & CIPHER_SUITE_WEP40 ||
00183                    wlan_status.pairwise_cipher & CIPHER_SUITE_WEP104) {
00184                 auth_status |= WLANCOND_WEP;
00185         } else {
00186                 auth_status |= WLANCOND_OPEN;
00187         }
00188         return auth_status;
00189 }
00190 
00194 int init_dbus_handler(void)
00195 {
00196         if (get_own_mac() < 0) {
00197                 DLOG_ERR("Could not get own MAC address");
00198                 return -1; 
00199         }
00200 
00201         return 0;
00202 }
00206 int clean_dbus_handler(void)
00207 {
00208         if (wlan_socket > 0)
00209                 close(wlan_socket);
00210         return 0;
00211 }
00216 void mode_change(const char *mode) {
00217 
00218         DLOG_DEBUG("WLAN flight mode changed to \"%s\"", mode);
00219         
00220         if (g_str_equal(mode, "flight")) {
00221                 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, FORCE_YES);
00222                 _flight_mode = TRUE;
00223         }
00224         else if (g_str_equal(mode, "normal")) {
00225                 _flight_mode = FALSE;
00226         }
00227         else {
00228                 DLOG_ERR("Invalid mode \"%s\" passed to mode_change()", mode);
00229         }
00230 }
00235 #ifdef USE_MCE_MODE
00236 static DBusHandlerResult mode_change_dbus(DBusMessage *message) {
00237 
00238         char *mode;
00239         
00240         if (!dbus_message_get_args(message, NULL,
00241                                    DBUS_TYPE_STRING, &mode,
00242                                    DBUS_TYPE_INVALID)) {
00243                 DLOG_ERR("Invalid arguments for device_mode_ind signal");
00244                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00245         }
00246         
00247         mode_change(mode);
00248         
00249         return DBUS_HANDLER_RESULT_HANDLED;
00250 }
00251 #ifdef ACTIVITY_CHECK
00252 static DBusHandlerResult activity_check_dbus(DBusMessage *message) {
00253         
00254         if (!dbus_message_get_args(message, NULL,
00255                                    DBUS_TYPE_BOOLEAN, &saved_inactivity,
00256                                    DBUS_TYPE_INVALID)) {
00257                 DLOG_ERR("Invalid arguments for device_activity signal");
00258                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00259         }
00260         activity_check(saved_inactivity);
00261         
00262         return DBUS_HANDLER_RESULT_HANDLED;
00263 }
00264 #endif
00265 #endif
00266 
00267 #ifdef ACTIVITY_CHECK
00268 
00271 void activity_check(dbus_bool_t inactivity) {
00272 
00273         int sock;
00274         
00275         if (get_wlan_state() != WLAN_CONNECTED) {
00276                 return;
00277         }
00278         
00279         sock = socket_open();
00280 
00281         if (inactivity == FALSE) {
00282                 //DLOG_DEBUG("WLAN activity mode changed to active");
00283         } else {
00284                 //DLOG_DEBUG("WLAN activity mode changed to inactive");
00285         }
00286 
00287         set_power_state(powersave, sock);     
00288 }
00289 
00293 static gboolean get_inactivity_status(void) 
00294 {
00295         return saved_inactivity;
00296 }
00297 #endif
00298 
00303 static DBusHandlerResult icd_check_signal_dbus(DBusMessage *message) {
00304 
00305         char *icd_name;
00306         char *icd_type;
00307         char *icd_state;
00308         char *icd_disconnect_reason;
00309         DBusError dbus_error;
00310         
00311         if ((get_wlan_state() != WLAN_CONNECTED &&
00312             get_wlan_state() != WLAN_NO_ADDRESS) ||
00313             get_mode() != WLANCOND_INFRA) {
00314                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00315         }
00316 
00317         dbus_error_init(&dbus_error);
00318         if (!dbus_message_get_args(message, &dbus_error,
00319                                    DBUS_TYPE_STRING, &icd_name,
00320                                    DBUS_TYPE_STRING, &icd_type,
00321                                    DBUS_TYPE_STRING, &icd_state,
00322                                    DBUS_TYPE_STRING, &icd_disconnect_reason,
00323                                    DBUS_TYPE_INVALID ) )
00324         {
00325                 DLOG_ERR("Could not get args from signal, '%s'",
00326                          dbus_error.message);
00327                 dbus_error_free(&dbus_error);
00328                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00329         }
00330         
00331         if (icd_state != NULL && strncmp(icd_state, "CONNECTED", 9) == 0) {
00332 
00333                 set_wlan_state(WLAN_CONNECTED, NO_SIGNAL, FORCE_NO);
00334 
00335                 DLOG_DEBUG("Going to power save");
00336                         
00337                 if (set_power_state(powersave, socket_open()) == FALSE) {
00338                         DLOG_ERR("Failed to set power save");
00339                 }
00340 
00341         }
00342 
00343         //DLOG_DEBUG("Handled icd signal, icd_state:%s", icd_state);
00344         
00345         return DBUS_HANDLER_RESULT_HANDLED;
00346 }
00347 
00348 static gboolean in_flight_mode(void) {
00349         return _flight_mode;
00350 }
00351 
00352 void set_wlan_signal(gboolean high_or_low) 
00353 {
00354         if (high_or_low == WLANCOND_HIGH) {
00355                 wlan_status.signal = WLANCOND_HIGH;
00356                 remove_roam_scan_timer();
00357         } else {
00358                 wlan_status.signal = WLANCOND_LOW;
00359         }
00360 }
00361 
00362 void remove_roam_scan_timer(void) 
00363 {
00364         if (wlan_status.roam_scan_id) {
00365                 g_source_remove(wlan_status.roam_scan_id);
00366                 wlan_status.roam_scan_id = 0;
00367         }
00368 }
00369 
00370 void remove_connect_timer(void) 
00371 {
00372         if (wlan_connect_timer_id) {
00373                 g_source_remove(wlan_connect_timer_id);
00374                 wlan_connect_timer_id = 0;
00375         }
00376 }
00377 
00378 static void remove_wlan_if_timer(void) 
00379 {
00380         // Remove shutdown timer if exists
00381         if (wlan_if_down_timer_id) {        
00382                 g_source_remove(wlan_if_down_timer_id);
00383                 wlan_if_down_timer_id = 0;
00384         }
00385 }
00386 
00387 void remove_scan_timer(void) 
00388 {
00389         if (wlan_status.scan_id) {
00390                 g_source_remove(wlan_status.scan_id);
00391                 wlan_status.scan_id = 0;
00392         }
00393 }
00399 static gboolean wlan_connect_timer_cb(void* data) 
00400 {
00401         wlan_connect_timer_id = 0;
00402         
00403         if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
00404                 
00405                 DLOG_DEBUG("Association timeout, try: %d", 
00406                            wlan_status.retry_count);
00407                 
00408                 /* Remove the failed AP from the list */
00409                 remove_from_roam_cache(wlan_status.conn.bssid);
00410                 
00411                 /* Set BSSID to 0 */
00412                 memset(wlan_status.conn.bssid, 0, ETH_ALEN);
00413                 
00414                 if (find_connection_and_associate(wlan_status.roam_cache, FALSE) == 0)
00415                         return FALSE;
00416                 
00417                 /* Try to scan again if retries left */
00418                 if (++wlan_status.retry_count < WLANCOND_MAX_SCAN_TRIES) {
00419                         if (scan(wlan_status.conn.ssid, 
00420                                  wlan_status.conn.ssid_len, FALSE) == 0) {
00421                                 return FALSE;
00422                         }
00423                 }
00424                 
00425                 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, 
00426                                FORCE_YES);
00427                 return FALSE;
00428         }
00429         
00430         //DLOG_DEBUG("Association OK");        
00431 
00432         return FALSE;
00433 }
00439 static gboolean wlan_scan_cb(void* data) 
00440 {
00441         
00442         wlan_status.scan_id = 0;
00443 
00444         DLOG_ERR("Scan failed, should not happen!");
00445         
00446         if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
00447                 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, 
00448                                FORCE_YES);
00449         }
00450         
00451         return FALSE;
00452 }
00458 static gboolean wlan_if_down_cb(void* data) 
00459 {
00460         
00461         wlan_if_down_timer_id = 0;
00462         
00463         if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
00464                 DLOG_DEBUG("Delayed shutdown occurred");
00465                 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
00466                 return FALSE;
00467         }
00468         
00469         //DLOG_DEBUG("Delayed shutdown did not happen");        
00470 
00471         return FALSE;
00472 }
00480 int mlme_command(guchar* addr, guint16 cmd, guint16 reason_code)
00481 {
00482         struct iwreq req;
00483         struct iw_mlme mlme;
00484 
00485         init_iwreq(&req);
00486 
00487         DLOG_DEBUG("%s", cmd==IW_MLME_DEAUTH?"Deauthenticating":
00488                    "Disassociating");
00489 
00490         memset(&mlme, 0, sizeof(mlme));
00491         
00492         mlme.cmd = cmd;
00493         mlme.reason_code = reason_code;
00494         mlme.addr.sa_family = ARPHRD_ETHER;
00495         memcpy(mlme.addr.sa_data, addr, ETH_ALEN);
00496         
00497         req.u.data.pointer = (caddr_t) &mlme;
00498         req.u.data.length = sizeof(mlme);
00499 
00500         if (ioctl(socket_open(), SIOCSIWMLME, &req) < 0) {
00501                 DLOG_ERR("Failed to run MLME command");
00502                 return -1;
00503         }
00504 
00505         return 0;
00506 }
00510 static int set_mode(guint32 mode) 
00511 {
00512         struct iwreq req;
00513 
00514         init_iwreq(&req);
00515 
00516         switch (mode) {
00517             case WLANCOND_ADHOC:
00518                     req.u.mode = IW_MODE_ADHOC;
00519                     DLOG_DEBUG("Setting mode: adhoc");
00520                     break;
00521             case WLANCOND_INFRA:
00522                     req.u.mode = IW_MODE_INFRA;
00523                     DLOG_DEBUG("Setting mode: infra");
00524                     break;
00525             default:
00526                     DLOG_ERR("Operating mode undefined\n");
00527                     return -1;
00528         }                               
00529         
00530         if (ioctl(socket_open(), SIOCSIWMODE, &req) < 0) {
00531                 DLOG_ERR("Operating mode setting failed\n");
00532                 return -1;
00533         }
00534         return 0;
00535 }
00541 static int set_wep_keys(struct connect_params_t *conn) 
00542 {
00543         struct iwreq req;
00544         guint nbr_of_keys = 0;
00545         int sock;
00546         guint i;
00547         
00548         sock = socket_open();
00549         
00550         /* Encryption keys */
00551         for (i=0;i<4;i++) {
00552                 if(conn->key_len[i] == 0) {
00553                         continue;
00554                 } else {
00555                         if (conn->key_len[i] < WLANCOND_MIN_KEY_LEN || 
00556                             conn->key_len[i] > WLANCOND_MAX_KEY_LEN) {
00557                                 return -1;
00558                         }
00559                         
00560                         init_iwreq(&req);
00561                         req.u.data.length = conn->key_len[i];
00562                         req.u.data.pointer = (caddr_t) &conn->key[i][0];
00563                         req.u.data.flags |= IW_ENCODE_RESTRICTED;
00564                         req.u.encoding.flags = i+1;
00565                         nbr_of_keys++;
00566                 }
00567 #define DEBUG_KEY
00568 #ifdef DEBUG_KEY
00569                 int k;
00570                 unsigned char* p = &conn->key[i][0];
00571                 for (k=0;k<conn->key_len[i];k++) {
00572                         DLOG_DEBUG("Key %d, 0x%02x\n", i, *(p+k));
00573                 }
00574 #endif
00575                 if (ioctl(sock, SIOCSIWENCODE, &req) < 0) {
00576                         DLOG_ERR("Set encode failed\n");
00577                         return -1;
00578                 }
00579                 
00580         }
00581         
00582         if (nbr_of_keys) {
00583                 
00584                 DLOG_DEBUG("Default key: %d\n", conn->default_key);
00585 
00586                 init_iwreq(&req);
00587                 
00588                 /* Set the default key */
00589                 req.u.encoding.flags = conn->default_key;
00590                 
00591                 if (ioctl(sock, SIOCSIWENCODE, &req) < 0) {
00592                         DLOG_ERR("Set encode failed\n");
00593                         return -1;
00594                 }
00595         }
00596 
00597         return 0;
00598 }
00599 
00606 static int set_essid(char* essid, int essid_len) 
00607 {
00608         struct iwreq req;
00609 
00610         DLOG_DEBUG("Setting SSID: %s", essid);
00611 
00612         init_iwreq(&req);
00613         
00614         req.u.essid.pointer = (caddr_t)essid;
00615         req.u.essid.length = essid_len -1; // Remove NULL termination
00616         req.u.essid.flags = 1;
00617 
00618         if (ioctl(socket_open(), SIOCSIWESSID, &req) < 0) {
00619                 DLOG_ERR("set ESSID failed");
00620                 return -1;
00621         }
00622         return 0;
00623 }
00629 int set_bssid(unsigned char *bssid)
00630 {
00631         struct iwreq req;
00632 
00633         print_mac("Setting BSSID", bssid);
00634         
00635         init_iwreq(&req);
00636 
00637         req.u.ap_addr.sa_family = ARPHRD_ETHER;
00638         
00639         memcpy(req.u.ap_addr.sa_data, bssid, ETH_ALEN);
00640         
00641         if (ioctl(socket_open(), SIOCSIWAP, &req) < 0) {
00642                 DLOG_ERR("Failed to set BSSID");
00643                 return -1;
00644         }
00645         return 0;
00646 }
00647 
00654 void set_wlan_state(int new_state, int send_signal, force_t force) 
00655 {
00656         char *status_table[] = 
00657                 {
00658                         (char*)"WLAN_NOT_INITIALIZED",
00659                         (char*)"WLAN_INITIALIZED",
00660                         (char*)"WLAN_INITIALIZED_FOR_SCAN",
00661                         (char*)"WLAN_INITIALIZED_FOR_CONNECTION",
00662                         (char*)"WLAN_NO_ADDRESS",
00663                         (char*)"WLAN_CONNECTED"
00664                 };
00665 
00666         switch (new_state) {
00667                 
00668             case WLAN_NOT_INITIALIZED:
00669 
00670                     if (wlan_status.state == WLAN_CONNECTED ||
00671                         wlan_status.state == WLAN_NO_ADDRESS) {
00672                             /* Disconnect previous connection */
00673                             mlme_command(wlan_status.conn.bssid,
00674                                          IW_MLME_DEAUTH,  
00675                                          WLANCOND_REASON_LEAVING);
00676                             set_bssid(NULL_BSSID);
00677                     }
00678 
00679                     set_scan_state(SCAN_NOT_ACTIVE);
00680                     
00681                     if (get_wlan_state() != WLAN_NOT_INITIALIZED &&
00682                         get_wlan_state() != WLAN_INITIALIZED_FOR_SCAN)
00683                             clear_wpa_mode();
00684 
00685                     wlan_status.retry_count = 0;
00686                     
00687                     /* Remove association timer */
00688                     remove_connect_timer();
00689 
00690                     /* Remove scan timer */
00691                     remove_scan_timer();
00692                     
00693                     set_wlan_signal(WLANCOND_HIGH);
00694                     
00695                     // Remove shutdown timer if exists
00696                     remove_wlan_if_timer();        
00697                 
00698                     if (force == FORCE_YES) {
00699                             
00700                             clean_roam_cache();
00701                             
00702                             if (set_interface_state(socket_open(), CLEAR, 
00703                                                     IFF_UP)<0) {
00704                                     DLOG_ERR("Could not set interface down");
00705                                     return;
00706                             }
00707                             
00708                     } else {
00709                             
00710                             DLOG_DEBUG("Delaying interface shutdown");
00711 
00712                             /* Removed, does not reduce power consumption
00713                                when not connected */
00714                             //set_power_state(WLANCOND_FULL_POWERSAVE, sock);
00715                             
00716                             wlan_if_down_timer_id = g_timeout_add(
00717                                     WLANCOND_SHUTDOWN_DELAY,
00718                                     wlan_if_down_cb,
00719                                     NULL); 
00720                             
00721                     }
00722                 
00723                     if (send_signal == DISCONNECTED_SIGNAL)
00724                             disconnected_signal();       
00725 
00726                     break;
00727             case WLAN_INITIALIZED_FOR_CONNECTION:
00728                     /* 
00729                        Set BSSID to 0, this state happens e.g when we drop from
00730                        the network 
00731                     */
00732                     memset(wlan_status.conn.bssid, 0, ETH_ALEN);
00733                     break;
00734             default:
00735                     break;
00736         }
00737         DLOG_DEBUG("Wlancond state change, old_state: %s, new_state: %s", 
00738                    status_table[wlan_status.state], status_table[new_state]);
00739         wlan_status.state = new_state;
00740 }
00741 
00746 guint get_wlan_state(void) 
00747 {
00748         return wlan_status.state;
00749 }
00750 
00755 void set_scan_state(guint new_state) 
00756 {
00757         if (wlan_status.scan == new_state) {
00758                 return;
00759         }
00760         if (new_state == SCAN_NOT_ACTIVE && wlan_status.scan == SCAN_ACTIVE && 
00761             scan_name_cache != NULL) {
00762                 DLOG_DEBUG("Sending empty results");
00763                 send_dbus_scan_results(NULL, scan_name_cache, 0);
00764                 g_free(scan_name_cache);
00765                 scan_name_cache = NULL;
00766         }
00767         
00768         DLOG_DEBUG("Wlancond scan change, old_state: %s, new_state: %s", 
00769                    wlan_status.scan==SCAN_NOT_ACTIVE ? "SCAN_IDLE":"SCANNING",
00770                    new_state == SCAN_NOT_ACTIVE ? "SCAN_IDLE":"SCANNING");
00771         wlan_status.scan = new_state;
00772 }
00773 
00778 guint get_scan_state(void) 
00779 {
00780         return wlan_status.scan;
00781 }
00786 guint get_mode(void) 
00787 {
00788         return wlan_status.conn.mode;
00789 }
00790 
00797 gboolean set_power_state(guint new_state, int sock) 
00798 {
00799 #if 0
00800         struct iwreq req;
00801         gint sleep_timeout;
00802         
00803         if (new_state == WLANCOND_SHORT_CAM && get_inactivity_status() == TRUE)
00804                 new_state = WLANCOND_VERY_SHORT_CAM;
00805         
00806         if (wlan_status.power == new_state) {
00807                 return TRUE;
00808         }
00809 
00810         init_iwreq(&req);
00811 
00812         switch (new_state) {
00813             case WLANCOND_POWER_ON:
00814                     req.u.power.disabled = 1;
00815                     break;
00816             case WLANCOND_LONG_CAM:
00817                     req.u.power.flags = IW_POWER_MULTICAST_R;
00818                     req.u.power.value = WLANCOND_LONG_CAM_TIMEOUT;
00819                     break;
00820             case WLANCOND_SHORT_CAM:
00821                     req.u.power.flags = IW_POWER_MULTICAST_R;
00822                     sleep_timeout = get_gconf_int(SLEEP_GCONF_PATH);
00823                     if (sleep_timeout < 0)
00824                             sleep_timeout = WLANCOND_DEFAULT_SLEEP_TIMEOUT;
00825                     req.u.power.value = sleep_timeout;
00826                     break;
00827             case WLANCOND_VERY_SHORT_CAM:
00828                     req.u.power.flags = IW_POWER_MULTICAST_R;
00829                     sleep_timeout = get_gconf_int(INACTIVE_SLEEP_GCONF_PATH);
00830                     if (sleep_timeout < 0)
00831                             sleep_timeout = WLANCOND_VERY_SHORT_CAM_TIMEOUT;
00832                     req.u.power.value = sleep_timeout;
00833                     break;
00834             default:
00835                     req.u.power.flags = IW_POWER_ALL_R;
00836                     break;
00837         }
00838         
00839         if (ioctl(sock, SIOCSIWPOWER, &req) < 0) {
00840                 DLOG_ERR("set power failed, state:%d", new_state);
00841                 return FALSE;
00842         }
00843 #endif        
00844         
00845         //DLOG_DEBUG("Power state set to %d", new_state);
00846         wlan_status.power = new_state;
00847 
00848         return TRUE;
00849 }
00850 
00851 
00857 static int init_if(int sock) 
00858 {
00859         int previous_state = get_wlan_state();
00860         
00861         if (previous_state == WLAN_NOT_INITIALIZED) {
00862                 /* Check if interface is still up from delayed shutdown */
00863                 if (wlan_if_down_timer_id == 0) {
00864                         if (set_interface_state(sock, SET, 
00865                                                 IFF_UP | IFF_RUNNING) < 0) {
00866                                 return -1;
00867                         }
00868                 }
00869                 set_power_state(WLANCOND_POWER_ON, sock);
00870                 set_wlan_state(WLAN_INITIALIZED, NO_SIGNAL, FORCE_YES);
00871         }
00872         
00873         return previous_state;
00874 }
00875 
00884 static int set_we_name(int sock, char *name, char *args[], int count)
00885 {
00886         struct iwreq req;
00887         
00888         memset(&req, 0, sizeof(req));
00889         strncpy(req.ifr_name, name, IFNAMSIZ);
00890         
00891         if (ioctl(sock, SIOCGIWNAME, &req) < 0) {
00892                 //DLOG_DEBUG("Ifname %s does not support wireless extensions\n",        name);
00893         } else {
00894                 //DLOG_DEBUG("Found interface %s", name);
00895                 if (g_str_has_prefix(name, WLAN_PREFIX_STR)) {
00896                         DLOG_DEBUG("Found WLAN interface %s", name);
00897                         memcpy(&wlan_status.ifname, name, IFNAMSIZ);
00898                         wlan_status.ifname[IFNAMSIZ] = '\0';
00899                 }
00900         }
00901         
00902         return 0;
00903 }
00909 int get_we_device_name(void) 
00910 {
00911         memset(&wlan_status, 0, sizeof(wlan_status));
00912 
00913         iw_enum_devices(socket_open(), &set_we_name, NULL, 0);
00914 
00915         if (strnlen(wlan_status.ifname, IFNAMSIZ) < 2)
00916                 return -1;
00917         
00918         return 0;
00919 }
00927 int set_interface_state(int sock, int dir, short flags) 
00928 {
00929         struct ifreq ifr;
00930 
00931         memset(&ifr, 0, sizeof(ifr));
00932         
00933         strncpy(ifr.ifr_name, wlan_status.ifname, IFNAMSIZ);
00934         
00935         if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
00936                 DLOG_ERR("Could not get interface %s flags\n", 
00937                          wlan_status.ifname); 
00938                 return -1;
00939         }
00940         if (dir == SET) {
00941                 ifr.ifr_flags |= flags;
00942         } else {
00943                 ifr.ifr_flags &= ~flags;
00944         }
00945         
00946         if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
00947                 DLOG_ERR("Could not set interface %s flags\n", 
00948                          wlan_status.ifname); 
00949                 return -1;
00950         }
00951         
00952         DLOG_DEBUG("%s is %s", wlan_status.ifname, dir == SET ? "UP":"DOWN");
00953 
00954         return 0;
00955 }
00956 
00963 static gboolean set_tx_power(guint power, int sock) 
00964 {
00965         struct iwreq req;
00966         init_iwreq(&req);
00967         
00968         req.u.txpower.fixed = 1;
00969         req.u.txpower.disabled = 0;
00970         req.u.txpower.flags = IW_TXPOW_DBM;
00971 
00972         if (power == WLANCOND_TX_POWER10) {
00973                 req.u.txpower.value = WLANCOND_TX_POWER10DBM;
00974         } else if (power == WLANCOND_TX_POWER100) {
00975                 req.u.txpower.value = WLANCOND_TX_POWER100DBM;
00976         } else {
00977                 return FALSE;
00978         }
00979         
00980         if (ioctl(sock, SIOCSIWTXPOW, &req) < 0) {
00981                 DLOG_ERR("set power failed\n");
00982                 return FALSE;
00983         }
00984         return TRUE;
00985         
00986 }
00992 static int update_algorithms(guint32 encryption) 
00993 {
00994         wlan_status.group_cipher = 0;
00995         wlan_status.pairwise_cipher = 0;
00996 
00997         // Open
00998         if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_OPEN) {
00999                 DLOG_DEBUG("Open mode");    
01000                 wlan_status.pairwise_cipher = CIPHER_SUITE_NONE;
01001                 return 0;
01002         }
01003         
01004         // WEP
01005         if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP) {
01006                 DLOG_DEBUG("WEP enabled");
01007                 wlan_status.pairwise_cipher = CIPHER_SUITE_WEP40;
01008                 return 0;
01009         } 
01010         
01011         // WPA modes
01012         if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) 
01013                    == WLANCOND_WPA_TKIP) {
01014                 DLOG_DEBUG("TKIP Selected for unicast");
01015                 wlan_status.pairwise_cipher = CIPHER_SUITE_TKIP;
01016         } else if ((encryption & WLANCOND_ENCRYPT_ALG_MASK) == 
01017                    WLANCOND_WPA_AES) {
01018                 DLOG_DEBUG("AES selected for unicast");
01019                 wlan_status.pairwise_cipher = CIPHER_SUITE_CCMP;
01020                 
01021         } else {
01022                 DLOG_ERR("Not supported encryption %08x", encryption);
01023                 return -1;
01024         }
01025         
01026         if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) == 
01027             WLANCOND_WPA_TKIP_GROUP) {
01028                 DLOG_DEBUG("TKIP Selected for multicast");
01029                 wlan_status.group_cipher = CIPHER_SUITE_TKIP;
01030         } else if ((encryption & WLANCOND_ENCRYPT_GROUP_ALG_MASK) == 
01031                    (unsigned int)WLANCOND_WPA_AES_GROUP) {
01032                 DLOG_DEBUG("AES Selected for multicast");
01033                 wlan_status.group_cipher = CIPHER_SUITE_CCMP;
01034         } else {
01035                 DLOG_ERR("Not supported encryption %08x", encryption);
01036                 return -1;
01037         }       
01038 
01039         return 0;
01040 }
01044 void clean_roam_cache(void) 
01045 {
01046         clean_scan_results(&wlan_status.roam_cache);
01047 }
01051 void clear_wpa_mode(void) 
01052 {
01053         g_free(wlan_status.wpa_ie.ie);
01054         wlan_status.wpa_ie.ie_len = 0;
01055         wlan_status.wpa_ie.ie = NULL;
01056 
01057         wlan_status.pairwise_cipher = CIPHER_SUITE_NONE;
01058         wlan_status.group_cipher = CIPHER_SUITE_NONE;
01059         
01060         //set_encryption_method(wlan_status.pairwise_cipher, &wlan_status);
01061         clear_wpa_keys(NULL);
01062         /* Clean PMK cache */
01063         g_slist_foreach(wlan_status.pmk_cache, (GFunc)g_free, NULL);
01064         g_slist_free(wlan_status.pmk_cache);
01065         wlan_status.pmk_cache = NULL;
01066 }
01071 gboolean get_wpa_mode(void)
01072 {
01073         if (wlan_status.pairwise_cipher & CIPHER_SUITE_TKIP ||
01074             wlan_status.pairwise_cipher & CIPHER_SUITE_CCMP) {
01075                 return TRUE;
01076         }
01077         return FALSE;
01078 }
01079 
01080 static gint compare_pmk_entry(gconstpointer a, gconstpointer b) 
01081 {
01082         struct pmksa_cache_t *pmk_cache = (struct pmksa_cache_t*)a;
01083         
01084         return memcmp(pmk_cache->mac, b, ETH_ALEN);
01085 }
01086 
01092 static void add_to_pmksa_cache(unsigned char* pmkid, unsigned char* mac)
01093 {
01094         guint i = 0;
01095         GSList *list;
01096         gboolean entry_found = FALSE;
01097         
01098         for (list = wlan_status.pmk_cache; list != NULL && entry_found == FALSE; list = list->next) {
01099                 struct pmksa_cache_t *pmk_cache = (struct pmksa_cache_t*)list->data;
01100                 /* First find if we have already the cache entry */
01101                 if (memcmp(pmk_cache->mac, mac, ETH_ALEN) == 0) {
01102                         DLOG_DEBUG("Found old entry: %i", i);
01103                         /* Remove the old entry */
01104                         wlan_status.pmk_cache = g_slist_remove(wlan_status.pmk_cache, pmk_cache);
01105                         g_free(pmk_cache);
01106                         
01107                         entry_found = TRUE;
01108                 } else {
01109                         i++;
01110                 }
01111         }
01112         
01113         if (i == PMK_CACHE_SIZE) {
01114                 DLOG_DEBUG("Cache full, remove oldest");
01115                 GSList *last_entry = g_slist_last(wlan_status.pmk_cache);
01116                 wlan_status.pmk_cache = g_slist_remove(wlan_status.pmk_cache, last_entry->data);
01117                 g_free(last_entry->data);
01118         }
01119         print_mac("Adding new entry:", mac);
01120         
01121         struct pmksa_cache_t *new_entry = g_malloc(sizeof(*new_entry));
01122         memcpy(new_entry->mac, mac, ETH_ALEN);
01123         memcpy(new_entry->pmkid, pmkid, IW_PMKID_LEN);
01124         
01125         wlan_status.pmk_cache = g_slist_prepend(wlan_status.pmk_cache, new_entry);
01126         return;
01127 }
01133 unsigned char* find_pmkid_from_pmk_cache(unsigned char* mac) 
01134 {
01135         GSList *list;
01136 
01137         list = g_slist_find_custom(wlan_status.pmk_cache, mac, &compare_pmk_entry);
01138         if (list != NULL) {
01139                 struct pmksa_cache_t *pmk_cache = (struct pmksa_cache_t*)list->data;
01140                 print_mac("Found PMKSA entry for:", mac);
01141                 return pmk_cache->pmkid;
01142         }
01143         return NULL;
01144 }
01145 
01152 int scan(gchar *ssid, int ssid_len, gboolean add_timer)
01153 {
01154         struct iwreq req;
01155         struct iw_scan_req scan_req;
01156         
01157         if (get_scan_state() == SCAN_ACTIVE)
01158                 return 0;
01159         
01160         set_scan_state(SCAN_ACTIVE);
01161 
01162         init_iwreq(&req);
01163         
01164         memset(&scan_req, 0, sizeof(scan_req));
01165         
01166         if (ssid_len > 1 && ssid != NULL) {
01167                 scan_req.essid_len = ssid_len -1;
01168                 scan_req.bssid.sa_family = ARPHRD_ETHER;
01169                 memset(scan_req.bssid.sa_data, 0xff, ETH_ALEN);
01170                 memcpy(scan_req.essid, ssid, ssid_len -1);
01171                 req.u.data.pointer = (caddr_t) &scan_req;
01172                 req.u.data.length = sizeof(scan_req);
01173                 req.u.data.flags = IW_SCAN_THIS_ESSID;
01174         }
01175         
01176         if (ioctl(socket_open(), SIOCSIWSCAN, &req) < 0) {
01177                 DLOG_ERR("Scan failed");
01178                 return -1;
01179         }
01180         
01181         if (add_timer == TRUE) {
01182                 wlan_status.scan_id = g_timeout_add(
01183                         WLANCOND_SCAN_TIMEOUT,
01184                         wlan_scan_cb,
01185                         NULL);
01186         }
01187 
01188         DLOG_DEBUG("Scan issued");
01189         
01190         return 0;       
01191 }
01197 static int set_freq(int channel)
01198 {
01199         struct iwreq req;
01200         
01201         DLOG_DEBUG("Setting channel: %d", channel);
01202         
01203         init_iwreq(&req);
01204         
01205         req.u.freq.m = channel;
01206         
01207         if (ioctl(socket_open(), SIOCSIWFREQ, &req) < 0) {
01208                 DLOG_ERR("Freq failed");
01209                 return -1;
01210         }
01211         
01212         return 0;
01213 }
01214 static void init_conn_params(struct connect_params_t *conn_params) 
01215 {
01216         memset(conn_params, 0, sizeof(*conn_params));
01217 }
01222 void clear_wpa_keys(unsigned char* bssid)
01223 {
01224         struct iwreq req;
01225         struct iw_encode_ext ext;
01226         int sock;
01227         guint i;
01228         
01229         init_iwreq(&req);
01230         
01231         sock = socket_open();
01232         
01233         for (i=0;i<4;i++) {
01234                 
01235                 memset(&ext, 0, sizeof(ext));
01236                 
01237                 req.u.encoding.flags = i + 1;
01238                 req.u.encoding.flags |= IW_ENCODE_DISABLED;
01239                 req.u.encoding.pointer = (caddr_t) &ext;
01240                 req.u.encoding.length = sizeof(ext);
01241                 
01242                 ext.ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
01243                 ext.addr.sa_family = ARPHRD_ETHER;
01244                 
01245                 memset(ext.addr.sa_data, 0xff, ETH_ALEN);
01246                 ext.alg = IW_ENCODE_ALG_NONE;
01247                 
01248                 if (ioctl(sock, SIOCSIWENCODEEXT, &req) < 0) {
01249                         DLOG_ERR("Key clearing failed");
01250                 }
01251         }
01252         if (bssid != NULL) {
01253                 
01254                 memset(&ext, 0, sizeof(ext));
01255                 
01256                 req.u.encoding.flags = 1; //Revisit
01257                 req.u.encoding.flags |= IW_ENCODE_DISABLED;
01258                 req.u.encoding.pointer = (caddr_t) &ext;
01259                 req.u.encoding.length = sizeof(ext);
01260                 
01261                 ext.addr.sa_family = ARPHRD_ETHER;
01262                 
01263                 memcpy(ext.addr.sa_data, bssid, ETH_ALEN);
01264                 ext.alg = IW_ENCODE_ALG_NONE;
01265                 
01266                 if (ioctl(sock, SIOCSIWENCODEEXT, &req) < 0) {
01267                         DLOG_ERR("Key clearing failed");
01268                 }
01269         }
01270         
01271         return;
01272 }
01280 static int check_connect_arguments(struct connect_params_t *conn, char* ssid,
01281                                    unsigned char** key) 
01282 {
01283         guint i;
01284         
01285         if (conn->flags & WLANCOND_DISABLE_POWERSAVE) {
01286                 DLOG_DEBUG("Powersave disabled");
01287                 powersave = WLANCOND_POWER_ON;
01288         } else if (conn->flags & WLANCOND_MINIMUM_POWERSAVE) {
01289                 DLOG_DEBUG("Powersave minimum");
01290                 powersave = WLANCOND_LONG_CAM;
01291         } else if (conn->flags & WLANCOND_MAXIMUM_POWERSAVE) {
01292                 DLOG_DEBUG("Powersave maximum");
01293                 powersave = WLANCOND_SHORT_CAM;
01294         } else {
01295                 powersave = WLANCOND_SHORT_CAM;
01296         }
01297         
01298         if (conn->power_level != WLANCOND_TX_POWER10 &&
01299             conn->power_level != WLANCOND_TX_POWER100) {
01300                 DLOG_ERR("Invalid power level");
01301                 return -1;
01302         }
01303         
01304         switch (conn->mode) {
01305             case WLANCOND_ADHOC:
01306             case WLANCOND_INFRA:
01307                     break;
01308             default:
01309                     DLOG_ERR("Operating mode undefined\n");
01310                     return -1;
01311         }
01312         /* Encryption settings */
01313         guint32 wpa2_mode = conn->encryption & WLANCOND_ENCRYPT_WPA2_MASK;
01314         
01315         DLOG_DEBUG("Encryption setting: %08x", conn->encryption);
01316         
01317         switch (conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) {
01318             case WLANCOND_OPEN:
01319                     break;
01320             case WLANCOND_WEP:
01321                     break;
01322             case WLANCOND_WPA_PSK:
01323                     DLOG_DEBUG("%s PSK selected", wpa2_mode!=0?"WPA2":"WPA"); 
01324                     if (wpa2_mode != 0)
01325                             conn->authentication_type = EAP_AUTH_TYPE_WPA2_PSK;
01326                     else
01327                             conn->authentication_type = EAP_AUTH_TYPE_WPA_PSK;
01328                     break;
01329             case WLANCOND_WPA_EAP:
01330                     DLOG_DEBUG("%s EAP selected", wpa2_mode!=0?"WPA2":"WPA");
01331                     if (wpa2_mode != 0)
01332                             conn->authentication_type = EAP_AUTH_TYPE_WPA2_EAP;
01333                     else
01334                             conn->authentication_type = EAP_AUTH_TYPE_WPA_EAP;
01335                     break;
01336             default:
01337                     DLOG_DEBUG("Unsupported encryption mode");
01338                     return -1;
01339         }
01340         if ((conn->encryption & WLANCOND_WPS_MASK) != 0) {
01341                 DLOG_DEBUG("WPS selected");
01342                 conn->authentication_type = EAP_AUTH_TYPE_WFA_SC;
01343         }
01344         
01345         if (!ssid || conn->ssid_len == 0 || 
01346             conn->ssid_len > WLANCOND_MAX_SSID_SIZE + 1) {
01347                 DLOG_DEBUG("Invalid SSID");
01348                 return -1;
01349         }
01350         for (i=0;i<4;i++) {
01351                 if (conn->key_len[i] != 0) {
01352                         DLOG_DEBUG("Found key %d", i);
01353                         memcpy(&conn->key[i][0], key[i], conn->key_len[i]);
01354                 }
01355         }
01356         return 0;
01357 }
01358         
01365 static DBusHandlerResult settings_and_connect_request(
01366         DBusMessage    *message,
01367         DBusConnection *connection) {
01368         
01369         DBusMessage *reply = NULL;
01370         DBusError derror;
01371         struct connect_params_t *conn;   
01372         char *ssid;
01373         unsigned char* key[4];
01374         dbus_int32_t old_mode;
01375 
01376         dbus_error_init(&derror);
01377 
01378         if (in_flight_mode()) {
01379                 reply = new_dbus_error(message, WLANCOND_ERROR_WLAN_DISABLED);
01380                 send_and_unref(connection, reply);
01381                 return DBUS_HANDLER_RESULT_HANDLED;
01382         }
01383 
01384         remove_connect_timer();
01385         remove_wlan_if_timer();
01386         
01387         conn = &wlan_status.conn;
01388         /* Save previous mode */
01389         old_mode = conn->mode;
01390         init_conn_params(conn);
01391 
01392         if (dbus_message_get_args(
01393                     message, NULL,        
01394                     DBUS_TYPE_INT32, &conn->power_level,
01395                     DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid, &conn->ssid_len,
01396                     DBUS_TYPE_INT32, &conn->mode,
01397                     DBUS_TYPE_INT32, &conn->encryption,
01398                     DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[0], &conn->key_len[0],
01399                     DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[1], &conn->key_len[1],
01400                     DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[2], &conn->key_len[2],
01401                     DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &key[3], &conn->key_len[3],
01402                     DBUS_TYPE_INT32, &conn->default_key,
01403                     DBUS_TYPE_UINT32, &conn->adhoc_channel,
01404                     DBUS_TYPE_UINT32, &conn->flags,
01405                     DBUS_TYPE_INVALID) == FALSE) 
01406         {
01407                 /* Try without flags */
01408                 if (dbus_message_get_args(
01409                             message, &derror,        
01410                             DBUS_TYPE_INT32, &conn->power_level,
01411                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid, 
01412                             &conn->ssid_len,
01413                             DBUS_TYPE_INT32, &conn->mode,
01414                             DBUS_TYPE_INT32, &conn->encryption,
01415                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
01416                             &key[0], &conn->key_len[0],
01417                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
01418                             &key[1], &conn->key_len[1],
01419                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
01420                             &key[2], &conn->key_len[2],
01421                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
01422                             &key[3], &conn->key_len[3],
01423                             DBUS_TYPE_INT32, &conn->default_key,
01424                             DBUS_TYPE_UINT32, &conn->adhoc_channel,
01425                             DBUS_TYPE_INVALID) == FALSE) {
01426 
01427                         DLOG_ERR("Failed to parse setting_and_connect: %s",
01428                                  derror.message);
01429                         dbus_error_free(&derror);
01430                         goto param_err;
01431                 }
01432         }
01433 
01434         if (check_connect_arguments(conn, ssid, key) < 0)
01435                 goto param_err;
01436 
01437         /* If we change mode, do it when interface is down */
01438         if (old_mode != conn->mode) {
01439                 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
01440         }
01441 
01442         /* Mode */
01443         if (set_mode(conn->mode) < 0) {
01444                 goto param_err;
01445         }
01446         
01447         if (init_if(socket_open()) < 0) {
01448                 reply = new_dbus_error(message, WLANCOND_ERROR_INIT_FAILED);
01449                 goto param_err;
01450         }
01451         
01452         set_power_state(WLANCOND_POWER_ON, socket_open());
01453 
01454         if (set_tx_power(conn->power_level, socket_open()) != TRUE) {
01455                 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
01456                 goto param_err;
01457         }
01458         
01459         memcpy(conn->ssid, ssid, conn->ssid_len);
01460 
01461         set_scan_state(SCAN_NOT_ACTIVE);        
01462         set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL, FORCE_NO);
01463         
01464         /* Try if our own cache has results */
01465         if (find_connection_and_associate(wlan_status.roam_cache, FALSE) != 0) {
01466                 /* Try if mac80211 has cached results */
01467                 DLOG_DEBUG("Checking mac80211 cache...");
01468                 
01469                 GSList *scan_results = NULL;                
01470                 scan_results_ioctl(0, &scan_results);
01471                 
01472                 if (find_connection_and_associate(scan_results, TRUE) != 0) {
01473                         clean_scan_results(&scan_results);
01474                         if (scan(conn->ssid, conn->ssid_len, TRUE) < 0) {
01475                                 goto param_err;
01476                         }
01477                 } else {
01478                         clean_scan_results(&scan_results);
01479                 }
01480         }
01481         
01482         g_free(connect_name_cache);
01483         connect_name_cache = g_strdup(dbus_message_get_sender(message));
01484         
01485         reply = new_dbus_method_return(message);
01486         
01487         gchar* ifname = wlan_status.ifname;
01488 
01489         append_dbus_args(reply,
01490                          DBUS_TYPE_STRING, &ifname,
01491                          DBUS_TYPE_INVALID);        
01492         
01493         send_and_unref(connection, reply);
01494         
01495         return DBUS_HANDLER_RESULT_HANDLED;
01496         
01497   param_err:
01498         if (reply == NULL) {
01499                 DLOG_DEBUG("Parameter error in settings_and_connect\n");
01500                 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
01501         }
01502         send_and_unref(connection, reply);
01503         return DBUS_HANDLER_RESULT_HANDLED;
01504 }
01510 int associate(struct scan_results_t *scan_results) 
01511 {
01512         struct connect_params_t *conn = &wlan_status.conn;
01513 
01514         DLOG_DEBUG("Starting associate...");
01515 
01516         if (memcmp(conn->bssid, "\0\0\0\0\0\0", ETH_ALEN)) {
01517                 clear_wpa_keys(conn->bssid);
01518         }
01519 
01520         if (update_algorithms(conn->encryption) < 0) {
01521                 return -1;
01522         }
01523         
01524         /* WEP keys */
01525         if ((conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP){
01526                 if (set_wep_keys(conn) < 0) {
01527                         return -1;
01528                 }
01529         }
01530         
01531         memcpy(conn->bssid, scan_results->bssid, ETH_ALEN);
01532 
01533         if (set_encryption_method(conn->encryption, &wlan_status) == FALSE) {
01534                 return -1;
01535         }
01536 
01537         if (get_wpa_mode() == TRUE || 
01538             conn->authentication_type == EAP_AUTH_TYPE_WFA_SC) {
01539 
01540                 // Initialize authentication SW if mode is WPA or WPS
01541                 if (wpa_ie_push(scan_results->bssid, 
01542                                 scan_results->wpa_ie, 
01543                                 scan_results->wpa_ie_len, 
01544                                 scan_results->ssid, 
01545                                 scan_results->ssid_len -1,
01546                                 conn->authentication_type) < 0)
01547                         return -1;
01548         }
01549 
01550         /* Channel */
01551         /* Ad-hoc channel */
01552         if (conn->adhoc_channel != 0 && (conn->mode & WLANCOND_ADHOC)) {
01553                 if (conn->adhoc_channel < WLANCOND_MIN_WLAN_CHANNEL ||
01554                     conn->adhoc_channel > WLANCOND_MAX_WLAN_CHANNEL) {
01555                         DLOG_ERR("Invalid ad-hoc channel: %d", 
01556                                  conn->adhoc_channel);
01557                         return -1;
01558                 }
01559                 
01560                 scan_results->channel = conn->adhoc_channel;
01561         }
01562         
01563         set_freq(scan_results->channel);
01564 
01565         /* ESSID */
01566         if (set_essid(conn->ssid, conn->ssid_len) < 0) {
01567                 return -1;
01568         }
01569 
01570         /* Set BSSID if known */
01571         if (memcmp(scan_results->bssid, "\0\0\0\0\0\0", ETH_ALEN)) {
01572                 if (set_bssid(scan_results->bssid) < 0) {
01573                         return -1;
01574                 }
01575         }
01576         
01577         /* Set association timer */
01578         if (conn->mode == WLANCOND_INFRA) {
01579                 wlan_connect_timer_id = g_timeout_add(
01580                         WLANCOND_CONNECT_TIMEOUT, 
01581                         wlan_connect_timer_cb, NULL);
01582         }
01583         
01584         return 0;
01585 }
01586 
01593 static DBusHandlerResult scan_request(DBusMessage    *message,
01594                                       DBusConnection *connection) {
01595         
01596         DBusMessage *reply = NULL;
01597         DBusMessageIter iter, array_iter;
01598         char *ssid;
01599         const char* sender;
01600         dbus_int32_t power_level;
01601         dbus_int32_t flags;
01602         guint previous_state = 0;
01603         
01604         if (in_flight_mode()) {
01605                 reply = new_dbus_error(message, WLANCOND_ERROR_WLAN_DISABLED);
01606                 send_and_unref(connection, reply);
01607                 return DBUS_HANDLER_RESULT_HANDLED;
01608         }
01609 
01610         sender = dbus_message_get_sender(message);
01611         if (sender == NULL) {
01612                 goto param_err;
01613         }
01614 
01615         DLOG_DEBUG("Got scan request from %s", sender);
01616         
01617         if (get_scan_state() == SCAN_ACTIVE) {
01618                 reply = new_dbus_error(message, WLANCOND_ERROR_ALREADY_ACTIVE);
01619                 send_and_unref(connection, reply);
01620                 return DBUS_HANDLER_RESULT_HANDLED;
01621         }
01622         
01623         if ((previous_state = init_if(socket_open())) < 0) {
01624                 reply = new_dbus_error(message, WLANCOND_ERROR_INIT_FAILED);
01625                 goto param_err;
01626         }
01627         if (previous_state == WLAN_NOT_INITIALIZED) {
01628                 set_wlan_state(WLAN_INITIALIZED_FOR_SCAN, NO_SIGNAL, FORCE_NO);
01629         }
01630         
01631         dbus_message_iter_init(message, &iter);
01632         
01633         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
01634                 goto param_err;
01635         dbus_message_iter_get_basic(&iter, &power_level);
01636 
01637         dbus_message_iter_next(&iter);
01638         
01639         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
01640             dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
01641                 goto param_err;
01642         dbus_message_iter_recurse(&iter, &array_iter);
01643         dbus_message_iter_get_fixed_array(&array_iter, &ssid, 
01644                                           &wlan_status.scan_ssid_len);
01645         dbus_message_iter_next(&iter);
01646 
01647         power_down_after_scan = FALSE;
01648         
01649         if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32) {
01650                 dbus_message_iter_get_basic(&iter, &flags);
01651                 DLOG_DEBUG("Found flags: %08x", flags);
01652                 
01653                 if (flags & WLANCOND_NO_DELAYED_SHUTDOWN)
01654                         power_down_after_scan = TRUE;
01655         }
01656         
01657         if (power_level != WLANCOND_TX_POWER10 &&
01658             power_level != WLANCOND_TX_POWER100) {
01659                 DLOG_ERR("Invalid power level");
01660                 goto param_err;
01661         }
01662         
01663         if (set_tx_power(power_level, socket_open()) != TRUE) {
01664                 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
01665                 goto param_err;
01666         }
01667         
01668         if (ssid != NULL && wlan_status.scan_ssid_len > 1 && 
01669             wlan_status.scan_ssid_len < WLANCOND_MAX_SSID_SIZE +1) {
01670                 memcpy(wlan_status.scan_ssid, ssid, wlan_status.scan_ssid_len);
01671         }
01672         
01673         if (scan(wlan_status.scan_ssid, wlan_status.scan_ssid_len, FALSE) < 0) { 
01674                 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
01675                 goto param_err;
01676         }
01677 
01678         g_free(scan_name_cache);
01679         scan_name_cache = g_strdup(sender);
01680         
01681         reply = new_dbus_method_return(message);
01682         send_and_unref(connection, reply);
01683         
01684         return DBUS_HANDLER_RESULT_HANDLED;
01685         
01686   param_err:
01687         if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
01688                 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
01689         }
01690         if (reply == NULL) {
01691                 DLOG_DEBUG("Parameter error in scan request");
01692                 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
01693         }
01694         send_and_unref(connection, reply);
01695         return DBUS_HANDLER_RESULT_HANDLED;
01696 }
01703 static int network_compare(gconstpointer a, gconstpointer b)
01704 {
01705         struct scan_results_t *results_a = (struct scan_results_t*)a;
01706         struct scan_results_t *results_b = (struct scan_results_t*)b;
01707         
01708         if (wlan_status.scan_ssid_len > 1) {
01709                 
01710                 //DLOG_DEBUG("Scan ssid = %s", scan_ssid);
01711                 
01712                 gint a_eq = strncmp(wlan_status.scan_ssid, results_a->ssid, WLANCOND_MAX_SSID_SIZE);
01713                 gint b_eq = strncmp(wlan_status.scan_ssid, results_b->ssid, WLANCOND_MAX_SSID_SIZE);
01714                 // Check if either network match the scan SSID
01715                 if (!a_eq && !b_eq) {
01716                         //DLOG_DEBUG("Both (%s, %s) match scan SSID", results_a->ssid, results_b->ssid);
01717                         return 0;
01718                 }
01719                 
01720                 if (!a_eq && b_eq) {
01721                         //DLOG_DEBUG("%s is better than %s", results_a->ssid, results_b->ssid);
01722                         return -1;
01723                 }
01724                 
01725                 if (a_eq && !b_eq) {
01726                         
01727                         //DLOG_DEBUG("%s is better than %s", results_b->ssid, results_a->ssid);
01728                         return 1;
01729                 }
01730                 
01731         }
01732         //DLOG_DEBUG("No scan ssid, returning just RSSI values");
01733 
01734         return (results_a->rssi > results_b->rssi) ? -1 : (results_a->rssi < results_b->rssi) ? 1 : 0;
01735 }
01736 
01737 static gint compare_scan_entry(gconstpointer a, gconstpointer b) 
01738 {
01739         struct scan_results_t *scan_entry = (struct scan_results_t*)a;
01740         return memcmp(scan_entry->bssid, b, ETH_ALEN);
01741 }
01746 static void add_to_roam_cache(struct scan_results_t *scan_results) 
01747 {
01748         GSList *list;
01749         
01750         list = g_slist_find_custom(wlan_status.roam_cache, scan_results->bssid,
01751                                    &compare_scan_entry);
01752         
01753         if (list != NULL) {
01754                 struct scan_results_t *roam_cache_entry = (struct scan_results_t*)list->data;
01755                 print_mac("Found old entry for:", scan_results->bssid);
01756                 
01757                 /* Remove the old entry */
01758                 wlan_status.roam_cache = g_slist_remove(
01759                         wlan_status.roam_cache, roam_cache_entry);
01760                 
01761                 clean_scan_results_item(roam_cache_entry, NULL);
01762         }
01763 
01764         print_mac("New AP to roam cache:", scan_results->bssid);
01765         
01766         struct scan_results_t *results_to_list = g_slice_dup(struct scan_results_t, scan_results);
01767         results_to_list->wpa_ie = g_memdup(scan_results->wpa_ie, 
01768                                            scan_results->wpa_ie_len);
01769         wlan_status.roam_cache = g_slist_prepend(wlan_status.roam_cache, 
01770                                                  results_to_list);
01771         
01772         return;
01773 }
01779 gboolean remove_from_roam_cache(unsigned char *bssid) 
01780 {
01781         GSList *list;
01782 
01783         list = g_slist_find_custom(wlan_status.roam_cache, bssid,
01784                                    &compare_scan_entry);
01785         
01786         if (list != NULL) {
01787                 struct scan_results_t *roam_cache_entry = (struct scan_results_t*)list->data;
01788                 print_mac("Found entry to be removed:", bssid);
01789                 
01790                 wlan_status.roam_cache = g_slist_remove(
01791                         wlan_status.roam_cache, roam_cache_entry);
01792                 
01793                 clean_scan_results_item(roam_cache_entry, NULL);
01794                 
01795                 return TRUE;
01796         }
01797         
01798         return FALSE;
01799 }
01800 
01806 gboolean decrease_signal_in_roam_cache(unsigned char *bssid) 
01807 {
01808         GSList *list;
01809 
01810         list = g_slist_find_custom(wlan_status.roam_cache, bssid,
01811                                    &compare_scan_entry);
01812         
01813         if (list != NULL) {
01814                 struct scan_results_t *roam_cache_entry = (struct scan_results_t*)list->data;
01815                 print_mac("Found entry to be decreased:", bssid);
01816                 
01817                 roam_cache_entry->rssi -= WLANCOND_RSSI_PENALTY;
01818                 
01819                 return TRUE;
01820         }
01821         
01822         return FALSE;
01823 }
01830 static int check_group_cipher(guint32 c1, guint32 c2) 
01831 {
01832         guint32 m1 = (c1 & WLANCOND_ENCRYPT_GROUP_ALG_MASK);
01833         guint32 m2 = (c2 & WLANCOND_ENCRYPT_GROUP_ALG_MASK);
01834 
01835         if (m1 == m2)
01836                 return 1;
01837         if (m2 == WLANCOND_WPA_TKIP_GROUP && (m1 & WLANCOND_WPA_TKIP_GROUP))
01838                 return 1;
01839         if (m2 == (unsigned int)WLANCOND_WPA_AES_GROUP && 
01840             (m1 & WLANCOND_WPA_AES_GROUP))
01841                 return 1;
01842         
01843         DLOG_DEBUG("Group ciphers don't match");
01844         
01845         return -1;
01846 }
01853 static int check_ciphers(guint32 c1, guint32 c2) 
01854 {
01855         guint32 u1 = (c1 & WLANCOND_ENCRYPT_ALG_MASK);
01856         guint32 u2 = (c2 & WLANCOND_ENCRYPT_ALG_MASK);
01857         
01858         if (check_group_cipher(c1, c2) < 0)
01859                 return -1;
01860         
01861         if (u1 == u2)
01862                 return 1;
01863         if (u2 == WLANCOND_WPA_TKIP && (u1 & WLANCOND_WPA_TKIP))
01864                 return 1;
01865         if (u2 == WLANCOND_WPA_AES && (u1 & WLANCOND_WPA_AES))
01866                 return 1;
01867         
01868         DLOG_DEBUG("Unicast ciphers don't match");
01869         
01870         return -1;
01871 }
01872 static gboolean wlan_roam_scan_cb(void* data) 
01873 {
01874         wlan_status.roam_scan_id = 0;
01875         
01876         if (wlan_status.signal == WLANCOND_LOW && 
01877             get_wlan_state() == WLAN_CONNECTED) {
01878                 
01879                 DLOG_DEBUG("Roam scan timeout, initiating new scan");
01880                 
01881                 // Ignore return value
01882                 scan(wlan_status.conn.ssid, wlan_status.conn.ssid_len, FALSE);
01883         }
01884         
01885         return FALSE;
01886 }
01890 static void reschedule_scan(void) 
01891 {
01892         /* 
01893            If we are active use shortest scan interval, otherwise
01894            use exponential backoff
01895         */
01896         if (get_inactivity_status() == TRUE) {
01897                 wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
01898         } else {
01899                 if (wlan_status.roam_scan <= WLANCOND_MIN_ROAM_SCAN_INTERVAL) {
01900                         wlan_status.roam_scan = WLANCOND_MIN_ROAM_SCAN_INTERVAL;
01901                 } else if (wlan_status.roam_scan >= WLANCOND_MAX_ROAM_SCAN_INTERVAL) {
01902                         wlan_status.roam_scan = WLANCOND_MAX_ROAM_SCAN_INTERVAL;
01903                 } else {
01904                         wlan_status.roam_scan = wlan_status.roam_scan * 2;
01905                 }
01906         }
01907         
01908         wlan_status.roam_scan_id = g_timeout_add(
01909                 wlan_status.roam_scan,
01910                 wlan_roam_scan_cb,
01911                 NULL);
01912 }
01919 static gboolean check_capabilities(struct scan_results_t *scan_results,
01920                                    struct connect_params_t *conn) 
01921 {
01922         // Check mode
01923         if ((scan_results->cap_bits & WLANCOND_MODE_MASK) != (guint32)conn->mode)
01924                 return FALSE;
01925         if ((scan_results->cap_bits & WLANCOND_ENCRYPT_METHOD_MASK) != (guint32)(conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK))
01926                 return FALSE;
01927         if ((scan_results->cap_bits & WLANCOND_ENCRYPT_WPA2_MASK) != (guint32)(conn->encryption & WLANCOND_ENCRYPT_WPA2_MASK))
01928                 return FALSE;
01929         if (check_ciphers(scan_results->cap_bits, conn->encryption) < 0)
01930                 return FALSE;
01931         
01932         return TRUE;
01933 }
01934 
01942 struct scan_results_t* find_connection(
01943         GSList* ap_list, struct connect_params_t *conn, 
01944         gboolean update_roam_cache)
01945 {
01946         GSList *list;
01947         struct scan_results_t *best_connection = NULL;
01948         gint current_rssi = 0;
01949 
01950         /* If update roam cache, clean it first */
01951         if (update_roam_cache == TRUE)
01952                 clean_roam_cache();
01953         
01954         for (list = ap_list; list != NULL; list = list->next) {
01955                 struct scan_results_t *scan_results = (struct scan_results_t*)list->data;
01956                 if (memcmp(scan_results->ssid, conn->ssid, scan_results->ssid_len) == 0) {
01957                         print_mac("Found AP:", scan_results->bssid);
01958                         
01959                         /* Find the current AP so that we know it's RSSI */
01960                         if (memcmp(scan_results->bssid, wlan_status.conn.bssid,
01961                                    ETH_ALEN) == 0) {
01962                                 current_rssi = scan_results->rssi;
01963                                 DLOG_DEBUG("Current AP: %d", current_rssi);
01964                         }
01965                         
01966                         if (check_capabilities(scan_results, conn) == 
01967                             FALSE)
01968                                 continue;
01969 
01970                         if (is_ap_in_black_list(scan_results->bssid) == TRUE) {
01971                                 DLOG_DEBUG("AP is in black list, discarded");
01972                                 continue;
01973                         }
01974                         
01975                         /* At this point we know the connection is good,
01976                            add to the roam cache
01977                         */
01978                         if (update_roam_cache == TRUE) {
01979                                 add_to_roam_cache(scan_results);
01980                         }
01981                         
01982                         if (best_connection == NULL || 
01983                             best_connection->rssi < scan_results->rssi) {
01984                                 DLOG_DEBUG("Best connection: %d (old %d)", 
01985                                            scan_results->rssi, 
01986                                            best_connection == NULL ? 
01987                                            WLANCOND_MINIMUM_SIGNAL:
01988                                            best_connection->rssi);
01989                                 best_connection = scan_results;
01990                         }
01991                 }
01992         }
01993         
01994         /* Did not find any connection */
01995         if (best_connection == NULL)
01996                 return NULL;
01997         
01998         /* Check if we are already connected but the best connection is not 
01999            worth changing
02000         */
02001         if (current_rssi != 0) {
02002                 if (best_connection->rssi < current_rssi + 
02003                     WLANCOND_ROAM_THRESHOLD) {
02004                         DLOG_DEBUG("Best connection not good enough");
02005                         return NULL;
02006                 }
02007         }
02008 
02009         /* Check if the signal level is good enough for connection */
02010         if (best_connection->rssi < WLANCOND_MINIMUM_SIGNAL)
02011                 return NULL;
02012         
02013         return best_connection;
02014 }
02015 
02021 int find_connection_and_associate(GSList *scan_results, gboolean update_roam_cache) 
02022 {
02023         struct scan_results_t adhoc;
02024         struct connect_params_t *conn = &wlan_status.conn;
02025 
02026         struct scan_results_t *connection = find_connection(
02027                 scan_results, &wlan_status.conn, update_roam_cache);
02028         
02029         if (connection == NULL && conn->mode == WLANCOND_ADHOC) {
02030                 DLOG_DEBUG("No existing adhoc connection");
02031                 memset(&adhoc, 0, sizeof(adhoc));
02032                 connection = &adhoc;
02033                 memcpy(connection->ssid, conn->ssid, conn->ssid_len);
02034         }       
02035         
02036         if (connection) {
02037                 int ret = associate(connection);
02038                 if (ret < 0)
02039                         memset(wlan_status.conn.bssid, 0, ETH_ALEN);
02040                 return ret;
02041         }
02042         return -1;
02043 }
02044 
02049 static void connect_from_scan_results(GSList *scan_results) 
02050 {
02051         int status = find_connection_and_associate(scan_results, TRUE);
02052         
02053         clean_scan_results(&scan_results);
02054         
02055         if (status == 0)
02056                 return;
02057         
02058         DLOG_DEBUG("Could not find suitable network");
02059         
02060         if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION) {
02061                 set_wlan_state(WLAN_NOT_INITIALIZED, 
02062                                DISCONNECTED_SIGNAL, FORCE_YES);
02063                 return;
02064         }
02065         
02066         /* We are connected but would prefer better connection */
02067         reschedule_scan();
02068 }
02075 int scan_results_ioctl(int ifindex, GSList** scan_results_save) 
02076 {
02077         struct iwreq req;
02078         char *buffer;
02079         unsigned int buflen = IW_SCAN_MAX_DATA*2;
02080         int sock;
02081         unsigned int counter = 3;
02082 
02083         //DLOG_DEBUG("Scan results ioctl");
02084 
02085         init_iwreq(&req);
02086 
02087         sock = socket_open();
02088         
02089         buffer = g_malloc(buflen);
02090         
02091   try_again:
02092         
02093         /* Read the results */
02094         req.u.data.pointer = buffer;
02095         req.u.data.flags = 0;
02096         req.u.data.length = buflen;
02097         
02098         if (ioctl(sock, SIOCGIWSCAN, &req) < 0) {
02099                 /* Check if we got too many results for 
02100                    our buffer*/
02101                 if (errno == E2BIG) {
02102                         DLOG_DEBUG("Too much data for buffer length %d "
02103                                    "needed %d\n", buflen, req.u.data.length);
02104                         
02105                         char* new_buffer = NULL;
02106                         buflen = (req.u.data.length > buflen ? 
02107                                   req.u.data.length : buflen * 2);
02108                         new_buffer = g_realloc(buffer, buflen);
02109                         
02110                         buffer = new_buffer;
02111                         goto try_again;
02112                 }                                 
02113 
02114                 /* Check if results not available yet */
02115                 if (errno == EAGAIN)
02116                 {
02117                         DLOG_DEBUG("Not yet ready...");
02118                         if (counter-- > 0) {
02119                                 sleep(1);
02120                                 goto try_again;
02121                         }
02122                 }
02123                 
02124                 DLOG_ERR("Get scan results failed");
02125                 
02126                 g_free(buffer);
02127                 return -1;
02128         }
02129             
02130         if (req.u.data.length)
02131         {
02132                 struct iw_event            iwe;
02133                 struct stream_descr        stream;
02134                 struct scan_results_t      *scan_results;
02135                 struct wireless_iface      *wireless_if;
02136                 int                        ret;
02137                 gboolean                   wap_handled = FALSE;
02138                 int                        we_version;
02139                 
02140                 scan_results = g_slice_new0(struct scan_results_t);
02141                 memset(&iwe, 0, sizeof(iwe));
02142                 
02143                 if (ifindex != 0) {
02144                         wireless_if = get_interface_data(ifindex);
02145                         we_version = wireless_if->range.we_version_compiled;
02146                 } else {
02147                         struct iw_range range;
02148                         iw_get_range_info(socket_open(), wlan_status.ifname, 
02149                                           &range);
02150                         we_version = range.we_version_compiled;
02151                 }
02152                 
02153                 iw_init_event_stream(&stream, buffer, req.u.data.length);
02154                 do
02155                 {
02156                         /* Extract an event */
02157                         ret = iw_extract_event_stream(
02158                                 &stream, &iwe, 
02159                                 we_version);
02160                         if (ret > 0) {
02161                                 /* Let's peek what is coming so that we can
02162                                    separate different access points from
02163                                    the stream */
02164 
02165                                 if (iwe.cmd == SIOCGIWAP) {
02166                                         /* Do not save if first time
02167                                            because WAP comes first, then other
02168                                            parameters */
02169                                         if (wap_handled == TRUE) {
02170                                                 *scan_results_save = save_scan_results(scan_results, *scan_results_save);
02171                                                 scan_results = g_slice_new0(struct scan_results_t);
02172                                         } else {
02173                                                 wap_handled = TRUE;
02174                                         }
02175                                 }
02176                                 print_event_token(&iwe, scan_results, ifindex, 
02177                                                   TRUE);
02178                         }
02179                         
02180                 }
02181                 while (ret > 0);
02182                 
02183                 /* Check if the final results is still in the queue before
02184                    the result is sent into DBUS */
02185                 if (wap_handled == TRUE) {
02186                         *scan_results_save = save_scan_results(
02187                                 scan_results, 
02188                                 *scan_results_save);
02189                 } else {
02190                         // No results
02191                         g_slice_free(struct scan_results_t, scan_results);
02192                 }
02193         }
02194         
02195         g_free(buffer);
02196 
02197         return 0;
02198 }
02199 
02200 
02206 gboolean ask_scan_results(int ifindex) 
02207 {
02208         GSList *scan_results_save = NULL;
02209         dbus_int32_t number_of_results;
02210         
02211         if (scan_results_ioctl(ifindex, &scan_results_save) < 0)
02212                 return FALSE;
02213         
02214         /* First send scan results if someone was expecting them */
02215         if (scan_name_cache != NULL) {        
02216                 number_of_results = g_slist_length(scan_results_save);
02217                 
02218                 /* Sort the list only if the amount of networks is very high and
02219                    we need to restrict the results */
02220                 if (number_of_results > WLANCOND_MAX_NETWORKS)
02221                         scan_results_save = g_slist_sort(scan_results_save, 
02222                                                          network_compare);
02223                 
02224                 send_dbus_scan_results(scan_results_save, scan_name_cache, 
02225                                        number_of_results);
02226                 g_free(scan_name_cache);
02227                 scan_name_cache = NULL;
02228         }
02229 
02230         /* Try to associate if state is initialized_for_connection or
02231            signal level is low */
02232         if ((get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION ||
02233              wlan_status.signal == WLANCOND_LOW) && 
02234             get_scan_state() == SCAN_ACTIVE) {
02235                 
02236                 DLOG_DEBUG("Connect from scan");
02237                 
02238                 set_scan_state(SCAN_NOT_ACTIVE);
02239 
02240                 connect_from_scan_results(scan_results_save);
02241                 
02242                 return TRUE;
02243         }
02244         
02245         set_scan_state(SCAN_NOT_ACTIVE);
02246         
02247         if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN &&
02248             power_down_after_scan == TRUE) {  
02249                 set_interface_state(socket_open(), CLEAR, IFF_UP);
02250         }
02251 
02252         if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN) {
02253                 /* Save scan results temporarily */
02254                 if (wlan_status.roam_cache) {
02255                         clean_roam_cache();
02256                 }
02257                 wlan_status.roam_cache = scan_results_save;                        
02258                 set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_NO);
02259         } else {
02260                 clean_scan_results(&scan_results_save);
02261         }
02262 
02263         return TRUE;        
02264 }
02265 
02272 static DBusHandlerResult disconnect_request(DBusMessage    *message,
02273                                             DBusConnection *connection) {
02274         DBusMessage *reply;
02275 
02276         set_scan_state(SCAN_NOT_ACTIVE);
02277 
02278         /* Set_wlan_state puts IF down */
02279         set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL, FORCE_YES);
02280 
02281         reply = new_dbus_method_return(message);
02282         send_and_unref(connection, reply);
02283         
02284         return DBUS_HANDLER_RESULT_HANDLED;
02285 }
02292 static DBusHandlerResult disassociate_request(DBusMessage    *message,
02293                                               DBusConnection *connection) {
02294         DBusMessage *reply;
02295         
02296         if (get_wlan_state() != WLAN_CONNECTED && 
02297             get_wlan_state() != WLAN_NO_ADDRESS) {
02298                 DLOG_ERR("Not in correct state for disassociation");
02299 
02300                 reply = new_dbus_method_return(message);
02301                 send_and_unref(connection, reply);
02302                 return DBUS_HANDLER_RESULT_HANDLED;
02303         }
02304         
02305         if (get_wpa_mode() == TRUE) {
02306                 clear_wpa_keys(wlan_status.conn.bssid);
02307         }
02308         
02309         mlme_command(wlan_status.conn.bssid, IW_MLME_DISASSOC, 
02310                      WLANCOND_REASON_LEAVING);
02311         
02312         set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL, FORCE_NO);
02313 
02314         DLOG_DEBUG("Disassociated, trying to find a new connection");
02315         
02316         if (scan(wlan_status.conn.ssid, wlan_status.conn.ssid_len, TRUE) < 0) {
02317                 /* Set_wlan_state puts IF down */
02318                 set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
02319                                FORCE_YES);
02320         }
02321         
02322         reply = new_dbus_method_return(message);
02323         send_and_unref(connection, reply);
02324         
02325         return DBUS_HANDLER_RESULT_HANDLED;
02326 }
02333 static DBusHandlerResult status_request(DBusMessage    *message,
02334                                         DBusConnection *connection) {
02335         DBusMessage *reply = NULL;
02336         struct iwreq req;
02337         struct iw_range range;
02338         char *essid = NULL;
02339         int essid_len;
02340         dbus_uint32_t sens = 0;
02341         dbus_uint32_t security = 0;
02342         dbus_uint32_t capability = 0;
02343         dbus_uint32_t channel = 0;
02344         unsigned char *bssid = NULL;
02345         //unsigned char *key = NULL;
02346         int sock;
02347 
02348         if (get_wlan_state() != WLAN_CONNECTED && 
02349             get_wlan_state() != WLAN_NO_ADDRESS &&
02350             get_mode() != WLANCOND_ADHOC) {
02351                 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02352                 send_and_unref(connection, reply);
02353                 return DBUS_HANDLER_RESULT_HANDLED;
02354         }
02355                 
02356         sock = socket_open();
02357 
02358         init_iwreq(&req);
02359         
02360         essid = g_malloc0(IW_ESSID_MAX_SIZE+1);
02361         req.u.essid.pointer = (caddr_t)essid;
02362         req.u.essid.length = IW_ESSID_MAX_SIZE;
02363         req.u.essid.flags = 0;
02364 
02365         /* essid */
02366         if (ioctl(sock, SIOCGIWESSID, &req) < 0) {
02367                 DLOG_ERR("Could not get ESSID");
02368                 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02369                 goto param_err;
02370         }
02371         essid_len = req.u.essid.length;
02372         
02373         // Handle corner cases to keep the API the same
02374         if (essid_len == 0 || essid_len == 32)
02375                 essid_len++;
02376         
02377         init_iwreq(&req);
02378         
02379         /* bssid */
02380         if (ioctl(sock, SIOCGIWAP, &req) < 0) {
02381                 DLOG_ERR("Could not get BSSID");
02382                 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02383                 goto param_err;
02384         }
02385         bssid = g_malloc(ETH_ALEN);
02386         memcpy(bssid, &req.u.ap_addr.sa_data, ETH_ALEN);
02387 
02388         init_iwreq(&req);
02389         struct iw_statistics stats;
02390         memset(&stats, 0, sizeof(struct iw_statistics));
02391         
02392         req.u.data.pointer = (caddr_t) &stats;
02393         req.u.data.length = sizeof(struct iw_statistics);
02394         req.u.data.flags = 1;
02395         
02396         /* Link quality i.e. stats */
02397         if (ioctl(sock, SIOCGIWSTATS, &req) < 0) {
02398                 DLOG_ERR("Could not get statistics");
02399                 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02400                 goto param_err;
02401         }
02402         sens = stats.qual.level - 0x100;
02403         
02404         /* Channel */
02405         init_iwreq(&req);
02406                 
02407         if (ioctl(sock, SIOCGIWFREQ, &req) < 0) {
02408                 DLOG_DEBUG("Could not get channel");
02409                 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02410                 goto param_err;
02411         }
02412         
02413         if (iw_get_range_info(sock, wlan_status.ifname, &range) >= 0) {
02414                 double freq = iw_freq2float(&(req.u.freq));
02415                 channel = iw_freq_to_channel(freq, &range);
02416         }
02417         
02418         if (channel < WLANCOND_MIN_WLAN_CHANNEL || 
02419             channel > WLANCOND_MAX_WLAN_CHANNEL) {
02420                 channel = 0;
02421                 DLOG_DEBUG("Got invalid channel\n");
02422         }
02423         
02424         /* Mode (Adhoc/Infra) */
02425         init_iwreq(&req);
02426 
02427         if (ioctl(sock, SIOCGIWMODE, &req) < 0) {
02428                 DLOG_ERR("Could not get operating mode");
02429                 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02430                 goto param_err;
02431         }
02432 
02433         if (req.u.mode == IW_MODE_ADHOC) {
02434                 capability |= WLANCOND_ADHOC;
02435         } else if (req.u.mode == IW_MODE_INFRA) {
02436                 capability |= WLANCOND_INFRA;
02437         }        
02438         
02439         init_iwreq(&req);
02440 
02441         /* encryption status */
02442         security = wlan_status.conn.encryption;
02443 
02444 #if 0
02445         key = g_malloc(IW_ENCODING_TOKEN_MAX);
02446         req.u.data.pointer = (caddr_t) key;
02447         req.u.data.length = IW_ENCODING_TOKEN_MAX;
02448         req.u.data.flags = 0;
02449         
02450         if (ioctl(sock, SIOCGIWENCODE, &req) < 0) {
02451                 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02452                 goto param_err;
02453         } 
02454         
02455         if (req.u.data.flags & IW_ENCODE_OPEN)
02456                 security |= WLANCOND_OPEN;
02457         
02458         if (req.u.data.flags & IW_ENCODE_RESTRICTED)
02459                 security |= WLANCOND_WEP;
02460         
02461         /* Currently we don't know if EAP or PSK is in use */
02462         if (req.u.data.flags & IW_ENCODE_TKIP)
02463                 security |= WLANCOND_WPA_PSK & WLANCOND_WPA_EAP & 
02464                         WLANCOND_WPA_TKIP;
02465         
02466         if (req.u.data.flags & IW_ENCODE_AES)
02467                 security |= WLANCOND_WPA_PSK & WLANCOND_WPA_EAP &
02468                         WLANCOND_WPA_AES;
02469         
02470         g_free(key);
02471 #endif        
02472         init_iwreq(&req);
02473 
02474         /* Speed / Rate */
02475         if (ioctl(sock, SIOCGIWRATE, &req) < 0) {
02476                 DLOG_ERR("Could not get the rate");
02477                 reply = new_dbus_error(message, WLANCOND_ERROR_IOCTL_FAILED);
02478                 goto param_err;
02479         } 
02480         capability |= req.u.bitrate.value;
02481         
02482         reply = new_dbus_method_return(message);
02483         
02484         gchar* ifname = wlan_status.ifname;
02485 
02486         append_dbus_args(reply,
02487                          DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
02488                          &essid, essid_len,
02489                          DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, ETH_ALEN,
02490                          DBUS_TYPE_UINT32, &sens,
02491                          DBUS_TYPE_UINT32, &channel,
02492                          DBUS_TYPE_UINT32, &capability,
02493                          DBUS_TYPE_UINT32, &security,
02494                          DBUS_TYPE_STRING, &ifname,
02495                          DBUS_TYPE_INVALID);
02496 
02497         send_and_unref(connection, reply);
02498 
02499         g_free(essid);
02500         g_free(bssid);
02501         
02502         return DBUS_HANDLER_RESULT_HANDLED;
02503         
02504   param_err:
02505         g_free(essid);
02506         g_free(bssid);
02507         //g_free(key);
02508         if (reply == NULL) {
02509                 DLOG_DEBUG("Parameter error in status request");
02510                 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
02511         }
02512         send_and_unref(connection, reply);
02513         return DBUS_HANDLER_RESULT_HANDLED;
02514 }
02515 
02522 static DBusHandlerResult interface_request(DBusMessage    *message,
02523                                            DBusConnection *connection) {
02524         DBusMessage *reply;
02525         gchar* ifname = wlan_status.ifname;
02526 
02527         reply = new_dbus_method_return(message);
02528         
02529         append_dbus_args(reply,
02530                          DBUS_TYPE_STRING, &ifname,
02531                          DBUS_TYPE_INVALID);        
02532         
02533         send_and_unref(connection, reply);
02534         
02535         return DBUS_HANDLER_RESULT_HANDLED;
02536 }
02537 
02544 static DBusHandlerResult connection_status_request(
02545         DBusMessage    *message,
02546         DBusConnection *connection) {
02547         
02548         DBusMessage *reply;
02549         dbus_bool_t state = FALSE;
02550         
02551         guint state_v = get_wlan_state();
02552 
02553         if (state_v == WLAN_INITIALIZED ||
02554             state_v == WLAN_NO_ADDRESS ||
02555             state_v == WLAN_CONNECTED)
02556                 state = TRUE;
02557         
02558         reply = new_dbus_method_return(message);
02559         
02560         append_dbus_args(reply,
02561                          DBUS_TYPE_BOOLEAN, &state,
02562                          DBUS_TYPE_INVALID);        
02563 
02564         send_and_unref(connection, reply);
02565         
02566         return DBUS_HANDLER_RESULT_HANDLED;
02567 }
02574 static DBusHandlerResult set_pmksa_request(DBusMessage    *message,
02575                                            DBusConnection *connection) {
02576         
02577         DBusMessage *reply = NULL;
02578         unsigned int pmkid_len, mac_len;
02579         unsigned char *pmkid;
02580         unsigned char *mac;
02581         dbus_uint32_t action;
02582         DBusError derror;
02583 
02584         dbus_error_init(&derror);
02585         
02586         if (dbus_message_get_args(
02587                     message, &derror,        
02588                     DBUS_TYPE_UINT32, &action,
02589                     DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &pmkid, &pmkid_len,
02590                     DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &mac, &mac_len,
02591                     DBUS_TYPE_INVALID) == FALSE) 
02592         {
02593                 DLOG_ERR("Failed to parse set_pmksa request: %s",
02594                          derror.message);
02595                 dbus_error_free(&derror);
02596                 goto param_err;
02597         }
02598         
02599         if (action != IW_PMKSA_ADD) {
02600                 DLOG_ERR("Invalid action");
02601                 goto param_err;
02602         }
02603         
02604         if (pmkid == NULL || pmkid_len != WLANCOND_PMKID_LEN || mac == NULL 
02605             || mac_len != ETH_ALEN) {
02606                 DLOG_ERR("Invalid arguments");
02607                 goto param_err;
02608         }
02609         
02610         add_to_pmksa_cache(pmkid, mac);
02611         
02612         print_mac("PMKSA added successfully for address:", mac);
02613         
02614         reply = new_dbus_method_return(message);
02615         send_and_unref(connection, reply);
02616         
02617         return DBUS_HANDLER_RESULT_HANDLED;
02618         
02619   param_err:
02620         if (reply == NULL) {
02621                 DLOG_DEBUG("Parameter error in set_pmksa");
02622                 reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
02623         }
02624         send_and_unref(connection, reply);
02625         return DBUS_HANDLER_RESULT_HANDLED;
02626 } 
02627 
02634 static DBusHandlerResult set_powersave_request(DBusMessage    *message,
02635                                                DBusConnection *connection) {
02636         
02637         DBusMessage *reply = NULL;
02638         int sock;
02639         DBusError error;
02640         dbus_bool_t onoff;
02641         
02642         sock = socket_open();
02643         
02644         dbus_error_init(&error);
02645         
02646         if (dbus_message_get_args(message, &error,
02647                                   DBUS_TYPE_BOOLEAN, &onoff,
02648                                   DBUS_TYPE_INVALID) == FALSE) {
02649                 DLOG_ERR("Failed to parse message: %s",
02650                          error.message);
02651                 dbus_error_free(&error);
02652                 
02653                 send_invalid_args(connection, message);
02654                 return DBUS_HANDLER_RESULT_HANDLED;
02655         }
02656         
02657         /* Powersave can be allowed only when we are properly connected
02658            or when the entity asking for connection wants powersave despite of
02659            the state */
02660         if (onoff == TRUE) {
02661                 if (get_wlan_state() == WLAN_NOT_INITIALIZED) {
02662                         set_wlan_state(WLAN_NOT_INITIALIZED, NO_SIGNAL, FORCE_YES);
02663                 } else if (get_wlan_state() != WLAN_NO_ADDRESS ||
02664                            (connect_name_cache != NULL && 
02665                             strcmp(dbus_message_get_sender(message), 
02666                                    connect_name_cache) == 0)) {
02667                         if (set_power_state(powersave, sock) == FALSE) {
02668                                 DLOG_ERR("Setting powersave failed");
02669                                 // Not fatal
02670                         }
02671                 }
02672         } else {
02673                 // Go to full power
02674                 if (set_power_state(WLANCOND_POWER_ON, sock) == FALSE) {
02675                         DLOG_ERR("Setting powersave failed");
02676                         // Not fatal
02677                 }
02678         }
02679         
02680         DLOG_DEBUG("WLAN powersave %s", onoff==TRUE?"on":"off");
02681         
02682         reply = new_dbus_method_return(message);
02683         send_and_unref(connection, reply);
02684         
02685         return DBUS_HANDLER_RESULT_HANDLED;
02686 }
02687 
02694 static void wpa_ie_push_cb(DBusPendingCall *pending, 
02695                            void *user_data)
02696 {
02697         DBusMessage *reply;
02698         DBusError error;
02699 
02700         //DLOG_DEBUG("WPA IE callback");
02701         
02702         dbus_error_init (&error);
02703         
02704         reply = dbus_pending_call_steal_reply(pending);
02705         
02706         if (dbus_set_error_from_message(&error, reply)) {
02707                 
02708                 DLOG_DEBUG("EAP WPA IE push call result:%s", error.name);
02709                 
02710                 dbus_error_free(&error);
02711                 
02712                 set_wlan_state(WLAN_NOT_INITIALIZED,
02713                                DISCONNECTED_SIGNAL,
02714                                FORCE_YES);
02715         }
02716         
02717         if (reply)
02718                 dbus_message_unref(reply);
02719         dbus_pending_call_unref(pending);
02720 }
02721 
02730 int wpa_ie_push(unsigned char* ap_mac_addr, unsigned char* ap_wpa_ie,
02731                 int ap_wpa_ie_len, char* ssid, int ssid_len, 
02732                 unsigned int authentication_type) {
02733 
02734         DBusMessage *msg;
02735         DBusPendingCall *pending;
02736 
02737         if (authentication_type != EAP_AUTH_TYPE_WFA_SC) {
02738                 if (wlan_status.wpa_ie.ie_len == 0 || ap_wpa_ie == NULL || 
02739                     ssid == NULL) {
02740                         DLOG_ERR("WPA IE / SSID (%s) not valid", ssid);
02741                         return -1;
02742                 }
02743         }
02744 
02745         msg = dbus_message_new_method_call(
02746                 EAP_SERVICE,
02747                 EAP_REQ_PATH,
02748                 EAP_REQ_INTERFACE,
02749                 EAP_WPA_IE_PUSH_REQ);
02750         
02751         if (msg == NULL) {
02752                 return -1;
02753         }
02754         
02755         append_dbus_args(
02756                 msg,
02757                 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
02758                 &wlan_status.wpa_ie.ie, wlan_status.wpa_ie.ie_len,
02759                 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ap_wpa_ie, 
02760                 ap_wpa_ie_len,
02761                 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
02762                 &ssid, ssid_len,
02763                 DBUS_TYPE_UINT32, &wlan_status.pairwise_cipher,
02764                 DBUS_TYPE_UINT32, &wlan_status.group_cipher,
02765                 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
02766                 &ap_mac_addr, ETH_ALEN,
02767                 DBUS_TYPE_UINT32, &authentication_type,
02768                 DBUS_TYPE_INVALID);
02769 
02770         if (!dbus_connection_send_with_reply(get_dbus_connection(), 
02771                                              msg, &pending, -1))
02772                 die("Out of memory");
02773         
02774         if (!dbus_pending_call_set_notify (pending, wpa_ie_push_cb, NULL, NULL))
02775                 die("Out of memory");
02776         
02777         dbus_message_unref(msg);
02778         
02779         return 0;
02780 }
02787 int wpa_mic_failure_event(dbus_bool_t key_type, dbus_bool_t is_fatal) {
02788         DBusMessage *msg;
02789         DBusMessage *reply;
02790         DBusError derr;
02791 
02792         msg = dbus_message_new_method_call(
02793                 EAP_SERVICE,
02794                 EAP_REQ_PATH,
02795                 EAP_REQ_INTERFACE,
02796                 EAP_WPA_MIC_FAILURE_REQ);
02797         
02798         if (msg == NULL) {
02799                 return -1;
02800         }
02801         
02802         append_dbus_args(msg,
02803                          DBUS_TYPE_BOOLEAN, &key_type, 
02804                          DBUS_TYPE_BOOLEAN, &is_fatal, 
02805                          DBUS_TYPE_INVALID);
02806         
02807         dbus_error_init(&derr);
02808         
02809         reply = dbus_connection_send_with_reply_and_block(
02810                 get_dbus_connection(), msg, -1, &derr);
02811         
02812         dbus_message_unref(msg);
02813         
02814         if (dbus_error_is_set(&derr)) {
02815                 DLOG_ERR("EAP returned error: %s", derr.name);
02816                 
02817                 dbus_error_free(&derr);
02818                 if (reply)
02819                         dbus_message_unref(reply);
02820                 return -1;
02821         }
02822         
02823         dbus_message_unref(reply);
02824         
02825         return 0;
02826 }
02831 int associate_supplicant(void) {
02832         DBusMessage *msg;
02833         DBusMessage *reply;
02834         DBusError derr;
02835         
02836         msg = dbus_message_new_method_call(
02837                 EAP_SERVICE,
02838                 EAP_REQ_PATH,
02839                 EAP_REQ_INTERFACE,
02840                 EAP_ASSOCIATE_REQ);
02841         
02842         if (msg == NULL) {
02843                 return -1;
02844         }
02845         
02846         dbus_error_init(&derr);
02847         
02848         reply = dbus_connection_send_with_reply_and_block(
02849                 get_dbus_connection(), msg, -1, &derr);
02850         
02851         dbus_message_unref(msg);
02852         
02853         if (dbus_error_is_set(&derr)) {
02854                 DLOG_ERR("EAP returned error: %s", derr.name);
02855                 
02856                 dbus_error_free(&derr);
02857                 if (reply)
02858                         dbus_message_unref(reply);
02859                 return -1;
02860         }
02861         
02862         dbus_message_unref(reply);
02863         
02864         return 0;
02865 }
02872 static void disassociate_cb(DBusPendingCall *pending, 
02873                             void *user_data)
02874 {
02875         DBusMessage *reply;
02876         DBusError error;
02877         
02878         dbus_error_init (&error);
02879         
02880         reply = dbus_pending_call_steal_reply(pending);
02881         
02882         if (dbus_set_error_from_message(&error, reply)) {
02883                 
02884                 DLOG_DEBUG("EAP disassociate call result:%s", error.name);
02885                 
02886                 dbus_error_free(&error);
02887         }
02888         
02889         if (reply)
02890                 dbus_message_unref(reply);
02891         dbus_pending_call_unref(pending);
02892 }
02893 
02898 int disassociate_eap(void) {
02899         DBusMessage *msg;
02900         DBusPendingCall *pending;
02901         
02902         msg = dbus_message_new_method_call(
02903                 EAP_SERVICE,
02904                 EAP_REQ_PATH,
02905                 EAP_REQ_INTERFACE,
02906                 EAP_DISASSOCIATE_REQ);
02907         
02908         if (msg == NULL) {
02909                 return -1;
02910         }
02911         
02912         if (!dbus_connection_send_with_reply(get_dbus_connection(), 
02913                                              msg, &pending, -1))
02914                 die("Out of memory");
02915         
02916         if (!dbus_pending_call_set_notify (pending, disassociate_cb, NULL, 
02917                                            NULL))
02918                 die("Out of memory");
02919         
02920         dbus_message_unref(msg);
02921         
02922         return 0;
02923 }
02924 
02925 typedef DBusHandlerResult (*handler_func)(DBusMessage *message,
02926                                           DBusConnection *connection);
02927 
02928 typedef struct {
02929         const char *interface;
02930         const char *name;
02931         handler_func func;
02932 } method_handler_t;
02933 
02934 static method_handler_t handlers[] = {
02935         { WLANCOND_REQ_INTERFACE, WLANCOND_SETTINGS_AND_CONNECT_REQ, settings_and_connect_request},
02936         { WLANCOND_REQ_INTERFACE, WLANCOND_SCAN_REQ, scan_request},        
02937         { WLANCOND_REQ_INTERFACE, WLANCOND_STATUS_REQ, status_request},        
02938         { WLANCOND_REQ_INTERFACE, WLANCOND_INTERFACE_REQ, interface_request},        
02939         { WLANCOND_REQ_INTERFACE, WLANCOND_CONNECTION_STATUS_REQ, connection_status_request},        
02940         { WLANCOND_REQ_INTERFACE, WLANCOND_SET_PMKSA_REQ, set_pmksa_request},
02941         { WLANCOND_REQ_INTERFACE, WLANCOND_SET_POWERSAVE_REQ, set_powersave_request},
02942         { WLANCOND_REQ_INTERFACE, WLANCOND_DISCONNECT_REQ, disconnect_request},
02943         { WLANCOND_REQ_INTERFACE, WLANCOND_DISASSOCIATE_REQ, disassociate_request},
02944         { NULL }
02945 };
02946 
02953 DBusHandlerResult wlancond_req_handler(DBusConnection     *connection,
02954                                        DBusMessage        *message,
02955                                        void               *user_data) {
02956         method_handler_t *handler;
02957         const char *dest;
02958 
02959 /*        DLOG_DEBUG("Received %s.%s",
02960                    dbus_message_get_interface(message),
02961                    dbus_message_get_member(message));
02962 */
02963 #ifdef USE_MCE_MODE        
02964         if (dbus_message_is_signal(message,
02965                                    MCE_SIGNAL_IF,
02966                                    MCE_DEVICE_MODE_SIG)) {
02967                 return mode_change_dbus(message);
02968         }
02969 #ifdef ACTIVITY_CHECK
02970         if (dbus_message_is_signal(message,
02971                                    MCE_SIGNAL_IF,
02972                                    MCE_INACTIVITY_SIG)) {
02973                 return activity_check_dbus(message);
02974         }
02975 #endif
02976 #endif 
02977         if (dbus_message_is_signal(message,
02978                                    ICD_DBUS_INTERFACE,
02979                                    ICD_STATUS_CHANGED_SIG))
02980                 return icd_check_signal_dbus(message);
02981         
02982         /* The rest should be just method calls */
02983         if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
02984                   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
02985         }
02986         
02987         dest = dbus_message_get_destination(message);
02988         if (!g_str_equal(dest, WLANCOND_SERVICE)) {
02989                 DLOG_DEBUG("Received D-Bus message not addressed to me.");
02990                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
02991         }
02992         
02993         for (handler = handlers; handler->interface != NULL; handler++) {
02994                 if (dbus_message_is_method_call(message,
02995                                                 handler->interface,
02996                                                 handler->name)) {
02997                         DLOG_DEBUG("Received %s", handler->name);
02998                         return handler->func(message, connection);
02999                 }
03000         }
03001         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03002 }
03003 
03004 static DBusObjectPathVTable wlancond_req_vtable = {
03005         .message_function    = wlancond_req_handler,
03006         .unregister_function = NULL
03007 };
03008 
03009 
03014 void init_dbus_handlers(DBusConnection *connection) {
03015         dbus_bool_t ret;
03016         ret = dbus_connection_register_object_path(connection,
03017                                                    WLANCOND_REQ_PATH,
03018                                                    &wlancond_req_vtable,
03019                                                    NULL);
03020         if (ret == FALSE) {
03021                 DLOG_ERR("dbus_connection_register_object_path failed");
03022         }
03023 #ifdef USE_MCE_MODE
03024         if (!add_mode_listener(connection)) {
03025                 DLOG_ERR("Adding mode listener failed");
03026         }
03027 #endif
03028         if (!add_icd_listener(connection)) {
03029                 DLOG_ERR("Adding icd listener failed");
03030         }  
03031 }
03032 
03037 void destroy_dbus_handlers(DBusConnection *connection) {
03038         dbus_connection_unregister_object_path(connection, WLANCOND_REQ_PATH);
03039 }

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