• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

libnl-handler.c

Go to the documentation of this file.
00001 
00023 #include <sys/types.h>
00024 #include <sys/socket.h>
00025 #include <linux/types.h>
00026 #include <linux/netlink.h>
00027 #include <linux/rtnetlink.h>
00028 #include <linux/if_ether.h>
00029 #include <dbus/dbus.h>
00030 #include <wlancond.h>
00031 #include <eap-dbus.h>
00032 
00033 #include <glib.h>
00034 #include <glib-object.h>
00035 #include <unistd.h>
00036 #include <fcntl.h>
00037 #include <errno.h>
00038 
00039 #include "wpa.h"
00040 #include "wapi.h"
00041 #include "daemon.h"
00042 #include "dbus-handler.h"
00043 #include "log.h"
00044 #include "libnl-handler.h"
00045 
00046 static int nl80211_scan_result_handler(struct nl_msg *msg, void* arg);
00047 static int nl80211_parse_ies(unsigned char* const ie, size_t ie_len, scan_results_t* const scan_result);
00048 static void save_caps(struct scan_results_t *, struct ap_info_t *, unsigned char *, unsigned int);
00049 
00051 static struct nl_handle *nl_handle = NULL;
00052 static struct nl_handle *nl_event_handle = NULL;
00053 static struct nl_cache *nl_cache = NULL;
00054 static struct nl_cache *nl_event_cache = NULL;
00055 static struct genl_family *nl80211 = NULL;
00056 static struct nl_cb *nl_cb = NULL;
00057 static unsigned int nl_family_id;
00058 static wlan_status_t * scan_wlan_status = NULL;
00059 
00066 static int get_family_cb(struct nl_msg *msg, void *arg)
00067 {
00068     struct get_family_t *data = arg;
00069     struct nlattr *tb[CTRL_ATTR_MAX + 1];
00070     struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
00071     struct nlattr *grp;
00072     int index;
00073      
00074     if (nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
00075                   genlmsg_attrlen(gnlh, 0), NULL)) {
00076             DLOG_ERR("nl80211: Failed to parse get family attributes!");
00077             return NL_SKIP;
00078     }   
00079     
00080     if (!tb[CTRL_ATTR_MCAST_GROUPS])
00081             return NL_SKIP;
00082          
00083     nla_for_each_nested(grp, tb[CTRL_ATTR_MCAST_GROUPS], index) {
00084             struct nlattr *tbg[CTRL_ATTR_MCAST_GRP_MAX + 1];
00085             if (nla_parse(tbg, CTRL_ATTR_MCAST_GRP_MAX, nla_data(grp),
00086                           nla_len(grp), NULL)) {
00087                     DLOG_ERR("nl80211: Failed to parse nested get "
00088                              "family attributes!");
00089                     return NL_SKIP;
00090                 }
00091             
00092             if (!tbg[CTRL_ATTR_MCAST_GRP_NAME] ||
00093                 !tbg[CTRL_ATTR_MCAST_GRP_ID] ||
00094                 strncmp(nla_data(tbg[CTRL_ATTR_MCAST_GRP_NAME]),
00095                         data->group_name, 
00096                         nla_len(tbg[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
00097                     continue;
00098             
00099             data->id = nla_get_u32(tbg[CTRL_ATTR_MCAST_GRP_ID]);
00100             break;
00101     };
00102     
00103     return NL_SKIP;
00104 }
00105 
00112 static int nl80211_get_family(const char *family_name, const char *group_name)
00113 {
00114     struct get_family_t data = { group_name, -ENOENT };
00115     struct nl_msg *msg;
00116     int ret = -1;
00117     void *hdr;
00118     
00119     int id = genl_ctrl_resolve(nl_event_handle, "nlctrl");
00120     if (id < 0) {
00121             DLOG_ERR("nl80211: Failed to put nl80211 message");
00122             return ret;
00123     }
00124     
00125     msg = nlmsg_alloc();
00126     if (!msg)
00127             return ret;
00128     
00129     hdr = genlmsg_put(msg, getpid(), 0, id, 0, 0, CTRL_CMD_GETFAMILY, 0);
00130     if (hdr == NULL) {
00131             DLOG_ERR("nl80211: Failed to put nl80211 message");
00132             goto nla_put_failure;
00133     }
00134     
00135     NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family_name);
00136     
00137     ret = nl_send_recv_msgs(msg, get_family_cb, &data);
00138     if (ret) {
00139             DLOG_ERR("nl80211: failed to send get family ret=%d (%s)", ret,
00140                      strerror(-ret));
00141             goto nla_put_failure;
00142     }
00143     
00144     if (ret == 0)  
00145             ret = data.id;
00146     
00147 nla_put_failure:
00148     nlmsg_free(msg); 
00149     return ret;
00150 } 
00151 
00157 static void handle_netlink_wap_event(unsigned char *sa_data)
00158 {
00159         print_mac(WLANCOND_PRIO_HIGH, "nl80211: BSSID:", sa_data);
00160 
00161         // Check if the address is valid
00162         if (memcmp(sa_data, NULL_BSSID, ETH_ALEN)) {
00163 
00164                 if (get_wlan_state() == WLAN_INITIALIZED_FOR_SCAN ||
00165                     get_wlan_state() == WLAN_NOT_INITIALIZED) {
00166                         DLOG_DEBUG("Connection opened while not initialized?"); 
00167                         nl80211_get_phy_info(wlan_status.ifindex);
00168                         connected_signal((char *)sa_data);
00169                         return;
00170                 }
00171 
00172                 remove_connect_timer();
00173 
00174                 set_wlan_signal(WLANCOND_HIGH);
00175 
00176                 connected_signal((char *)sa_data);
00177 
00178                 if (get_wpa_mode() == TRUE ||
00179                     wlan_status.conn.authentication_type ==
00180                     EAP_AUTH_TYPE_WFA_SC) {
00181                         if (wpa_ie_push((char *) sa_data) < 0) {
00182                                 set_wlan_state(WLAN_NOT_INITIALIZED,
00183                                                DISCONNECTED_SIGNAL,
00184                                                FALSE);
00185                                 return;
00186                         }
00187                 } else {
00188                         /* In WPA mode retry count is zeroed only after
00189                            succesful authentication and we get information
00190                            about that when the supplicant sends EAP_AUTH_STATUS
00191                            signal which we catch.
00192                         */
00193                         wlan_status.retry_count = 0;
00194                         
00195                         if (netlink_send_linkmode(WLANCOND_IF_READY) != 0) {
00196                                 DLOG_ERR("Setting oper state to "
00197                                          "ready failed");
00198                         }
00199                 }
00200 
00201                 // If not roaming, set NO_ADDRESS state
00202                 if (wlan_status.ip_ok == FALSE) {
00203                         /* Set iptables only if we are not active */
00204                         if (get_inactivity_status() == TRUE) {
00205                                 if (set_iptables() < 0)
00206                                         DLOG_ERR("Setting iptables failed");
00207                         }
00208                         set_wlan_state(WLAN_NO_ADDRESS, NO_SIGNAL, TRUE);
00209                 } else {
00210                         set_wlan_state(WLAN_CONNECTED, NO_SIGNAL, TRUE);
00211                 }
00212 
00213                 /* Clear AUTOCONNECT flag */
00214                 wlan_status.conn.flags &= ~WLANCOND_AUTOCONNECT;
00215         } else {
00216                 if (get_wlan_state() == WLAN_INITIALIZED_FOR_CONNECTION &&
00217                     get_scan_state() == SCAN_ACTIVE) {
00218                         /* We are alredy searching for better connection */
00219                         return;
00220                 }
00221                 if (get_wlan_state() != WLAN_CONNECTED &&
00222                     get_wlan_state() != WLAN_NO_ADDRESS &&
00223                     get_wlan_state() != WLAN_INITIALIZED_FOR_CONNECTION) {
00224                         DLOG_ERR("nl80211: Not even connected?!?");
00225                         disconnected_signal();
00226                         return;
00227                 }
00228                 /* No roaming in WPS state */
00229                 if (wlan_status.conn.authentication_type ==
00230                     EAP_AUTH_TYPE_WFA_SC) {
00231                         return;
00232                 }
00233 
00234                 // Disconnect supplicant
00235                 if (get_wpa_mode() == TRUE &&
00236                     (get_wlan_state() == WLAN_CONNECTED ||
00237                      get_wlan_state() == WLAN_NO_ADDRESS)) {
00238                         disassociate_eap();
00239                 }
00240 
00241                 DLOG_DEBUG("nl80211: Trying to find a new connection");
00242 
00243                 if (is_connected_state()) {
00244                         DLOG_DEBUG("Disconnecting previous connection");
00245                         mlme_command(wlan_status.conn.bssid, 
00246                                      WLANCOND_NL80211_MLME_DISCONNECT, 
00247                                      WLANCOND_REASON_LEAVING);
00248                 }
00249 
00250                 /* Decrese failed AP signal */
00251 
00252                 roam_cache_key_t key = { wlan_status.conn.bssid, wlan_status.conn.channel };
00253                 decrease_signal_in_roam_cache(&key);
00254 
00255                 set_wlan_state(WLAN_INITIALIZED_FOR_CONNECTION, NO_SIGNAL,
00256                                TRUE);
00257 
00258                 int ret = find_connection_and_associate(wlan_status.roam_cache,
00259                                                         FALSE, FALSE, FALSE);
00260                 if (ret == 0)
00261                         return;
00262                 
00263                 if (ret == ESUPPLICANT) {
00264                         set_wlan_state(WLAN_NOT_INITIALIZED,
00265                                        DISCONNECTED_SIGNAL, FALSE);
00266                         return;
00267                 }
00268                 /* Break eternal loop if all APs are failing */
00269                 if (scan_retries_left() == FALSE) {
00270                         DLOG_ERR("nl80211: Too many failures: %d",
00271                                  wlan_status.retry_count);
00272                         set_wlan_state(WLAN_NOT_INITIALIZED,
00273                                        DISCONNECTED_SIGNAL,
00274                                        FALSE);
00275                         return;
00276                 }
00277 
00278                 /* No luck, start scanning */
00279                 scan(wlan_status.conn.ssid, wlan_status.conn.ssid_len, TRUE);
00280         }
00281 }
00282 
00283 static int ignore_seq_check(struct nl_msg *msg, void *arg)
00284 {
00285         return NL_OK;
00286 }
00287 
00292 static void process_cqm_event(struct nlattr *tb[])
00293 {
00294         struct nlattr *monitor[NL80211_ATTR_CQM_MAX + 1];
00295         struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
00296                 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
00297                 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
00298                 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
00299         };
00300 
00301         if (nla_parse_nested(monitor, NL80211_ATTR_CQM_MAX, 
00302                              tb[NL80211_ATTR_CQM], cqm_policy)) {
00303                 DLOG_ERR("nl80211: Failed to parse nested cqm attributes!");
00304                 return;
00305         }
00306 
00307         if (monitor[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]) {
00308                 if (nla_get_u32(monitor[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]) == 
00309                                 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {
00310                         DLOG_INFO("High signal");
00311                         set_wlan_signal(WLANCOND_HIGH);
00312                 } else {
00313                         DLOG_INFO("Low signal");
00314                         set_wlan_signal(WLANCOND_LOW);
00315                         if (get_wlan_state() == WLAN_CONNECTED) {
00316                                 if (roam_scanning())
00317                                         // Already roam scanned 
00318                                         schedule_scan(WLANCOND_MIN_ROAM_SCAN_INTERVAL);
00319                                 else
00320                                         schedule_scan(WLANCOND_INITIAL_ROAM_SCAN_DELAY);
00321                         }
00322                 }
00323         }
00324 }
00325 
00332 static int print_netlink_event_token(struct nl_msg *msg, void *arg)
00333 {
00334         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
00335         struct nlattr *tb[NL80211_ATTR_MAX + 1];
00336 
00337         if (nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
00338                       genlmsg_attrlen(gnlh, 0), NULL)) {
00339                 DLOG_ERR("nl80211: Failed to parse netlink event attributes!");
00340                 return NL_SKIP;
00341         }
00342 
00343         if (tb[NL80211_ATTR_IFINDEX]) {
00344                 if (nla_get_u32(tb[NL80211_ATTR_IFINDEX]) != wlan_status.ifindex) {
00345                         DLOG_DEBUG("nl80211: Ignoring, not a wireless event.");
00346                         return NL_SKIP;
00347                 }
00348         }
00349 
00350         switch (gnlh->cmd) {
00351         case NL80211_CMD_TRIGGER_SCAN:
00352                 DLOG_DEBUG("nl80211: scan triggered");
00353                 break;
00354         case NL80211_CMD_NEW_SCAN_RESULTS:
00355         case NL80211_CMD_SCAN_ABORTED:
00356                 nl80211_scan_ready();
00357                 break;
00358         case NL80211_CMD_AUTHENTICATE:
00359         case NL80211_CMD_ASSOCIATE:
00360                 if (tb[NL80211_ATTR_TIMED_OUT]) {
00361                         DLOG_ERR("authentication/association timed out");
00362                         handle_netlink_wap_event(NULL_BSSID);
00363                 }
00364                 break;
00365         case NL80211_CMD_DEAUTHENTICATE:
00366         case NL80211_CMD_DISASSOCIATE:
00367                 break;
00368         case NL80211_CMD_CONNECT:
00369         case NL80211_CMD_ROAM:
00370                 if (nla_get_u16(tb[NL80211_ATTR_STATUS_CODE]) == 0) {
00371                         unsigned char *bssid = nla_data(tb[NL80211_ATTR_MAC]);
00372                         handle_netlink_wap_event(bssid);
00373                 } else {
00374                         DLOG_DEBUG("nl80211: Failed to connect. reason: %d", 
00375                                    nla_get_u16(tb[NL80211_ATTR_STATUS_CODE]));
00376                         handle_netlink_wap_event(NULL_BSSID);
00377                 }
00378                 break;
00379         case NL80211_CMD_DISCONNECT:
00380                 if (tb[NL80211_ATTR_DISCONNECTED_BY_AP]) {
00381                         DLOG_DEBUG("nl80211: Disconnected by the access point.");
00382                         handle_netlink_wap_event(NULL_BSSID);
00383                 } else {
00384                         if (tb[NL80211_ATTR_REASON_CODE]) {
00385                                 DLOG_DEBUG("nl80211: Disconnected by local choice due to reason: %d",
00386                                            nla_get_u16(tb[NL80211_ATTR_REASON_CODE]));
00387                         } else {
00388                                 DLOG_DEBUG("nl80211: Disconnected");
00389                                 if (get_wlan_state() == WLAN_NO_ADDRESS ||
00390                                     get_wlan_state() == WLAN_CONNECTED)
00391                                         handle_netlink_wap_event(NULL_BSSID);
00392                         }
00393                 }
00394         break;
00395         case NL80211_CMD_MICHAEL_MIC_FAILURE:
00396                 DLOG_DEBUG("nl80211: MIC failure event received.");
00397                 dbus_bool_t key_type = TRUE;
00398                 
00399                 if (tb[NL80211_ATTR_KEY_TYPE]) {
00400                         enum nl80211_key_type type = nla_get_u32(tb[NL80211_ATTR_KEY_TYPE]);
00401         
00402                         if (type == NL80211_KEYTYPE_PAIRWISE)
00403                                 key_type = FALSE;
00404                 }
00405                 DLOG_DEBUG("MIC failure event for %s key", 
00406                            key_type==FALSE?"unicast":"group");
00407                 if ((wlan_status.conn.encryption & WLANCOND_ENCRYPT_METHOD_MASK)
00408                     != WLANCOND_WAPI_PSK &&
00409                     (wlan_status.conn.encryption & WLANCOND_ENCRYPT_METHOD_MASK)
00410                     != WLANCOND_WAPI_CERT) {
00411                         handle_mic_failure(key_type, wlan_status.conn.bssid);
00412                 }
00413                 break;
00414         case NL80211_CMD_JOIN_IBSS:
00415                 if (tb[NL80211_ATTR_MAC]) {
00416                         unsigned char *bssid = nla_data(tb[NL80211_ATTR_MAC]);
00417                         handle_netlink_wap_event(bssid);
00418                 } else {
00419                         DLOG_ERR("nl80211: Joined adhoc with no address.");
00420                 }
00421                 break;
00422         case NL80211_CMD_GET_STATION:
00423         case NL80211_CMD_SET_STATION:
00424         case NL80211_CMD_NEW_STATION:
00425         case NL80211_CMD_DEL_STATION:
00426                 break;
00427         case NL80211_CMD_NOTIFY_CQM:
00428                 process_cqm_event(tb);          
00429                 break;
00430         default:
00431                 DLOG_DEBUG("nl80211: unknown event cmd (%d)", gnlh->cmd);
00432                 break;
00433         }
00434         return NL_SKIP;
00435 }
00436 
00444 static gboolean event_receive(GIOChannel *chan, GIOCondition cond, gpointer data)
00445 {
00446         struct nl_cb *cb;
00447         int ret;
00448 
00449         cb = nl_cb_clone(nl_cb);
00450 
00451         if (!cb) {
00452                 DLOG_ERR("nl80211: event receive cb clone fail");
00453                 return TRUE;
00454         }
00455 
00456         if (cond != G_IO_IN) {
00457                 DLOG_INFO("nl80211: received event is not g_io_in");
00458                 guint watch_id = *((guint *)data);
00459                 g_source_remove(watch_id);
00460                 g_io_channel_unref(chan);
00461                 goto nla_put_failure;
00462         }
00463 
00464         ret = nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, ignore_seq_check, NULL);
00465         if (ret) {
00466                 DLOG_ERR("nl80211: ignore seq cb set returned error: %d", ret);         
00467                 goto nla_put_failure;
00468         }       
00469         ret = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_netlink_event_token, NULL);
00470         if (ret) {
00471                 DLOG_ERR("nl80211: print netlink event cb set returned error: %d", ret);                
00472                 goto nla_put_failure;
00473         }
00474         if (fcntl(nl_socket_get_fd(nl_event_handle), F_SETFL, O_NONBLOCK) == -1) {
00475                 DLOG_ERR("nl80211: failed to set receive netlink message");
00476                 goto nla_put_failure;
00477         }
00478         if (nl_recvmsgs(nl_event_handle, cb)) {
00479                 DLOG_ERR("nl80211: failed to receive netlink message");
00480                 goto nla_put_failure;
00481         }
00482         nl_cb_put(cb);
00483         return TRUE;
00484 
00485 nla_put_failure:
00486         nl_cb_put(cb);
00487         return FALSE;
00488 }
00489 
00494 int init_nl80211(void)
00495 {
00496         int ret = -1;
00497         static guint watch_id = 0;
00498         GIOChannel *gio;
00499 
00500         /* Initialize generic netlink and nl80211 */
00501 
00502         nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
00503         if (!nl_cb) {
00504                 DLOG_ERR("nl80211: failed to allocate netlink callbacks");
00505                 return ret;
00506         }
00507 
00508         nl_handle = nl_handle_alloc();
00509         if (!nl_handle) {
00510                 DLOG_ERR("nl80211: failed to allocate netlink handle");
00511                 goto out_cb_clear;
00512         }
00513 
00514         nl_event_handle = nl_handle_alloc_cb(nl_cb);
00515         if (!nl_event_handle) {
00516                 DLOG_ERR("nl80211: failed to allocate netlink event handle");
00517                 goto out_handle_destroy_b;
00518         }
00519 
00520         if (genl_connect(nl_handle)) {
00521                 DLOG_ERR("nl80211: failed to connect netlink");
00522                 goto out_handle_destroy_a;
00523         }
00524 
00525         nl_disable_sequence_check(nl_event_handle);
00526 
00527         if (genl_connect(nl_event_handle)) {
00528                 DLOG_ERR("nl80211: failed to connect netlink event");
00529                 goto out_handle_destroy_a;
00530         }
00531 
00532         nl_cache = genl_ctrl_alloc_cache(nl_handle);
00533         if (!nl_cache) {
00534                 DLOG_ERR("nl80211: failed to allocate netlink control cache");
00535                 goto out_handle_destroy_a;
00536         }
00537         
00538         nl_event_cache = genl_ctrl_alloc_cache(nl_event_handle);
00539         if (!nl_event_cache) {
00540                 DLOG_ERR("nl80211: failed to allocate netlink event control cache");
00541                 goto out_clean_cache_b;
00542         }
00543 
00544         nl80211 = genl_ctrl_search_by_name(nl_cache, "nl80211");
00545         if (!nl80211) {
00546                 DLOG_ERR("nl80211: didn't find nl80211 netlink control");
00547                 goto out_clean_cache_a;
00548         }
00549 
00550         ret = nl80211_get_family("nl80211", "scan");
00551         if (ret >= 0) {
00552                 ret = nl_socket_add_membership(nl_event_handle, ret);
00553         } else {
00554                 DLOG_ERR("nl80211: couldn't add multicast membership"
00555                          " for scan events: %d (%s)", ret, strerror(-ret));
00556                 goto out_clean_cache_a;
00557         }
00558 
00559         ret = nl80211_get_family("nl80211", "mlme");
00560         if (ret >= 0) {
00561                 ret = nl_socket_add_membership(nl_event_handle, ret);
00562         } else {
00563                 DLOG_ERR("nl80211: couldn't add multicast membership"
00564                          " for mlme events: %d (%s)", ret, strerror(-ret));
00565                 goto out_clean_cache_a;
00566         }
00567 
00568         nl_family_id = genl_family_get_id(nl80211);
00569         DLOG_DEBUG("nl80211: netlink family id %d", nl_family_id);
00570 
00571         gio = g_io_channel_unix_new(nl_socket_get_fd(nl_event_handle));
00572         g_io_channel_set_close_on_unref(gio, TRUE);
00573         watch_id = g_io_add_watch(gio, G_IO_IN | G_IO_PRI | G_IO_ERR |
00574                         G_IO_HUP, event_receive, &watch_id);
00575 
00576         return 0;
00577 
00578 out_clean_cache_a:
00579         nl_cache_free(nl_event_cache);
00580 
00581 out_clean_cache_b:
00582         nl_cache_free(nl_cache);
00583 
00584 out_handle_destroy_a:
00585         nl_handle_destroy(nl_event_handle);
00586 
00587 out_handle_destroy_b:
00588         nl_handle_destroy(nl_handle);
00589 
00590 out_cb_clear:
00591         nl_cb_put(nl_cb);
00592 
00593         return ret;
00594 }
00595 
00596 static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
00597                          void *arg)
00598 {
00599         int *ret = arg;
00600         DLOG_DEBUG("nl80211: %s() %d\n", __func__, err->error);
00601         *ret = err->error;
00602         return NL_SKIP;
00603 }
00604 
00605 static int finish_handler(struct nl_msg *msg, void *arg)
00606 {
00607         int *ret = arg;
00608         DLOG_DEBUG("nl80211: %s()\n", __func__);
00609         *ret = 0;
00610         return NL_SKIP;
00611 }
00612 
00613 static int ack_handler(struct nl_msg *msg, void *arg)
00614 {
00615         int *ret = arg;
00616         //DLOG_DEBUG("nl80211: %s()\n", __func__);
00617         *ret = 0;
00618         return NL_STOP;
00619 }
00620 
00628 int nl_send_recv_msgs(struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), void *valid_data)
00629 {
00630         struct nl_cb *cb;
00631         int ret;
00632 
00633         cb = nl_cb_clone(nl_cb);
00634 
00635         if (!cb) {
00636                 DLOG_ERR("nl80211: failed to alloc netlink callback");
00637                 ret = -nl_get_errno();
00638                 return ret;
00639         }
00640         ret = nl_send_auto_complete(nl_handle, msg);
00641 
00642         if (ret < 0) {
00643                 DLOG_ERR("nl80211: failed to send netlink message");
00644                 goto end_func;
00645         }
00646 
00647         ret = 1;
00648 
00649         if (nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret)) {
00650                 DLOG_DEBUG("nl80211: send and recv nl_cb_err returned error");          
00651                 ret = -1;
00652                 goto end_func;
00653         }
00654         if (nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &ret)) {
00655                 DLOG_DEBUG("nl80211: send and recv set finnish handler returned error");                
00656                 ret = -1;
00657                 goto end_func;
00658         }
00659         if (nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &ret)) {
00660                 DLOG_DEBUG("nl80211: send and recv set ack handler returned error");            
00661                 ret = -1;
00662                 goto end_func;
00663         }
00664 
00665         if (valid_handler) {
00666                 if (nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, 
00667                               valid_data)) {
00668                         DLOG_DEBUG("nl80211: send and recv set valid handler error");           
00669                         ret = -1;
00670                         goto end_func;
00671                 }
00672         }
00673 
00674         while (ret > 0) {
00675                 if (nl_recvmsgs(nl_handle, cb)) {
00676                         DLOG_ERR("nl80211: failed to receive netlink message"
00677                                  " after command");
00678                         goto end_func;
00679                 }
00680         }
00681 
00682 end_func:
00683         nl_cb_put(cb);
00684         return ret;
00685 }
00686 
00690 void nl80211_cleanup(void)
00691 {
00692         DLOG_DEBUG("nl80211: cleanup destroying all");
00693 
00694         if (nl80211)
00695                 genl_family_put(nl80211);
00696 
00697         if (nl_cache)
00698                 nl_cache_free(nl_cache);
00699 
00700         if (nl_handle)
00701                 nl_handle_destroy(nl_handle);
00702 }
00703 
00710 static int nl80211_set_wep_keys(struct connect_params_t *conn, struct nl_msg *msg)
00711 {
00712         int i, privacy = 0; 
00713         struct nlattr *nl_keys, *nl_key;
00714         
00715         for (i = 0; i < 4; i++) {
00716                 if (conn->key_len[i] == 0)
00717                         continue;
00718 
00719                 privacy = 1;
00720                 break;
00721         }
00722         if (!privacy)
00723                 return 0;
00724         
00725         DLOG_DEBUG("nl80211: setting wep keys"); 
00726         NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
00727         nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
00728 
00729         if (!nl_keys)
00730                 goto nla_put_failure;
00731 
00732         for (i = 0; i < 4; i++) {
00733                 if (conn->key_len[i] == 0)
00734                         continue;
00735 
00736                 char *key_phrase;
00737                 nl_key = nla_nest_start(msg, i);
00738                 if (!nl_key)
00739                         goto nla_put_failure;
00740 
00741                 NLA_PUT_U8(msg, NL80211_KEY_IDX, i);
00742 
00743                 if (conn->key_len[i] == 5)
00744                         NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 
00745                                     WLANCOND_CIPHER_SUITE_WEP40);
00746                 else
00747                         NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 
00748                                     WLANCOND_CIPHER_SUITE_WEP104);
00749                 
00750                 key_phrase = (caddr_t) &conn->key[i][0];
00751 
00752                 NLA_PUT(msg, NL80211_KEY_DATA, conn->key_len[i], key_phrase);   
00753 
00754                 /* If the default key is 1 and only one key is specified 
00755                    then it never enters the following if condition, adding 
00756                    +1 to i as the for loop starts from 0. */    
00757                 
00758                 if (conn->default_key == i+1) {
00759                         NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
00760                         DLOG_DEBUG("nl80211: default key: %d", 
00761                                    conn->default_key);
00762                 }
00763                 nla_nest_end(msg, nl_key);
00764         }
00765         nla_nest_end(msg, nl_keys);
00766         return 0;
00767 
00768 nla_put_failure:
00769         return -ENOBUFS;
00770 }
00776 static guint32 channel_to_freq(guint32 channel) {       
00777         guint32 freq;
00778 
00779         if (channel < 14) {
00780                 freq = 2407 + (5 * /* 5 is the bandwidth of one channel */ channel);
00781         } else if (channel == 14) {
00782                 freq = 2484;
00783         } else {
00784                 freq = 5 * (channel + 1000);
00785         }
00786         return freq;
00787 }
00793 static guint32 freq_to_channel(guint32 freq)
00794 {
00795         if (freq < 2484)
00796                 return (freq - 2407) / 5;
00797 
00798         if (freq == 2484)
00799                 return 14;
00800 
00801         return freq / 5 - 1000;
00802 }
00808 int nl80211_connect(struct scan_results_t *scan_results, struct wlan_status_t *wlan_status)
00809 {
00810         struct connect_params_t *conn = &wlan_status->conn;
00811         struct nl_msg *msg;
00812         void *hdr;
00813         gint ret = -1;
00814         guint mode = NL80211_CMD_CONNECT;
00815         /* wep_shared_and_open_try is used to try the alternate 
00816            authentication type in wep */
00817         enum nl80211_auth_type type = NL80211_AUTHTYPE_OPEN_SYSTEM;
00818 
00819         DLOG_DEBUG("nl80211: Starting the nl80211_connect");
00820 
00821         msg = nlmsg_alloc();
00822 
00823         if (msg == NULL) {
00824                 return -ENOMEM;
00825         }
00826         if (get_mode() == WLANCOND_ADHOC)
00827                 mode = NL80211_CMD_JOIN_IBSS;
00828         
00829         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0, mode, 0);
00830         if (hdr == NULL) {
00831                 DLOG_ERR("nl80211: Failed to put nl80211 connect message");
00832                 goto nla_put_failure;
00833         }
00834 
00835         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wlan_status->ifindex);
00836 
00837         NLA_PUT(msg, NL80211_ATTR_SSID, conn->ssid_len-1, conn->ssid);
00838         DLOG_DEBUG("nl80211: ESSID: %s", conn->ssid);
00839 
00840         if (memcmp(conn->bssid, "\0\0\0\0\0\0", ETH_ALEN)) {
00841                 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, conn->bssid);
00842                 print_mac(WLANCOND_PRIO_HIGH, "nl80211: BSSID", conn->bssid);
00843         }
00844 
00845         if (scan_results->channel) {
00846                 guint32 freq = channel_to_freq(scan_results->channel);
00847 
00848                 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
00849                 DLOG_DEBUG("nl80211: Channel: %d", scan_results->channel);
00850         }
00851 
00852         if ((conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP) {
00853                 DLOG_DEBUG("nl80211: WEP selected");
00854 
00855                 if (get_mode() == WLANCOND_INFRA) {
00856                         if (wlan_status->conn.wep_try_open_mode_first == TRUE) {
00857                                 type = NL80211_AUTHTYPE_OPEN_SYSTEM;            
00858                                 DLOG_DEBUG("nl80211: open system");
00859                                 wlan_status->conn.wep_try_open_mode_first = FALSE;                      
00860                         } else {
00861                                 type = NL80211_AUTHTYPE_SHARED_KEY;
00862                                 DLOG_DEBUG("nl80211: shared key");
00863                                 wlan_status->conn.wep_try_open_mode_first = TRUE;
00864                         }
00865                 }
00866 
00867                 ret = nl80211_set_wep_keys(conn, msg);
00868                 if (ret) {
00869                         DLOG_DEBUG("nl80211: set key failure");
00870                         goto nla_put_failure;
00871                 }
00872         }
00873 
00874         NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
00875 
00876         if (get_wpa_mode() == TRUE ||
00877             conn->authentication_type == EAP_AUTH_TYPE_WFA_SC) {
00878                 struct wpa_ie_save_t *wpa_ie = &wlan_status->wpa_ie;
00879 
00880                 NLA_PUT(msg, NL80211_ATTR_IE, wpa_ie->ie_len, wpa_ie->ie);
00881                 
00882                 if (get_wpa_mode() == TRUE || 
00883                    (conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WEP) {
00884                         NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
00885                 }
00886                 DLOG_DEBUG("nl80211: Setting IE, len %d", wpa_ie->ie_len);
00887         }       
00888 
00889         if (scan_results->wpa_ie_len && scan_results->wpa_ie &&
00890            (conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) != WLANCOND_WAPI_PSK &&
00891            (conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) != WLANCOND_WAPI_CERT) {
00892 
00893                 enum nl80211_wpa_versions ver;
00894 
00895                 if (conn->encryption & WLANCOND_ENCRYPT_WPA2_MASK)
00896                         ver = NL80211_WPA_VERSION_2;
00897                 else
00898                         ver = NL80211_WPA_VERSION_1;
00899 
00900                 DLOG_DEBUG("nl80211: %s", ver==NL80211_WPA_VERSION_2?
00901                            "WPA2":"WPA1");
00902 
00903                 NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
00904         }
00905 
00906         if ((conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK || 
00907             (conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_EAP) {
00908 
00909                 switch (wlan_status->pairwise_cipher) {
00910                 case CIPHER_SUITE_TKIP:
00911                         NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, WLANCOND_CIPHER_SUITE_TKIP);
00912                         DLOG_DEBUG("nl80211: TKIP pairwise");
00913                         break;
00914                 case CIPHER_SUITE_CCMP:
00915                         NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, WLANCOND_CIPHER_SUITE_CCMP);
00916                         DLOG_DEBUG("nl80211: AES pairwise");
00917                         break;
00918                 case CIPHER_SUITE_WEP104:
00919                         NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, WLANCOND_CIPHER_SUITE_WEP104);
00920                         DLOG_DEBUG("nl80211: WEP104 pairwise");
00921                         break;
00922                 case CIPHER_SUITE_WEP40:
00923                         NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, WLANCOND_CIPHER_SUITE_WEP40);
00924                         DLOG_DEBUG("nl80211: WEP40 pairwise");
00925                         break;
00926                 default:
00927                         DLOG_ERR("NL80211: Not supported unicast encryption");
00928                         nlmsg_free(msg);
00929                         return -1;
00930                 } /* switch */
00931 
00932                 switch (wlan_status->group_cipher) {
00933                 case CIPHER_SUITE_TKIP:
00934                         NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, WLANCOND_CIPHER_SUITE_TKIP);
00935                         DLOG_DEBUG("nl80211: TKIP group");
00936                         break;
00937                 case CIPHER_SUITE_CCMP:
00938                         NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, WLANCOND_CIPHER_SUITE_CCMP);
00939                         DLOG_DEBUG("nl80211: AES group");
00940                         break;
00941                 case CIPHER_SUITE_WEP104:
00942                         NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, WLANCOND_CIPHER_SUITE_WEP104);
00943                         DLOG_DEBUG("nl80211: WEP104 group");
00944                         break;
00945                 case CIPHER_SUITE_WEP40:
00946                         NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, WLANCOND_CIPHER_SUITE_WEP40);
00947                         DLOG_DEBUG("nl80211: WEP40 group");
00948                         break;
00949                 default:
00950                         DLOG_ERR("nl80211: Not supported multicast encryption");
00951                         nlmsg_free(msg);
00952                         return -1;
00953                 } /* switch */
00954 
00955                 if ((conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WPA_PSK) {
00956                         NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, WLANCOND_KEY_MGMT_PSK);
00957                         DLOG_DEBUG("nl80211: PSK");
00958                 }
00959                 else if ((conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) ==  WLANCOND_WPA_EAP) { 
00960                         NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, WLANCOND_KEY_MGMT_802_1X);
00961                         DLOG_DEBUG("nl80211: EAP");
00962                 }
00963                 else {
00964                         DLOG_ERR("nl80211: unsupported AKM ");
00965                         goto nla_put_failure;
00966                 }
00967         } /* WPA/WPA2 */
00968         else if ((conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WAPI_PSK ||
00969                  (conn->encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WAPI_CERT) {
00970                         NLA_PUT_U16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, 0x88B4);
00971                         DLOG_DEBUG("nl80211: WAPI");
00972                         NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);
00973         }
00974 
00975         /* Set IBSS basic data rates */
00976         if (get_mode() == WLANCOND_ADHOC) {
00977                 if (scan_results->channel <= 14) {
00978                         /* 2.4 GHz */
00979                         const unsigned char rates[] = {
00980                                 2,  /*   1 Mbps */
00981                                 4,  /*   2 Mbps */
00982                                 11, /* 5.5 Mbps */
00983                                 22  /*  11 Mbps */
00984                         };
00985                         if (sizeof(rates) / sizeof(rates[0]) <= 
00986                             NL80211_MAX_SUPP_RATES)
00987                                 NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, 
00988                                         sizeof(rates) / sizeof(rates[0]), 
00989                                         rates);
00990                 } else {
00991                         /* 5 GHz */
00992                         const unsigned char rates[] = {
00993                                 12,  /*  6 Mbps */
00994                                 24,  /* 12 Mbps */
00995                                 48   /* 24 Mbps */
00996                         };
00997                         if (sizeof(rates) / sizeof(rates[0]) <= 
00998                             NL80211_MAX_SUPP_RATES)
00999                                 NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, 
01000                                         sizeof(rates) / sizeof(rates[0]), 
01001                                         rates);
01002                 }
01003         }
01004                 
01005         ret = nl_send_recv_msgs(msg, NULL, NULL);
01006         if (ret) {
01007                 DLOG_ERR("nl80211: MLME connect failed: ret=%d (%s)", 
01008                          ret, strerror(-ret));
01009                 goto nla_put_failure;
01010         }
01011 
01012         ret = 0;
01013         DLOG_DEBUG("nl80211: Connect request send successfully");
01014 
01015 nla_put_failure:
01016         nlmsg_free(msg);
01017         return ret;
01018 }
01019 
01026 int nl80211_set_op_mode(guint32 ifindex, guint32 mode)
01027 {
01028         struct nl_msg *msg;
01029         gint ret = -1;
01030         void *hdr;
01031         enum nl80211_iftype nlmode;
01032         
01033         msg = nlmsg_alloc();
01034         if (!msg)
01035                 return -ENOMEM;
01036 
01037         switch (mode) {
01038 
01039                 case WLANCOND_ADHOC:
01040                         nlmode = NL80211_IFTYPE_ADHOC;
01041                         DLOG_DEBUG("nl80211: selecting mode: ADHOC");
01042                         break;
01043                 case WLANCOND_INFRA:
01044                         nlmode = NL80211_IFTYPE_STATION;
01045                         DLOG_DEBUG("nl80211: selecting mode: INFRA");
01046                         break;
01047                 default:
01048                         DLOG_ERR("Operating mode undefined");
01049                         goto nla_put_failure;
01050         }
01051         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0, 
01052                           NL80211_CMD_SET_INTERFACE, 0);
01053         if (hdr == NULL) {
01054                 DLOG_ERR("nl80211: Failed to put set interface message");
01055                 goto nla_put_failure;
01056         }
01057         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
01058         NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, nlmode);
01059 
01060         ret = nl_send_recv_msgs(msg, NULL, NULL);
01061 
01062         if (ret) {
01063                 DLOG_ERR("nl80211: failed to send set interface ret=%d (%s)", 
01064                          ret, strerror(-ret));
01065                 goto nla_put_failure;
01066         }
01067         ret = 0;
01068 
01069 nla_put_failure:
01070         nlmsg_free(msg);
01071         return ret;
01072 }
01079 static int phy_info_handler(struct nl_msg *msg, void *arg)
01080 {
01081         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
01082         struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
01083         
01084         if (nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
01085                       genlmsg_attrlen(gnlh, 0), NULL))
01086                 return NL_SKIP;
01087         
01088         if (tb_msg[NL80211_ATTR_IFTYPE]) {
01089                 switch (nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE])) {
01090                 case NL80211_IFTYPE_ADHOC:
01091                         wlan_status.conn.mode = WLANCOND_ADHOC;
01092                         break;
01093                 case NL80211_IFTYPE_STATION:
01094                         wlan_status.conn.mode = WLANCOND_INFRA;
01095                         break;
01096                 default:
01097                         break;
01098                 }
01099         }
01100         return NL_SKIP;
01101 }
01107 int nl80211_get_phy_info(guint32 ifindex)
01108 {
01109         struct nl_msg *msg;
01110         gint ret = -1;
01111         void *hdr;
01112         
01113         msg = nlmsg_alloc();
01114         if (!msg)
01115                 return -ENOMEM;
01116 
01117         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0, 
01118                           NL80211_CMD_GET_INTERFACE, 0);
01119         if (hdr == NULL) {
01120                 goto nla_put_failure;
01121         }
01122         
01123         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
01124 
01125         ret = nl_send_recv_msgs(msg, phy_info_handler, NULL);
01126 
01127         if (ret)
01128                 DLOG_ERR("nl80211: failed to send get phy info ret=%d (%s)", 
01129                          ret, strerror(-ret));
01130 
01131 nla_put_failure:
01132         nlmsg_free(msg);
01133         return ret;
01134 }
01141 int nl80211_set_channel(guint32 ifindex, guint32 channel)
01142 {
01143         struct nl_msg *msg;
01144         gint ret = -1;
01145         void *hdr;
01146         
01147         msg = nlmsg_alloc();
01148         if (!msg)
01149                 return -ENOMEM;
01150 
01151         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0, 
01152                           NL80211_CMD_SET_WIPHY, 0);
01153         if (hdr == NULL) {
01154                 goto nla_put_failure;
01155         }
01156         guint32 freq = channel_to_freq(channel);
01157         
01158         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
01159         NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
01160         
01161         ret = nl_send_recv_msgs(msg, NULL, NULL);
01162         
01163         if (ret)
01164                 DLOG_ERR("nl80211: failed to send set channel ret=%d (%s)", 
01165                          ret, strerror(-ret));
01166         
01167 nla_put_failure:
01168         nlmsg_free(msg);
01169         return ret;
01170 }       
01176 int nl80211_leave_adhoc(guint32 ifindex)
01177 {
01178         struct nl_msg *msg;
01179         gint ret = -1;
01180         void *hdr;
01181 
01182         msg = nlmsg_alloc();
01183         if (!msg)
01184                 return -ENOMEM;
01185 
01186         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0, NL80211_CMD_LEAVE_IBSS, 0);
01187         if (hdr == NULL) {
01188                 DLOG_ERR("nl80211: Failed to put leave ibss message");
01189                 goto nla_put_failure;
01190         }
01191         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
01192         ret = nl_send_recv_msgs(msg, NULL, NULL);
01193         if (ret) {
01194                 DLOG_ERR("nl80211: Leave IBSS failed: ret=%d (%s)", ret, 
01195                          strerror(-ret));
01196                 goto nla_put_failure;
01197         }
01198         ret = 0;
01199         DLOG_DEBUG("nl80211: Leave IBSS request sent successfully");
01200 
01201 nla_put_failure:
01202         nlmsg_free(msg);
01203         return ret;
01204 }
01213 int nl80211_mlme_command(guchar* addr, guint16 cmd, guint16 reason_code, guint32 ifindex)
01214 {
01215         gint ret = -1;
01216         struct nl_msg *msg;
01217         void *hdr;
01218 
01219         msg = nlmsg_alloc();
01220         if (!msg)
01221                 return -ENOMEM;
01222 
01223         switch (cmd)
01224         {       
01225                 case WLANCOND_MLME_DEAUTH:
01226                         DLOG_INFO("nl80211: Deauthenticating");
01227                         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0,
01228                                           NL80211_CMD_DEAUTHENTICATE, 0);
01229                         if (hdr == NULL) {
01230                                 DLOG_ERR("nl80211: Failed to deauthenticate");
01231                                 goto nla_put_failure;
01232                         }               
01233                         break;
01234                 case WLANCOND_MLME_DISASSOC:            
01235                         DLOG_INFO("nl80211: Disassociating");
01236                         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0,
01237                                           NL80211_CMD_DISASSOCIATE, 0);
01238                         if (hdr == NULL) {
01239                                 DLOG_ERR("nl80211: Failed to disassociate");
01240                                 goto nla_put_failure;
01241                         }
01242                         break;
01243                 case WLANCOND_NL80211_MLME_DISCONNECT:
01244                         DLOG_INFO("nl80211: Disconnecting");
01245                         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0,
01246                                           NL80211_CMD_DISCONNECT, 0);
01247                         if (hdr == NULL) {
01248                                 DLOG_ERR("nl80211: Failed to disconnect");
01249                                 goto nla_put_failure;
01250                         }
01251                         break;
01252                 default:
01253                         DLOG_ERR("nl80211: Invalid mlme command");
01254                         goto nla_put_failure;
01255         }
01256                 
01257         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
01258         NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason_code);
01259         NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
01260         
01261         ret = nl_send_recv_msgs(msg, NULL, NULL);
01262         if (ret) {
01263                 DLOG_DEBUG("nl80211: MLME command failed in %s: ret=%d (%s)", 
01264                            __FUNCTION__, ret, strerror(-ret));
01265                 goto nla_put_failure;
01266         }
01267         ret = 0;
01268 
01269 nla_put_failure:
01270         nlmsg_free(msg);
01271         return ret;
01272 }
01273 
01280 static int nl80211_signal_power_handler(struct nl_msg *msg, void *arg)
01281 {
01282         struct nlattr *tb[NL80211_ATTR_MAX + 1];
01283         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
01284         struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
01285         guint8 *power = arg;
01286         *power = 0;
01287 
01288         static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
01289                 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
01290                 [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
01291                 [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
01292                 [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
01293                 [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
01294                 [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
01295                 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
01296                 [NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
01297                 [NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
01298                 [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
01299         };
01300 
01301         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
01302                   genlmsg_attrlen(gnlh, 0), NULL);
01303 
01304         if (!tb[NL80211_ATTR_STA_INFO]) {
01305                 DLOG_ERR("nl80211: sta stats missing!");
01306                 return NL_SKIP;
01307         }
01308         if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
01309                              tb[NL80211_ATTR_STA_INFO],
01310                              stats_policy)) {
01311                 DLOG_ERR("nl80211: Failed to parse nested info attributes!");
01312                 return NL_SKIP;
01313         }
01314 
01315         if (sinfo[NL80211_STA_INFO_SIGNAL])
01316                 *power = (guint8)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
01317         
01318         return NL_SKIP;
01319 }
01320 
01327 int nl80211_get_signal_info(guint8 *power, struct wlan_status_t *wlan_status)
01328 {
01329         struct nl_msg *msg;
01330         gint ret = -1;
01331         void *hdr;
01332         struct connect_params_t *conn = &wlan_status->conn;
01333         
01334         msg = nlmsg_alloc();
01335         if (!msg)
01336                 return ret;
01337 
01338         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0, 
01339                           NL80211_CMD_GET_STATION, 0);
01340         if (hdr == NULL) {
01341                 DLOG_ERR("nl80211: Failed to put get station message");
01342                 goto nla_put_failure;
01343         }
01344 
01345         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wlan_status->ifindex);
01346         NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, conn->bssid);
01347 
01348         ret = nl_send_recv_msgs(msg, nl80211_signal_power_handler, power);
01349         if (ret) {
01350                 DLOG_ERR("nl80211: MLME command failed in %s: ret=%d (%s)", 
01351                            __FUNCTION__, ret, strerror(-ret));
01352                 goto nla_put_failure;
01353         }
01354         ret = 0;
01355 
01356 nla_put_failure:
01357         nlmsg_free(msg);
01358         return ret;
01359 }
01360 
01367 int nl80211_set_power_save(gboolean new_state, guint32 ifindex)
01368 {
01369         struct nl_msg *msg;
01370         gint ret = -1;
01371         void *hdr;
01372         enum nl80211_ps_state ps_state;
01373 
01374         msg = nlmsg_alloc();
01375         if (!msg)
01376                 return ret;
01377 
01378         if (new_state)
01379                 ps_state = NL80211_PS_ENABLED;          
01380         else
01381                 ps_state = NL80211_PS_DISABLED;
01382                 
01383         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0, 
01384                           NL80211_CMD_SET_POWER_SAVE, 0);
01385         if (hdr == NULL) {
01386                 DLOG_ERR("nl80211: Failed to put set power save message");
01387                 goto nla_put_failure;
01388         }
01389 
01390         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
01391         NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state);
01392 
01393         ret = nl_send_recv_msgs(msg, NULL, NULL);
01394         if (ret) {
01395                 DLOG_ERR("nl80211: MLME command failed in %s: ret=%d (%s)", 
01396                            __FUNCTION__, ret, strerror(-ret));
01397                 goto nla_put_failure;
01398         }
01399         ret = 0;
01400 
01401 nla_put_failure:
01402         nlmsg_free(msg);
01403         return ret;
01404 }
01405 
01413 int nl80211_scan(wlan_status_t* const wlan_status, int ssid_len, char* const ssid)
01414 {
01415         struct nl_msg *msg;
01416         struct nl_msg *ssid_attr = NULL;
01417 
01418         void *hdr;
01419         gint ret = -ENOBUFS;
01420 
01421         msg = nlmsg_alloc();
01422         if (!msg) {
01423                 nl_perror(__func__);
01424                 return -ENOMEM;
01425         }
01426 
01427         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0, 
01428                           NL80211_CMD_TRIGGER_SCAN, 0);
01429         if (!hdr) {
01430                 DLOG_ERR("nl80211: Failed to put nl80211 message");
01431                 nlmsg_free(msg);
01432                 return -ENOMEM;
01433         }
01434 
01435         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wlan_status->ifindex);
01436 
01437         ssid_attr = nlmsg_alloc();
01438         if (ssid_attr == NULL) {
01439                 nl_perror(__func__);
01440                 nlmsg_free(msg);
01441                 return -ENOMEM;
01442         }
01443         
01444         if (ssid_len && ssid)
01445                 NLA_PUT(ssid_attr, 1, ssid_len, ssid);
01446         else
01447                 NLA_PUT(ssid_attr, 1, 0, "");
01448         
01449         if (nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssid_attr)) {
01450                 ret = -ENOMEM;
01451                 goto nla_put_failure;
01452         }
01453         
01454         ret = nl_send_recv_msgs(msg, NULL, NULL);
01455 
01456 nla_put_failure:
01457         nlmsg_free(ssid_attr);
01458         nlmsg_free(msg);
01459         return ret;
01460 }
01461 
01468 int nl80211_send_get_scan_results(wlan_status_t* const wlan_status, GSList** const scan_results)
01469 {
01470         struct nl_msg *msg;
01471 
01472         void *hdr;
01473         gint ret = -ENOBUFS;
01474 
01475         msg = nlmsg_alloc();
01476         if (!msg) {
01477                 nl_perror(__func__);
01478                 return -ENOMEM;
01479         }
01480 
01481         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, NLM_F_DUMP, 
01482                           NL80211_CMD_GET_SCAN, 0);
01483         if (!hdr) {
01484                 DLOG_ERR("nl80211: Failed to put nl80211 message");
01485                 nlmsg_free(msg);
01486                 return -ENOMEM;
01487         }
01488 
01489         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wlan_status->ifindex);
01490 
01491         scan_wlan_status = wlan_status;
01492 
01493         ret = nl_send_recv_msgs(msg, nl80211_scan_result_handler, scan_results);
01494 
01495 nla_put_failure:
01496         nlmsg_free(msg);
01497         return ret;
01498 }
01499 
01506 static int nl80211_scan_result_handler(struct nl_msg *msg, void* arg)
01507 {
01508         struct nlattr *tb[NL80211_ATTR_MAX + 1];
01509         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
01510         struct nlattr *bss[NL80211_BSS_MAX + 1];
01511 
01512         GSList **scan_results = (GSList**) arg;
01513         struct scan_results_t *scan_result;
01514         int ret = 0;
01515 
01516         static const struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
01517                 [NL80211_BSS_TSF] = { .type = NLA_U64 },
01518                 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
01519                 [NL80211_BSS_BSSID] = { },
01520                 [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
01521                 [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
01522                 [NL80211_BSS_INFORMATION_ELEMENTS] = { },
01523                 [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
01524                 [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
01525                 [NL80211_BSS_STATUS] = { .type = NLA_U32 },
01526                 [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
01527                 [NL80211_BSS_BEACON_IES] = { },
01528         };
01529 
01530         unsigned char *ie;
01531         size_t ie_len;
01532         guint16 capabilities;
01533 
01534         if (nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 
01535                       genlmsg_attrlen(gnlh, 0), NULL))
01536                 return NL_SKIP;
01537 
01538         if (!tb[NL80211_ATTR_BSS])
01539                 return NL_SKIP;
01540 
01541         if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], 
01542                              (struct nla_policy *) bss_policy))
01543                 return NL_SKIP;
01544 
01545         if (!bss[NL80211_BSS_BSSID]
01546             || !bss[NL80211_BSS_INFORMATION_ELEMENTS]
01547             || !bss[NL80211_BSS_CAPABILITY]
01548             || !bss[NL80211_BSS_SIGNAL_MBM]
01549             || !bss[NL80211_BSS_FREQUENCY])
01550                 return NL_SKIP;
01551 
01552         int signal = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
01553         if (signal > 0 || signal < WLANCOND_MINIMUM_SIGNAL * 100)
01554                 return NL_SKIP;
01555 
01556         scan_result = g_slice_new0(struct scan_results_t);
01557 
01558         capabilities = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
01559         if (capabilities & 0x10)
01560                 scan_result->cap_bits |= WLANCOND_WEP;
01561 
01562         scan_result->channel = freq_to_channel(
01563                 nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
01564 
01565         ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
01566         ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
01567         ret = nl80211_parse_ies(ie, ie_len, scan_result);
01568         
01569         if (ret == 0) {
01570                 memcpy(scan_result->bssid, nla_data(bss[NL80211_BSS_BSSID]), 
01571                        ETH_ALEN);
01572                 print_mac(WLANCOND_PRIO_LOW, "BSSID:", scan_result->bssid);
01573                 
01574                 scan_result->rssi = signal / 100;
01575                 
01576                 if (capabilities & 0x02)
01577                         scan_result->cap_bits |= WLANCOND_ADHOC;
01578                 else
01579                         scan_result->cap_bits |= WLANCOND_INFRA;
01580 
01581                 if (!(scan_result->cap_bits & WLANCOND_ENCRYPT_METHOD_MASK))
01582                         scan_result->cap_bits |= WLANCOND_OPEN;
01583 
01584                 *scan_results = g_slist_prepend(*scan_results, scan_result);
01585         } else {
01586                 /* Don't print in the common case (wrong ESSID) */
01587                 if (ret != -2)
01588                         DLOG_DEBUG("Scan result discarded");
01589                 clean_scan_results_item(scan_result, NULL);
01590         }
01591 
01592         return NL_SKIP;
01593 }
01594 
01600 static gboolean nl80211_is_supported_data_rate(guint8 data_rate) {
01601 
01602         switch (data_rate) {
01603         case 108: //  54 Mpbs
01604         case 96:  //  48 Mbps
01605         case 72:  //  36 Mbps
01606         case 48:  //  24 Mbps
01607         case 36:  //  18 Mbps
01608         case 24:  //  12 Mbps
01609         case 22:  //  11 Mbps
01610         case 18:  //   9 Mbps
01611         case 12:  //   6 Mbps
01612         case 11:  // 5.5 Mbps
01613         case 4:   //   2 Mbps
01614         case 2:   //   1 Mbps
01615                 return TRUE;
01616         default:
01617                 return FALSE;
01618         }
01619 }
01620 
01628 static int nl80211_parse_ies(unsigned char* const ie, size_t ie_len, scan_results_t* const scan_result)
01629 {
01630         struct ap_info_t ap_info;
01631         unsigned char *ie_last_byte = ie + ie_len - 1;
01632         unsigned char *current_ie = ie;
01633         guchar* security_ie = NULL;
01634         guint security_ie_len = 0;
01635         unsigned int i;
01636         const guint32 WMM_QOS_OFFSET = 8;
01637         const guint8 WMM_OUI[] = { 0x00, 0x50, 0xF2, 0x02, 0x01 };
01638         const guint8 WMM_UAPSD_MASK = 0x80;
01639         const guint8 WPA1_OUI[] = { 0x00, 0x50, 0xf2, 1 };
01640         const guint8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
01641         gboolean wapi_ie = FALSE;
01642         guint8 max_rate = 0;
01643         guint8 data_rate = 0;
01644 
01645 
01646         while (current_ie + 1 + current_ie[1] <= ie_last_byte) {
01647 
01648                 switch (current_ie[0]) {
01649 
01650                 case 0: /* SSID */
01651                         if (scan_result->ssid_len)
01652                                 break; /* Bug 168117 workaround */
01653 
01654                         if (current_ie[1] > WLANCOND_MAX_SSID_SIZE)
01655                                 return -1;
01656                 
01657                         scan_result->ssid_len = current_ie[1] + 1;
01658 
01659                         if (scan_wlan_status->scan_ssid_len - 1 > 0 &&
01660                             ((gint) scan_result->ssid_len != scan_wlan_status->scan_ssid_len
01661                              || memcmp(current_ie + 2, scan_wlan_status->scan_ssid, scan_result->ssid_len - 1) != 0))
01662                                 return -2;
01663 
01664                         strncpy(scan_result->ssid, (char*) current_ie + 2, current_ie[1]);
01665                         scan_result->ssid[current_ie[1]] = '\0';
01666                         DLOG_DEBUG("SSID: %s", scan_result->ssid);
01667                         break;
01668 
01669                 case 1: /* Supported data rates */
01670                 case 50: /* Extended data rates */
01671                         for (i = 0; i < current_ie[1]; i++ ) {
01672                                 data_rate = current_ie[2 + i];
01673                                 if (nl80211_is_supported_data_rate(data_rate & 0x7F)) {
01674                                         if ((data_rate & 0x7F) > max_rate)
01675                                                 max_rate = data_rate & 0x7F;
01676                                 }
01677                                 else if (data_rate & 0x80) {
01678                                         /* Unsupported basic data rate */
01679                                         scan_result->cap_bits |= WLANCOND_UNSUPPORTED_NETWORK;
01680                                         DLOG_ERR("Basic data rate %u.%u Mbps not supported", (data_rate & 0x7F), data_rate % 2 ? 5 : 0);
01681                                 }
01682                         }
01683                         break;
01684 
01685                 case 45: /* HT Capabilities */
01686                         scan_result->cap_bits |= WLANCOND_RATE_HT_SUPPORT;
01687                         DLOG_DEBUG("HT supported");
01688                         break;
01689 
01690                 case 48: /* RSN */
01691                         if (current_ie[1] < 3)
01692                                 break;
01693                         security_ie_len = current_ie[1] + 2;
01694                         security_ie = current_ie;
01695                         scan_result->cap_bits |= WLANCOND_WPA2;
01696                         break;
01697 
01698                 case 68: /* WAPI */
01699                         if (current_ie[2] != WAPI_VERSION)
01700                                 break;
01701                         security_ie_len = current_ie[1] + 2;
01702                         security_ie = current_ie;
01703                         wapi_ie = TRUE;
01704                         break;
01705                         
01706                 case 221: /* WMM/WPA1/WPS */
01707                         if (current_ie[1] < 6)
01708                                 break;
01709 
01710                         if (!memcmp(&current_ie[2], WMM_OUI, sizeof(WMM_OUI))
01711                             && (current_ie[WMM_QOS_OFFSET] & WMM_UAPSD_MASK)) { 
01712                                 /* WMM U-APSD */
01713                                 scan_result->extra_cap_bits |= WLANCOND_UAPSD_SUPPORTED;
01714                                 DLOG_DEBUG("U-APSD supported");
01715                         }
01716                         else if (!(scan_result->cap_bits & WLANCOND_ENCRYPT_WPA2_MASK)
01717                                  && memcmp(&current_ie[2], WPA1_OUI, 
01718                                            sizeof(WPA1_OUI)) == 0) { /* WPA1 */
01719                                 security_ie_len = current_ie[1] + 2;
01720                                 security_ie = current_ie;
01721                         }
01722                         else if (memcmp(&current_ie[2], WPS_OUI, 
01723                                         sizeof(WPS_OUI)) == 0) { /* WPS */
01724                                 handle_wps_ie(&current_ie[6], scan_result, 
01725                                               current_ie[1] + 2);
01726                         }
01727                         break;
01728 
01729                 default:
01730                         break;
01731                 }
01732 
01733                 current_ie += (current_ie[1] + 2);
01734         } /* while */
01735 
01736         if (scan_result->ssid_len == 0)
01737                 return -1;
01738 
01739         /* Set maximum data rate */
01740 
01741         switch (max_rate) {
01742         case 108:
01743                 scan_result->cap_bits |= WLANCOND_RATE_540;
01744                 break;
01745         case 22:
01746                 scan_result->cap_bits |= WLANCOND_RATE_110;
01747                 break;
01748         case 96:
01749                 scan_result->cap_bits |= WLANCOND_RATE_480;
01750                 break;
01751         case 72:
01752                 scan_result->cap_bits |= WLANCOND_RATE_360;
01753                 break;
01754         case 48:
01755                 scan_result->cap_bits |= WLANCOND_RATE_240;
01756                 break;
01757         case 36:
01758                 scan_result->cap_bits |= WLANCOND_RATE_180;
01759                 break;
01760         case 24:
01761                 scan_result->cap_bits |= WLANCOND_RATE_120;
01762                 break;
01763         case 18:
01764                 scan_result->cap_bits |= WLANCOND_RATE_90;
01765                 break;
01766         case 12:
01767                 scan_result->cap_bits |= WLANCOND_RATE_60;
01768                 break;
01769         case 11:
01770                 scan_result->cap_bits |= WLANCOND_RATE_55;
01771                 break;
01772         case 4:
01773                 scan_result->cap_bits |= WLANCOND_RATE_20;
01774                 break;
01775         case 2:
01776                 scan_result->cap_bits |= WLANCOND_RATE_10;
01777                 break;
01778         default:
01779                 DLOG_ERR("Invalid max rate: %d", max_rate);
01780                 return -1;
01781         }
01782 
01783         if (security_ie) {
01784                 memset(&ap_info, 0, sizeof(ap_info));
01785 
01786                 if (wapi_ie == TRUE) {
01787                         if (parse_wapi_ie(security_ie, security_ie_len, &ap_info) < 0) {
01788                                 return -1;
01789                         }
01790                 } else if (scan_result->cap_bits & WLANCOND_ENCRYPT_WPA2_MASK) {
01791                         if (parse_rsn_ie(security_ie, security_ie_len, &ap_info) < 0) {
01792                                 return -1;
01793                         }
01794                 } else {
01795                         if (parse_wpa_ie(security_ie, security_ie_len, &ap_info) < 0) {
01796                                 return -1;
01797                         }
01798                 }
01799         
01800                 save_caps(scan_result, &ap_info, security_ie, security_ie_len);
01801         }
01802 
01803         return 0;
01804 }
01805 
01812 int nl80211_set_cqm(guint32 threshold, guint32 hyst)
01813 {
01814         struct nl_msg *msg;
01815         struct nl_msg *cqm_msg;
01816         int ret = -1;
01817         void *hdr;
01818 
01819         /* CQM is not supported in Adhoc */
01820         if (get_mode() == WLANCOND_ADHOC)
01821                 return 0;
01822         
01823         msg = nlmsg_alloc();
01824         if (!msg)
01825                 return ret;
01826 
01827         cqm_msg = nlmsg_alloc();
01828         if (!cqm_msg) {
01829                 nlmsg_free(msg);
01830                 return ret;
01831         }
01832 
01833         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0, 
01834                           NL80211_CMD_SET_CQM, 0);
01835         if (hdr == NULL) {
01836                 DLOG_ERR("nl80211: Failed to put set cqm message");
01837                 goto nla_put_failure;
01838         }
01839 
01840         NLA_PUT_U32(cqm_msg, NL80211_ATTR_CQM_RSSI_THOLD, threshold);
01841         NLA_PUT_U32(cqm_msg, NL80211_ATTR_CQM_RSSI_HYST, hyst);
01842 
01843         if (nla_put_nested(msg, NL80211_ATTR_CQM, cqm_msg)) {
01844                 ret = -ENOMEM;
01845                 goto nla_put_failure;
01846         }
01847 
01848         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wlan_status.ifindex);
01849 
01850         ret = nl_send_recv_msgs(msg, NULL, NULL);
01851         if (ret) {
01852                 DLOG_ERR("nl80211: set cqm failed: err=%d %s)", ret, 
01853                          strerror(-ret));
01854                 goto nla_put_failure;
01855         }
01856 
01857         ret = 0;
01858 
01859 nla_put_failure:
01860         nlmsg_free(msg);
01861         nlmsg_free(cqm_msg);
01862         return ret;
01863 }
01864 
01872 static void save_caps(struct scan_results_t *scan_results,
01873                       struct ap_info_t *ap_info, unsigned char *p,
01874                       unsigned int length)
01875 {
01876         scan_results->wpa_ie = g_memdup(p, length);
01877         scan_results->wpa_ie_len = length;
01878 
01879         /* Save method */
01880         scan_results->cap_bits |= 
01881                 ap_info->key_mgmt & WLANCOND_ENCRYPT_METHOD_MASK;
01882         
01883         /* WPA */
01884         if ((ap_info->key_mgmt & WLANCOND_ENCRYPT_METHOD_MASK) == 
01885             WLANCOND_WPA_PSK || 
01886             (ap_info->key_mgmt & WLANCOND_ENCRYPT_METHOD_MASK) == 
01887             WLANCOND_WPA_EAP) {
01888                 if ((ap_info->key_mgmt & WLANCOND_ENCRYPT_METHOD_MASK) == 
01889                     WLANCOND_WPA_EAP) {
01890                         /* No WPS in EAP mode */
01891                         scan_results->cap_bits &= ~WLANCOND_WPS_MASK;
01892                 }
01893                 /* Remove WEP bit to make UI show correct dialogs */
01894                 scan_results->cap_bits &= ~WLANCOND_WEP;
01895                 
01896                 DLOG_DEBUG("%s %s supported",
01897                            (scan_results->cap_bits & WLANCOND_WPA2) ? 
01898                            "WPA2":"WPA",
01899                            (ap_info->key_mgmt & WLANCOND_WPA_PSK) ? 
01900                            "PSK":"EAP");
01901                 
01902                 /* Algorithms */
01903                 /* Pairwise */
01904                 if (ap_info->pairwise_cipher & CIPHER_SUITE_CCMP)
01905                         scan_results->cap_bits |= WLANCOND_WPA_AES;
01906                
01907                 if (ap_info->pairwise_cipher & CIPHER_SUITE_TKIP)
01908                         scan_results->cap_bits |= WLANCOND_WPA_TKIP;
01909 
01910                 if (wlan_status.allow_all_ciphers == TRUE) {
01911                         if (ap_info->pairwise_cipher & CIPHER_SUITE_WEP40) {
01912                                 scan_results->extra_cap_bits |= WLANCOND_WEP40;
01913                         }
01914                         if (ap_info->pairwise_cipher & CIPHER_SUITE_WEP104) {
01915                                 scan_results->extra_cap_bits |= WLANCOND_WEP104;
01916                         }
01917                         if (ap_info->group_cipher & CIPHER_SUITE_WEP40) {
01918                                 scan_results->extra_cap_bits |= WLANCOND_WEP40_GROUP;
01919                         }
01920                         if (ap_info->group_cipher & CIPHER_SUITE_WEP104) {
01921                                 scan_results->extra_cap_bits |= WLANCOND_WEP104_GROUP;
01922                         }
01923                 } else {
01924                         if (ap_info->pairwise_cipher & CIPHER_SUITE_WEP40 ||
01925                             ap_info->pairwise_cipher & CIPHER_SUITE_WEP104 ||
01926                             ap_info->group_cipher & CIPHER_SUITE_WEP40 ||
01927                             ap_info->group_cipher & CIPHER_SUITE_WEP104) {
01928                                 DLOG_DEBUG("In WPA mode WEP is not allowed");
01929                                 scan_results->cap_bits |= 
01930                                         WLANCOND_UNSUPPORTED_NETWORK;
01931                         }
01932                 }
01933                 DLOG_DEBUG("%s/%s/%s/%s for unicast",
01934                            (ap_info->pairwise_cipher & CIPHER_SUITE_CCMP)?"AES":"-",
01935                            (ap_info->pairwise_cipher & CIPHER_SUITE_TKIP)?"TKIP":"-",
01936                            (ap_info->pairwise_cipher & CIPHER_SUITE_WEP104)?"WEP104":"-",
01937                            (ap_info->pairwise_cipher & CIPHER_SUITE_WEP40)?"WEP40":"-");
01938                 /* Group */
01939                 if (ap_info->group_cipher & CIPHER_SUITE_CCMP)
01940                         scan_results->cap_bits |= WLANCOND_WPA_AES_GROUP;
01941                 
01942                 if (ap_info->group_cipher & CIPHER_SUITE_TKIP)
01943                         scan_results->cap_bits |= WLANCOND_WPA_TKIP_GROUP;
01944                 
01945                 DLOG_DEBUG("%s/%s/%s/%s for multicast",
01946                            (ap_info->group_cipher & CIPHER_SUITE_CCMP)?"AES":"-",
01947                            (ap_info->group_cipher & CIPHER_SUITE_TKIP)?"TKIP":"-",
01948                            (ap_info->group_cipher & CIPHER_SUITE_WEP104)?"WEP104":"-",
01949                            (ap_info->group_cipher & CIPHER_SUITE_WEP40)?"WEP40":"-");
01950                 
01951         }
01952 
01953         /* WAPI */
01954         else if ((ap_info->key_mgmt & WLANCOND_ENCRYPT_METHOD_MASK) == 
01955             WLANCOND_WAPI_PSK || 
01956             (ap_info->key_mgmt & WLANCOND_ENCRYPT_METHOD_MASK) == 
01957             WLANCOND_WAPI_CERT) {
01958 
01959                 DLOG_DEBUG("WAPI %s supported",
01960                            ((ap_info->key_mgmt & WLANCOND_ENCRYPT_METHOD_MASK) 
01961                             == WLANCOND_WAPI_PSK) ? "PSK":"CERT");
01962                 
01963                 if (ap_info->pairwise_cipher & CIPHER_SUITE_SMS4)
01964                         scan_results->cap_bits |= WLANCOND_WAPI_SMS4; 
01965                 if (ap_info->group_cipher & CIPHER_SUITE_SMS4)
01966                         scan_results->cap_bits |= WLANCOND_WAPI_SMS4_GROUP;
01967                 
01968                 DLOG_DEBUG("%s/%s ciphers",
01969                            (ap_info->pairwise_cipher & CIPHER_SUITE_SMS4)?
01970                            "SMS4":"-",
01971                            (ap_info->group_cipher & CIPHER_SUITE_SMS4)?
01972                            "SMS4":"-");
01973         }
01974 }
01975 
01982 int nl80211_set_tx_power(int tx_power, guint32 ifindex)
01983 {
01984         struct nl_msg *msg;
01985         gint ret = -1;
01986         enum nl80211_tx_power_setting type = NL80211_TX_POWER_LIMITED;
01987         void *hdr;
01988 
01989         msg = nlmsg_alloc();
01990         if (!msg)
01991                 return ret;
01992 
01993         hdr = genlmsg_put(msg, getpid(), 0, nl_family_id, 0, 0, 
01994                           NL80211_CMD_SET_WIPHY, 0);
01995         if (hdr == NULL) {
01996                 DLOG_ERR("nl80211: Failed to put set tx power message");
01997                 goto nla_put_failure;
01998         }
01999 
02000         NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
02001         NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_SETTING, type);
02002         NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, tx_power);
02003 
02004         ret = nl_send_recv_msgs(msg, NULL, NULL);
02005         if (ret) {
02006                 DLOG_ERR("nl80211: set tx power command failed: ret=%d (%s)",
02007                          ret, strerror(-ret));
02008                 goto nla_put_failure;
02009         }
02010 
02011 nla_put_failure:
02012         nlmsg_free(msg);
02013         return ret;
02014 }
02015 

Generated on Wed Aug 10 2011 16:02:33 for WLAN Connection Daemon by  doxygen 1.7.1