]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/hwinfo/src/hd/wlan.c
Kleiner netter neuer Versuch.
[people/pmueller/ipfire-2.x.git] / src / hwinfo / src / hd / wlan.c
CommitLineData
a6316ce4
MT
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <sys/socket.h>
6#include <sys/ioctl.h>
7#include <linux/wireless.h>
8#include <net/ethernet.h>
9
10#include "hd.h"
11#include "hd_int.h"
12#include "wlan.h"
13
14#ifndef LIBHD_TINY
15
16#define AUTH_ALG_OPEN_SYSTEM 0x01
17#define AUTH_ALG_SHARED_KEY 0x02
18#define AUTH_ALG_LEAP 0x04
19
20typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
21typedef uint8_t u8;
22typedef uint16_t u16;
23typedef uint32_t u32;
24
25struct wpa_driver_ops {
26 int (*set_wpa)(const char *ifnmae, int enabled);
27 int (*set_auth_alg)(const char *ifname, int auth_alg);
28 int (*set_key)(const char *ifname, wpa_alg alg, unsigned char *addr,
29 int key_idx, int set_tx, u8 *seq, size_t seq_len,
30 u8 *key, size_t key_len);
31};
32
33struct wpa_driver_ops wpa_driver_hostap_ops;
34struct wpa_driver_ops wpa_driver_prism54_ops;
35struct wpa_driver_ops wpa_driver_hermes_ops;
36struct wpa_driver_ops wpa_driver_madwifi_ops;
37struct wpa_driver_ops wpa_driver_atmel_ops;
38struct wpa_driver_ops wpa_driver_wext_ops;
39struct wpa_driver_ops wpa_driver_ndiswrapper_ops;
40struct wpa_driver_ops wpa_driver_ipw_ops;
41
42/* the iw_ functions are copied from libiw, so we do not need to
43 link against it */
44
45int iw_sockets_open(void)
46{
47 static const int families[] = {
48 AF_INET, AF_IPX, AF_AX25, AF_APPLETALK
49 };
50 unsigned int i;
51 int sock;
52
53 /*
54 * Now pick any (exisiting) useful socket family for generic queries
55 * Note : don't open all the socket, only returns when one matches,
56 * all protocols might not be valid.
57 * Workaround by Jim Kaba <jkaba@sarnoff.com>
58 * Note : in 99% of the case, we will just open the inet_sock.
59 * The remaining 1% case are not fully correct...
60 */
61
62 /* Try all families we support */
63 for(i = 0; i < sizeof(families)/sizeof(int); ++i)
64 {
65 /* Try to open the socket, if success returns it */
66 sock = socket(families[i], SOCK_DGRAM, 0);
67 if(sock >= 0)
68 return sock;
69 }
70
71 return -1;
72}
73
74static inline int
75iw_get_ext(int skfd, /* Socket to the kernel */
76 const char * ifname, /* Device name */
77 int request, /* WE ID */
78 struct iwreq * pwrq) /* Fixed part of the request */
79{
80 /* Set device name */
81 strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
82 /* Do the request */
83 return(ioctl(skfd, request, pwrq));
84}
85
86int iw_get_range_info(int skfd,
87 const char * ifname,
88 struct iw_range * range)
89{
90 struct iwreq wrq;
91 char buffer[sizeof(struct iw_range) * 2]; /* Large enough */
92 struct iw_range * range_raw;
93
94 /* Cleanup */
95 bzero(buffer, sizeof(buffer));
96
97 wrq.u.data.pointer = (caddr_t) buffer;
98 wrq.u.data.length = sizeof(buffer);
99 wrq.u.data.flags = 0;
100 if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0)
101 return(-1);
102
103 /* Point to the buffer */
104 range_raw = (struct iw_range *) buffer;
105
106 /* For new versions, we can check the version directly, for old versions
107 * we use magic. 300 bytes is a also magic number, don't touch... */
108 if(wrq.u.data.length < 300) {
109 /* That's v10 or earlier. Ouch ! Let's make a guess...*/
110 range_raw->we_version_compiled = 9;
111 }
112
113 /* Check how it needs to be processed */
114 if(range_raw->we_version_compiled > 15) {
115 /* This is our native format, that's easy... */
116 /* Copy stuff at the right place, ignore extra */
117 memcpy((char *) range, buffer, sizeof(struct iw_range));
118 }
119 else {
120 /* not supported */
121 return(-1);
122 }
123
124 return(0);
125}
126
127double iw_freq2float(const struct iw_freq * in)
128{
129 int i;
130 double res = (double) in->m;
131 for(i = 0; i < in->e; i++)
132 res *= 10;
133 return(res);
134}
135
136void hd_scan_wlan(hd_data_t *hd_data)
137{
138 hd_t *hd;
139 hd_res_t *res;
140 struct iw_range range;
141 int k;
142 int skfd;
143 struct wpa_driver_ops *wpa_drv=NULL;
144
145 if(!hd_probe_feature(hd_data, pr_wlan)) return;
146
147 hd_data->module = mod_wlan;
148
149 PROGRESS(1, 0, "detecting wlan features");
150
151 if ((skfd = iw_sockets_open()) < 0) {
152 ADD2LOG( "could not open socket, wlan feature query failed\n" );
153 return;
154 }
155
156 for(hd = hd_data->hd; hd; hd = hd->next) {
157 if(
158 hd->base_class.id == bc_network &&
159 hd->unix_dev_name ) {
160 /* Get list of frequencies / channels */
161 if(iw_get_range_info(skfd, hd->unix_dev_name, &range) < 0) {
162 /* this failed, maybe device does not support wireless extensions */
163 continue;
164 }
165 ADD2LOG("*** device %s is wireless ***\n", hd->unix_dev_name);
166 hd->is.wlan = 1;
167 res = new_mem(sizeof *res);
168 res->any.type = res_wlan;
169
170 if(range.num_frequency > 0) {
171 char buff[20];
172 for(k = 0; k < range.num_frequency; k++) {
173 snprintf(buff, 19, "%i", range.freq[k].i);
174 add_str_list(&res->wlan.channels, buff);
175 snprintf(buff, 19, "%g", (float)iw_freq2float(&(range.freq[k]))/1000000000);
176 add_str_list(&res->wlan.frequencies, buff);
177 }
178 for(k = 0; k < range.num_bitrates; k++) {
179 snprintf(buff, 19, "%g", (float)range.bitrate[k]/1000000);
180 add_str_list(&res->wlan.bitrates, buff);
181 }
182 for(k = 0; k < range.num_encoding_sizes; k++) {
183 snprintf(buff, 19, "WEP%i", range.encoding_size[k]*8);
184 add_str_list(&res->wlan.enc_modes, buff);
185 }
186
187 /* open mode is always supported */
188 add_str_list(&res->wlan.auth_modes, "open");
189 /* if WEP is supported, be assume shared key auth support */
190 if(range.num_encoding_sizes) {
191 add_str_list(&res->wlan.auth_modes, "sharedkey");
192 }
193
194 /* detect WPA capabilities */
195 if (hd->drivers) {
196 if (search_str_list(hd->drivers, "hostap_cs") ||
197 search_str_list(hd->drivers, "hostap_pci") ||
198 search_str_list(hd->drivers, "hostap_plx") )
199 wpa_drv = &wpa_driver_hostap_ops;
200 /* prism54 is not ready yet
201 else if (search_str_list(hd->drivers, "prism54")==0)
202 wpa_drv = &wpa_driver_prism54_ops;
203 */
204 else if (search_str_list(hd->drivers, "ath_pci"))
205 wpa_drv = &wpa_driver_madwifi_ops;
206 else if (strncmp(hd->drivers->str, "at76", 4)==0)
207 wpa_drv = &wpa_driver_atmel_ops;
208 else if (search_str_list(hd->drivers, "ndiswrapper"))
209 wpa_drv = &wpa_driver_ndiswrapper_ops;
210 else if ((search_str_list(hd->drivers, "ipw2100")) ||
211 (search_str_list(hd->drivers, "ipw2200")) )
212 wpa_drv = &wpa_driver_ipw_ops;
213 }
214
215 if (wpa_drv) {
216 if (wpa_drv->set_wpa(hd->unix_dev_name, 1) == 0) {
217 add_str_list(&res->wlan.auth_modes, "wpa-psk");
218 add_str_list(&res->wlan.auth_modes, "wpa-eap");
219 if (wpa_drv->set_auth_alg &&
220 wpa_drv->set_auth_alg(hd->unix_dev_name, AUTH_ALG_LEAP)==0)
221 add_str_list(&res->wlan.auth_modes, "wpa-leap");
222 if (wpa_drv->set_key(hd->unix_dev_name, WPA_ALG_TKIP, "ff:ff:ff:ff:ff:ff",
223 0, 0, 0, 0,
224 "00000000000000000000000000000000", 32) ==0)
225 add_str_list(&res->wlan.enc_modes, "TKIP");
226 if (wpa_drv->set_key(hd->unix_dev_name, WPA_ALG_CCMP, "ff:ff:ff:ff:ff:ff",
227 0, 0, 0, 0,
228 "0000000000000000", 16) ==0)
229 add_str_list(&res->wlan.enc_modes, "CCMP");
230 wpa_drv->set_wpa(hd->unix_dev_name, 0);
231 }
232 }
233 }
234 add_res_entry(&hd->res, res);
235 }
236 }
237}
238
239/* following functions are copied from wpa_supplicant
240 they are used to detect WPA capabilities */
241
242/* begin hostap */
243
244#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
245#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14)
246#define HOSTAP_CRYPT_ALG_NAME_LEN 16
247#define HOSTAP_CRYPT_FLAG_SET_TX_KEY (1 << (0))
248#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
249 ((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
250
251enum {
252 PRISM2_SET_ENCRYPTION = 6,
253 PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12,
254 PRISM2_PARAM_AP_AUTH_ALGS = 15,
255 PRISM2_PARAM_HOST_ROAMING = 21,
256 PRISM2_PARAM_WPA = 36,
257 PRISM2_PARAM_PRIVACY_INVOKED = 37,
258};
259
260struct prism2_hostapd_param {
261 u32 cmd;
262 u8 sta_addr[ETH_ALEN];
263 union {
264 struct {
265 u16 aid;
266 u16 capability;
267 u8 tx_supp_rates;
268 } add_sta;
269 struct {
270 u32 inactive_sec;
271 } get_info_sta;
272 struct {
273 u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];
274 u32 flags;
275 u32 err;
276 u8 idx;
277 u8 seq[8]; /* sequence counter (set: RX, get: TX) */
278 u16 key_len;
279 u8 key[0];
280 } crypt;
281 struct {
282 u32 flags_and;
283 u32 flags_or;
284 } set_flags_sta;
285 struct {
286 u16 rid;
287 u16 len;
288 u8 data[0];
289 } rid;
290 struct {
291 u8 len;
292 u8 data[0];
293 } generic_elem;
294 struct {
295 u16 cmd;
296 u16 reason_code;
297 } mlme;
298 struct {
299 u8 ssid_len;
300 u8 ssid[32];
301 } scan_req;
302 } u;
303};
304
305
306int hostapd_ioctl(const char *dev, struct prism2_hostapd_param *param,
307 int len, int show_err)
308{
309 int s;
310 int ret =0;
311 struct iwreq iwr;
312
313 s = socket(PF_INET, SOCK_DGRAM, 0);
314 if (s < 0) {
315 return -1;
316 }
317
318 memset(&iwr, 0, sizeof(iwr));
319 strncpy(iwr.ifr_name, dev, IFNAMSIZ);
320 iwr.u.data.pointer = (caddr_t) param;
321 iwr.u.data.length = len;
322
323 if (ioctl(s, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
324 ret=1;
325 }
326 close(s);
327
328 return 0;
329}
330
331int prism2param(const char *ifname, int param, int value)
332{
333 struct iwreq iwr;
334 int *i, s, ret = 0;
335
336 s = socket(PF_INET, SOCK_DGRAM, 0);
337 if (s < 0) {
338 return -1;
339 }
340
341 memset(&iwr, 0, sizeof(iwr));
342 strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
343 i = (int *) iwr.u.name;
344 *i++ = param;
345 *i++ = value;
346
347 if (ioctl(s, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) {
348 ret = -1;
349 }
350 close(s);
351 return ret;
352}
353
354int wpa_driver_hostap_set_auth_alg(const char *ifname, int auth_alg)
355{
356 int algs = 0;
357
358 if (auth_alg & AUTH_ALG_OPEN_SYSTEM)
359 algs |= 1;
360 if (auth_alg & AUTH_ALG_SHARED_KEY)
361 algs |= 2;
362 if (auth_alg & AUTH_ALG_LEAP)
363 algs |= 4;
364 if (algs == 0)
365 algs = 1; /* at least one algorithm should be set */
366
367 return prism2param(ifname, PRISM2_PARAM_AP_AUTH_ALGS, algs);
368}
369
370int wpa_driver_hostap_set_wpa(const char *ifname, int enabled)
371{
372 int ret = 0;
373
374 if (prism2param(ifname, PRISM2_PARAM_HOST_ROAMING,
375 enabled ? 2 : 0) < 0)
376 ret = -1;
377 if (prism2param(ifname, PRISM2_PARAM_PRIVACY_INVOKED, enabled) < 0)
378 ret = -1;
379 if (prism2param(ifname, PRISM2_PARAM_WPA, enabled) < 0)
380 ret = -1;
381
382 return ret;
383}
384
385int wpa_driver_hostap_set_key(const char *ifname, wpa_alg alg,
386 unsigned char *addr, int key_idx,
387 int set_tx, u8 *seq, size_t seq_len,
388 u8 *key, size_t key_len)
389{
390 struct prism2_hostapd_param *param;
391 u8 *buf;
392 size_t blen;
393 int ret = 0;
394 char *alg_name;
395
396 switch (alg) {
397 case WPA_ALG_NONE:
398 alg_name = "none";
399 break;
400 case WPA_ALG_WEP:
401 alg_name = "WEP";
402 break;
403 case WPA_ALG_TKIP:
404 alg_name = "TKIP";
405 break;
406 case WPA_ALG_CCMP:
407 alg_name = "CCMP";
408 break;
409 default:
410 return -1;
411 }
412
413 if (seq_len > 8)
414 return -2;
415
416 blen = sizeof(*param) + key_len;
417 buf = malloc(blen);
418 if (buf == NULL)
419 return -1;
420 memset(buf, 0, blen);
421
422 param = (struct prism2_hostapd_param *) buf;
423 param->cmd = PRISM2_SET_ENCRYPTION;
424 memset(param->sta_addr, 0xff, ETH_ALEN);
425
426 strncpy(param->u.crypt.alg, alg_name, HOSTAP_CRYPT_ALG_NAME_LEN);
427 param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
428 param->u.crypt.idx = key_idx;
429 memcpy(param->u.crypt.seq, seq, seq_len);
430 param->u.crypt.key_len = key_len;
431 memcpy((u8 *) (param + 1), key, key_len);
432
433 if (hostapd_ioctl(ifname, param, blen, 1)) {
434 ret = -1;
435 }
436 free(buf);
437
438 return ret;
439}
440
441struct wpa_driver_ops wpa_driver_hostap_ops = {
442 .set_wpa = wpa_driver_hostap_set_wpa,
443 .set_key = wpa_driver_hostap_set_key,
444 .set_auth_alg = wpa_driver_hostap_set_auth_alg,
445};
446
447/* end hostap */
448
449/* begin madwifi */
450
451#define IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0)
452#define IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+2)
453#define IEEE80211_CIPHER_WEP 0
454#define IEEE80211_CIPHER_TKIP 1
455#define IEEE80211_CIPHER_AES_CCM 3
456#define IEEE80211_ADDR_LEN 6
457#define IEEE80211_KEY_XMIT 0x01
458#define IEEE80211_KEY_RECV 0x02
459#define IEEE80211_KEYBUF_SIZE 16
460#define IEEE80211_MICBUF_SIZE 16
461
462enum {
463 IEEE80211_PARAM_WPA = 10, /* WPA mode (0,1,2) */
464 IEEE80211_PARAM_ROAMING = 12, /* roaming mode */
465 IEEE80211_PARAM_PRIVACY = 13, /* privacy invoked */
466};
467
468struct ieee80211req_key {
469 u_int8_t ik_type; /* key/cipher type */
470 u_int8_t ik_pad;
471 u_int16_t ik_keyix; /* key index */
472 u_int8_t ik_keylen; /* key length in bytes */
473 u_int8_t ik_flags;
474#define IEEE80211_KEY_DEFAULT 0x80 /* default xmit key */
475 u_int8_t ik_macaddr[IEEE80211_ADDR_LEN];
476 u_int64_t ik_keyrsc; /* key receive sequence counter */
477 u_int64_t ik_keytsc; /* key transmit sequence counter */
478 u_int8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
479};
480
481int
482set80211param(const char *dev, int op, int arg)
483{
484 struct iwreq iwr;
485 int s=-1;
486
487 if (s < 0 ? (s = socket(AF_INET, SOCK_DGRAM, 0)) == -1 : 0) {
488 return -1;
489 }
490
491 memset(&iwr, 0, sizeof(iwr));
492 strncpy(iwr.ifr_name, dev, IFNAMSIZ);
493 iwr.u.mode = op;
494 memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg));
495
496 if (ioctl(s, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
497 return -1;
498 }
499 return 0;
500}
501
502static int
503wpa_driver_madwifi_set_wpa(const char *ifname, int enabled)
504{
505 int ret = 0;
506
507 if (set80211param(ifname, IEEE80211_PARAM_ROAMING, enabled ? 2 : 0) < 0)
508 ret = -1;
509 if (set80211param(ifname, IEEE80211_PARAM_PRIVACY, enabled) < 0)
510 ret = -1;
511 if (set80211param(ifname, IEEE80211_PARAM_WPA, enabled ? 3 : 0) < 0)
512 ret = -1;
513
514 return ret;
515}
516
517static int
518set80211priv(const char *dev, int op, void *data, int len)
519{
520 struct iwreq iwr;
521 int s=-1;
522
523 if (s < 0 ? (s = socket(AF_INET, SOCK_DGRAM, 0)) == -1 : 0) {
524 return -1;
525 }
526
527 memset(&iwr, 0, sizeof(iwr));
528 strncpy(iwr.ifr_name, dev, IFNAMSIZ);
529 if (len < IFNAMSIZ) {
530 /*
531 * Argument data fits inline; put it there.
532 */
533 memcpy(iwr.u.name, data, len);
534 } else {
535 /*
536 * Argument data too big for inline transfer; setup a
537 * parameter block instead; the kernel will transfer
538 * the data for the driver.
539 */
540 iwr.u.data.pointer = data;
541 iwr.u.data.length = len;
542 }
543
544 if (ioctl(s, op, &iwr) < 0) {
545 return -1;
546 }
547 return 0;
548}
549
550static int
551wpa_driver_madwifi_set_key(const char *ifname, wpa_alg alg,
552 unsigned char *addr, int key_idx,
553 int set_tx, u8 *seq, size_t seq_len,
554 u8 *key, size_t key_len)
555{
556 struct ieee80211req_key wk;
557 char *alg_name;
558 u_int8_t cipher;
559
560 if (alg == WPA_ALG_NONE)
561 return 0;
562
563 switch (alg) {
564 case WPA_ALG_WEP:
565 alg_name = "WEP";
566 cipher = IEEE80211_CIPHER_WEP;
567 break;
568 case WPA_ALG_TKIP:
569 alg_name = "TKIP";
570 cipher = IEEE80211_CIPHER_TKIP;
571 break;
572 case WPA_ALG_CCMP:
573 alg_name = "CCMP";
574 cipher = IEEE80211_CIPHER_AES_CCM;
575 break;
576 default:
577 return -1;
578 }
579
580 if (seq_len > sizeof(u_int64_t)) {
581 return -2;
582 }
583 if (key_len > sizeof(wk.ik_keydata)) {
584 return -3;
585 }
586
587 memset(&wk, 0, sizeof(wk));
588 wk.ik_type = cipher;
589 wk.ik_flags = IEEE80211_KEY_RECV;
590 if (set_tx) {
591 wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
592 memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
593 } else
594 memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN);
595 wk.ik_keyix = key_idx;
596 wk.ik_keylen = key_len;
597 memcpy(&wk.ik_keyrsc, seq, seq_len);
598 memcpy(wk.ik_keydata, key, key_len);
599
600 return set80211priv(ifname, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk));
601}
602
603struct wpa_driver_ops wpa_driver_madwifi_ops = {
604 .set_wpa = wpa_driver_madwifi_set_wpa,
605 .set_key = wpa_driver_madwifi_set_key,
606};
607
608/* end madwifi */
609
610/* begin ipw */
611
612#define IPW_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30
613#define IPW_CMD_SET_WPA_PARAM 1
614#define IPW_CMD_SET_ENCRYPTION 3
615#define IPW_PARAM_WPA_ENABLED 1
616#define IPW_PARAM_AUTH_ALGS 5
617#define IPW_CRYPT_ALG_NAME_LEN 16
618
619struct ipw_param {
620 u32 cmd;
621 u8 sta_addr[ETH_ALEN];
622 union {
623 struct {
624 u8 name;
625 u32 value;
626 } wpa_param;
627 struct {
628 u32 len;
629 u8 *data;
630 } wpa_ie;
631 struct{
632 int command;
633 int reason_code;
634 } mlme;
635 struct {
636 u8 alg[IPW_CRYPT_ALG_NAME_LEN];
637 u8 set_tx;
638 u32 err;
639 u8 idx;
640 u8 seq[8];
641 u16 key_len;
642 u8 key[0];
643 } crypt;
644
645 } u;
646};
647
648int ipw_ioctl(const char *dev, struct ipw_param *param, int len)
649{
650 struct iwreq iwr;
651 int s;
652 int ret = 0;
653
654 s = socket(PF_INET, SOCK_DGRAM, 0);
655 if (s < 0) {
656 return -1;
657 }
658
659 memset(&iwr, 0, sizeof(iwr));
660 strncpy(iwr.ifr_name, dev, IFNAMSIZ);
661 iwr.u.data.pointer = (caddr_t) param;
662 iwr.u.data.length = len;
663
664 if (ioctl(s, IPW_IOCTL_WPA_SUPPLICANT, &iwr) < 0) {
665 ret = -1;
666 }
667
668 close(s);
669 return ret;
670}
671
672int wpa_driver_ipw_set_wpa(const char *ifname, int enabled)
673{
674 int ret = 0;
675 struct ipw_param param;
676
677 memset(&param, 0, sizeof(param));
678 param.cmd = IPW_CMD_SET_WPA_PARAM;
679 param.u.wpa_param.name = IPW_PARAM_WPA_ENABLED;
680 param.u.wpa_param.value = enabled;
681
682 if (ipw_ioctl(ifname, &param, sizeof(param)) < 0)
683 ret = -1;
684
685 return ret;
686}
687
688int wpa_driver_ipw_set_key(const char *ifname, wpa_alg alg,
689 unsigned char *addr, int key_idx, int set_tx,
690 u8 *seq, size_t seq_len,
691 u8 *key, size_t key_len)
692{
693 struct ipw_param *param;
694 u8 *buf;
695 size_t blen;
696 int ret = 0;
697 char *alg_name;
698
699 switch (alg) {
700 case WPA_ALG_NONE:
701 alg_name = "none";
702 break;
703 case WPA_ALG_WEP:
704 alg_name = "WEP";
705 break;
706 case WPA_ALG_TKIP:
707 alg_name = "TKIP";
708 break;
709 case WPA_ALG_CCMP:
710 alg_name = "CCMP";
711 break;
712 default:
713 return -1;
714 }
715
716 if (seq_len > 8)
717 return -2;
718
719 blen = sizeof(*param) + key_len;
720 buf = malloc(blen);
721 if (buf == NULL)
722 return -1;
723 memset(buf, 0, blen);
724
725 param = (struct ipw_param *) buf;
726 param->cmd = IPW_CMD_SET_ENCRYPTION;
727 memset(param->sta_addr, 0xff, ETH_ALEN);
728 strncpy(param->u.crypt.alg, alg_name, IPW_CRYPT_ALG_NAME_LEN);
729 param->u.crypt.set_tx = set_tx ? 1 : 0;
730 param->u.crypt.idx = key_idx;
731 memcpy(param->u.crypt.seq, seq, seq_len);
732 param->u.crypt.key_len = key_len;
733 memcpy((u8 *) (param + 1), key, key_len);
734
735 if (ipw_ioctl(ifname, param, blen)) {
736 ret = -1;
737 }
738 free(buf);
739
740 return ret;
741}
742
743int wpa_driver_ipw_set_auth_alg(const char *ifname, int auth_alg)
744{
745 int algs = 0;
746 struct ipw_param param;
747
748 if (auth_alg & AUTH_ALG_OPEN_SYSTEM)
749 algs |= 1;
750 if (auth_alg & AUTH_ALG_SHARED_KEY)
751 algs |= 2;
752 if (auth_alg & AUTH_ALG_LEAP)
753 algs |= 4;
754 if (algs == 0)
755 algs = 1; /* at least one algorithm should be set */
756
757 memset(&param, 0, sizeof(param));
758 param.cmd = IPW_CMD_SET_WPA_PARAM;
759 param.u.wpa_param.name = IPW_PARAM_AUTH_ALGS;
760 param.u.wpa_param.value = algs;
761
762 return ipw_ioctl(ifname, &param, sizeof(param));
763}
764
765struct wpa_driver_ops wpa_driver_ipw_ops = {
766 .set_wpa = wpa_driver_ipw_set_wpa,
767 .set_key = wpa_driver_ipw_set_key,
768 .set_auth_alg = wpa_driver_ipw_set_auth_alg
769};
770
771/* end ipw */
772
773/* begin atmel */
774
775#define ATMEL_WPA_IOCTL (SIOCIWFIRSTPRIV + 2)
776#define ATMEL_WPA_IOCTL_PARAM (SIOCIWFIRSTPRIV + 3)
777#define ATMEL_WPA_IOCTL_GET_PARAM (SIOCIWFIRSTPRIV + 4)
778
779#define MAX_KEY_LENGTH 40
780
781/* ATMEL_WPA_IOCTL ioctl() cmd: */
782enum {
783 SET_WPA_ENCRYPTION = 1,
784 SET_CIPHER_SUITES = 2,
785};
786
787/* ATMEL_WPA_IOCTL_PARAM ioctl() cmd: */
788enum {
789 ATMEL_PARAM_WPA = 1,
790 ATMEL_PARAM_PRIVACY_INVOKED = 2,
791 ATMEL_PARAM_WPA_TYPE = 3,
792};
793
794struct atmel_param{
795 unsigned char sta_addr[6];
796 int cmd;
797 u8 alg;
798 u8 key_idx;
799 u8 set_tx;
800 u8 seq[8];
801 u8 seq_len;
802 u16 key_len;
803 u8 key[MAX_KEY_LENGTH];
804 struct{
805 int reason_code;
806 u8 state;
807 }mlme;
808 u8 pairwise_suite;
809 u8 group_suite;
810 u8 key_mgmt_suite;
811};
812
813int atmel_ioctl(const char *dev, struct atmel_param *param, int len)
814{
815 int s;
816 int ret=0;
817 struct iwreq iwr;
818
819 s = socket(PF_INET, SOCK_DGRAM, 0);
820 if (s < 0) {
821 return -1;
822 }
823
824 memset(&iwr, 0, sizeof(iwr));
825 strncpy(iwr.ifr_name, dev, IFNAMSIZ);
826 iwr.u.data.pointer = (caddr_t) param;
827 iwr.u.data.length = len;
828
829 if (ioctl(s, ATMEL_WPA_IOCTL, &iwr) < 0) {
830 ret = -1;
831 }
832 close(s);
833
834 return 0;
835}
836
837int atmel2param(const char *ifname, int param, int value)
838{
839 struct iwreq iwr;
840 int *i, s, ret = 0;
841
842 s = socket(PF_INET, SOCK_DGRAM, 0);
843 if (s < 0) {
844 return -1;
845 }
846
847 memset(&iwr, 0, sizeof(iwr));
848 strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
849 i = (int *) iwr.u.name;
850 *i++ = param;
851 *i++ = value;
852
853 if (ioctl(s, ATMEL_WPA_IOCTL_PARAM, &iwr) < 0) {
854 ret = -1;
855 }
856 close(s);
857 return ret;
858}
859
860int wpa_driver_atmel_set_wpa(const char *ifname, int enabled)
861{
862 int ret = 0;
863
864 if (atmel2param(ifname, ATMEL_PARAM_PRIVACY_INVOKED, enabled) < 0)
865 ret = -1;
866 if (atmel2param(ifname, ATMEL_PARAM_WPA, enabled) < 0)
867 ret = -1;
868
869 return ret;
870}
871
872int wpa_driver_atmel_set_key(const char *ifname, wpa_alg alg,
873 unsigned char *addr, int key_idx,
874 int set_tx, u8 *seq, size_t seq_len,
875 u8 *key, size_t key_len)
876{
877 int ret = 0;
878 struct atmel_param *param;
879 u8 *buf;
880 u8 alg_type;
881
882 size_t blen;
883 char *alg_name;
884
885 switch (alg) {
886 case WPA_ALG_NONE:
887 alg_name = "none";
888 alg_type = 0;
889 break;
890 case WPA_ALG_WEP:
891 alg_name = "WEP";
892 alg_type = 1;
893 break;
894 case WPA_ALG_TKIP:
895 alg_name = "TKIP";
896 alg_type = 2;
897 break;
898 case WPA_ALG_CCMP:
899 alg_name = "CCMP";
900 alg_type = 3;
901 break;
902 default:
903 return -1;
904 }
905
906 if (seq_len > 8)
907 return -2;
908
909 blen = sizeof(*param) + key_len;
910 buf = malloc(blen);
911 if (buf == NULL)
912 return -1;
913 memset(buf, 0, blen);
914
915 param = (struct atmel_param *) buf;
916
917 param->cmd = SET_WPA_ENCRYPTION;
918
919 if (addr == NULL)
920 memset(param->sta_addr, 0xff, ETH_ALEN);
921 else
922 memcpy(param->sta_addr, addr, ETH_ALEN);
923
924 param->alg = alg_type;
925 param->key_idx = key_idx;
926 param->set_tx = set_tx;
927 memcpy(param->seq, seq, seq_len);
928 param->seq_len = seq_len;
929 param->key_len = key_len;
930 memcpy((u8 *)param->key, key, key_len);
931
932 if (atmel_ioctl(ifname, param, blen)) {
933 ret = -1;
934 }
935 free(buf);
936
937 return ret;
938}
939
940struct wpa_driver_ops wpa_driver_atmel_ops = {
941 .set_wpa = wpa_driver_atmel_set_wpa,
942 .set_key = wpa_driver_atmel_set_key,
943};
944
945/* end atmel */
946
947/* begin ndiswrapper */
948
949#define WPA_SET_WPA SIOCIWFIRSTPRIV+1
950#define WPA_SET_KEY SIOCIWFIRSTPRIV+2
951#define WPA_SET_AUTH_ALG SIOCIWFIRSTPRIV+8
952
953struct wpa_key
954{
955 wpa_alg alg;
956 u8 *addr;
957 int key_index;
958 int set_tx;
959 u8 *seq;
960 size_t seq_len;
961 u8 *key;
962 size_t key_len;
963};
964
965int wpa_ndiswrapper_set_ext(const char *ifname, int request, struct iwreq *pwrq)
966{
967 int s;
968 int ret;
969
970 s = socket( AF_INET, SOCK_DGRAM, 0);
971 if (s < 0)
972 return -1;
973
974 strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
975 ret = ioctl(s, request, pwrq);
976 close(s);
977 return ret;
978}
979
980int wpa_ndiswrapper_set_wpa(const char *ifname, int enabled)
981{
982 struct iwreq priv_req;
983 int ret = 0;
984
985 memset(&priv_req, 0, sizeof(priv_req));
986
987 priv_req.u.data.flags = enabled;
988 if (wpa_ndiswrapper_set_ext(ifname, WPA_SET_WPA, &priv_req) < 0)
989 ret = -1;
990 return ret;
991}
992
993int wpa_ndiswrapper_set_key(const char *ifname, wpa_alg alg, u8 *addr,
994 int key_idx, int set_tx, u8 *seq,
995 size_t seq_len, u8 *key, size_t key_len)
996{
997 struct wpa_key wpa_key;
998 int ret = 0;
999 struct iwreq priv_req;
1000
1001 memset(&priv_req, 0, sizeof(priv_req));
1002
1003 wpa_key.alg = alg;
1004 wpa_key.addr = addr;
1005 wpa_key.key_index = key_idx;
1006 wpa_key.set_tx = set_tx;
1007 wpa_key.seq = seq;
1008 wpa_key.seq_len = seq_len;
1009 wpa_key.key = key;
1010 wpa_key.key_len = key_len;
1011
1012 priv_req.u.data.pointer = (void *)&wpa_key;
1013
1014 if (wpa_ndiswrapper_set_ext(ifname, WPA_SET_KEY, &priv_req) < 0)
1015 ret = -1;
1016 return ret;
1017}
1018
1019static int wpa_ndiswrapper_set_auth_alg(const char *ifname, int auth_alg)
1020{
1021 int ret = 0;
1022 struct iwreq priv_req;
1023
1024 memset(&priv_req, 0, sizeof(priv_req));
1025
1026 priv_req.u.param.value = auth_alg;
1027 if (wpa_ndiswrapper_set_ext(ifname, WPA_SET_AUTH_ALG, &priv_req) < 0)
1028 ret = -1;
1029 return ret;
1030}
1031
1032struct wpa_driver_ops wpa_driver_ndiswrapper_ops = {
1033 .set_wpa = wpa_ndiswrapper_set_wpa,
1034 .set_key = wpa_ndiswrapper_set_key,
1035 .set_auth_alg = wpa_ndiswrapper_set_auth_alg,
1036};
1037
1038/* end ndiswrapper */
1039
1040#endif /* !defined(LIBHD_TINY) */
1041