driver_ndis.c

Go to the documentation of this file.
00001 
00016 #include <stdlib.h>
00017 #include <Packet32.h>
00018 #include <stdio.h>
00019 #include <string.h>
00020 #include <sys/unistd.h>
00021 #include <ntddndis.h>
00022 
00023 #include "common.h"
00024 #include "driver.h"
00025 #include "wpa_supplicant.h"
00026 #include "l2_packet.h"
00027 #include "eloop.h"
00028 #include "wpa.h"
00029 #include "driver_ndis.h"
00030 
00031 int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv);
00032 
00033 static void wpa_driver_ndis_poll(void *drv);
00034 
00035 
00036 /* FIX: to be removed once this can be compiled with the complete NDIS
00037  * header files */
00038 #ifndef OID_802_11_BSSID
00039 #define OID_802_11_BSSID                        0x0d010101
00040 #define OID_802_11_SSID                         0x0d010102
00041 #define OID_802_11_INFRASTRUCTURE_MODE          0x0d010108
00042 #define OID_802_11_ADD_WEP                      0x0D010113
00043 #define OID_802_11_REMOVE_WEP                   0x0D010114
00044 #define OID_802_11_DISASSOCIATE                 0x0D010115
00045 #define OID_802_11_BSSID_LIST                   0x0d010217
00046 #define OID_802_11_AUTHENTICATION_MODE          0x0d010118
00047 #define OID_802_11_PRIVACY_FILTER               0x0d010119
00048 #define OID_802_11_BSSID_LIST_SCAN              0x0d01011A
00049 #define OID_802_11_WEP_STATUS                   0x0d01011B
00050 #define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS
00051 #define OID_802_11_ADD_KEY                      0x0d01011D
00052 #define OID_802_11_REMOVE_KEY                   0x0d01011E
00053 #define OID_802_11_ASSOCIATION_INFORMATION      0x0d01011F
00054 #define OID_802_11_TEST                         0x0d010120
00055 #define OID_802_11_CAPABILITY                   0x0d010122
00056 #define OID_802_11_PMKID                        0x0d010123
00057 
00058 #define NDIS_802_11_LENGTH_SSID 32
00059 #define NDIS_802_11_LENGTH_RATES 8
00060 #define NDIS_802_11_LENGTH_RATES_EX 16
00061 
00062 typedef UCHAR NDIS_802_11_MAC_ADDRESS[6];
00063 
00064 typedef struct NDIS_802_11_SSID {
00065         ULONG SsidLength;
00066         UCHAR Ssid[NDIS_802_11_LENGTH_SSID];
00067 } NDIS_802_11_SSID;
00068 
00069 typedef LONG NDIS_802_11_RSSI;
00070 
00071 typedef enum NDIS_802_11_NETWORK_TYPE {
00072         Ndis802_11FH,
00073         Ndis802_11DS,
00074         Ndis802_11OFDM5,
00075         Ndis802_11OFDM24,
00076         Ndis802_11NetworkTypeMax
00077 } NDIS_802_11_NETWORK_TYPE;
00078 
00079 typedef struct NDIS_802_11_CONFIGURATION_FH {
00080         ULONG Length;
00081         ULONG HopPattern;
00082         ULONG HopSet;
00083         ULONG DwellTime;
00084 } NDIS_802_11_CONFIGURATION_FH;
00085 
00086 typedef struct NDIS_802_11_CONFIGURATION {
00087         ULONG Length;
00088         ULONG BeaconPeriod;
00089         ULONG ATIMWindow;
00090         ULONG DSConfig;
00091         NDIS_802_11_CONFIGURATION_FH FHConfig;
00092 } NDIS_802_11_CONFIGURATION;
00093 
00094 typedef enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
00095         Ndis802_11IBSS,
00096         Ndis802_11Infrastructure,
00097         Ndis802_11AutoUnknown,
00098         Ndis802_11InfrastructureMax
00099 } NDIS_802_11_NETWORK_INFRASTRUCTURE;
00100 
00101 typedef enum NDIS_802_11_AUTHENTICATION_MODE {
00102         Ndis802_11AuthModeOpen,
00103         Ndis802_11AuthModeShared,
00104         Ndis802_11AuthModeAutoSwitch,
00105         Ndis802_11AuthModeWPA,
00106         Ndis802_11AuthModeWPAPSK,
00107         Ndis802_11AuthModeWPANone,
00108         Ndis802_11AuthModeWPA2,
00109         Ndis802_11AuthModeWPA2PSK,
00110         Ndis802_11AuthModeMax
00111 } NDIS_802_11_AUTHENTICATION_MODE;
00112 
00113 typedef enum NDIS_802_11_WEP_STATUS {
00114         Ndis802_11WEPEnabled,
00115         Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
00116         Ndis802_11WEPDisabled,
00117         Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
00118         Ndis802_11WEPKeyAbsent,
00119         Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
00120         Ndis802_11WEPNotSupported,
00121         Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
00122         Ndis802_11Encryption2Enabled,
00123         Ndis802_11Encryption2KeyAbsent,
00124         Ndis802_11Encryption3Enabled,
00125         Ndis802_11Encryption3KeyAbsent
00126 } NDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS;
00127 
00128 typedef enum NDIS_802_11_PRIVACY_FILTER {
00129         Ndis802_11PrivFilterAcceptAll,
00130         Ndis802_11PrivFilter8021xWEP
00131 } NDIS_802_11_PRIVACY_FILTER;
00132 
00133 typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES];
00134 typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
00135 
00136 typedef struct NDIS_WLAN_BSSID_EX {
00137         ULONG Length;
00138         NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */
00139         UCHAR Reserved[2];
00140         NDIS_802_11_SSID Ssid;
00141         ULONG Privacy;
00142         NDIS_802_11_RSSI Rssi;
00143         NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
00144         NDIS_802_11_CONFIGURATION Configuration;
00145         NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
00146         NDIS_802_11_RATES_EX SupportedRates;
00147         ULONG IELength;
00148         UCHAR IEs[1];
00149 } NDIS_WLAN_BSSID_EX;
00150 
00151 typedef struct NDIS_802_11_BSSID_LIST_EX {
00152         ULONG NumberOfItems;
00153         NDIS_WLAN_BSSID_EX Bssid[1];
00154 } NDIS_802_11_BSSID_LIST_EX;
00155 
00156 typedef struct NDIS_802_11_FIXED_IEs {
00157         UCHAR Timestamp[8];
00158         USHORT BeaconInterval;
00159         USHORT Capabilities;
00160 } NDIS_802_11_FIXED_IEs;
00161 
00162 typedef struct NDIS_802_11_WEP {
00163         ULONG Length;
00164         ULONG KeyIndex;
00165         ULONG KeyLength;
00166         UCHAR KeyMaterial[1];
00167 } NDIS_802_11_WEP;
00168 
00169 typedef ULONG NDIS_802_11_KEY_INDEX;
00170 typedef ULONGLONG NDIS_802_11_KEY_RSC;
00171 
00172 typedef struct NDIS_802_11_KEY {
00173         ULONG Length;
00174         ULONG KeyIndex;
00175         ULONG KeyLength;
00176         NDIS_802_11_MAC_ADDRESS BSSID;
00177         NDIS_802_11_KEY_RSC KeyRSC;
00178         UCHAR KeyMaterial[1];
00179 } NDIS_802_11_KEY;
00180 
00181 typedef struct NDIS_802_11_REMOVE_KEY {
00182         ULONG Length;
00183         ULONG KeyIndex;
00184         NDIS_802_11_MAC_ADDRESS BSSID;
00185 } NDIS_802_11_REMOVE_KEY;
00186 
00187 typedef struct NDIS_802_11_AI_REQFI {
00188         USHORT Capabilities;
00189         USHORT ListenInterval;
00190         NDIS_802_11_MAC_ADDRESS CurrentAPAddress;
00191 } NDIS_802_11_AI_REQFI;
00192 
00193 typedef struct NDIS_802_11_AI_RESFI {
00194         USHORT Capabilities;
00195         USHORT StatusCode;
00196         USHORT AssociationId;
00197 } NDIS_802_11_AI_RESFI;
00198 
00199 typedef struct NDIS_802_11_ASSOCIATION_INFORMATION {
00200         ULONG Length;
00201         USHORT AvailableRequestFixedIEs;
00202         NDIS_802_11_AI_REQFI RequestFixedIEs;
00203         ULONG RequestIELength;
00204         ULONG OffsetRequestIEs;
00205         USHORT AvailableResponseFixedIEs;
00206         NDIS_802_11_AI_RESFI ResponseFixedIEs;
00207         ULONG ResponseIELength;
00208         ULONG OffsetResponseIEs;
00209 } NDIS_802_11_ASSOCIATION_INFORMATION;
00210 
00211 typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION {
00212         NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported;
00213         NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported;
00214 } NDIS_802_11_AUTHENTICATION_ENCRYPTION;
00215 
00216 typedef struct NDIS_802_11_CAPABILITY {
00217         ULONG Length;
00218         ULONG Version;
00219         ULONG NoOfPMKIDs;
00220         ULONG NoOfAuthEncryptPairSupported;
00221         NDIS_802_11_AUTHENTICATION_ENCRYPTION
00222                 AuthenticationEncryptionSupported[1];
00223 } NDIS_802_11_CAPABILITY;
00224 
00225 typedef UCHAR NDIS_802_11_PMKID_VALUE[16];
00226 
00227 typedef struct BSSID_INFO {
00228         NDIS_802_11_MAC_ADDRESS BSSID;
00229         NDIS_802_11_PMKID_VALUE PMKID;
00230 } BSSID_INFO;
00231 
00232 typedef struct NDIS_802_11_PMKID {
00233         ULONG Length;
00234         ULONG BSSIDInfoCount;
00235         BSSID_INFO BSSIDInfo[1];
00236 } NDIS_802_11_PMKID;
00237 
00238 typedef enum NDIS_802_11_STATUS_TYPE {
00239         Ndis802_11StatusType_Authentication,
00240         Ndis802_11StatusType_PMKID_CandidateList = 2,
00241         Ndis802_11StatusTypeMax
00242 } NDIS_802_11_STATUS_TYPE;
00243 
00244 typedef struct NDIS_802_11_STATUS_INDICATION {
00245         NDIS_802_11_STATUS_TYPE StatusType;
00246 } NDIS_802_11_STATUS_INDICATION;
00247 
00248 typedef struct PMKID_CANDIDATE {
00249         NDIS_802_11_MAC_ADDRESS BSSID;
00250         ULONG Flags;
00251 } PMKID_CANDIDATE;
00252 
00253 #define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01
00254 
00255 typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST {
00256         ULONG Version;
00257         ULONG NumCandidates;
00258         PMKID_CANDIDATE CandidateList[1];
00259 } NDIS_802_11_PMKID_CANDIDATE_LIST;
00260 
00261 typedef struct NDIS_802_11_AUTHENTICATION_REQUEST {
00262         ULONG Length;
00263         NDIS_802_11_MAC_ADDRESS Bssid;
00264         ULONG Flags;
00265 } NDIS_802_11_AUTHENTICATION_REQUEST;
00266 
00267 #define NDIS_802_11_AUTH_REQUEST_REAUTH                 0x01
00268 #define NDIS_802_11_AUTH_REQUEST_KEYUPDATE              0x02
00269 #define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR         0x06
00270 #define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR            0x0E
00271 
00272 #endif
00273 
00274 
00275 static int ndis_get_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
00276                         char *data, int len)
00277 {
00278         char *buf;
00279         PACKET_OID_DATA *o;
00280         int ret;
00281 
00282         buf = malloc(sizeof(*o) + len);
00283         if (buf == NULL)
00284                 return -1;
00285         memset(buf, 0, sizeof(*o) + len);
00286         o = (PACKET_OID_DATA *) buf;
00287         o->Oid = oid;
00288         o->Length = len;
00289 
00290         if (!PacketRequest(drv->adapter, FALSE, o)) {
00291                 wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
00292                            __func__, oid, len);
00293                 free(buf);
00294                 return -1;
00295         }
00296         if (o->Length > len) {
00297                 wpa_printf(MSG_DEBUG, "%s: oid=0x%x Length (%d) > len (%d)",
00298                            __func__, oid, (unsigned int) o->Length, len);
00299                 free(buf);
00300                 return -1;
00301         }
00302         memcpy(data, o->Data, o->Length);
00303         ret = o->Length;
00304         free(buf);
00305         return ret;
00306 }
00307 
00308 
00309 static int ndis_set_oid(struct wpa_driver_ndis_data *drv, unsigned int oid,
00310                         char *data, int len)
00311 {
00312         char *buf;
00313         PACKET_OID_DATA *o;
00314 
00315         buf = malloc(sizeof(*o) + len);
00316         if (buf == NULL)
00317                 return -1;
00318         memset(buf, 0, sizeof(*o) + len);
00319         o = (PACKET_OID_DATA *) buf;
00320         o->Oid = oid;
00321         o->Length = len;
00322         if (data)
00323                 memcpy(o->Data, data, len);
00324 
00325         if (!PacketRequest(drv->adapter, TRUE, o)) {
00326                 wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
00327                            __func__, oid, len);
00328                 free(buf);
00329                 return -1;
00330         }
00331         free(buf);
00332         return 0;
00333 }
00334 
00335 
00336 static int ndis_set_auth_mode(struct wpa_driver_ndis_data *drv, int mode)
00337 {
00338         u32 auth_mode = mode;
00339         if (ndis_set_oid(drv, OID_802_11_AUTHENTICATION_MODE,
00340                          (char *) &auth_mode, sizeof(auth_mode)) < 0) {
00341                 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
00342                            "OID_802_11_AUTHENTICATION_MODE (%d)",
00343                            (int) auth_mode);
00344                 return -1;
00345         }
00346         return 0;
00347 }
00348 
00349 
00350 static int ndis_get_auth_mode(struct wpa_driver_ndis_data *drv)
00351 {
00352         u32 auth_mode;
00353         int res;
00354         res = ndis_get_oid(drv, OID_802_11_AUTHENTICATION_MODE,
00355                            (char *) &auth_mode, sizeof(auth_mode));
00356         if (res != sizeof(auth_mode)) {
00357                 wpa_printf(MSG_DEBUG, "NDIS: Failed to get "
00358                            "OID_802_11_AUTHENTICATION_MODE");
00359                 return -1;
00360         }
00361         return auth_mode;
00362 }
00363 
00364 
00365 static int ndis_set_encr_status(struct wpa_driver_ndis_data *drv, int encr)
00366 {
00367         u32 encr_status = encr;
00368         if (ndis_set_oid(drv, OID_802_11_ENCRYPTION_STATUS,
00369                          (char *) &encr_status, sizeof(encr_status)) < 0) {
00370                 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
00371                            "OID_802_11_ENCRYPTION_STATUS (%d)", encr);
00372                 return -1;
00373         }
00374         return 0;
00375 }
00376 
00377 
00378 static int ndis_get_encr_status(struct wpa_driver_ndis_data *drv)
00379 {
00380         u32 encr;
00381         int res;
00382         res = ndis_get_oid(drv, OID_802_11_ENCRYPTION_STATUS,
00383                            (char *) &encr, sizeof(encr));
00384         if (res != sizeof(encr)) {
00385                 wpa_printf(MSG_DEBUG, "NDIS: Failed to get "
00386                            "OID_802_11_ENCRYPTION_STATUS");
00387                 return -1;
00388         }
00389         return encr;
00390 }
00391 
00392 
00393 static int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid)
00394 {
00395         struct wpa_driver_ndis_data *drv = priv;
00396 
00397         if (drv->wired) {
00398                 /*
00399                  * Report PAE group address as the "BSSID" for wired
00400                  * connection.
00401                  */
00402                 bssid[0] = 0x01;
00403                 bssid[1] = 0x80;
00404                 bssid[2] = 0xc2;
00405                 bssid[3] = 0x00;
00406                 bssid[4] = 0x00;
00407                 bssid[5] = 0x03;
00408                 return 0;
00409         }
00410 
00411         return ndis_get_oid(drv, OID_802_11_BSSID, bssid, ETH_ALEN) < 0 ?
00412                 -1 : 0;
00413 }
00414 
00415 
00416 
00417 static int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid)
00418 {
00419         struct wpa_driver_ndis_data *drv = priv;
00420         NDIS_802_11_SSID buf;
00421         int res;
00422 
00423         res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
00424         if (res < 4) {
00425                 wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID");
00426                 if (drv->wired) {
00427                         wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure "
00428                                    "with a wired interface");
00429                         return 0;
00430                 }
00431                 return -1;
00432         }
00433         memcpy(ssid, buf.Ssid, buf.SsidLength);
00434         return buf.SsidLength;
00435 }
00436 
00437 
00438 static int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv,
00439                                     const u8 *ssid, size_t ssid_len)
00440 {
00441         NDIS_802_11_SSID buf;
00442 
00443         memset(&buf, 0, sizeof(buf));
00444         buf.SsidLength = ssid_len;
00445         memcpy(buf.Ssid, ssid, ssid_len);
00446         /*
00447          * Make sure radio is marked enabled here so that scan request will not
00448          * force SSID to be changed to a random one in order to enable radio at
00449          * that point.
00450          */
00451         drv->radio_enabled = 1;
00452         return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
00453 }
00454 
00455 
00456 /* Disconnect using OID_802_11_DISASSOCIATE. This will also turn the radio off.
00457  */
00458 static int wpa_driver_ndis_radio_off(struct wpa_driver_ndis_data *drv)
00459 {
00460         drv->radio_enabled = 0;
00461         return ndis_set_oid(drv, OID_802_11_DISASSOCIATE, "    ", 4);
00462 }
00463 
00464 
00465 /* Disconnect by setting SSID to random (i.e., likely not used). */
00466 static int wpa_driver_ndis_disconnect(struct wpa_driver_ndis_data *drv)
00467 {
00468         char ssid[32];
00469         int i;
00470         for (i = 0; i < 32; i++)
00471                 ssid[i] = rand() & 0xff;
00472         return wpa_driver_ndis_set_ssid(drv, ssid, 32);
00473 }
00474 
00475 
00476 static int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr,
00477                                           int reason_code)
00478 {
00479         struct wpa_driver_ndis_data *drv = priv;
00480         return wpa_driver_ndis_disconnect(drv);
00481 }
00482 
00483 
00484 static int wpa_driver_ndis_disassociate(void *priv, const u8 *addr,
00485                                         int reason_code)
00486 {
00487         struct wpa_driver_ndis_data *drv = priv;
00488         return wpa_driver_ndis_disconnect(drv);
00489 }
00490 
00491 
00492 static int wpa_driver_ndis_set_wpa(void *priv, int enabled)
00493 {
00494         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
00495         return 0;
00496 }
00497 
00498 
00499 static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx)
00500 {
00501         wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
00502         wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
00503 }
00504 
00505 
00506 static int wpa_driver_ndis_scan(void *priv, const u8 *ssid, size_t ssid_len)
00507 {
00508         struct wpa_driver_ndis_data *drv = priv;
00509         int res;
00510 
00511         if (!drv->radio_enabled) {
00512                 wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first"
00513                            " scan");
00514                 if (wpa_driver_ndis_disconnect(drv) < 0) {
00515                         wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio");
00516                 }
00517                 drv->radio_enabled = 1;
00518         }
00519 
00520         res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, "    ", 4);
00521         eloop_register_timeout(3, 0, wpa_driver_ndis_scan_timeout, drv,
00522                                drv->ctx);
00523         return res;
00524 }
00525 
00526 
00527 static void wpa_driver_ndis_get_ies(struct wpa_scan_result *res, u8 *ie,
00528                                     size_t ie_len)
00529 {
00530         u8 *pos = ie;
00531         u8 *end = ie + ie_len;
00532 
00533         if (ie_len < sizeof(NDIS_802_11_FIXED_IEs))
00534                 return;
00535 
00536         pos += sizeof(NDIS_802_11_FIXED_IEs);
00537         /* wpa_hexdump(MSG_MSGDUMP, "IEs", pos, end - pos); */
00538         while (pos + 1 < end && pos + 2 + pos[1] <= end) {
00539                 u8 ielen = 2 + pos[1];
00540                 if (ielen > SSID_MAX_WPA_IE_LEN) {
00541                         pos += ielen;
00542                         continue;
00543                 }
00544                 if (pos[0] == GENERIC_INFO_ELEM && pos[1] >= 4 &&
00545                     memcmp(pos + 2, "\x00\x50\xf2\x01", 4) == 0) {
00546                         memcpy(res->wpa_ie, pos, ielen);
00547                         res->wpa_ie_len = ielen;
00548                 } else if (pos[0] == RSN_INFO_ELEM) {
00549                         memcpy(res->rsn_ie, pos, ielen);
00550                         res->rsn_ie_len = ielen;
00551                 }
00552                 pos += ielen;
00553         }
00554 }
00555 
00556 
00557 static int wpa_driver_ndis_get_scan_results(void *priv,
00558                                             struct wpa_scan_result *results,
00559                                             size_t max_size)
00560 {
00561         struct wpa_driver_ndis_data *drv = priv;
00562         NDIS_802_11_BSSID_LIST_EX *b;
00563         size_t blen;
00564         int len, count, i, j;
00565         char *pos;
00566 
00567         blen = 65535;
00568         b = malloc(blen);
00569         if (b == NULL)
00570                 return -1;
00571         memset(b, 0, blen);
00572         len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
00573         if (len < 0) {
00574                 wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
00575                 free(b);
00576                 return -1;
00577         }
00578         count = b->NumberOfItems;
00579 
00580         if (count > max_size)
00581                 count = max_size;
00582 
00583         memset(results, 0, max_size * sizeof(struct wpa_scan_result));
00584         pos = (char *) &b->Bssid[0];
00585         for (i = 0; i < count; i++) {
00586                 NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
00587                 memcpy(results[i].bssid, bss->MacAddress, ETH_ALEN);
00588                 memcpy(results[i].ssid, bss->Ssid.Ssid, bss->Ssid.SsidLength);
00589                 results[i].ssid_len = bss->Ssid.SsidLength;
00590                 if (bss->Privacy)
00591                         results[i].caps |= IEEE80211_CAP_PRIVACY;
00592                 results[i].level = (int) bss->Rssi;
00593                 results[i].freq = bss->Configuration.DSConfig / 1000;
00594                 for (j = 0; j < sizeof(bss->SupportedRates); j++) {
00595                         if ((bss->SupportedRates[j] & 0x7f) >
00596                             results[i].maxrate) {
00597                                 results[i].maxrate =
00598                                         bss->SupportedRates[j] & 0x7f;
00599                         }
00600                 }
00601                 wpa_driver_ndis_get_ies(&results[i], bss->IEs, bss->IELength);
00602                 pos += bss->Length;
00603                 if (pos > (char *) b + blen)
00604                         break;
00605         }
00606 
00607         free(b);
00608         return count;
00609 }
00610 
00611 
00612 static int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_data *drv,
00613                                       int key_idx, const u8 *addr,
00614                                       const u8 *bssid, int pairwise)
00615 {
00616         NDIS_802_11_REMOVE_KEY rkey;
00617         NDIS_802_11_KEY_INDEX index;
00618         int res, res2;
00619 
00620         memset(&rkey, 0, sizeof(rkey));
00621 
00622         rkey.Length = sizeof(rkey);
00623         rkey.KeyIndex = key_idx;
00624         if (pairwise)
00625                 rkey.KeyIndex |= 1 << 30;
00626         memcpy(rkey.BSSID, bssid, ETH_ALEN);
00627 
00628         res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey,
00629                            sizeof(rkey));
00630         if (!pairwise) {
00631                 res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP,
00632                                     (char *) &index, sizeof(index));
00633         } else
00634                 res2 = 0;
00635 
00636         if (res < 0 && res2 < 0)
00637                 return res;
00638         return 0;
00639 }
00640 
00641 
00642 static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv,
00643                                    int pairwise, int key_idx, int set_tx,
00644                                    const u8 *key, size_t key_len)
00645 {
00646         NDIS_802_11_WEP *wep;
00647         size_t len;
00648         int res;
00649 
00650         len = 12 + key_len;
00651         wep = malloc(len);
00652         if (wep == NULL)
00653                 return -1;
00654         memset(wep, 0, len);
00655         wep->Length = len;
00656         wep->KeyIndex = key_idx;
00657         if (set_tx)
00658                 wep->KeyIndex |= 1 << 31;
00659 #if 0 /* Setting bit30 does not seem to work with some NDIS drivers */
00660         if (pairwise)
00661                 wep->KeyIndex |= 1 << 30;
00662 #endif
00663         wep->KeyLength = key_len;
00664         memcpy(wep->KeyMaterial, key, key_len);
00665 
00666         wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OIS_802_11_ADD_WEP",
00667                         (char *) wep, len);
00668         res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len);
00669 
00670         free(wep);
00671 
00672         return res;
00673 }
00674 
00675 static int wpa_driver_ndis_set_key(void *priv, wpa_alg alg, const u8 *addr,
00676                                    int key_idx, int set_tx,
00677                                    const u8 *seq, size_t seq_len,
00678                                    const u8 *key, size_t key_len)
00679 {
00680         struct wpa_driver_ndis_data *drv = priv;
00681         size_t len;
00682         NDIS_802_11_KEY *nkey;
00683         int i, res, pairwise;
00684         u8 bssid[ETH_ALEN];
00685 
00686         if (addr == NULL || memcmp(addr, "\xff\xff\xff\xff\xff\xff",
00687                                    ETH_ALEN) == 0) {
00688                 /* Group Key */
00689                 pairwise = 0;
00690                 wpa_driver_ndis_get_bssid(drv, bssid);
00691         } else {
00692                 /* Pairwise Key */
00693                 pairwise = 1;
00694                 memcpy(bssid, addr, ETH_ALEN);
00695         }
00696 
00697         if (alg == WPA_ALG_NONE || key_len == 0) {
00698                 return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid,
00699                                                   pairwise);
00700         }
00701 
00702         if (alg == WPA_ALG_WEP) {
00703                 return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx,
00704                                                key, key_len);
00705         }
00706 
00707         len = 12 + 6 + 6 + 8 + key_len;
00708 
00709         nkey = malloc(len);
00710         if (nkey == NULL)
00711                 return -1;
00712         memset(nkey, 0, len);
00713 
00714         nkey->Length = len;
00715         nkey->KeyIndex = key_idx;
00716         if (set_tx)
00717                 nkey->KeyIndex |= 1 << 31;
00718         if (pairwise)
00719                 nkey->KeyIndex |= 1 << 30;
00720         if (seq && seq_len)
00721                 nkey->KeyIndex |= 1 << 29;
00722         nkey->KeyLength = key_len;
00723         memcpy(nkey->BSSID, bssid, ETH_ALEN);
00724         if (seq && seq_len) {
00725                 for (i = 0; i < seq_len; i++)
00726                         nkey->KeyRSC |= seq[i] << (i * 8);
00727         }
00728         if (alg == WPA_ALG_TKIP && key_len == 32) {
00729                 memcpy(nkey->KeyMaterial, key, 16);
00730                 memcpy(nkey->KeyMaterial + 16, key + 24, 8);
00731                 memcpy(nkey->KeyMaterial + 24, key + 16, 8);
00732         } else {
00733                 memcpy(nkey->KeyMaterial, key, key_len);
00734         }
00735 
00736         wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OIS_802_11_ADD_KEY",
00737                         (char *) nkey, len);
00738         res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len);
00739         free(nkey);
00740 
00741         return res;
00742 }
00743 
00744 
00745 static int
00746 wpa_driver_ndis_associate(void *priv,
00747                           struct wpa_driver_associate_params *params)
00748 {
00749         struct wpa_driver_ndis_data *drv = priv;
00750         u32 auth_mode, encr, priv_mode, mode;
00751 
00752         /* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys,
00753          * so static WEP keys needs to be set again after this. */
00754         if (params->mode == IEEE80211_MODE_IBSS)
00755                 mode = Ndis802_11IBSS;
00756         else
00757                 mode = Ndis802_11Infrastructure;
00758         if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
00759                          (char *) &mode, sizeof(mode)) < 0) {
00760                 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
00761                            "OID_802_11_INFRASTRUCTURE_MODE (%d)",
00762                            (int) mode);
00763                 /* Try to continue anyway */
00764         }
00765 
00766         if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
00767                 if (params->auth_alg & AUTH_ALG_SHARED_KEY) {
00768                         if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM)
00769                                 auth_mode = Ndis802_11AuthModeAutoSwitch;
00770                         else
00771                                 auth_mode = Ndis802_11AuthModeShared;
00772                 } else
00773                         auth_mode = Ndis802_11AuthModeOpen;
00774                 priv_mode = Ndis802_11PrivFilterAcceptAll;
00775         } else if (params->wpa_ie[0] == RSN_INFO_ELEM) {
00776                 priv_mode = Ndis802_11PrivFilter8021xWEP;
00777                 if (params->key_mgmt_suite == KEY_MGMT_PSK)
00778                         auth_mode = Ndis802_11AuthModeWPA2PSK;
00779                 else
00780                         auth_mode = Ndis802_11AuthModeWPA2;
00781         } else {
00782                 priv_mode = Ndis802_11PrivFilter8021xWEP;
00783                 if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE)
00784                         auth_mode = Ndis802_11AuthModeWPANone;
00785                 else if (params->key_mgmt_suite == KEY_MGMT_PSK)
00786                         auth_mode = Ndis802_11AuthModeWPAPSK;
00787                 else
00788                         auth_mode = Ndis802_11AuthModeWPA;
00789         }
00790 
00791         switch (params->pairwise_suite) {
00792         case CIPHER_CCMP:
00793                 encr = Ndis802_11Encryption3Enabled;
00794                 break;
00795         case CIPHER_TKIP:
00796                 encr = Ndis802_11Encryption2Enabled;
00797                 break;
00798         case CIPHER_WEP40:
00799         case CIPHER_WEP104:
00800                 encr = Ndis802_11Encryption1Enabled;
00801                 break;
00802         case CIPHER_NONE:
00803                 if (params->group_suite == CIPHER_CCMP)
00804                         encr = Ndis802_11Encryption3Enabled;
00805                 else if (params->group_suite == CIPHER_TKIP)
00806                         encr = Ndis802_11Encryption2Enabled;
00807                 else
00808                         encr = Ndis802_11EncryptionDisabled;
00809                 break;
00810         default:
00811                 encr = Ndis802_11EncryptionDisabled;
00812         };
00813 
00814         if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER,
00815                          (char *) &priv_mode, sizeof(priv_mode)) < 0) {
00816                 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
00817                            "OID_802_11_PRIVACY_FILTER (%d)",
00818                            (int) priv_mode);
00819                 /* Try to continue anyway */
00820         }
00821 
00822         ndis_set_auth_mode(drv, auth_mode);
00823         ndis_set_encr_status(drv, encr);
00824 
00825         return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len);
00826 }
00827 
00828 
00829 static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv)
00830 {
00831         int len, count, i, ret;
00832         struct ndis_pmkid_entry *entry;
00833         NDIS_802_11_PMKID *p;
00834 
00835         count = 0;
00836         entry = drv->pmkid;
00837         while (entry) {
00838                 count++;
00839                 if (count >= drv->no_of_pmkid)
00840                         break;
00841                 entry = entry->next;
00842         }
00843         len = 8 + count * sizeof(BSSID_INFO);
00844         p = malloc(len);
00845         if (p == NULL)
00846                 return -1;
00847         memset(p, 0, len);
00848         p->Length = len;
00849         p->BSSIDInfoCount = count;
00850         entry = drv->pmkid;
00851         for (i = 0; i < count; i++) {
00852                 memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN);
00853                 memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16);
00854                 entry = entry->next;
00855         }
00856         wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (char *) p, len);
00857         ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len);
00858         free(p);
00859         return ret;
00860 }
00861 
00862 
00863 static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid,
00864                                      const u8 *pmkid)
00865 {
00866         struct wpa_driver_ndis_data *drv = priv;
00867         struct ndis_pmkid_entry *entry, *prev;
00868 
00869         if (drv->no_of_pmkid == 0)
00870                 return 0;
00871 
00872         prev = NULL;
00873         entry = drv->pmkid;
00874         while (entry) {
00875                 if (memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
00876                         break;
00877                 prev = entry;
00878                 entry = entry->next;
00879         }
00880 
00881         if (entry) {
00882                 /* Replace existing entry for this BSSID and move it into the
00883                  * beginning of the list. */
00884                 memcpy(entry->pmkid, pmkid, 16);
00885                 if (prev) {
00886                         prev->next = entry->next;
00887                         entry->next = drv->pmkid;
00888                         drv->pmkid = entry;
00889                 }
00890         } else {
00891                 entry = malloc(sizeof(*entry));
00892                 if (entry) {
00893                         memcpy(entry->bssid, bssid, ETH_ALEN);
00894                         memcpy(entry->pmkid, pmkid, 16);
00895                         entry->next = drv->pmkid;
00896                         drv->pmkid = entry;
00897                 }
00898         }
00899 
00900         return wpa_driver_ndis_set_pmkid(drv);
00901 }
00902 
00903 
00904 static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid,
00905                                         const u8 *pmkid)
00906 {
00907         struct wpa_driver_ndis_data *drv = priv;
00908         struct ndis_pmkid_entry *entry, *prev;
00909 
00910         if (drv->no_of_pmkid == 0)
00911                 return 0;
00912 
00913         entry = drv->pmkid;
00914         prev = NULL;
00915         drv->pmkid = NULL;
00916         while (entry) {
00917                 if (memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
00918                     memcmp(entry->pmkid, pmkid, 16) == 0) {
00919                         if (prev)
00920                                 prev->next = entry->next;
00921                         else
00922                                 drv->pmkid = entry->next;
00923                         free(entry);
00924                         break;
00925                 }
00926                 prev = entry;
00927                 entry = entry->next;
00928         }
00929         return wpa_driver_ndis_set_pmkid(drv);
00930 }
00931 
00932 
00933 static int wpa_driver_ndis_flush_pmkid(void *priv)
00934 {
00935         struct wpa_driver_ndis_data *drv = priv;
00936         NDIS_802_11_PMKID p;
00937         struct ndis_pmkid_entry *pmkid, *prev;
00938 
00939         if (drv->no_of_pmkid == 0)
00940                 return 0;
00941 
00942         pmkid = drv->pmkid;
00943         drv->pmkid = NULL;
00944         while (pmkid) {
00945                 prev = pmkid;
00946                 pmkid = pmkid->next;
00947                 free(prev);
00948         }
00949 
00950         memset(&p, 0, sizeof(p));
00951         p.Length = 8;
00952         p.BSSIDInfoCount = 0;
00953         wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)",
00954                     (char *) &p, 8);
00955         return ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);
00956 }
00957 
00958 
00959 static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv)
00960 {
00961         char buf[512], *pos;
00962         NDIS_802_11_ASSOCIATION_INFORMATION *ai;
00963         int len, i;
00964         union wpa_event_data data;
00965         NDIS_802_11_BSSID_LIST_EX *b;
00966         size_t blen;
00967 
00968         len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf,
00969                            sizeof(buf));
00970         if (len < 0) {
00971                 wpa_printf(MSG_DEBUG, "NDIS: failed to get association "
00972                            "information");
00973                 return -1;
00974         }
00975         if (len > sizeof(buf)) {
00976                 /* Some drivers seem to be producing incorrect length for this
00977                  * data. Limit the length to the current buffer size to avoid
00978                  * crashing in hexdump. The data seems to be otherwise valid,
00979                  * so better try to use it. */
00980                 wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association "
00981                            "information length %d", len);
00982                 len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION,
00983                                    buf, sizeof(buf));
00984                 if (len < -1) {
00985                         wpa_printf(MSG_DEBUG, "NDIS: re-reading association "
00986                                    "information failed");
00987                         return -1;
00988                 }
00989                 if (len > sizeof(buf)) {
00990                         wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association"
00991                                    " information length %d (re-read)", len);
00992                         len = sizeof(buf);
00993                 }
00994         }
00995         wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", buf, len);
00996         if (len < sizeof(*ai)) {
00997                 wpa_printf(MSG_DEBUG, "NDIS: too short association "
00998                            "information");
00999                 return -1;
01000         }
01001         ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf;
01002         wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d "
01003                    "off_resp=%d len_req=%d len_resp=%d",
01004                    ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs,
01005                    (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs,
01006                    (int) ai->RequestIELength, (int) ai->ResponseIELength);
01007 
01008         if (ai->OffsetRequestIEs + ai->RequestIELength > len ||
01009             ai->OffsetResponseIEs + ai->ResponseIELength > len) {
01010                 wpa_printf(MSG_DEBUG, "NDIS: association information - "
01011                            "IE overflow");
01012                 return -1;
01013         }
01014 
01015         wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", 
01016                     buf + ai->OffsetRequestIEs, ai->RequestIELength);
01017         wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", 
01018                     buf + ai->OffsetResponseIEs, ai->ResponseIELength);
01019 
01020         memset(&data, 0, sizeof(data));
01021         data.assoc_info.req_ies = buf + ai->OffsetRequestIEs;
01022         data.assoc_info.req_ies_len = ai->RequestIELength;
01023         data.assoc_info.resp_ies = buf + ai->OffsetResponseIEs;
01024         data.assoc_info.resp_ies_len = ai->ResponseIELength;
01025 
01026         blen = 65535;
01027         b = malloc(blen);
01028         if (b == NULL)
01029                 goto skip_scan_results;
01030         memset(b, 0, blen);
01031         len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
01032         if (len < 0) {
01033                 wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
01034                 free(b);
01035                 b = NULL;
01036                 goto skip_scan_results;
01037         }
01038         wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo",
01039                    (unsigned int) b->NumberOfItems);
01040 
01041         pos = (char *) &b->Bssid[0];
01042         for (i = 0; i < b->NumberOfItems; i++) {
01043                 NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
01044                 if (memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 &&
01045                     bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) {
01046                         data.assoc_info.beacon_ies =
01047                                 ((u8 *) bss->IEs) +
01048                                 sizeof(NDIS_802_11_FIXED_IEs);
01049                         data.assoc_info.beacon_ies_len =
01050                                 bss->IELength - sizeof(NDIS_802_11_FIXED_IEs);
01051                         wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs",
01052                                     data.assoc_info.beacon_ies,
01053                                     data.assoc_info.beacon_ies_len);
01054                         break;
01055                 }
01056                 pos += bss->Length;
01057                 if (pos > (char *) b + blen)
01058                         break;
01059         }
01060 
01061 skip_scan_results:
01062         wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
01063 
01064         free(b);
01065 
01066         return 0;
01067 }
01068 
01069 
01070 static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx)
01071 {
01072         struct wpa_driver_ndis_data *drv = eloop_ctx;
01073         u8 bssid[ETH_ALEN];
01074 
01075         if (drv->wired)
01076                 return;
01077 
01078         if (wpa_driver_ndis_get_bssid(drv, bssid)) {
01079                 /* Disconnected */
01080                 if (memcmp(drv->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)
01081                     != 0) {
01082                         memset(drv->bssid, 0, ETH_ALEN);
01083                         wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
01084                 }
01085         } else {
01086                 /* Connected */
01087                 if (memcmp(drv->bssid, bssid, ETH_ALEN) != 0) {
01088                         memcpy(drv->bssid, bssid, ETH_ALEN);
01089                         wpa_driver_ndis_get_associnfo(drv);
01090                         wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
01091                 }
01092         }
01093         eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);
01094 }
01095 
01096 
01097 static void wpa_driver_ndis_poll(void *priv)
01098 {
01099         struct wpa_driver_ndis_data *drv = priv;
01100         eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
01101         wpa_driver_ndis_poll_timeout(drv, NULL);
01102 }
01103 
01104 
01105 /* Called when driver generates Media Connect Event by calling
01106  * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */
01107 void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv)
01108 {
01109         wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event");
01110         if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) {
01111                 wpa_driver_ndis_get_associnfo(drv);
01112                 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
01113         }
01114 }
01115 
01116 
01117 /* Called when driver generates Media Disconnect Event by calling
01118  * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */
01119 void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv)
01120 {
01121         wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event");
01122         memset(drv->bssid, 0, ETH_ALEN);
01123         wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
01124 }
01125 
01126 
01127 static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv,
01128                                        const u8 *data, size_t data_len)
01129 {
01130         NDIS_802_11_AUTHENTICATION_REQUEST *req;
01131         int pairwise = 0, group = 0;
01132         union wpa_event_data event;
01133 
01134         if (data_len < sizeof(*req)) {
01135                 wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request "
01136                            "Event (len=%d)", data_len);
01137                 return;
01138         }
01139         req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data;
01140 
01141         wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: "
01142                    "Bssid " MACSTR " Flags 0x%x",
01143                    MAC2STR(req->Bssid), (int) req->Flags);
01144 
01145         if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) ==
01146             NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR)
01147                 pairwise = 1;
01148         else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) ==
01149             NDIS_802_11_AUTH_REQUEST_GROUP_ERROR)
01150                 group = 1;
01151 
01152         if (pairwise || group) {
01153                 memset(&event, 0, sizeof(event));
01154                 event.michael_mic_failure.unicast = pairwise;
01155                 wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE,
01156                                      &event);
01157         }
01158 }
01159 
01160 
01161 static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv,
01162                                         const u8 *data, size_t data_len)
01163 {
01164         NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid;
01165         int i;
01166         union wpa_event_data event;
01167 
01168         if (data_len < 8) {
01169                 wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List "
01170                            "Event (len=%d)", data_len);
01171                 return;
01172         }
01173         pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data;
01174         wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d "
01175                    "NumCandidates %d",
01176                    (int) pmkid->Version, (int) pmkid->NumCandidates);
01177 
01178         if (pmkid->Version != 1) {
01179                 wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List "
01180                            "Version %d", (int) pmkid->Version);
01181                 return;
01182         }
01183 
01184         if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) {
01185                 wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow");
01186                 return;
01187         }
01188 
01189         memset(&event, 0, sizeof(event));
01190         for (i = 0; i < pmkid->NumCandidates; i++) {
01191                 PMKID_CANDIDATE *p = &pmkid->CandidateList[i];
01192                 wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x",
01193                            i, MAC2STR(p->BSSID), (int) p->Flags);
01194                 memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN);
01195                 event.pmkid_candidate.index = i;
01196                 event.pmkid_candidate.preauth =
01197                         p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
01198                 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE,
01199                                      &event);
01200         }
01201 }
01202 
01203 
01204 /* Called when driver calls NdisMIndicateStatus() with
01205  * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */
01206 void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv,
01207                                           const u8 *data, size_t data_len)
01208 {
01209         NDIS_802_11_STATUS_INDICATION *status;
01210 
01211         if (data == NULL || data_len < sizeof(*status))
01212                 return;
01213 
01214         wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication",
01215                     data, data_len);
01216 
01217         status = (NDIS_802_11_STATUS_INDICATION *) data;
01218         data += sizeof(status);
01219         data_len -= sizeof(status);
01220 
01221         switch (status->StatusType) {
01222         case Ndis802_11StatusType_Authentication:
01223                 wpa_driver_ndis_event_auth(drv, data, data_len);
01224                 break;
01225         case Ndis802_11StatusType_PMKID_CandidateList:
01226                 wpa_driver_ndis_event_pmkid(drv, data, data_len);
01227                 break;
01228         default:
01229                 wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d",
01230                            (int) status->StatusType);
01231                 break;
01232         }
01233 }
01234 
01235 
01236 static void
01237 wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv)
01238 {
01239         wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability");
01240 
01241         if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 &&
01242             ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) {
01243                 wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported");
01244                 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
01245         }
01246 
01247         if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 &&
01248             ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) {
01249                 wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management "
01250                            "supported");
01251                 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
01252         }
01253 
01254         if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 &&
01255             ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) {
01256                 wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported");
01257                 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
01258         }
01259 
01260         if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 &&
01261             ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) {
01262                 wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported");
01263                 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
01264         }
01265 
01266         if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 &&
01267             ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) {
01268                 wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported");
01269                 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
01270                         WPA_DRIVER_CAPA_ENC_WEP104;
01271         }
01272 
01273         if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 &&
01274             ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) {
01275                 drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
01276         }
01277 
01278         if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 &&
01279             ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) {
01280                 drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
01281         }
01282 
01283         ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled);
01284 
01285         /* Could also verify OID_802_11_ADD_KEY error reporting and
01286          * support for OID_802_11_ASSOCIATION_INFORMATION. */
01287 
01288         if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA &&
01289             drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP |
01290                              WPA_DRIVER_CAPA_ENC_CCMP)) {
01291                 wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA");
01292                 drv->has_capability = 1;
01293         } else {
01294                 wpa_printf(MSG_DEBUG, "NDIS: no WPA support found");
01295         }
01296 
01297         wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
01298                    "enc 0x%x auth 0x%x",
01299                    drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
01300 }
01301 
01302 
01303 static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv)
01304 {
01305         char buf[512];
01306         int len, i;
01307         NDIS_802_11_CAPABILITY *c;
01308 
01309         drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE |
01310                 WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC;
01311 
01312         len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf));
01313         if (len < 0) {
01314                 wpa_driver_ndis_get_wpa_capability(drv);
01315                 return;
01316         }
01317 
01318         wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", buf, len);
01319         c = (NDIS_802_11_CAPABILITY *) buf;
01320         if (len < sizeof(*c) || c->Version != 2) {
01321                 wpa_printf(MSG_DEBUG, "NDIS: unsupported "
01322                            "OID_802_11_CAPABILITY data");
01323                 return;
01324         }
01325         wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - "
01326                    "NoOfPMKIDs %d NoOfAuthEncrPairs %d",
01327                    (int) c->NoOfPMKIDs, (int) c->NoOfAuthEncryptPairSupported);
01328         drv->has_capability = 1;
01329         drv->no_of_pmkid = c->NoOfPMKIDs;
01330         for (i = 0; i < c->NoOfAuthEncryptPairSupported; i++) {
01331                 NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae;
01332                 ae = &c->AuthenticationEncryptionSupported[i];
01333                 if ((char *) (ae + 1) > buf + len) {
01334                         wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list "
01335                                    "overflow");
01336                         break;
01337                 }
01338                 wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d",
01339                            i, (int) ae->AuthModeSupported,
01340                            (int) ae->EncryptStatusSupported);
01341                 switch (ae->AuthModeSupported) {
01342                 case Ndis802_11AuthModeOpen:
01343                         drv->capa.auth |= WPA_DRIVER_AUTH_OPEN;
01344                         break;
01345                 case Ndis802_11AuthModeShared:
01346                         drv->capa.auth |= WPA_DRIVER_AUTH_SHARED;
01347                         break;
01348                 case Ndis802_11AuthModeWPA:
01349                         drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA;
01350                         break;
01351                 case Ndis802_11AuthModeWPAPSK:
01352                         drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
01353                         break;
01354                 case Ndis802_11AuthModeWPA2:
01355                         drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2;
01356                         break;
01357                 case Ndis802_11AuthModeWPA2PSK:
01358                         drv->capa.key_mgmt |=
01359                                 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
01360                         break;
01361                 case Ndis802_11AuthModeWPANone:
01362                         drv->capa.key_mgmt |=
01363                                 WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE;
01364                         break;
01365                 default:
01366                         break;
01367                 }
01368                 switch (ae->EncryptStatusSupported) {
01369                 case Ndis802_11Encryption1Enabled:
01370                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40;
01371                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104;
01372                         break;
01373                 case Ndis802_11Encryption2Enabled:
01374                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
01375                         break;
01376                 case Ndis802_11Encryption3Enabled:
01377                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
01378                         break;
01379                 default:
01380                         break;
01381                 }
01382         }
01383 
01384         wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x "
01385                    "enc 0x%x auth 0x%x",
01386                    drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth);
01387 }
01388 
01389 
01390 static int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa)
01391 {
01392         struct wpa_driver_ndis_data *drv = priv;
01393         if (!drv->has_capability)
01394                 return -1;
01395         memcpy(capa, &drv->capa, sizeof(*capa));
01396         return 0;
01397 }
01398 
01399 
01400 static const char * wpa_driver_ndis_get_ifname(void *priv)
01401 {
01402         struct wpa_driver_ndis_data *drv = priv;
01403         return drv->ifname;
01404 }
01405 
01406 
01407 static const u8 * wpa_driver_ndis_get_mac_addr(void *priv)
01408 {
01409         struct wpa_driver_ndis_data *drv = priv;
01410         return drv->own_addr;
01411 }
01412 
01413 
01414 static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv)
01415 {
01416         PTSTR names, pos, pos2;
01417         ULONG len;
01418         BOOLEAN res;
01419         const int MAX_ADAPTERS = 32;
01420         char *name[MAX_ADAPTERS];
01421         char *desc[MAX_ADAPTERS];
01422         int num_name, num_desc, i, found_name, found_desc;
01423         size_t dlen;
01424 
01425         wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s",
01426                    PacketGetVersion());
01427 
01428         len = 8192;
01429         names = malloc(len);
01430         if (names == NULL)
01431                 return -1;
01432         memset(names, 0, len);
01433 
01434         res = PacketGetAdapterNames(names, &len);
01435         if (!res && len > 8192) {
01436                 free(names);
01437                 names = malloc(len);
01438                 if (names == NULL)
01439                         return -1;
01440                 memset(names, 0, len);
01441                 res = PacketGetAdapterNames(names, &len);
01442         }
01443 
01444         if (!res) {
01445                 wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list "
01446                            "(PacketGetAdapterNames)");
01447                 free(names);
01448                 return -1;
01449         }
01450 
01451         /* wpa_hexdump_ascii(MSG_DEBUG, "NDIS: AdapterNames", names, len); */
01452 
01453         if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') {
01454                 wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in "
01455                            "UNICODE");
01456                 /* Convert to ASCII */
01457                 pos2 = pos = names;
01458                 while (pos2 < names + len) {
01459                         if (pos2[0] == '\0' && pos2[1] == '\0' &&
01460                             pos2[2] == '\0' && pos2[3] == '\0') {
01461                                 pos2 += 4;
01462                                 break;
01463                         }
01464                         *pos++ = pos2[0];
01465                         pos2 += 2;
01466                 }
01467                 memcpy(pos + 2, names, pos - names);
01468                 pos += 2;
01469         } else
01470                 pos = names;
01471 
01472         num_name = 0;
01473         while (pos < names + len) {
01474                 name[num_name] = pos;
01475                 while (*pos && pos < names + len)
01476                         pos++;
01477                 if (pos + 1 >= names + len) {
01478                         free(names);
01479                         return -1;
01480                 }
01481                 pos++;
01482                 num_name++;
01483                 if (num_name >= MAX_ADAPTERS) {
01484                         wpa_printf(MSG_DEBUG, "NDIS: Too many adapters");
01485                         free(names);
01486                         return -1;
01487                 }
01488                 if (*pos == '\0') {
01489                         wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found",
01490                                    num_name);
01491                         pos++;
01492                         break;
01493                 }
01494         }
01495 
01496         num_desc = 0;
01497         while (pos < names + len) {
01498                 desc[num_desc] = pos;
01499                 while (*pos && pos < names + len)
01500                         pos++;
01501                 if (pos + 1 >= names + len) {
01502                         free(names);
01503                         return -1;
01504                 }
01505                 pos++;
01506                 num_desc++;
01507                 if (num_desc >= MAX_ADAPTERS) {
01508                         wpa_printf(MSG_DEBUG, "NDIS: Too many adapter "
01509                                    "descriptions");
01510                         free(names);
01511                         return -1;
01512                 }
01513                 if (*pos == '\0') {
01514                         wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions "
01515                                    "found", num_name);
01516                         pos++;
01517                         break;
01518                 }
01519         }
01520 
01521         /*
01522          * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter
01523          * descriptions. Fill in dummy descriptors to work around this.
01524          */
01525         while (num_desc < num_name)
01526                 desc[num_desc++] = "dummy description";
01527 
01528         if (num_name != num_desc) {
01529                 wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
01530                            "description counts (%d != %d)",
01531                            num_name, num_desc);
01532                 free(names);
01533                 return -1;
01534         }
01535 
01536         found_name = found_desc = -1;
01537         for (i = 0; i < num_name; i++) {
01538                 wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s",
01539                            i, name[i], desc[i]);
01540                 if (found_name == -1 && strcmp(name[i], drv->ifname) == 0) {
01541                         found_name = i;
01542                 }
01543                 if (found_desc == -1 &&
01544                     strncmp(desc[i], drv->ifname, strlen(drv->ifname)) == 0) {
01545                         found_desc = i;
01546                 }
01547         }
01548 
01549         if (found_name < 0 && found_desc >= 0) {
01550                 wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on "
01551                            "description '%s'",
01552                            name[found_desc], desc[found_desc]);
01553                 found_name = found_desc;
01554                 strncpy(drv->ifname, name[found_desc], sizeof(drv->ifname));
01555         }
01556 
01557         if (found_name < 0) {
01558                 wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'",
01559                            drv->ifname);
01560                 free(names);
01561                 return -1;
01562         }
01563 
01564         i = found_name;
01565         pos = strchr(desc[i], '(');
01566         if (pos) {
01567                 dlen = pos - desc[i];
01568                 pos--;
01569                 if (pos > desc[i] && *pos == ' ')
01570                         dlen--;
01571         } else {
01572                 dlen = strlen(desc[i]);
01573         }
01574         drv->adapter_desc = malloc(dlen + 1);
01575         if (drv->adapter_desc) {
01576                 memcpy(drv->adapter_desc, desc[i], dlen);
01577                 drv->adapter_desc[dlen] = '\0';
01578         }
01579 
01580         free(names);
01581 
01582         if (drv->adapter_desc == NULL)
01583                 return -1;
01584 
01585         wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'",
01586                    drv->adapter_desc);
01587 
01588         return 0;
01589 }
01590 
01591 
01592 static void * wpa_driver_ndis_init(void *ctx, const char *ifname)
01593 {
01594         struct wpa_driver_ndis_data *drv;
01595         u32 mode;
01596 
01597         drv = malloc(sizeof(*drv));
01598         if (drv == NULL)
01599                 return NULL;
01600         memset(drv, 0, sizeof(*drv));
01601         drv->ctx = ctx;
01602         strncpy(drv->ifname, ifname, sizeof(drv->ifname));
01603         drv->event_sock = -1;
01604 
01605         if (wpa_driver_ndis_get_names(drv) < 0) {
01606                 free(drv);
01607                 return NULL;
01608         }
01609 
01610         drv->adapter = PacketOpenAdapter(drv->ifname);
01611         if (drv->adapter == NULL) {
01612                 wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for "
01613                            "'%s'", drv->ifname);
01614                 free(drv);
01615                 return NULL;
01616         }
01617 
01618         if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS,
01619                          drv->own_addr, ETH_ALEN) < 0) {
01620                 wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS "
01621                            "failed");
01622                 PacketCloseAdapter(drv->adapter);
01623                 free(drv);
01624                 return NULL;
01625         }
01626         wpa_driver_ndis_get_capability(drv);
01627 
01628         /* Make sure that the driver does not have any obsolete PMKID entries.
01629          */
01630         wpa_driver_ndis_flush_pmkid(drv);
01631 
01632         eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL);
01633 
01634         wpa_driver_register_event_cb(drv);
01635 
01636         /* Set mode here in case card was configured for ad-hoc mode
01637          * previously. */
01638         mode = Ndis802_11Infrastructure;
01639         if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
01640                          (char *) &mode, sizeof(mode)) < 0) {
01641                 wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
01642                            "OID_802_11_INFRASTRUCTURE_MODE (%d)",
01643                            (int) mode);
01644                 /* Try to continue anyway */
01645 
01646                 if (!drv->has_capability && drv->capa.enc == 0) {
01647                         wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide "
01648                                    "any wireless capabilities - assume it is "
01649                                    "a wired interface");
01650                         drv->wired = 1;
01651                 }
01652         }
01653 
01654         return drv;
01655 }
01656 
01657 
01658 static void wpa_driver_ndis_deinit(void *priv)
01659 {
01660         struct wpa_driver_ndis_data *drv = priv;
01661         eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL);
01662         wpa_driver_ndis_flush_pmkid(drv);
01663         wpa_driver_ndis_disconnect(drv);
01664         if (wpa_driver_ndis_radio_off(drv) < 0) {
01665                 wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn "
01666                            "radio off");
01667         }
01668         if (drv->event_sock >= 0) {
01669                 eloop_unregister_read_sock(drv->event_sock);
01670                 close(drv->event_sock);
01671         }
01672         if (drv->adapter)
01673                 PacketCloseAdapter(drv->adapter);
01674 
01675         free(drv->adapter_desc);
01676         free(drv);
01677 }
01678 
01679 
01680 const struct wpa_driver_ops wpa_driver_ndis_ops = {
01681         .name = "ndis",
01682         .desc = "Windows NDIS driver",
01683         .init = wpa_driver_ndis_init,
01684         .deinit = wpa_driver_ndis_deinit,
01685         .set_wpa = wpa_driver_ndis_set_wpa,
01686         .scan = wpa_driver_ndis_scan,
01687         .get_scan_results = wpa_driver_ndis_get_scan_results,
01688         .get_bssid = wpa_driver_ndis_get_bssid,
01689         .get_ssid = wpa_driver_ndis_get_ssid,
01690         .set_key = wpa_driver_ndis_set_key,
01691         .associate = wpa_driver_ndis_associate,
01692         .deauthenticate = wpa_driver_ndis_deauthenticate,
01693         .disassociate = wpa_driver_ndis_disassociate,
01694         .poll = wpa_driver_ndis_poll,
01695         .add_pmkid = wpa_driver_ndis_add_pmkid,
01696         .remove_pmkid = wpa_driver_ndis_remove_pmkid,
01697         .flush_pmkid = wpa_driver_ndis_flush_pmkid,
01698         .get_capa = wpa_driver_ndis_get_capa,
01699         .get_ifname = wpa_driver_ndis_get_ifname,
01700         .get_mac_addr = wpa_driver_ndis_get_mac_addr,
01701 };
01702 

Generated on Sat May 6 21:13:33 2006 for wpa_supplicant by  doxygen 1.4.2