2 * WPA Supplicant - driver interaction with Linux ipw2100/2200 drivers
3 * Copyright (c) 2005 Zhu Yi <yi.zhu@intel.com>
4 * Copyright (c) 2004 Lubomir Gelo <lgelo@cnc.sk>
5 * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Alternatively, this software may be distributed under the terms of BSD
14 * See README and COPYING for more details.
16 * Please note that ipw2100/2200 drivers change to use generic Linux wireless
17 * extensions if the kernel includes support for WE-18 or newer (Linux 2.6.13
18 * or newer). driver_wext.c should be used in those cases.
22 #include <sys/ioctl.h>
24 #include "wireless_copy.h"
27 #include "driver_wext.h"
29 struct wpa_driver_ipw_data
{
30 void *wext
; /* private data for driver_wext */
32 char ifname
[IFNAMSIZ
+ 1];
36 /* following definitions must be kept in sync with ipw2100.c and ipw2200.c */
38 #define IPW_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30
40 #define IPW_CMD_SET_WPA_PARAM 1
41 #define IPW_CMD_SET_WPA_IE 2
42 #define IPW_CMD_SET_ENCRYPTION 3
43 #define IPW_CMD_MLME 4
45 #define IPW_PARAM_WPA_ENABLED 1
46 #define IPW_PARAM_TKIP_COUNTERMEASURES 2
47 #define IPW_PARAM_DROP_UNENCRYPTED 3
48 #define IPW_PARAM_PRIVACY_INVOKED 4
49 #define IPW_PARAM_AUTH_ALGS 5
50 #define IPW_PARAM_IEEE_802_1X 6
52 #define IPW_MLME_STA_DEAUTH 1
53 #define IPW_MLME_STA_DISASSOC 2
55 #define IPW_CRYPT_ERR_UNKNOWN_ALG 2
56 #define IPW_CRYPT_ERR_UNKNOWN_ADDR 3
57 #define IPW_CRYPT_ERR_CRYPT_INIT_FAILED 4
58 #define IPW_CRYPT_ERR_KEY_SET_FAILED 5
59 #define IPW_CRYPT_ERR_TX_KEY_SET_FAILED 6
60 #define IPW_CRYPT_ERR_CARD_CONF_FAILED 7
62 #define IPW_CRYPT_ALG_NAME_LEN 16
66 u8 sta_addr
[ETH_ALEN
];
82 u8 alg
[IPW_CRYPT_ALG_NAME_LEN
];
94 /* end of ipw2100.c and ipw2200.c code */
96 static int ipw_ioctl(struct wpa_driver_ipw_data
*drv
,
97 struct ipw_param
*param
, int len
, int show_err
)
101 os_memset(&iwr
, 0, sizeof(iwr
));
102 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
103 iwr
.u
.data
.pointer
= (caddr_t
) param
;
104 iwr
.u
.data
.length
= len
;
106 if (ioctl(drv
->sock
, IPW_IOCTL_WPA_SUPPLICANT
, &iwr
) < 0) {
109 perror("ioctl[IPW_IOCTL_WPA_SUPPLICANT]");
117 static void ipw_show_set_key_error(struct ipw_param
*param
)
119 switch (param
->u
.crypt
.err
) {
120 case IPW_CRYPT_ERR_UNKNOWN_ALG
:
121 wpa_printf(MSG_INFO
, "Unknown algorithm '%s'.",
123 wpa_printf(MSG_INFO
, "You may need to load kernel module to "
124 "register that algorithm.");
125 wpa_printf(MSG_INFO
, "E.g., 'modprobe ieee80211_crypt_wep' for"
128 case IPW_CRYPT_ERR_UNKNOWN_ADDR
:
129 wpa_printf(MSG_INFO
, "Unknown address " MACSTR
".",
130 MAC2STR(param
->sta_addr
));
132 case IPW_CRYPT_ERR_CRYPT_INIT_FAILED
:
133 wpa_printf(MSG_INFO
, "Crypt algorithm initialization failed.");
135 case IPW_CRYPT_ERR_KEY_SET_FAILED
:
136 wpa_printf(MSG_INFO
, "Key setting failed.");
138 case IPW_CRYPT_ERR_TX_KEY_SET_FAILED
:
139 wpa_printf(MSG_INFO
, "TX key index setting failed.");
141 case IPW_CRYPT_ERR_CARD_CONF_FAILED
:
142 wpa_printf(MSG_INFO
, "Card configuration failed.");
148 static int ipw_set_wpa_ie(struct wpa_driver_ipw_data
*drv
,
149 const u8
*wpa_ie
, size_t wpa_ie_len
)
151 struct ipw_param
*param
;
153 size_t blen
= sizeof(*param
) + wpa_ie_len
;
155 param
= os_zalloc(blen
);
159 param
->cmd
= IPW_CMD_SET_WPA_IE
;
160 param
->u
.wpa_ie
.len
= wpa_ie_len
;
161 os_memcpy(param
->u
.wpa_ie
.data
, wpa_ie
, wpa_ie_len
);
163 ret
= ipw_ioctl(drv
, param
, blen
, 1);
170 static int ipw_set_wpa_param(struct wpa_driver_ipw_data
*drv
, u8 name
,
173 struct ipw_param param
;
175 os_memset(¶m
, 0, sizeof(param
));
176 param
.cmd
= IPW_CMD_SET_WPA_PARAM
;
177 param
.u
.wpa_param
.name
= name
;
178 param
.u
.wpa_param
.value
= value
;
180 return ipw_ioctl(drv
, ¶m
, sizeof(param
), 1);
184 static int ipw_mlme(struct wpa_driver_ipw_data
*drv
, const u8
*addr
,
187 struct ipw_param param
;
189 os_memset(¶m
, 0, sizeof(param
));
190 os_memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
191 param
.cmd
= IPW_CMD_MLME
;
192 param
.u
.mlme
.command
= cmd
;
193 param
.u
.mlme
.reason_code
= reason
;
195 return ipw_ioctl(drv
, ¶m
, sizeof(param
), 1);
199 static int wpa_driver_ipw_set_wpa(void *priv
, int enabled
)
201 struct wpa_driver_ipw_data
*drv
= priv
;
204 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
206 if (!enabled
&& ipw_set_wpa_ie(drv
, NULL
, 0) < 0)
209 if (ipw_set_wpa_param(drv
, IPW_PARAM_WPA_ENABLED
, enabled
) < 0)
216 static int wpa_driver_ipw_set_key(void *priv
, wpa_alg alg
,
217 const u8
*addr
, int key_idx
, int set_tx
,
218 const u8
*seq
, size_t seq_len
,
219 const u8
*key
, size_t key_len
)
221 struct wpa_driver_ipw_data
*drv
= priv
;
222 struct ipw_param
*param
;
245 wpa_printf(MSG_DEBUG
, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
246 "key_len=%lu", __FUNCTION__
, alg_name
, key_idx
, set_tx
,
247 (unsigned long) seq_len
, (unsigned long) key_len
);
252 blen
= sizeof(*param
) + key_len
;
253 buf
= os_zalloc(blen
);
257 param
= (struct ipw_param
*) buf
;
258 param
->cmd
= IPW_CMD_SET_ENCRYPTION
;
259 os_memset(param
->sta_addr
, 0xff, ETH_ALEN
);
260 os_strlcpy((char *) param
->u
.crypt
.alg
, alg_name
,
261 IPW_CRYPT_ALG_NAME_LEN
);
262 param
->u
.crypt
.set_tx
= set_tx
? 1 : 0;
263 param
->u
.crypt
.idx
= key_idx
;
264 os_memcpy(param
->u
.crypt
.seq
, seq
, seq_len
);
265 param
->u
.crypt
.key_len
= key_len
;
266 os_memcpy((u8
*) (param
+ 1), key
, key_len
);
268 if (ipw_ioctl(drv
, param
, blen
, 1)) {
269 wpa_printf(MSG_WARNING
, "Failed to set encryption.");
270 ipw_show_set_key_error(param
);
279 static int wpa_driver_ipw_set_countermeasures(void *priv
, int enabled
)
281 struct wpa_driver_ipw_data
*drv
= priv
;
282 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
283 return ipw_set_wpa_param(drv
, IPW_PARAM_TKIP_COUNTERMEASURES
,
289 static int wpa_driver_ipw_set_drop_unencrypted(void *priv
, int enabled
)
291 struct wpa_driver_ipw_data
*drv
= priv
;
292 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
293 return ipw_set_wpa_param(drv
, IPW_PARAM_DROP_UNENCRYPTED
,
298 static int wpa_driver_ipw_deauthenticate(void *priv
, const u8
*addr
,
301 struct wpa_driver_ipw_data
*drv
= priv
;
302 return ipw_mlme(drv
, addr
, IPW_MLME_STA_DEAUTH
, reason_code
);
306 static int wpa_driver_ipw_disassociate(void *priv
, const u8
*addr
,
309 struct wpa_driver_ipw_data
*drv
= priv
;
310 return ipw_mlme(drv
, addr
, IPW_MLME_STA_DISASSOC
, reason_code
);
315 wpa_driver_ipw_associate(void *priv
, struct wpa_driver_associate_params
*params
)
317 struct wpa_driver_ipw_data
*drv
= priv
;
319 int unencrypted_eapol
;
321 if (ipw_set_wpa_ie(drv
, params
->wpa_ie
, params
->wpa_ie_len
) < 0)
323 if (wpa_driver_wext_set_ssid(drv
->wext
, params
->ssid
,
324 params
->ssid_len
) < 0)
326 if (wpa_driver_wext_set_bssid(drv
->wext
, params
->bssid
) < 0)
329 if (params
->key_mgmt_suite
== KEY_MGMT_802_1X
||
330 params
->key_mgmt_suite
== KEY_MGMT_PSK
)
331 unencrypted_eapol
= 0;
333 unencrypted_eapol
= 1;
335 if (ipw_set_wpa_param(drv
, IPW_PARAM_IEEE_802_1X
,
336 unencrypted_eapol
) < 0) {
337 wpa_printf(MSG_DEBUG
, "ipw: Failed to configure "
338 "ieee_802_1x param");
345 static int wpa_driver_ipw_set_auth_alg(void *priv
, int auth_alg
)
347 struct wpa_driver_ipw_data
*drv
= priv
;
350 if (auth_alg
& AUTH_ALG_OPEN_SYSTEM
)
352 if (auth_alg
& AUTH_ALG_SHARED_KEY
)
354 if (auth_alg
& AUTH_ALG_LEAP
)
357 algs
= 1; /* at least one algorithm should be set */
359 wpa_printf(MSG_DEBUG
, "%s: auth_alg=0x%x", __FUNCTION__
, algs
);
360 return ipw_set_wpa_param(drv
, IPW_PARAM_AUTH_ALGS
, algs
);
364 static int wpa_driver_ipw_get_bssid(void *priv
, u8
*bssid
)
366 struct wpa_driver_ipw_data
*drv
= priv
;
367 return wpa_driver_wext_get_bssid(drv
->wext
, bssid
);
371 static int wpa_driver_ipw_get_ssid(void *priv
, u8
*ssid
)
373 struct wpa_driver_ipw_data
*drv
= priv
;
374 return wpa_driver_wext_get_ssid(drv
->wext
, ssid
);
378 static int wpa_driver_ipw_scan(void *priv
, const u8
*ssid
, size_t ssid_len
)
380 struct wpa_driver_ipw_data
*drv
= priv
;
381 return wpa_driver_wext_scan(drv
->wext
, ssid
, ssid_len
);
385 static struct wpa_scan_results
* wpa_driver_ipw_get_scan_results(void *priv
)
387 struct wpa_driver_ipw_data
*drv
= priv
;
388 return wpa_driver_wext_get_scan_results(drv
->wext
);
392 static int wpa_driver_ipw_set_operstate(void *priv
, int state
)
394 struct wpa_driver_ipw_data
*drv
= priv
;
395 return wpa_driver_wext_set_operstate(drv
->wext
, state
);
399 static void * wpa_driver_ipw_init(void *ctx
, const char *ifname
)
401 struct wpa_driver_ipw_data
*drv
;
404 wpa_printf(MSG_DEBUG
, "%s is called", __FUNCTION__
);
405 drv
= os_zalloc(sizeof(*drv
));
408 drv
->wext
= wpa_driver_wext_init(ctx
, ifname
);
409 if (drv
->wext
== NULL
) {
414 ver
= wpa_driver_wext_get_version(drv
->wext
);
416 wpa_printf(MSG_WARNING
, "Linux wireless extensions version %d "
418 wpa_printf(MSG_WARNING
, "ipw2x00 driver uses driver_wext "
419 "(-Dwext) instead of driver_ipw.");
423 os_strlcpy(drv
->ifname
, ifname
, sizeof(drv
->ifname
));
424 drv
->sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
426 wpa_driver_wext_deinit(drv
->wext
);
435 static void wpa_driver_ipw_deinit(void *priv
)
437 struct wpa_driver_ipw_data
*drv
= priv
;
438 wpa_driver_wext_deinit(drv
->wext
);
444 const struct wpa_driver_ops wpa_driver_ipw_ops
= {
446 .desc
= "Intel ipw2100/2200 driver (old; use wext with Linux 2.6.13 "
448 .get_bssid
= wpa_driver_ipw_get_bssid
,
449 .get_ssid
= wpa_driver_ipw_get_ssid
,
450 .set_wpa
= wpa_driver_ipw_set_wpa
,
451 .set_key
= wpa_driver_ipw_set_key
,
452 .set_countermeasures
= wpa_driver_ipw_set_countermeasures
,
453 .set_drop_unencrypted
= wpa_driver_ipw_set_drop_unencrypted
,
454 .scan
= wpa_driver_ipw_scan
,
455 .get_scan_results2
= wpa_driver_ipw_get_scan_results
,
456 .deauthenticate
= wpa_driver_ipw_deauthenticate
,
457 .disassociate
= wpa_driver_ipw_disassociate
,
458 .associate
= wpa_driver_ipw_associate
,
459 .set_auth_alg
= wpa_driver_ipw_set_auth_alg
,
460 .init
= wpa_driver_ipw_init
,
461 .deinit
= wpa_driver_ipw_deinit
,
462 .set_operstate
= wpa_driver_ipw_set_operstate
,