driver_ipw.c

Go to the documentation of this file.
00001 
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <unistd.h>
00021 #include <string.h>
00022 #include <sys/ioctl.h>
00023 #include <errno.h>
00024 
00025 #include "wireless_copy.h"
00026 #include "common.h"
00027 #include "driver.h"
00028 #include "l2_packet.h"
00029 #include "driver_wext.h"
00030 #include "wpa_supplicant.h"
00031 
00032 struct wpa_driver_ipw_data {
00033         void *wext; /* private data for driver_wext */
00034         void *ctx;
00035         char ifname[IFNAMSIZ + 1];
00036         int sock;
00037 };
00038 
00039 /* following definitions must be kept in sync with ipw2100.c and ipw2200.c */
00040 
00041 #define IPW_IOCTL_WPA_SUPPLICANT                SIOCIWFIRSTPRIV+30
00042 
00043 #define IPW_CMD_SET_WPA_PARAM                   1
00044 #define IPW_CMD_SET_WPA_IE                      2
00045 #define IPW_CMD_SET_ENCRYPTION                  3
00046 #define IPW_CMD_MLME                            4
00047 
00048 #define IPW_PARAM_WPA_ENABLED                   1
00049 #define IPW_PARAM_TKIP_COUNTERMEASURES          2
00050 #define IPW_PARAM_DROP_UNENCRYPTED              3
00051 #define IPW_PARAM_PRIVACY_INVOKED               4
00052 #define IPW_PARAM_AUTH_ALGS                     5
00053 #define IPW_PARAM_IEEE_802_1X                   6
00054 
00055 #define IPW_MLME_STA_DEAUTH                     1
00056 #define IPW_MLME_STA_DISASSOC                   2
00057 
00058 #define IPW_CRYPT_ERR_UNKNOWN_ALG               2
00059 #define IPW_CRYPT_ERR_UNKNOWN_ADDR              3
00060 #define IPW_CRYPT_ERR_CRYPT_INIT_FAILED         4
00061 #define IPW_CRYPT_ERR_KEY_SET_FAILED            5
00062 #define IPW_CRYPT_ERR_TX_KEY_SET_FAILED         6
00063 #define IPW_CRYPT_ERR_CARD_CONF_FAILED          7
00064 
00065 #define IPW_CRYPT_ALG_NAME_LEN                  16
00066 
00067 struct ipw_param {
00068         u32 cmd;
00069         u8 sta_addr[ETH_ALEN];
00070         union {
00071                 struct {
00072                         u8 name;
00073                         u32 value;
00074                 } wpa_param;
00075                 struct {
00076                         u32 len;
00077                         u8 reserved[32];
00078                         u8 data[0];
00079                 } wpa_ie;
00080                 struct{
00081                         u32 command;
00082                         u32 reason_code;
00083                 } mlme;
00084                 struct {
00085                         u8 alg[IPW_CRYPT_ALG_NAME_LEN];
00086                         u8 set_tx;
00087                         u32 err;
00088                         u8 idx;
00089                         u8 seq[8];
00090                         u16 key_len;
00091                         u8 key[0];
00092                 } crypt;
00093 
00094         } u;
00095 };
00096 
00097 /* end of ipw2100.c and ipw2200.c code */
00098 
00099 static int ipw_ioctl(struct wpa_driver_ipw_data *drv,
00100                      struct ipw_param *param, int len, int show_err)
00101 {
00102         struct iwreq iwr;
00103 
00104         memset(&iwr, 0, sizeof(iwr));
00105         strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
00106         iwr.u.data.pointer = (caddr_t) param;
00107         iwr.u.data.length = len;
00108 
00109         if (ioctl(drv->sock, IPW_IOCTL_WPA_SUPPLICANT, &iwr) < 0) {
00110                 int ret = errno;
00111                 if (show_err) 
00112                         perror("ioctl[IPW_IOCTL_WPA_SUPPLICANT]");
00113                 return ret;
00114         }
00115 
00116         return 0;
00117 }
00118 
00119 
00120 static void ipw_show_set_key_error(struct ipw_param *param)
00121 {
00122         switch (param->u.crypt.err) {
00123         case IPW_CRYPT_ERR_UNKNOWN_ALG:
00124                 wpa_printf(MSG_INFO, "Unknown algorithm '%s'.",
00125                            param->u.crypt.alg);
00126                 wpa_printf(MSG_INFO, "You may need to load kernel module to "
00127                            "register that algorithm.");
00128                 wpa_printf(MSG_INFO, "E.g., 'modprobe ieee80211_crypt_wep' for"
00129                            " WEP.");
00130                 break;
00131         case IPW_CRYPT_ERR_UNKNOWN_ADDR:
00132                 wpa_printf(MSG_INFO, "Unknown address " MACSTR ".",
00133                            MAC2STR(param->sta_addr));
00134                 break;
00135         case IPW_CRYPT_ERR_CRYPT_INIT_FAILED:
00136                 wpa_printf(MSG_INFO, "Crypt algorithm initialization failed.");
00137                 break;
00138         case IPW_CRYPT_ERR_KEY_SET_FAILED:
00139                 wpa_printf(MSG_INFO, "Key setting failed.");
00140                 break;
00141         case IPW_CRYPT_ERR_TX_KEY_SET_FAILED:
00142                 wpa_printf(MSG_INFO, "TX key index setting failed.");
00143                 break;
00144         case IPW_CRYPT_ERR_CARD_CONF_FAILED:
00145                 wpa_printf(MSG_INFO, "Card configuration failed.");
00146                 break;
00147         }
00148 }
00149 
00150 
00151 static int ipw_set_wpa_ie(struct wpa_driver_ipw_data *drv,
00152                           const u8 *wpa_ie, size_t wpa_ie_len)
00153 {
00154         struct ipw_param *param;
00155         int ret;
00156         size_t blen = sizeof(*param) + wpa_ie_len;
00157 
00158         param = (struct ipw_param *) malloc(blen);
00159         if (param == NULL)
00160                 return -1;
00161 
00162         memset(param, 0, blen);
00163         param->cmd = IPW_CMD_SET_WPA_IE;
00164         param->u.wpa_ie.len = wpa_ie_len;
00165         memcpy(param->u.wpa_ie.data, wpa_ie, wpa_ie_len);
00166         
00167         ret = ipw_ioctl(drv, param, blen, 1);
00168 
00169         free(param);
00170         return ret;
00171 }
00172 
00173 
00174 static int ipw_set_wpa_param(struct wpa_driver_ipw_data *drv, u8 name,
00175                              u32 value)
00176 {
00177         struct ipw_param param;
00178 
00179         memset(&param, 0, sizeof(param));
00180         param.cmd = IPW_CMD_SET_WPA_PARAM;
00181         param.u.wpa_param.name = name;
00182         param.u.wpa_param.value = value;
00183 
00184         return ipw_ioctl(drv, &param, sizeof(param), 1);
00185 }
00186 
00187 
00188 static int ipw_mlme(struct wpa_driver_ipw_data *drv, const u8 *addr,
00189                     int cmd, int reason)
00190 {
00191         struct ipw_param param;
00192 
00193         memset(&param, 0, sizeof(param));
00194         memcpy(param.sta_addr, addr, ETH_ALEN); 
00195         param.cmd = IPW_CMD_MLME;
00196         param.u.mlme.command = cmd;
00197         param.u.mlme.reason_code = reason;
00198 
00199         return ipw_ioctl(drv, &param, sizeof(param), 1);
00200 }
00201 
00202 
00203 static int wpa_driver_ipw_set_wpa(void *priv, int enabled)
00204 {
00205         struct wpa_driver_ipw_data *drv = priv;
00206         int ret = 0;
00207 
00208         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
00209 
00210         if (!enabled && ipw_set_wpa_ie(drv, NULL, 0) < 0)
00211                 ret = -1;
00212 
00213         if (ipw_set_wpa_param(drv, IPW_PARAM_WPA_ENABLED, enabled) < 0)
00214                 ret = -1;
00215 
00216         return ret;
00217 }
00218 
00219 
00220 static int wpa_driver_ipw_set_key(void *priv, wpa_alg alg,
00221                                       const u8 *addr, int key_idx, int set_tx,
00222                                       const u8 *seq, size_t seq_len,
00223                                       const u8 *key, size_t key_len)
00224 {
00225         struct wpa_driver_ipw_data *drv = priv;
00226         struct ipw_param *param;
00227         u8 *buf;
00228         size_t blen;
00229         int ret = 0;
00230         char *alg_name;
00231 
00232         switch (alg) {
00233         case WPA_ALG_NONE:
00234                 alg_name = "none";
00235                 break;
00236         case WPA_ALG_WEP:
00237                 alg_name = "WEP";
00238                 break;
00239         case WPA_ALG_TKIP:
00240                 alg_name = "TKIP";
00241                 break;
00242         case WPA_ALG_CCMP:
00243                 alg_name = "CCMP";
00244                 break;
00245         default:
00246                 return -1;
00247         }
00248 
00249         wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
00250                    "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
00251                    (unsigned long) seq_len, (unsigned long) key_len);
00252 
00253         if (seq_len > 8)
00254                 return -2;
00255 
00256         blen = sizeof(*param) + key_len;
00257         buf = malloc(blen);
00258         if (buf == NULL)
00259                 return -1;
00260         memset(buf, 0, blen);
00261 
00262         param = (struct ipw_param *) buf;
00263         param->cmd = IPW_CMD_SET_ENCRYPTION;
00264         memset(param->sta_addr, 0xff, ETH_ALEN);
00265         strncpy((char *) param->u.crypt.alg, alg_name, IPW_CRYPT_ALG_NAME_LEN);
00266         param->u.crypt.set_tx = set_tx ? 1 : 0;
00267         param->u.crypt.idx = key_idx;
00268         memcpy(param->u.crypt.seq, seq, seq_len);
00269         param->u.crypt.key_len = key_len;
00270         memcpy((u8 *) (param + 1), key, key_len);
00271 
00272         if (ipw_ioctl(drv, param, blen, 1)) {
00273                 wpa_printf(MSG_WARNING, "Failed to set encryption.");
00274                 ipw_show_set_key_error(param);
00275                 ret = -1;
00276         }
00277         free(buf);
00278 
00279         return ret;
00280 }
00281 
00282 
00283 static int wpa_driver_ipw_set_countermeasures(void *priv, int enabled)
00284 {
00285         struct wpa_driver_ipw_data *drv = priv;
00286         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
00287         return ipw_set_wpa_param(drv, IPW_PARAM_TKIP_COUNTERMEASURES,
00288                                      enabled);
00289 
00290 }
00291 
00292 
00293 static int wpa_driver_ipw_set_drop_unencrypted(void *priv, int enabled)
00294 {
00295         struct wpa_driver_ipw_data *drv = priv;
00296         wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
00297         return ipw_set_wpa_param(drv, IPW_PARAM_DROP_UNENCRYPTED,
00298                                      enabled);
00299 }
00300 
00301 
00302 static int wpa_driver_ipw_deauthenticate(void *priv, const u8 *addr,
00303                                          int reason_code)
00304 {
00305         struct wpa_driver_ipw_data *drv = priv;
00306         return ipw_mlme(drv, addr, IPW_MLME_STA_DEAUTH, reason_code);
00307 }
00308 
00309 
00310 static int wpa_driver_ipw_disassociate(void *priv, const u8 *addr,
00311                                        int reason_code)
00312 {
00313         struct wpa_driver_ipw_data *drv = priv;
00314         return ipw_mlme(drv, addr, IPW_MLME_STA_DISASSOC, reason_code);
00315 }
00316 
00317 
00318 static int
00319 wpa_driver_ipw_associate(void *priv, struct wpa_driver_associate_params *params)
00320 {
00321         struct wpa_driver_ipw_data *drv = priv;
00322         int ret = 0;
00323         int unencrypted_eapol;
00324 
00325         if (ipw_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
00326                 ret = -1;
00327         if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
00328                                      params->ssid_len) < 0)
00329                 ret = -1;
00330         if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0)
00331                 ret = -1;
00332 
00333         if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
00334             params->key_mgmt_suite == KEY_MGMT_PSK)
00335                 unencrypted_eapol = 0;
00336         else
00337                 unencrypted_eapol = 1;
00338         
00339         if (ipw_set_wpa_param(drv, IPW_PARAM_IEEE_802_1X,
00340                               unencrypted_eapol) < 0) {
00341                 wpa_printf(MSG_DEBUG, "ipw: Failed to configure "
00342                            "ieee_802_1x param");
00343         }
00344 
00345         return ret;
00346 }
00347 
00348 
00349 static int wpa_driver_ipw_set_auth_alg(void *priv, int auth_alg)
00350 {
00351         struct wpa_driver_ipw_data *drv = priv;
00352         int algs = 0;
00353 
00354         if (auth_alg & AUTH_ALG_OPEN_SYSTEM)
00355                 algs |= 1;
00356         if (auth_alg & AUTH_ALG_SHARED_KEY)
00357                 algs |= 2;
00358         if (auth_alg & AUTH_ALG_LEAP)
00359                 algs |= 4;
00360         if (algs == 0)
00361                 algs = 1; /* at least one algorithm should be set */
00362 
00363         wpa_printf(MSG_DEBUG, "%s: auth_alg=0x%x", __FUNCTION__, algs);
00364         return ipw_set_wpa_param(drv, IPW_PARAM_AUTH_ALGS, algs);
00365 }
00366 
00367 
00368 static int wpa_driver_ipw_get_bssid(void *priv, u8 *bssid)
00369 {
00370         struct wpa_driver_ipw_data *drv = priv;
00371         return wpa_driver_wext_get_bssid(drv->wext, bssid);
00372 }
00373 
00374 
00375 static int wpa_driver_ipw_get_ssid(void *priv, u8 *ssid)
00376 {
00377         struct wpa_driver_ipw_data *drv = priv;
00378         return wpa_driver_wext_get_ssid(drv->wext, ssid);
00379 }
00380 
00381 
00382 static int wpa_driver_ipw_scan(void *priv, const u8 *ssid, size_t ssid_len)
00383 {
00384         struct wpa_driver_ipw_data *drv = priv;
00385         return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
00386 }
00387 
00388 
00389 static int wpa_driver_ipw_get_scan_results(void *priv,
00390                                             struct wpa_scan_result *results,
00391                                             size_t max_size)
00392 {
00393         struct wpa_driver_ipw_data *drv = priv;
00394         return wpa_driver_wext_get_scan_results(drv->wext, results, max_size);
00395 }
00396 
00397 
00398 static void * wpa_driver_ipw_init(void *ctx, const char *ifname)
00399 {
00400         struct wpa_driver_ipw_data *drv;
00401 
00402         wpa_printf(MSG_DEBUG, "%s is called", __FUNCTION__);
00403         drv = malloc(sizeof(*drv));
00404         if (drv == NULL)
00405                 return NULL;
00406         memset(drv, 0, sizeof(*drv));
00407         drv->wext = wpa_driver_wext_init(ctx, ifname);
00408         if (drv->wext == NULL) {
00409                 free(drv);
00410                 return NULL;
00411         }
00412 
00413         drv->ctx = ctx;
00414         strncpy(drv->ifname, ifname, sizeof(drv->ifname));
00415         drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
00416         if (drv->sock < 0) {
00417                 wpa_driver_wext_deinit(drv->wext);
00418                 free(drv);
00419                 return NULL;
00420         }
00421 
00422         return drv;
00423 }
00424 
00425 
00426 static void wpa_driver_ipw_deinit(void *priv)
00427 {
00428         struct wpa_driver_ipw_data *drv = priv;
00429         wpa_driver_wext_deinit(drv->wext);
00430         close(drv->sock);
00431         free(drv);
00432 }
00433 
00434 
00435 const struct wpa_driver_ops wpa_driver_ipw_ops = {
00436         .name = "ipw",
00437         .desc = "Intel ipw2100/2200 driver",
00438         .get_bssid = wpa_driver_ipw_get_bssid,
00439         .get_ssid = wpa_driver_ipw_get_ssid,
00440         .set_wpa = wpa_driver_ipw_set_wpa,
00441         .set_key = wpa_driver_ipw_set_key,
00442         .set_countermeasures = wpa_driver_ipw_set_countermeasures,
00443         .set_drop_unencrypted = wpa_driver_ipw_set_drop_unencrypted,
00444         .scan = wpa_driver_ipw_scan,
00445         .get_scan_results = wpa_driver_ipw_get_scan_results,
00446         .deauthenticate = wpa_driver_ipw_deauthenticate,
00447         .disassociate = wpa_driver_ipw_disassociate,
00448         .associate = wpa_driver_ipw_associate,
00449         .set_auth_alg = wpa_driver_ipw_set_auth_alg,
00450         .init = wpa_driver_ipw_init,
00451         .deinit = wpa_driver_ipw_deinit,
00452 };
00453 

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