1/* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */
2
3#include <linux/slab.h>
4#include <linux/types.h>
5#include <linux/sched.h>
6#include <linux/ethtool.h>
7#include <linux/if_arp.h>
8#include <linux/module.h>
9#include <net/lib80211.h>
10
11#include "hostap_wlan.h"
12#include "hostap.h"
13#include "hostap_ap.h"
14
15static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
16{
17	struct hostap_interface *iface;
18	local_info_t *local;
19	struct iw_statistics *wstats;
20
21	iface = netdev_priv(dev);
22	local = iface->local;
23
24	/* Why are we doing that ? Jean II */
25	if (iface->type != HOSTAP_INTERFACE_MAIN)
26		return NULL;
27
28	wstats = &local->wstats;
29
30	wstats->status = 0;
31	wstats->discard.code =
32		local->comm_tallies.rx_discards_wep_undecryptable;
33	wstats->discard.misc =
34		local->comm_tallies.rx_fcs_errors +
35		local->comm_tallies.rx_discards_no_buffer +
36		local->comm_tallies.tx_discards_wrong_sa;
37
38	wstats->discard.retries =
39		local->comm_tallies.tx_retry_limit_exceeded;
40	wstats->discard.fragment =
41		local->comm_tallies.rx_message_in_bad_msg_fragments;
42
43	if (local->iw_mode != IW_MODE_MASTER &&
44	    local->iw_mode != IW_MODE_REPEAT) {
45		int update = 1;
46#ifdef in_atomic
47		/* RID reading might sleep and it must not be called in
48		 * interrupt context or while atomic. However, this
49		 * function seems to be called while atomic (at least in Linux
50		 * 2.5.59). Update signal quality values only if in suitable
51		 * context. Otherwise, previous values read from tick timer
52		 * will be used. */
53		if (in_atomic())
54			update = 0;
55#endif /* in_atomic */
56
57		if (update && prism2_update_comms_qual(dev) == 0)
58			wstats->qual.updated = IW_QUAL_ALL_UPDATED |
59				IW_QUAL_DBM;
60
61		wstats->qual.qual = local->comms_qual;
62		wstats->qual.level = local->avg_signal;
63		wstats->qual.noise = local->avg_noise;
64	} else {
65		wstats->qual.qual = 0;
66		wstats->qual.level = 0;
67		wstats->qual.noise = 0;
68		wstats->qual.updated = IW_QUAL_ALL_INVALID;
69	}
70
71	return wstats;
72}
73
74
75static int prism2_get_datarates(struct net_device *dev, u8 *rates)
76{
77	struct hostap_interface *iface;
78	local_info_t *local;
79	u8 buf[12];
80	int len;
81	u16 val;
82
83	iface = netdev_priv(dev);
84	local = iface->local;
85
86	len = local->func->get_rid(dev, HFA384X_RID_SUPPORTEDDATARATES, buf,
87				   sizeof(buf), 0);
88	if (len < 2)
89		return 0;
90
91	val = le16_to_cpu(*(__le16 *) buf); /* string length */
92
93	if (len - 2 < val || val > 10)
94		return 0;
95
96	memcpy(rates, buf + 2, val);
97	return val;
98}
99
100
101static int prism2_get_name(struct net_device *dev,
102			   struct iw_request_info *info,
103			   char *name, char *extra)
104{
105	u8 rates[10];
106	int len, i, over2 = 0;
107
108	len = prism2_get_datarates(dev, rates);
109
110	for (i = 0; i < len; i++) {
111		if (rates[i] == 0x0b || rates[i] == 0x16) {
112			over2 = 1;
113			break;
114		}
115	}
116
117	strcpy(name, over2 ? "IEEE 802.11b" : "IEEE 802.11-DS");
118
119	return 0;
120}
121
122
123static int prism2_ioctl_siwencode(struct net_device *dev,
124				  struct iw_request_info *info,
125				  struct iw_point *erq, char *keybuf)
126{
127	struct hostap_interface *iface;
128	local_info_t *local;
129	int i;
130	struct lib80211_crypt_data **crypt;
131
132	iface = netdev_priv(dev);
133	local = iface->local;
134
135	i = erq->flags & IW_ENCODE_INDEX;
136	if (i < 1 || i > 4)
137		i = local->crypt_info.tx_keyidx;
138	else
139		i--;
140	if (i < 0 || i >= WEP_KEYS)
141		return -EINVAL;
142
143	crypt = &local->crypt_info.crypt[i];
144
145	if (erq->flags & IW_ENCODE_DISABLED) {
146		if (*crypt)
147			lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
148		goto done;
149	}
150
151	if (*crypt != NULL && (*crypt)->ops != NULL &&
152	    strcmp((*crypt)->ops->name, "WEP") != 0) {
153		/* changing to use WEP; deinit previously used algorithm */
154		lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
155	}
156
157	if (*crypt == NULL) {
158		struct lib80211_crypt_data *new_crypt;
159
160		/* take WEP into use */
161		new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
162				GFP_KERNEL);
163		if (new_crypt == NULL)
164			return -ENOMEM;
165		new_crypt->ops = lib80211_get_crypto_ops("WEP");
166		if (!new_crypt->ops) {
167			request_module("lib80211_crypt_wep");
168			new_crypt->ops = lib80211_get_crypto_ops("WEP");
169		}
170		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
171			new_crypt->priv = new_crypt->ops->init(i);
172		if (!new_crypt->ops || !new_crypt->priv) {
173			kfree(new_crypt);
174			new_crypt = NULL;
175
176			printk(KERN_WARNING "%s: could not initialize WEP: "
177			       "load module hostap_crypt_wep.o\n",
178			       dev->name);
179			return -EOPNOTSUPP;
180		}
181		*crypt = new_crypt;
182	}
183
184	if (erq->length > 0) {
185		int len = erq->length <= 5 ? 5 : 13;
186		int first = 1, j;
187		if (len > erq->length)
188			memset(keybuf + erq->length, 0, len - erq->length);
189		(*crypt)->ops->set_key(keybuf, len, NULL, (*crypt)->priv);
190		for (j = 0; j < WEP_KEYS; j++) {
191			if (j != i && local->crypt_info.crypt[j]) {
192				first = 0;
193				break;
194			}
195		}
196		if (first)
197			local->crypt_info.tx_keyidx = i;
198	} else {
199		/* No key data - just set the default TX key index */
200		local->crypt_info.tx_keyidx = i;
201	}
202
203 done:
204	local->open_wep = erq->flags & IW_ENCODE_OPEN;
205
206	if (hostap_set_encryption(local)) {
207		printk(KERN_DEBUG "%s: set_encryption failed\n", dev->name);
208		return -EINVAL;
209	}
210
211	/* Do not reset port0 if card is in Managed mode since resetting will
212	 * generate new IEEE 802.11 authentication which may end up in looping
213	 * with IEEE 802.1X. Prism2 documentation seem to require port reset
214	 * after WEP configuration. However, keys are apparently changed at
215	 * least in Managed mode. */
216	if (local->iw_mode != IW_MODE_INFRA && local->func->reset_port(dev)) {
217		printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
218		return -EINVAL;
219	}
220
221	return 0;
222}
223
224
225static int prism2_ioctl_giwencode(struct net_device *dev,
226				  struct iw_request_info *info,
227				  struct iw_point *erq, char *key)
228{
229	struct hostap_interface *iface;
230	local_info_t *local;
231	int i, len;
232	u16 val;
233	struct lib80211_crypt_data *crypt;
234
235	iface = netdev_priv(dev);
236	local = iface->local;
237
238	i = erq->flags & IW_ENCODE_INDEX;
239	if (i < 1 || i > 4)
240		i = local->crypt_info.tx_keyidx;
241	else
242		i--;
243	if (i < 0 || i >= WEP_KEYS)
244		return -EINVAL;
245
246	crypt = local->crypt_info.crypt[i];
247	erq->flags = i + 1;
248
249	if (crypt == NULL || crypt->ops == NULL) {
250		erq->length = 0;
251		erq->flags |= IW_ENCODE_DISABLED;
252		return 0;
253	}
254
255	if (strcmp(crypt->ops->name, "WEP") != 0) {
256		/* only WEP is supported with wireless extensions, so just
257		 * report that encryption is used */
258		erq->length = 0;
259		erq->flags |= IW_ENCODE_ENABLED;
260		return 0;
261	}
262
263	/* Reads from HFA384X_RID_CNFDEFAULTKEY* return bogus values, so show
264	 * the keys from driver buffer */
265	len = crypt->ops->get_key(key, WEP_KEY_LEN, NULL, crypt->priv);
266	erq->length = (len >= 0 ? len : 0);
267
268	if (local->func->get_rid(dev, HFA384X_RID_CNFWEPFLAGS, &val, 2, 1) < 0)
269	{
270		printk("CNFWEPFLAGS reading failed\n");
271		return -EOPNOTSUPP;
272	}
273	le16_to_cpus(&val);
274	if (val & HFA384X_WEPFLAGS_PRIVACYINVOKED)
275		erq->flags |= IW_ENCODE_ENABLED;
276	else
277		erq->flags |= IW_ENCODE_DISABLED;
278	if (val & HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED)
279		erq->flags |= IW_ENCODE_RESTRICTED;
280	else
281		erq->flags |= IW_ENCODE_OPEN;
282
283	return 0;
284}
285
286
287static int hostap_set_rate(struct net_device *dev)
288{
289	struct hostap_interface *iface;
290	local_info_t *local;
291	int ret, basic_rates;
292
293	iface = netdev_priv(dev);
294	local = iface->local;
295
296	basic_rates = local->basic_rates & local->tx_rate_control;
297	if (!basic_rates || basic_rates != local->basic_rates) {
298		printk(KERN_INFO "%s: updating basic rate set automatically "
299		       "to match with the new supported rate set\n",
300		       dev->name);
301		if (!basic_rates)
302			basic_rates = local->tx_rate_control;
303
304		local->basic_rates = basic_rates;
305		if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES,
306				    basic_rates))
307			printk(KERN_WARNING "%s: failed to set "
308			       "cnfBasicRates\n", dev->name);
309	}
310
311	ret = (hostap_set_word(dev, HFA384X_RID_TXRATECONTROL,
312			       local->tx_rate_control) ||
313	       hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES,
314			       local->tx_rate_control) ||
315	       local->func->reset_port(dev));
316
317	if (ret) {
318		printk(KERN_WARNING "%s: TXRateControl/cnfSupportedRates "
319		       "setting to 0x%x failed\n",
320		       dev->name, local->tx_rate_control);
321	}
322
323	/* Update TX rate configuration for all STAs based on new operational
324	 * rate set. */
325	hostap_update_rates(local);
326
327	return ret;
328}
329
330
331static int prism2_ioctl_siwrate(struct net_device *dev,
332				struct iw_request_info *info,
333				struct iw_param *rrq, char *extra)
334{
335	struct hostap_interface *iface;
336	local_info_t *local;
337
338	iface = netdev_priv(dev);
339	local = iface->local;
340
341	if (rrq->fixed) {
342		switch (rrq->value) {
343		case 11000000:
344			local->tx_rate_control = HFA384X_RATES_11MBPS;
345			break;
346		case 5500000:
347			local->tx_rate_control = HFA384X_RATES_5MBPS;
348			break;
349		case 2000000:
350			local->tx_rate_control = HFA384X_RATES_2MBPS;
351			break;
352		case 1000000:
353			local->tx_rate_control = HFA384X_RATES_1MBPS;
354			break;
355		default:
356			local->tx_rate_control = HFA384X_RATES_1MBPS |
357				HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
358				HFA384X_RATES_11MBPS;
359			break;
360		}
361	} else {
362		switch (rrq->value) {
363		case 11000000:
364			local->tx_rate_control = HFA384X_RATES_1MBPS |
365				HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
366				HFA384X_RATES_11MBPS;
367			break;
368		case 5500000:
369			local->tx_rate_control = HFA384X_RATES_1MBPS |
370				HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS;
371			break;
372		case 2000000:
373			local->tx_rate_control = HFA384X_RATES_1MBPS |
374				HFA384X_RATES_2MBPS;
375			break;
376		case 1000000:
377			local->tx_rate_control = HFA384X_RATES_1MBPS;
378			break;
379		default:
380			local->tx_rate_control = HFA384X_RATES_1MBPS |
381				HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
382				HFA384X_RATES_11MBPS;
383			break;
384		}
385	}
386
387	return hostap_set_rate(dev);
388}
389
390
391static int prism2_ioctl_giwrate(struct net_device *dev,
392				struct iw_request_info *info,
393				struct iw_param *rrq, char *extra)
394{
395	u16 val;
396	struct hostap_interface *iface;
397	local_info_t *local;
398	int ret = 0;
399
400	iface = netdev_priv(dev);
401	local = iface->local;
402
403	if (local->func->get_rid(dev, HFA384X_RID_TXRATECONTROL, &val, 2, 1) <
404	    0)
405		return -EINVAL;
406
407	if ((val & 0x1) && (val > 1))
408		rrq->fixed = 0;
409	else
410		rrq->fixed = 1;
411
412	if (local->iw_mode == IW_MODE_MASTER && local->ap != NULL &&
413	    !local->fw_tx_rate_control) {
414		/* HFA384X_RID_CURRENTTXRATE seems to always be 2 Mbps in
415		 * Host AP mode, so use the recorded TX rate of the last sent
416		 * frame */
417		rrq->value = local->ap->last_tx_rate > 0 ?
418			local->ap->last_tx_rate * 100000 : 11000000;
419		return 0;
420	}
421
422	if (local->func->get_rid(dev, HFA384X_RID_CURRENTTXRATE, &val, 2, 1) <
423	    0)
424		return -EINVAL;
425
426	switch (val) {
427	case HFA384X_RATES_1MBPS:
428		rrq->value = 1000000;
429		break;
430	case HFA384X_RATES_2MBPS:
431		rrq->value = 2000000;
432		break;
433	case HFA384X_RATES_5MBPS:
434		rrq->value = 5500000;
435		break;
436	case HFA384X_RATES_11MBPS:
437		rrq->value = 11000000;
438		break;
439	default:
440		/* should not happen */
441		rrq->value = 11000000;
442		ret = -EINVAL;
443		break;
444	}
445
446	return ret;
447}
448
449
450static int prism2_ioctl_siwsens(struct net_device *dev,
451				struct iw_request_info *info,
452				struct iw_param *sens, char *extra)
453{
454	struct hostap_interface *iface;
455	local_info_t *local;
456
457	iface = netdev_priv(dev);
458	local = iface->local;
459
460	/* Set the desired AP density */
461	if (sens->value < 1 || sens->value > 3)
462		return -EINVAL;
463
464	if (hostap_set_word(dev, HFA384X_RID_CNFSYSTEMSCALE, sens->value) ||
465	    local->func->reset_port(dev))
466		return -EINVAL;
467
468	return 0;
469}
470
471static int prism2_ioctl_giwsens(struct net_device *dev,
472				struct iw_request_info *info,
473				struct iw_param *sens, char *extra)
474{
475	struct hostap_interface *iface;
476	local_info_t *local;
477	__le16 val;
478
479	iface = netdev_priv(dev);
480	local = iface->local;
481
482	/* Get the current AP density */
483	if (local->func->get_rid(dev, HFA384X_RID_CNFSYSTEMSCALE, &val, 2, 1) <
484	    0)
485		return -EINVAL;
486
487	sens->value = le16_to_cpu(val);
488	sens->fixed = 1;
489
490	return 0;
491}
492
493
494/* Deprecated in new wireless extension API */
495static int prism2_ioctl_giwaplist(struct net_device *dev,
496				  struct iw_request_info *info,
497				  struct iw_point *data, char *extra)
498{
499	struct hostap_interface *iface;
500	local_info_t *local;
501	struct sockaddr *addr;
502	struct iw_quality *qual;
503
504	iface = netdev_priv(dev);
505	local = iface->local;
506
507	if (local->iw_mode != IW_MODE_MASTER) {
508		printk(KERN_DEBUG "SIOCGIWAPLIST is currently only supported "
509		       "in Host AP mode\n");
510		data->length = 0;
511		return -EOPNOTSUPP;
512	}
513
514	addr = kmalloc(sizeof(struct sockaddr) * IW_MAX_AP, GFP_KERNEL);
515	qual = kmalloc(sizeof(struct iw_quality) * IW_MAX_AP, GFP_KERNEL);
516	if (addr == NULL || qual == NULL) {
517		kfree(addr);
518		kfree(qual);
519		data->length = 0;
520		return -ENOMEM;
521	}
522
523	data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1);
524
525	memcpy(extra, &addr, sizeof(struct sockaddr) * data->length);
526	data->flags = 1; /* has quality information */
527	memcpy(extra + sizeof(struct sockaddr) * data->length, &qual,
528	       sizeof(struct iw_quality) * data->length);
529
530	kfree(addr);
531	kfree(qual);
532	return 0;
533}
534
535
536static int prism2_ioctl_siwrts(struct net_device *dev,
537			       struct iw_request_info *info,
538			       struct iw_param *rts, char *extra)
539{
540	struct hostap_interface *iface;
541	local_info_t *local;
542	__le16 val;
543
544	iface = netdev_priv(dev);
545	local = iface->local;
546
547	if (rts->disabled)
548		val = cpu_to_le16(2347);
549	else if (rts->value < 0 || rts->value > 2347)
550		return -EINVAL;
551	else
552		val = cpu_to_le16(rts->value);
553
554	if (local->func->set_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2) ||
555	    local->func->reset_port(dev))
556		return -EINVAL;
557
558	local->rts_threshold = rts->value;
559
560	return 0;
561}
562
563static int prism2_ioctl_giwrts(struct net_device *dev,
564			       struct iw_request_info *info,
565			       struct iw_param *rts, char *extra)
566{
567	struct hostap_interface *iface;
568	local_info_t *local;
569	__le16 val;
570
571	iface = netdev_priv(dev);
572	local = iface->local;
573
574	if (local->func->get_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2, 1) <
575	    0)
576		return -EINVAL;
577
578	rts->value = le16_to_cpu(val);
579	rts->disabled = (rts->value == 2347);
580	rts->fixed = 1;
581
582	return 0;
583}
584
585
586static int prism2_ioctl_siwfrag(struct net_device *dev,
587				struct iw_request_info *info,
588				struct iw_param *rts, char *extra)
589{
590	struct hostap_interface *iface;
591	local_info_t *local;
592	__le16 val;
593
594	iface = netdev_priv(dev);
595	local = iface->local;
596
597	if (rts->disabled)
598		val = cpu_to_le16(2346);
599	else if (rts->value < 256 || rts->value > 2346)
600		return -EINVAL;
601	else
602		val = cpu_to_le16(rts->value & ~0x1); /* even numbers only */
603
604	local->fragm_threshold = rts->value & ~0x1;
605	if (local->func->set_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD, &val,
606				 2)
607	    || local->func->reset_port(dev))
608		return -EINVAL;
609
610	return 0;
611}
612
613static int prism2_ioctl_giwfrag(struct net_device *dev,
614				struct iw_request_info *info,
615				struct iw_param *rts, char *extra)
616{
617	struct hostap_interface *iface;
618	local_info_t *local;
619	__le16 val;
620
621	iface = netdev_priv(dev);
622	local = iface->local;
623
624	if (local->func->get_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD,
625				 &val, 2, 1) < 0)
626		return -EINVAL;
627
628	rts->value = le16_to_cpu(val);
629	rts->disabled = (rts->value == 2346);
630	rts->fixed = 1;
631
632	return 0;
633}
634
635
636#ifndef PRISM2_NO_STATION_MODES
637static int hostap_join_ap(struct net_device *dev)
638{
639	struct hostap_interface *iface;
640	local_info_t *local;
641	struct hfa384x_join_request req;
642	unsigned long flags;
643	int i;
644	struct hfa384x_hostscan_result *entry;
645
646	iface = netdev_priv(dev);
647	local = iface->local;
648
649	memcpy(req.bssid, local->preferred_ap, ETH_ALEN);
650	req.channel = 0;
651
652	spin_lock_irqsave(&local->lock, flags);
653	for (i = 0; i < local->last_scan_results_count; i++) {
654		if (!local->last_scan_results)
655			break;
656		entry = &local->last_scan_results[i];
657		if (memcmp(local->preferred_ap, entry->bssid, ETH_ALEN) == 0) {
658			req.channel = entry->chid;
659			break;
660		}
661	}
662	spin_unlock_irqrestore(&local->lock, flags);
663
664	if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
665				 sizeof(req))) {
666		printk(KERN_DEBUG "%s: JoinRequest %pM failed\n",
667		       dev->name, local->preferred_ap);
668		return -1;
669	}
670
671	printk(KERN_DEBUG "%s: Trying to join BSSID %pM\n",
672	       dev->name, local->preferred_ap);
673
674	return 0;
675}
676#endif /* PRISM2_NO_STATION_MODES */
677
678
679static int prism2_ioctl_siwap(struct net_device *dev,
680			      struct iw_request_info *info,
681			      struct sockaddr *ap_addr, char *extra)
682{
683#ifdef PRISM2_NO_STATION_MODES
684	return -EOPNOTSUPP;
685#else /* PRISM2_NO_STATION_MODES */
686	struct hostap_interface *iface;
687	local_info_t *local;
688
689	iface = netdev_priv(dev);
690	local = iface->local;
691
692	memcpy(local->preferred_ap, &ap_addr->sa_data, ETH_ALEN);
693
694	if (local->host_roaming == 1 && local->iw_mode == IW_MODE_INFRA) {
695		struct hfa384x_scan_request scan_req;
696		memset(&scan_req, 0, sizeof(scan_req));
697		scan_req.channel_list = cpu_to_le16(0x3fff);
698		scan_req.txrate = cpu_to_le16(HFA384X_RATES_1MBPS);
699		if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST,
700					 &scan_req, sizeof(scan_req))) {
701			printk(KERN_DEBUG "%s: ScanResults request failed - "
702			       "preferred AP delayed to next unsolicited "
703			       "scan\n", dev->name);
704		}
705	} else if (local->host_roaming == 2 &&
706		   local->iw_mode == IW_MODE_INFRA) {
707		if (hostap_join_ap(dev))
708			return -EINVAL;
709	} else {
710		printk(KERN_DEBUG "%s: Preferred AP (SIOCSIWAP) is used only "
711		       "in Managed mode when host_roaming is enabled\n",
712		       dev->name);
713	}
714
715	return 0;
716#endif /* PRISM2_NO_STATION_MODES */
717}
718
719static int prism2_ioctl_giwap(struct net_device *dev,
720			      struct iw_request_info *info,
721			      struct sockaddr *ap_addr, char *extra)
722{
723	struct hostap_interface *iface;
724	local_info_t *local;
725
726	iface = netdev_priv(dev);
727	local = iface->local;
728
729	ap_addr->sa_family = ARPHRD_ETHER;
730	switch (iface->type) {
731	case HOSTAP_INTERFACE_AP:
732		memcpy(&ap_addr->sa_data, dev->dev_addr, ETH_ALEN);
733		break;
734	case HOSTAP_INTERFACE_STA:
735		memcpy(&ap_addr->sa_data, local->assoc_ap_addr, ETH_ALEN);
736		break;
737	case HOSTAP_INTERFACE_WDS:
738		memcpy(&ap_addr->sa_data, iface->u.wds.remote_addr, ETH_ALEN);
739		break;
740	default:
741		if (local->func->get_rid(dev, HFA384X_RID_CURRENTBSSID,
742					 &ap_addr->sa_data, ETH_ALEN, 1) < 0)
743			return -EOPNOTSUPP;
744
745		/* local->bssid is also updated in LinkStatus handler when in
746		 * station mode */
747		memcpy(local->bssid, &ap_addr->sa_data, ETH_ALEN);
748		break;
749	}
750
751	return 0;
752}
753
754
755static int prism2_ioctl_siwnickn(struct net_device *dev,
756				 struct iw_request_info *info,
757				 struct iw_point *data, char *nickname)
758{
759	struct hostap_interface *iface;
760	local_info_t *local;
761
762	iface = netdev_priv(dev);
763	local = iface->local;
764
765	memset(local->name, 0, sizeof(local->name));
766	memcpy(local->name, nickname, data->length);
767	local->name_set = 1;
768
769	if (hostap_set_string(dev, HFA384X_RID_CNFOWNNAME, local->name) ||
770	    local->func->reset_port(dev))
771		return -EINVAL;
772
773	return 0;
774}
775
776static int prism2_ioctl_giwnickn(struct net_device *dev,
777				 struct iw_request_info *info,
778				 struct iw_point *data, char *nickname)
779{
780	struct hostap_interface *iface;
781	local_info_t *local;
782	int len;
783	char name[MAX_NAME_LEN + 3];
784	u16 val;
785
786	iface = netdev_priv(dev);
787	local = iface->local;
788
789	len = local->func->get_rid(dev, HFA384X_RID_CNFOWNNAME,
790				   &name, MAX_NAME_LEN + 2, 0);
791	val = le16_to_cpu(*(__le16 *) name);
792	if (len > MAX_NAME_LEN + 2 || len < 0 || val > MAX_NAME_LEN)
793		return -EOPNOTSUPP;
794
795	name[val + 2] = '\0';
796	data->length = val + 1;
797	memcpy(nickname, name + 2, val + 1);
798
799	return 0;
800}
801
802
803static int prism2_ioctl_siwfreq(struct net_device *dev,
804				struct iw_request_info *info,
805				struct iw_freq *freq, char *extra)
806{
807	struct hostap_interface *iface;
808	local_info_t *local;
809
810	iface = netdev_priv(dev);
811	local = iface->local;
812
813	/* freq => chan. */
814	if (freq->e == 1 &&
815	    freq->m / 100000 >= freq_list[0] &&
816	    freq->m / 100000 <= freq_list[FREQ_COUNT - 1]) {
817		int ch;
818		int fr = freq->m / 100000;
819		for (ch = 0; ch < FREQ_COUNT; ch++) {
820			if (fr == freq_list[ch]) {
821				freq->e = 0;
822				freq->m = ch + 1;
823				break;
824			}
825		}
826	}
827
828	if (freq->e != 0 || freq->m < 1 || freq->m > FREQ_COUNT ||
829	    !(local->channel_mask & (1 << (freq->m - 1))))
830		return -EINVAL;
831
832	local->channel = freq->m; /* channel is used in prism2_setup_rids() */
833	if (hostap_set_word(dev, HFA384X_RID_CNFOWNCHANNEL, local->channel) ||
834	    local->func->reset_port(dev))
835		return -EINVAL;
836
837	return 0;
838}
839
840static int prism2_ioctl_giwfreq(struct net_device *dev,
841				struct iw_request_info *info,
842				struct iw_freq *freq, char *extra)
843{
844	struct hostap_interface *iface;
845	local_info_t *local;
846	u16 val;
847
848	iface = netdev_priv(dev);
849	local = iface->local;
850
851	if (local->func->get_rid(dev, HFA384X_RID_CURRENTCHANNEL, &val, 2, 1) <
852	    0)
853		return -EINVAL;
854
855	le16_to_cpus(&val);
856	if (val < 1 || val > FREQ_COUNT)
857		return -EINVAL;
858
859	freq->m = freq_list[val - 1] * 100000;
860	freq->e = 1;
861
862	return 0;
863}
864
865
866static void hostap_monitor_set_type(local_info_t *local)
867{
868	struct net_device *dev = local->ddev;
869
870	if (dev == NULL)
871		return;
872
873	if (local->monitor_type == PRISM2_MONITOR_PRISM ||
874	    local->monitor_type == PRISM2_MONITOR_CAPHDR) {
875		dev->type = ARPHRD_IEEE80211_PRISM;
876	} else if (local->monitor_type == PRISM2_MONITOR_RADIOTAP) {
877		dev->type = ARPHRD_IEEE80211_RADIOTAP;
878	} else {
879		dev->type = ARPHRD_IEEE80211;
880	}
881}
882
883
884static int prism2_ioctl_siwessid(struct net_device *dev,
885				 struct iw_request_info *info,
886				 struct iw_point *data, char *ssid)
887{
888	struct hostap_interface *iface;
889	local_info_t *local;
890
891	iface = netdev_priv(dev);
892	local = iface->local;
893
894	if (iface->type == HOSTAP_INTERFACE_WDS)
895		return -EOPNOTSUPP;
896
897	if (data->flags == 0)
898		ssid[0] = '\0'; /* ANY */
899
900	if (local->iw_mode == IW_MODE_MASTER && ssid[0] == '\0') {
901		/* Setting SSID to empty string seems to kill the card in
902		 * Host AP mode */
903		printk(KERN_DEBUG "%s: Host AP mode does not support "
904		       "'Any' essid\n", dev->name);
905		return -EINVAL;
906	}
907
908	memcpy(local->essid, ssid, data->length);
909	local->essid[data->length] = '\0';
910
911	if ((!local->fw_ap &&
912	     hostap_set_string(dev, HFA384X_RID_CNFDESIREDSSID, local->essid))
913	    || hostap_set_string(dev, HFA384X_RID_CNFOWNSSID, local->essid) ||
914	    local->func->reset_port(dev))
915		return -EINVAL;
916
917	return 0;
918}
919
920static int prism2_ioctl_giwessid(struct net_device *dev,
921				 struct iw_request_info *info,
922				 struct iw_point *data, char *essid)
923{
924	struct hostap_interface *iface;
925	local_info_t *local;
926	u16 val;
927
928	iface = netdev_priv(dev);
929	local = iface->local;
930
931	if (iface->type == HOSTAP_INTERFACE_WDS)
932		return -EOPNOTSUPP;
933
934	data->flags = 1; /* active */
935	if (local->iw_mode == IW_MODE_MASTER) {
936		data->length = strlen(local->essid);
937		memcpy(essid, local->essid, IW_ESSID_MAX_SIZE);
938	} else {
939		int len;
940		char ssid[MAX_SSID_LEN + 2];
941		memset(ssid, 0, sizeof(ssid));
942		len = local->func->get_rid(dev, HFA384X_RID_CURRENTSSID,
943					   &ssid, MAX_SSID_LEN + 2, 0);
944		val = le16_to_cpu(*(__le16 *) ssid);
945		if (len > MAX_SSID_LEN + 2 || len < 0 || val > MAX_SSID_LEN) {
946			return -EOPNOTSUPP;
947		}
948		data->length = val;
949		memcpy(essid, ssid + 2, IW_ESSID_MAX_SIZE);
950	}
951
952	return 0;
953}
954
955
956static int prism2_ioctl_giwrange(struct net_device *dev,
957				 struct iw_request_info *info,
958				 struct iw_point *data, char *extra)
959{
960	struct hostap_interface *iface;
961	local_info_t *local;
962	struct iw_range *range = (struct iw_range *) extra;
963	u8 rates[10];
964	u16 val;
965	int i, len, over2;
966
967	iface = netdev_priv(dev);
968	local = iface->local;
969
970	data->length = sizeof(struct iw_range);
971	memset(range, 0, sizeof(struct iw_range));
972
973	/* TODO: could fill num_txpower and txpower array with
974	 * something; however, there are 128 different values.. */
975
976	range->txpower_capa = IW_TXPOW_DBM;
977
978	if (local->iw_mode == IW_MODE_INFRA || local->iw_mode == IW_MODE_ADHOC)
979	{
980		range->min_pmp = 1 * 1024;
981		range->max_pmp = 65535 * 1024;
982		range->min_pmt = 1 * 1024;
983		range->max_pmt = 1000 * 1024;
984		range->pmp_flags = IW_POWER_PERIOD;
985		range->pmt_flags = IW_POWER_TIMEOUT;
986		range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT |
987			IW_POWER_UNICAST_R | IW_POWER_ALL_R;
988	}
989
990	range->we_version_compiled = WIRELESS_EXT;
991	range->we_version_source = 18;
992
993	range->retry_capa = IW_RETRY_LIMIT;
994	range->retry_flags = IW_RETRY_LIMIT;
995	range->min_retry = 0;
996	range->max_retry = 255;
997
998	range->num_channels = FREQ_COUNT;
999
1000	val = 0;
1001	for (i = 0; i < FREQ_COUNT; i++) {
1002		if (local->channel_mask & (1 << i)) {
1003			range->freq[val].i = i + 1;
1004			range->freq[val].m = freq_list[i] * 100000;
1005			range->freq[val].e = 1;
1006			val++;
1007		}
1008		if (val == IW_MAX_FREQUENCIES)
1009			break;
1010	}
1011	range->num_frequency = val;
1012
1013	if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1)) {
1014		range->max_qual.qual = 70; /* what is correct max? This was not
1015					    * documented exactly. At least
1016					    * 69 has been observed. */
1017		range->max_qual.level = 0; /* dB */
1018		range->max_qual.noise = 0; /* dB */
1019
1020		/* What would be suitable values for "average/typical" qual? */
1021		range->avg_qual.qual = 20;
1022		range->avg_qual.level = -60;
1023		range->avg_qual.noise = -95;
1024	} else {
1025		range->max_qual.qual = 92; /* 0 .. 92 */
1026		range->max_qual.level = 154; /* 27 .. 154 */
1027		range->max_qual.noise = 154; /* 27 .. 154 */
1028	}
1029	range->sensitivity = 3;
1030
1031	range->max_encoding_tokens = WEP_KEYS;
1032	range->num_encoding_sizes = 2;
1033	range->encoding_size[0] = 5;
1034	range->encoding_size[1] = 13;
1035
1036	over2 = 0;
1037	len = prism2_get_datarates(dev, rates);
1038	range->num_bitrates = 0;
1039	for (i = 0; i < len; i++) {
1040		if (range->num_bitrates < IW_MAX_BITRATES) {
1041			range->bitrate[range->num_bitrates] =
1042				rates[i] * 500000;
1043			range->num_bitrates++;
1044		}
1045		if (rates[i] == 0x0b || rates[i] == 0x16)
1046			over2 = 1;
1047	}
1048	/* estimated maximum TCP throughput values (bps) */
1049	range->throughput = over2 ? 5500000 : 1500000;
1050
1051	range->min_rts = 0;
1052	range->max_rts = 2347;
1053	range->min_frag = 256;
1054	range->max_frag = 2346;
1055
1056	/* Event capability (kernel + driver) */
1057	range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
1058				IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
1059				IW_EVENT_CAPA_MASK(SIOCGIWAP) |
1060				IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
1061	range->event_capa[1] = IW_EVENT_CAPA_K_1;
1062	range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) |
1063				IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
1064				IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
1065				IW_EVENT_CAPA_MASK(IWEVEXPIRED));
1066
1067	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
1068		IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
1069
1070	if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1))
1071		range->scan_capa = IW_SCAN_CAPA_ESSID;
1072
1073	return 0;
1074}
1075
1076
1077static int hostap_monitor_mode_enable(local_info_t *local)
1078{
1079	struct net_device *dev = local->dev;
1080
1081	printk(KERN_DEBUG "Enabling monitor mode\n");
1082	hostap_monitor_set_type(local);
1083
1084	if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
1085			    HFA384X_PORTTYPE_PSEUDO_IBSS)) {
1086		printk(KERN_DEBUG "Port type setting for monitor mode "
1087		       "failed\n");
1088		return -EOPNOTSUPP;
1089	}
1090
1091	/* Host decrypt is needed to get the IV and ICV fields;
1092	 * however, monitor mode seems to remove WEP flag from frame
1093	 * control field */
1094	if (hostap_set_word(dev, HFA384X_RID_CNFWEPFLAGS,
1095			    HFA384X_WEPFLAGS_HOSTENCRYPT |
1096			    HFA384X_WEPFLAGS_HOSTDECRYPT)) {
1097		printk(KERN_DEBUG "WEP flags setting failed\n");
1098		return -EOPNOTSUPP;
1099	}
1100
1101	if (local->func->reset_port(dev) ||
1102	    local->func->cmd(dev, HFA384X_CMDCODE_TEST |
1103			     (HFA384X_TEST_MONITOR << 8),
1104			     0, NULL, NULL)) {
1105		printk(KERN_DEBUG "Setting monitor mode failed\n");
1106		return -EOPNOTSUPP;
1107	}
1108
1109	return 0;
1110}
1111
1112
1113static int hostap_monitor_mode_disable(local_info_t *local)
1114{
1115	struct net_device *dev = local->ddev;
1116
1117	if (dev == NULL)
1118		return -1;
1119
1120	printk(KERN_DEBUG "%s: Disabling monitor mode\n", dev->name);
1121	dev->type = ARPHRD_ETHER;
1122
1123	if (local->func->cmd(dev, HFA384X_CMDCODE_TEST |
1124			     (HFA384X_TEST_STOP << 8),
1125			     0, NULL, NULL))
1126		return -1;
1127	return hostap_set_encryption(local);
1128}
1129
1130
1131static int prism2_ioctl_siwmode(struct net_device *dev,
1132				struct iw_request_info *info,
1133				__u32 *mode, char *extra)
1134{
1135	struct hostap_interface *iface;
1136	local_info_t *local;
1137	int double_reset = 0;
1138
1139	iface = netdev_priv(dev);
1140	local = iface->local;
1141
1142	if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
1143	    *mode != IW_MODE_MASTER && *mode != IW_MODE_REPEAT &&
1144	    *mode != IW_MODE_MONITOR)
1145		return -EOPNOTSUPP;
1146
1147#ifdef PRISM2_NO_STATION_MODES
1148	if (*mode == IW_MODE_ADHOC || *mode == IW_MODE_INFRA)
1149		return -EOPNOTSUPP;
1150#endif /* PRISM2_NO_STATION_MODES */
1151
1152	if (*mode == local->iw_mode)
1153		return 0;
1154
1155	if (*mode == IW_MODE_MASTER && local->essid[0] == '\0') {
1156		printk(KERN_WARNING "%s: empty SSID not allowed in Master "
1157		       "mode\n", dev->name);
1158		return -EINVAL;
1159	}
1160
1161	if (local->iw_mode == IW_MODE_MONITOR)
1162		hostap_monitor_mode_disable(local);
1163
1164	if ((local->iw_mode == IW_MODE_ADHOC ||
1165	     local->iw_mode == IW_MODE_MONITOR) && *mode == IW_MODE_MASTER) {
1166		/* There seems to be a firmware bug in at least STA f/w v1.5.6
1167		 * that leaves beacon frames to use IBSS type when moving from
1168		 * IBSS to Host AP mode. Doing double Port0 reset seems to be
1169		 * enough to workaround this. */
1170		double_reset = 1;
1171	}
1172
1173	printk(KERN_DEBUG "prism2: %s: operating mode changed "
1174	       "%d -> %d\n", dev->name, local->iw_mode, *mode);
1175	local->iw_mode = *mode;
1176
1177	if (local->iw_mode == IW_MODE_MONITOR)
1178		hostap_monitor_mode_enable(local);
1179	else if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt &&
1180		 !local->fw_encrypt_ok) {
1181		printk(KERN_DEBUG "%s: defaulting to host-based encryption as "
1182		       "a workaround for firmware bug in Host AP mode WEP\n",
1183		       dev->name);
1184		local->host_encrypt = 1;
1185	}
1186
1187	if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
1188			    hostap_get_porttype(local)))
1189		return -EOPNOTSUPP;
1190
1191	if (local->func->reset_port(dev))
1192		return -EINVAL;
1193	if (double_reset && local->func->reset_port(dev))
1194		return -EINVAL;
1195
1196	if (local->iw_mode != IW_MODE_INFRA && local->iw_mode != IW_MODE_ADHOC)
1197	{
1198		/* netif_carrier is used only in client modes for now, so make
1199		 * sure carrier is on when moving to non-client modes. */
1200		netif_carrier_on(local->dev);
1201		netif_carrier_on(local->ddev);
1202	}
1203	return 0;
1204}
1205
1206
1207static int prism2_ioctl_giwmode(struct net_device *dev,
1208				struct iw_request_info *info,
1209				__u32 *mode, char *extra)
1210{
1211	struct hostap_interface *iface;
1212	local_info_t *local;
1213
1214	iface = netdev_priv(dev);
1215	local = iface->local;
1216
1217	switch (iface->type) {
1218	case HOSTAP_INTERFACE_STA:
1219		*mode = IW_MODE_INFRA;
1220		break;
1221	case HOSTAP_INTERFACE_WDS:
1222		*mode = IW_MODE_REPEAT;
1223		break;
1224	default:
1225		*mode = local->iw_mode;
1226		break;
1227	}
1228	return 0;
1229}
1230
1231
1232static int prism2_ioctl_siwpower(struct net_device *dev,
1233				 struct iw_request_info *info,
1234				 struct iw_param *wrq, char *extra)
1235{
1236#ifdef PRISM2_NO_STATION_MODES
1237	return -EOPNOTSUPP;
1238#else /* PRISM2_NO_STATION_MODES */
1239	int ret = 0;
1240
1241	if (wrq->disabled)
1242		return hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 0);
1243
1244	switch (wrq->flags & IW_POWER_MODE) {
1245	case IW_POWER_UNICAST_R:
1246		ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 0);
1247		if (ret)
1248			return ret;
1249		ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
1250		if (ret)
1251			return ret;
1252		break;
1253	case IW_POWER_ALL_R:
1254		ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 1);
1255		if (ret)
1256			return ret;
1257		ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
1258		if (ret)
1259			return ret;
1260		break;
1261	case IW_POWER_ON:
1262		break;
1263	default:
1264		return -EINVAL;
1265	}
1266
1267	if (wrq->flags & IW_POWER_TIMEOUT) {
1268		ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
1269		if (ret)
1270			return ret;
1271		ret = hostap_set_word(dev, HFA384X_RID_CNFPMHOLDOVERDURATION,
1272				      wrq->value / 1024);
1273		if (ret)
1274			return ret;
1275	}
1276	if (wrq->flags & IW_POWER_PERIOD) {
1277		ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
1278		if (ret)
1279			return ret;
1280		ret = hostap_set_word(dev, HFA384X_RID_CNFMAXSLEEPDURATION,
1281				      wrq->value / 1024);
1282		if (ret)
1283			return ret;
1284	}
1285
1286	return ret;
1287#endif /* PRISM2_NO_STATION_MODES */
1288}
1289
1290
1291static int prism2_ioctl_giwpower(struct net_device *dev,
1292				 struct iw_request_info *info,
1293				 struct iw_param *rrq, char *extra)
1294{
1295#ifdef PRISM2_NO_STATION_MODES
1296	return -EOPNOTSUPP;
1297#else /* PRISM2_NO_STATION_MODES */
1298	struct hostap_interface *iface;
1299	local_info_t *local;
1300	__le16 enable, mcast;
1301
1302	iface = netdev_priv(dev);
1303	local = iface->local;
1304
1305	if (local->func->get_rid(dev, HFA384X_RID_CNFPMENABLED, &enable, 2, 1)
1306	    < 0)
1307		return -EINVAL;
1308
1309	if (!le16_to_cpu(enable)) {
1310		rrq->disabled = 1;
1311		return 0;
1312	}
1313
1314	rrq->disabled = 0;
1315
1316	if ((rrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
1317		__le16 timeout;
1318		if (local->func->get_rid(dev,
1319					 HFA384X_RID_CNFPMHOLDOVERDURATION,
1320					 &timeout, 2, 1) < 0)
1321			return -EINVAL;
1322
1323		rrq->flags = IW_POWER_TIMEOUT;
1324		rrq->value = le16_to_cpu(timeout) * 1024;
1325	} else {
1326		__le16 period;
1327		if (local->func->get_rid(dev, HFA384X_RID_CNFMAXSLEEPDURATION,
1328					 &period, 2, 1) < 0)
1329			return -EINVAL;
1330
1331		rrq->flags = IW_POWER_PERIOD;
1332		rrq->value = le16_to_cpu(period) * 1024;
1333	}
1334
1335	if (local->func->get_rid(dev, HFA384X_RID_CNFMULTICASTRECEIVE, &mcast,
1336				 2, 1) < 0)
1337		return -EINVAL;
1338
1339	if (le16_to_cpu(mcast))
1340		rrq->flags |= IW_POWER_ALL_R;
1341	else
1342		rrq->flags |= IW_POWER_UNICAST_R;
1343
1344	return 0;
1345#endif /* PRISM2_NO_STATION_MODES */
1346}
1347
1348
1349static int prism2_ioctl_siwretry(struct net_device *dev,
1350				 struct iw_request_info *info,
1351				 struct iw_param *rrq, char *extra)
1352{
1353	struct hostap_interface *iface;
1354	local_info_t *local;
1355
1356	iface = netdev_priv(dev);
1357	local = iface->local;
1358
1359	if (rrq->disabled)
1360		return -EINVAL;
1361
1362	/* setting retry limits is not supported with the current station
1363	 * firmware code; simulate this with alternative retry count for now */
1364	if (rrq->flags == IW_RETRY_LIMIT) {
1365		if (rrq->value < 0) {
1366			/* disable manual retry count setting and use firmware
1367			 * defaults */
1368			local->manual_retry_count = -1;
1369			local->tx_control &= ~HFA384X_TX_CTRL_ALT_RTRY;
1370		} else {
1371			if (hostap_set_word(dev, HFA384X_RID_CNFALTRETRYCOUNT,
1372					    rrq->value)) {
1373				printk(KERN_DEBUG "%s: Alternate retry count "
1374				       "setting to %d failed\n",
1375				       dev->name, rrq->value);
1376				return -EOPNOTSUPP;
1377			}
1378
1379			local->manual_retry_count = rrq->value;
1380			local->tx_control |= HFA384X_TX_CTRL_ALT_RTRY;
1381		}
1382		return 0;
1383	}
1384
1385	return -EOPNOTSUPP;
1386
1387#if 0
1388	/* what could be done, if firmware would support this.. */
1389
1390	if (rrq->flags & IW_RETRY_LIMIT) {
1391		if (rrq->flags & IW_RETRY_LONG)
1392			HFA384X_RID_LONGRETRYLIMIT = rrq->value;
1393		else if (rrq->flags & IW_RETRY_SHORT)
1394			HFA384X_RID_SHORTRETRYLIMIT = rrq->value;
1395		else {
1396			HFA384X_RID_LONGRETRYLIMIT = rrq->value;
1397			HFA384X_RID_SHORTRETRYLIMIT = rrq->value;
1398		}
1399
1400	}
1401
1402	if (rrq->flags & IW_RETRY_LIFETIME) {
1403		HFA384X_RID_MAXTRANSMITLIFETIME = rrq->value / 1024;
1404	}
1405
1406	return 0;
1407#endif /* 0 */
1408}
1409
1410static int prism2_ioctl_giwretry(struct net_device *dev,
1411				 struct iw_request_info *info,
1412				 struct iw_param *rrq, char *extra)
1413{
1414	struct hostap_interface *iface;
1415	local_info_t *local;
1416	__le16 shortretry, longretry, lifetime, altretry;
1417
1418	iface = netdev_priv(dev);
1419	local = iface->local;
1420
1421	if (local->func->get_rid(dev, HFA384X_RID_SHORTRETRYLIMIT, &shortretry,
1422				 2, 1) < 0 ||
1423	    local->func->get_rid(dev, HFA384X_RID_LONGRETRYLIMIT, &longretry,
1424				 2, 1) < 0 ||
1425	    local->func->get_rid(dev, HFA384X_RID_MAXTRANSMITLIFETIME,
1426				 &lifetime, 2, 1) < 0)
1427		return -EINVAL;
1428
1429	rrq->disabled = 0;
1430
1431	if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
1432		rrq->flags = IW_RETRY_LIFETIME;
1433		rrq->value = le16_to_cpu(lifetime) * 1024;
1434	} else {
1435		if (local->manual_retry_count >= 0) {
1436			rrq->flags = IW_RETRY_LIMIT;
1437			if (local->func->get_rid(dev,
1438						 HFA384X_RID_CNFALTRETRYCOUNT,
1439						 &altretry, 2, 1) >= 0)
1440				rrq->value = le16_to_cpu(altretry);
1441			else
1442				rrq->value = local->manual_retry_count;
1443		} else if ((rrq->flags & IW_RETRY_LONG)) {
1444			rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
1445			rrq->value = le16_to_cpu(longretry);
1446		} else {
1447			rrq->flags = IW_RETRY_LIMIT;
1448			rrq->value = le16_to_cpu(shortretry);
1449			if (shortretry != longretry)
1450				rrq->flags |= IW_RETRY_SHORT;
1451		}
1452	}
1453	return 0;
1454}
1455
1456
1457/* Note! This TX power controlling is experimental and should not be used in
1458 * production use. It just sets raw power register and does not use any kind of
1459 * feedback information from the measured TX power (CR58). This is now
1460 * commented out to make sure that it is not used by accident. TX power
1461 * configuration will be enabled again after proper algorithm using feedback
1462 * has been implemented. */
1463
1464#ifdef RAW_TXPOWER_SETTING
1465/* Map HFA386x's CR31 to and from dBm with some sort of ad hoc mapping..
1466 * This version assumes following mapping:
1467 * CR31 is 7-bit value with -64 to +63 range.
1468 * -64 is mapped into +20dBm and +63 into -43dBm.
1469 * This is certainly not an exact mapping for every card, but at least
1470 * increasing dBm value should correspond to increasing TX power.
1471 */
1472
1473static int prism2_txpower_hfa386x_to_dBm(u16 val)
1474{
1475	signed char tmp;
1476
1477	if (val > 255)
1478		val = 255;
1479
1480	tmp = val;
1481	tmp >>= 2;
1482
1483	return -12 - tmp;
1484}
1485
1486static u16 prism2_txpower_dBm_to_hfa386x(int val)
1487{
1488	signed char tmp;
1489
1490	if (val > 20)
1491		return 128;
1492	else if (val < -43)
1493		return 127;
1494
1495	tmp = val;
1496	tmp = -12 - tmp;
1497	tmp <<= 2;
1498
1499	return (unsigned char) tmp;
1500}
1501#endif /* RAW_TXPOWER_SETTING */
1502
1503
1504static int prism2_ioctl_siwtxpow(struct net_device *dev,
1505				 struct iw_request_info *info,
1506				 struct iw_param *rrq, char *extra)
1507{
1508	struct hostap_interface *iface;
1509	local_info_t *local;
1510#ifdef RAW_TXPOWER_SETTING
1511	char *tmp;
1512#endif
1513	u16 val;
1514	int ret = 0;
1515
1516	iface = netdev_priv(dev);
1517	local = iface->local;
1518
1519	if (rrq->disabled) {
1520		if (local->txpower_type != PRISM2_TXPOWER_OFF) {
1521			val = 0xff; /* use all standby and sleep modes */
1522			ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
1523					       HFA386X_CR_A_D_TEST_MODES2,
1524					       &val, NULL);
1525			printk(KERN_DEBUG "%s: Turning radio off: %s\n",
1526			       dev->name, ret ? "failed" : "OK");
1527			local->txpower_type = PRISM2_TXPOWER_OFF;
1528		}
1529		return (ret ? -EOPNOTSUPP : 0);
1530	}
1531
1532	if (local->txpower_type == PRISM2_TXPOWER_OFF) {
1533		val = 0; /* disable all standby and sleep modes */
1534		ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
1535				       HFA386X_CR_A_D_TEST_MODES2, &val, NULL);
1536		printk(KERN_DEBUG "%s: Turning radio on: %s\n",
1537		       dev->name, ret ? "failed" : "OK");
1538		local->txpower_type = PRISM2_TXPOWER_UNKNOWN;
1539	}
1540
1541#ifdef RAW_TXPOWER_SETTING
1542	if (!rrq->fixed && local->txpower_type != PRISM2_TXPOWER_AUTO) {
1543		printk(KERN_DEBUG "Setting ALC on\n");
1544		val = HFA384X_TEST_CFG_BIT_ALC;
1545		local->func->cmd(dev, HFA384X_CMDCODE_TEST |
1546				 (HFA384X_TEST_CFG_BITS << 8), 1, &val, NULL);
1547		local->txpower_type = PRISM2_TXPOWER_AUTO;
1548		return 0;
1549	}
1550
1551	if (local->txpower_type != PRISM2_TXPOWER_FIXED) {
1552		printk(KERN_DEBUG "Setting ALC off\n");
1553		val = HFA384X_TEST_CFG_BIT_ALC;
1554		local->func->cmd(dev, HFA384X_CMDCODE_TEST |
1555				 (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL);
1556			local->txpower_type = PRISM2_TXPOWER_FIXED;
1557	}
1558
1559	if (rrq->flags == IW_TXPOW_DBM)
1560		tmp = "dBm";
1561	else if (rrq->flags == IW_TXPOW_MWATT)
1562		tmp = "mW";
1563	else
1564		tmp = "UNKNOWN";
1565	printk(KERN_DEBUG "Setting TX power to %d %s\n", rrq->value, tmp);
1566
1567	if (rrq->flags != IW_TXPOW_DBM) {
1568		printk("SIOCSIWTXPOW with mW is not supported; use dBm\n");
1569		return -EOPNOTSUPP;
1570	}
1571
1572	local->txpower = rrq->value;
1573	val = prism2_txpower_dBm_to_hfa386x(local->txpower);
1574	if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
1575			     HFA386X_CR_MANUAL_TX_POWER, &val, NULL))
1576		ret = -EOPNOTSUPP;
1577#else /* RAW_TXPOWER_SETTING */
1578	if (rrq->fixed)
1579		ret = -EOPNOTSUPP;
1580#endif /* RAW_TXPOWER_SETTING */
1581
1582	return ret;
1583}
1584
1585static int prism2_ioctl_giwtxpow(struct net_device *dev,
1586				 struct iw_request_info *info,
1587				 struct iw_param *rrq, char *extra)
1588{
1589#ifdef RAW_TXPOWER_SETTING
1590	struct hostap_interface *iface;
1591	local_info_t *local;
1592	u16 resp0;
1593
1594	iface = netdev_priv(dev);
1595	local = iface->local;
1596
1597	rrq->flags = IW_TXPOW_DBM;
1598	rrq->disabled = 0;
1599	rrq->fixed = 0;
1600
1601	if (local->txpower_type == PRISM2_TXPOWER_AUTO) {
1602		if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF,
1603				     HFA386X_CR_MANUAL_TX_POWER,
1604				     NULL, &resp0) == 0) {
1605			rrq->value = prism2_txpower_hfa386x_to_dBm(resp0);
1606		} else {
1607			/* Could not get real txpower; guess 15 dBm */
1608			rrq->value = 15;
1609		}
1610	} else if (local->txpower_type == PRISM2_TXPOWER_OFF) {
1611		rrq->value = 0;
1612		rrq->disabled = 1;
1613	} else if (local->txpower_type == PRISM2_TXPOWER_FIXED) {
1614		rrq->value = local->txpower;
1615		rrq->fixed = 1;
1616	} else {
1617		printk("SIOCGIWTXPOW - unknown txpower_type=%d\n",
1618		       local->txpower_type);
1619	}
1620	return 0;
1621#else /* RAW_TXPOWER_SETTING */
1622	return -EOPNOTSUPP;
1623#endif /* RAW_TXPOWER_SETTING */
1624}
1625
1626
1627#ifndef PRISM2_NO_STATION_MODES
1628
1629/* HostScan request works with and without host_roaming mode. In addition, it
1630 * does not break current association. However, it requires newer station
1631 * firmware version (>= 1.3.1) than scan request. */
1632static int prism2_request_hostscan(struct net_device *dev,
1633				   u8 *ssid, u8 ssid_len)
1634{
1635	struct hostap_interface *iface;
1636	local_info_t *local;
1637	struct hfa384x_hostscan_request scan_req;
1638
1639	iface = netdev_priv(dev);
1640	local = iface->local;
1641
1642	memset(&scan_req, 0, sizeof(scan_req));
1643	scan_req.channel_list = cpu_to_le16(local->channel_mask &
1644					    local->scan_channel_mask);
1645	scan_req.txrate = cpu_to_le16(HFA384X_RATES_1MBPS);
1646	if (ssid) {
1647		if (ssid_len > 32)
1648			return -EINVAL;
1649		scan_req.target_ssid_len = cpu_to_le16(ssid_len);
1650		memcpy(scan_req.target_ssid, ssid, ssid_len);
1651	}
1652
1653	if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req,
1654				 sizeof(scan_req))) {
1655		printk(KERN_DEBUG "%s: HOSTSCAN failed\n", dev->name);
1656		return -EINVAL;
1657	}
1658	return 0;
1659}
1660
1661
1662static int prism2_request_scan(struct net_device *dev)
1663{
1664	struct hostap_interface *iface;
1665	local_info_t *local;
1666	struct hfa384x_scan_request scan_req;
1667	int ret = 0;
1668
1669	iface = netdev_priv(dev);
1670	local = iface->local;
1671
1672	memset(&scan_req, 0, sizeof(scan_req));
1673	scan_req.channel_list = cpu_to_le16(local->channel_mask &
1674					    local->scan_channel_mask);
1675	scan_req.txrate = cpu_to_le16(HFA384X_RATES_1MBPS);
1676
1677	/* FIX:
1678	 * It seems to be enough to set roaming mode for a short moment to
1679	 * host-based and then setup scanrequest data and return the mode to
1680	 * firmware-based.
1681	 *
1682	 * Master mode would need to drop to Managed mode for a short while
1683	 * to make scanning work.. Or sweep through the different channels and
1684	 * use passive scan based on beacons. */
1685
1686	if (!local->host_roaming)
1687		hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE,
1688				HFA384X_ROAMING_HOST);
1689
1690	if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST, &scan_req,
1691				 sizeof(scan_req))) {
1692		printk(KERN_DEBUG "SCANREQUEST failed\n");
1693		ret = -EINVAL;
1694	}
1695
1696	if (!local->host_roaming)
1697		hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE,
1698				HFA384X_ROAMING_FIRMWARE);
1699
1700	return ret;
1701}
1702
1703#else /* !PRISM2_NO_STATION_MODES */
1704
1705static inline int prism2_request_hostscan(struct net_device *dev,
1706					  u8 *ssid, u8 ssid_len)
1707{
1708	return -EOPNOTSUPP;
1709}
1710
1711
1712static inline int prism2_request_scan(struct net_device *dev)
1713{
1714	return -EOPNOTSUPP;
1715}
1716
1717#endif /* !PRISM2_NO_STATION_MODES */
1718
1719
1720static int prism2_ioctl_siwscan(struct net_device *dev,
1721				struct iw_request_info *info,
1722				struct iw_point *data, char *extra)
1723{
1724	struct hostap_interface *iface;
1725	local_info_t *local;
1726	int ret;
1727	u8 *ssid = NULL, ssid_len = 0;
1728	struct iw_scan_req *req = (struct iw_scan_req *) extra;
1729
1730	iface = netdev_priv(dev);
1731	local = iface->local;
1732
1733	if (data->length < sizeof(struct iw_scan_req))
1734		req = NULL;
1735
1736	if (local->iw_mode == IW_MODE_MASTER) {
1737		/* In master mode, we just return the results of our local
1738		 * tables, so we don't need to start anything...
1739		 * Jean II */
1740		data->length = 0;
1741		return 0;
1742	}
1743
1744	if (!local->dev_enabled)
1745		return -ENETDOWN;
1746
1747	if (req && data->flags & IW_SCAN_THIS_ESSID) {
1748		ssid = req->essid;
1749		ssid_len = req->essid_len;
1750
1751		if (ssid_len &&
1752		    ((local->iw_mode != IW_MODE_INFRA &&
1753		      local->iw_mode != IW_MODE_ADHOC) ||
1754		     (local->sta_fw_ver < PRISM2_FW_VER(1,3,1))))
1755			return -EOPNOTSUPP;
1756	}
1757
1758	if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1))
1759		ret = prism2_request_hostscan(dev, ssid, ssid_len);
1760	else
1761		ret = prism2_request_scan(dev);
1762
1763	if (ret == 0)
1764		local->scan_timestamp = jiffies;
1765
1766	/* Could inquire F101, F103 or wait for SIOCGIWSCAN and read RID */
1767
1768	return ret;
1769}
1770
1771
1772#ifndef PRISM2_NO_STATION_MODES
1773static char * __prism2_translate_scan(local_info_t *local,
1774				      struct iw_request_info *info,
1775				      struct hfa384x_hostscan_result *scan,
1776				      struct hostap_bss_info *bss,
1777				      char *current_ev, char *end_buf)
1778{
1779	int i, chan;
1780	struct iw_event iwe;
1781	char *current_val;
1782	u16 capabilities;
1783	u8 *pos;
1784	u8 *ssid, *bssid;
1785	size_t ssid_len;
1786	char *buf;
1787
1788	if (bss) {
1789		ssid = bss->ssid;
1790		ssid_len = bss->ssid_len;
1791		bssid = bss->bssid;
1792	} else {
1793		ssid = scan->ssid;
1794		ssid_len = le16_to_cpu(scan->ssid_len);
1795		bssid = scan->bssid;
1796	}
1797	if (ssid_len > 32)
1798		ssid_len = 32;
1799
1800	/* First entry *MUST* be the AP MAC address */
1801	memset(&iwe, 0, sizeof(iwe));
1802	iwe.cmd = SIOCGIWAP;
1803	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1804	memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN);
1805	current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1806					  IW_EV_ADDR_LEN);
1807
1808	/* Other entries will be displayed in the order we give them */
1809
1810	memset(&iwe, 0, sizeof(iwe));
1811	iwe.cmd = SIOCGIWESSID;
1812	iwe.u.data.length = ssid_len;
1813	iwe.u.data.flags = 1;
1814	current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1815					  &iwe, ssid);
1816
1817	memset(&iwe, 0, sizeof(iwe));
1818	iwe.cmd = SIOCGIWMODE;
1819	if (bss) {
1820		capabilities = bss->capab_info;
1821	} else {
1822		capabilities = le16_to_cpu(scan->capability);
1823	}
1824	if (capabilities & (WLAN_CAPABILITY_ESS |
1825			    WLAN_CAPABILITY_IBSS)) {
1826		if (capabilities & WLAN_CAPABILITY_ESS)
1827			iwe.u.mode = IW_MODE_MASTER;
1828		else
1829			iwe.u.mode = IW_MODE_ADHOC;
1830		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
1831						  &iwe, IW_EV_UINT_LEN);
1832	}
1833
1834	memset(&iwe, 0, sizeof(iwe));
1835	iwe.cmd = SIOCGIWFREQ;
1836	if (scan) {
1837		chan = le16_to_cpu(scan->chid);
1838	} else if (bss) {
1839		chan = bss->chan;
1840	} else {
1841		chan = 0;
1842	}
1843
1844	if (chan > 0) {
1845		iwe.u.freq.m = freq_list[chan - 1] * 100000;
1846		iwe.u.freq.e = 1;
1847		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
1848						  &iwe, IW_EV_FREQ_LEN);
1849	}
1850
1851	if (scan) {
1852		memset(&iwe, 0, sizeof(iwe));
1853		iwe.cmd = IWEVQUAL;
1854		if (local->last_scan_type == PRISM2_HOSTSCAN) {
1855			iwe.u.qual.level = le16_to_cpu(scan->sl);
1856			iwe.u.qual.noise = le16_to_cpu(scan->anl);
1857		} else {
1858			iwe.u.qual.level =
1859				HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->sl));
1860			iwe.u.qual.noise =
1861				HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->anl));
1862		}
1863		iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
1864			| IW_QUAL_NOISE_UPDATED
1865			| IW_QUAL_QUAL_INVALID
1866			| IW_QUAL_DBM;
1867		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
1868						  &iwe, IW_EV_QUAL_LEN);
1869	}
1870
1871	memset(&iwe, 0, sizeof(iwe));
1872	iwe.cmd = SIOCGIWENCODE;
1873	if (capabilities & WLAN_CAPABILITY_PRIVACY)
1874		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1875	else
1876		iwe.u.data.flags = IW_ENCODE_DISABLED;
1877	iwe.u.data.length = 0;
1878	current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, "");
1879
1880	/* TODO: add SuppRates into BSS table */
1881	if (scan) {
1882		memset(&iwe, 0, sizeof(iwe));
1883		iwe.cmd = SIOCGIWRATE;
1884		current_val = current_ev + iwe_stream_lcp_len(info);
1885		pos = scan->sup_rates;
1886		for (i = 0; i < sizeof(scan->sup_rates); i++) {
1887			if (pos[i] == 0)
1888				break;
1889			/* Bit rate given in 500 kb/s units (+ 0x80) */
1890			iwe.u.bitrate.value = ((pos[i] & 0x7f) * 500000);
1891			current_val = iwe_stream_add_value(
1892				info, current_ev, current_val, end_buf, &iwe,
1893				IW_EV_PARAM_LEN);
1894		}
1895		/* Check if we added any event */
1896		if ((current_val - current_ev) > iwe_stream_lcp_len(info))
1897			current_ev = current_val;
1898	}
1899
1900	/* TODO: add BeaconInt,resp_rate,atim into BSS table */
1901	buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_ATOMIC);
1902	if (buf && scan) {
1903		memset(&iwe, 0, sizeof(iwe));
1904		iwe.cmd = IWEVCUSTOM;
1905		sprintf(buf, "bcn_int=%d", le16_to_cpu(scan->beacon_interval));
1906		iwe.u.data.length = strlen(buf);
1907		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1908						  &iwe, buf);
1909
1910		memset(&iwe, 0, sizeof(iwe));
1911		iwe.cmd = IWEVCUSTOM;
1912		sprintf(buf, "resp_rate=%d", le16_to_cpu(scan->rate));
1913		iwe.u.data.length = strlen(buf);
1914		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1915						  &iwe, buf);
1916
1917		if (local->last_scan_type == PRISM2_HOSTSCAN &&
1918		    (capabilities & WLAN_CAPABILITY_IBSS)) {
1919			memset(&iwe, 0, sizeof(iwe));
1920			iwe.cmd = IWEVCUSTOM;
1921			sprintf(buf, "atim=%d", le16_to_cpu(scan->atim));
1922			iwe.u.data.length = strlen(buf);
1923			current_ev = iwe_stream_add_point(info, current_ev,
1924							  end_buf, &iwe, buf);
1925		}
1926	}
1927	kfree(buf);
1928
1929	if (bss && bss->wpa_ie_len > 0 && bss->wpa_ie_len <= MAX_WPA_IE_LEN) {
1930		memset(&iwe, 0, sizeof(iwe));
1931		iwe.cmd = IWEVGENIE;
1932		iwe.u.data.length = bss->wpa_ie_len;
1933		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1934						  &iwe, bss->wpa_ie);
1935	}
1936
1937	if (bss && bss->rsn_ie_len > 0 && bss->rsn_ie_len <= MAX_WPA_IE_LEN) {
1938		memset(&iwe, 0, sizeof(iwe));
1939		iwe.cmd = IWEVGENIE;
1940		iwe.u.data.length = bss->rsn_ie_len;
1941		current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1942						  &iwe, bss->rsn_ie);
1943	}
1944
1945	return current_ev;
1946}
1947
1948
1949/* Translate scan data returned from the card to a card independent
1950 * format that the Wireless Tools will understand - Jean II */
1951static inline int prism2_translate_scan(local_info_t *local,
1952					struct iw_request_info *info,
1953					char *buffer, int buflen)
1954{
1955	struct hfa384x_hostscan_result *scan;
1956	int entry, hostscan;
1957	char *current_ev = buffer;
1958	char *end_buf = buffer + buflen;
1959	struct list_head *ptr;
1960
1961	spin_lock_bh(&local->lock);
1962
1963	list_for_each(ptr, &local->bss_list) {
1964		struct hostap_bss_info *bss;
1965		bss = list_entry(ptr, struct hostap_bss_info, list);
1966		bss->included = 0;
1967	}
1968
1969	hostscan = local->last_scan_type == PRISM2_HOSTSCAN;
1970	for (entry = 0; entry < local->last_scan_results_count; entry++) {
1971		int found = 0;
1972		scan = &local->last_scan_results[entry];
1973
1974		/* Report every SSID if the AP is using multiple SSIDs. If no
1975		 * BSS record is found (e.g., when WPA mode is disabled),
1976		 * report the AP once. */
1977		list_for_each(ptr, &local->bss_list) {
1978			struct hostap_bss_info *bss;
1979			bss = list_entry(ptr, struct hostap_bss_info, list);
1980			if (memcmp(bss->bssid, scan->bssid, ETH_ALEN) == 0) {
1981				bss->included = 1;
1982				current_ev = __prism2_translate_scan(
1983					local, info, scan, bss, current_ev,
1984					end_buf);
1985				found++;
1986			}
1987		}
1988		if (!found) {
1989			current_ev = __prism2_translate_scan(
1990				local, info, scan, NULL, current_ev, end_buf);
1991		}
1992		/* Check if there is space for one more entry */
1993		if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) {
1994			/* Ask user space to try again with a bigger buffer */
1995			spin_unlock_bh(&local->lock);
1996			return -E2BIG;
1997		}
1998	}
1999
2000	/* Prism2 firmware has limits (32 at least in some versions) for number
2001	 * of BSSes in scan results. Extend this limit by using local BSS list.
2002	 */
2003	list_for_each(ptr, &local->bss_list) {
2004		struct hostap_bss_info *bss;
2005		bss = list_entry(ptr, struct hostap_bss_info, list);
2006		if (bss->included)
2007			continue;
2008		current_ev = __prism2_translate_scan(local, info, NULL, bss,
2009						     current_ev, end_buf);
2010		/* Check if there is space for one more entry */
2011		if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) {
2012			/* Ask user space to try again with a bigger buffer */
2013			spin_unlock_bh(&local->lock);
2014			return -E2BIG;
2015		}
2016	}
2017
2018	spin_unlock_bh(&local->lock);
2019
2020	return current_ev - buffer;
2021}
2022#endif /* PRISM2_NO_STATION_MODES */
2023
2024
2025static inline int prism2_ioctl_giwscan_sta(struct net_device *dev,
2026					   struct iw_request_info *info,
2027					   struct iw_point *data, char *extra)
2028{
2029#ifdef PRISM2_NO_STATION_MODES
2030	return -EOPNOTSUPP;
2031#else /* PRISM2_NO_STATION_MODES */
2032	struct hostap_interface *iface;
2033	local_info_t *local;
2034	int res;
2035
2036	iface = netdev_priv(dev);
2037	local = iface->local;
2038
2039	/* Wait until the scan is finished. We can probably do better
2040	 * than that - Jean II */
2041	if (local->scan_timestamp &&
2042	    time_before(jiffies, local->scan_timestamp + 3 * HZ)) {
2043		/* Important note : we don't want to block the caller
2044		 * until results are ready for various reasons.
2045		 * First, managing wait queues is complex and racy
2046		 * (there may be multiple simultaneous callers).
2047		 * Second, we grab some rtnetlink lock before coming
2048		 * here (in dev_ioctl()).
2049		 * Third, the caller can wait on the Wireless Event
2050		 * - Jean II */
2051		return -EAGAIN;
2052	}
2053	local->scan_timestamp = 0;
2054
2055	res = prism2_translate_scan(local, info, extra, data->length);
2056
2057	if (res >= 0) {
2058		data->length = res;
2059		return 0;
2060	} else {
2061		data->length = 0;
2062		return res;
2063	}
2064#endif /* PRISM2_NO_STATION_MODES */
2065}
2066
2067
2068static int prism2_ioctl_giwscan(struct net_device *dev,
2069				struct iw_request_info *info,
2070				struct iw_point *data, char *extra)
2071{
2072	struct hostap_interface *iface;
2073	local_info_t *local;
2074	int res;
2075
2076	iface = netdev_priv(dev);
2077	local = iface->local;
2078
2079	if (local->iw_mode == IW_MODE_MASTER) {
2080		/* In MASTER mode, it doesn't make sense to go around
2081		 * scanning the frequencies and make the stations we serve
2082		 * wait when what the user is really interested about is the
2083		 * list of stations and access points we are talking to.
2084		 * So, just extract results from our cache...
2085		 * Jean II */
2086
2087		/* Translate to WE format */
2088		res = prism2_ap_translate_scan(dev, info, extra);
2089		if (res >= 0) {
2090			printk(KERN_DEBUG "Scan result translation succeeded "
2091			       "(length=%d)\n", res);
2092			data->length = res;
2093			return 0;
2094		} else {
2095			printk(KERN_DEBUG
2096			       "Scan result translation failed (res=%d)\n",
2097			       res);
2098			data->length = 0;
2099			return res;
2100		}
2101	} else {
2102		/* Station mode */
2103		return prism2_ioctl_giwscan_sta(dev, info, data, extra);
2104	}
2105}
2106
2107
2108static const struct iw_priv_args prism2_priv[] = {
2109	{ PRISM2_IOCTL_MONITOR,
2110	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor" },
2111	{ PRISM2_IOCTL_READMIF,
2112	  IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
2113	  IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "readmif" },
2114	{ PRISM2_IOCTL_WRITEMIF,
2115	  IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2, 0, "writemif" },
2116	{ PRISM2_IOCTL_RESET,
2117	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "reset" },
2118	{ PRISM2_IOCTL_INQUIRE,
2119	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "inquire" },
2120	{ PRISM2_IOCTL_SET_RID_WORD,
2121	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_rid_word" },
2122	{ PRISM2_IOCTL_MACCMD,
2123	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maccmd" },
2124	{ PRISM2_IOCTL_WDS_ADD,
2125	  IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_add" },
2126	{ PRISM2_IOCTL_WDS_DEL,
2127	  IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_del" },
2128	{ PRISM2_IOCTL_ADDMAC,
2129	  IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addmac" },
2130	{ PRISM2_IOCTL_DELMAC,
2131	  IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "delmac" },
2132	{ PRISM2_IOCTL_KICKMAC,
2133	  IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "kickmac" },
2134	/* --- raw access to sub-ioctls --- */
2135	{ PRISM2_IOCTL_PRISM2_PARAM,
2136	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "prism2_param" },
2137	{ PRISM2_IOCTL_GET_PRISM2_PARAM,
2138	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
2139	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprism2_param" },
2140	/* --- sub-ioctls handlers --- */
2141	{ PRISM2_IOCTL_PRISM2_PARAM,
2142	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" },
2143	{ PRISM2_IOCTL_GET_PRISM2_PARAM,
2144	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" },
2145	/* --- sub-ioctls definitions --- */
2146	{ PRISM2_PARAM_TXRATECTRL,
2147	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "txratectrl" },
2148	{ PRISM2_PARAM_TXRATECTRL,
2149	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettxratectrl" },
2150	{ PRISM2_PARAM_BEACON_INT,
2151	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beacon_int" },
2152	{ PRISM2_PARAM_BEACON_INT,
2153	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbeacon_int" },
2154#ifndef PRISM2_NO_STATION_MODES
2155	{ PRISM2_PARAM_PSEUDO_IBSS,
2156	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "pseudo_ibss" },
2157	{ PRISM2_PARAM_PSEUDO_IBSS,
2158	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpseudo_ibss" },
2159#endif /* PRISM2_NO_STATION_MODES */
2160	{ PRISM2_PARAM_ALC,
2161	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "alc" },
2162	{ PRISM2_PARAM_ALC,
2163	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getalc" },
2164	{ PRISM2_PARAM_DUMP,
2165	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dump" },
2166	{ PRISM2_PARAM_DUMP,
2167	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdump" },
2168	{ PRISM2_PARAM_OTHER_AP_POLICY,
2169	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "other_ap_policy" },
2170	{ PRISM2_PARAM_OTHER_AP_POLICY,
2171	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getother_ap_pol" },
2172	{ PRISM2_PARAM_AP_MAX_INACTIVITY,
2173	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_inactivity" },
2174	{ PRISM2_PARAM_AP_MAX_INACTIVITY,
2175	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_inactivi" },
2176	{ PRISM2_PARAM_AP_BRIDGE_PACKETS,
2177	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bridge_packets" },
2178	{ PRISM2_PARAM_AP_BRIDGE_PACKETS,
2179	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbridge_packe" },
2180	{ PRISM2_PARAM_DTIM_PERIOD,
2181	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dtim_period" },
2182	{ PRISM2_PARAM_DTIM_PERIOD,
2183	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdtim_period" },
2184	{ PRISM2_PARAM_AP_NULLFUNC_ACK,
2185	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "nullfunc_ack" },
2186	{ PRISM2_PARAM_AP_NULLFUNC_ACK,
2187	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getnullfunc_ack" },
2188	{ PRISM2_PARAM_MAX_WDS,
2189	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_wds" },
2190	{ PRISM2_PARAM_MAX_WDS,
2191	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_wds" },
2192	{ PRISM2_PARAM_AP_AUTOM_AP_WDS,
2193	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "autom_ap_wds" },
2194	{ PRISM2_PARAM_AP_AUTOM_AP_WDS,
2195	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getautom_ap_wds" },
2196	{ PRISM2_PARAM_AP_AUTH_ALGS,
2197	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_auth_algs" },
2198	{ PRISM2_PARAM_AP_AUTH_ALGS,
2199	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_auth_algs" },
2200	{ PRISM2_PARAM_MONITOR_ALLOW_FCSERR,
2201	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "allow_fcserr" },
2202	{ PRISM2_PARAM_MONITOR_ALLOW_FCSERR,
2203	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getallow_fcserr" },
2204	{ PRISM2_PARAM_HOST_ENCRYPT,
2205	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_encrypt" },
2206	{ PRISM2_PARAM_HOST_ENCRYPT,
2207	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_encrypt" },
2208	{ PRISM2_PARAM_HOST_DECRYPT,
2209	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_decrypt" },
2210	{ PRISM2_PARAM_HOST_DECRYPT,
2211	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_decrypt" },
2212#ifndef PRISM2_NO_STATION_MODES
2213	{ PRISM2_PARAM_HOST_ROAMING,
2214	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_roaming" },
2215	{ PRISM2_PARAM_HOST_ROAMING,
2216	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_roaming" },
2217#endif /* PRISM2_NO_STATION_MODES */
2218	{ PRISM2_PARAM_BCRX_STA_KEY,
2219	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bcrx_sta_key" },
2220	{ PRISM2_PARAM_BCRX_STA_KEY,
2221	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbcrx_sta_key" },
2222	{ PRISM2_PARAM_IEEE_802_1X,
2223	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ieee_802_1x" },
2224	{ PRISM2_PARAM_IEEE_802_1X,
2225	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getieee_802_1x" },
2226	{ PRISM2_PARAM_ANTSEL_TX,
2227	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_tx" },
2228	{ PRISM2_PARAM_ANTSEL_TX,
2229	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_tx" },
2230	{ PRISM2_PARAM_ANTSEL_RX,
2231	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_rx" },
2232	{ PRISM2_PARAM_ANTSEL_RX,
2233	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_rx" },
2234	{ PRISM2_PARAM_MONITOR_TYPE,
2235	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor_type" },
2236	{ PRISM2_PARAM_MONITOR_TYPE,
2237	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmonitor_type" },
2238	{ PRISM2_PARAM_WDS_TYPE,
2239	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wds_type" },
2240	{ PRISM2_PARAM_WDS_TYPE,
2241	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwds_type" },
2242	{ PRISM2_PARAM_HOSTSCAN,
2243	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostscan" },
2244	{ PRISM2_PARAM_HOSTSCAN,
2245	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostscan" },
2246	{ PRISM2_PARAM_AP_SCAN,
2247	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_scan" },
2248	{ PRISM2_PARAM_AP_SCAN,
2249	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_scan" },
2250	{ PRISM2_PARAM_ENH_SEC,
2251	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "enh_sec" },
2252	{ PRISM2_PARAM_ENH_SEC,
2253	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getenh_sec" },
2254#ifdef PRISM2_IO_DEBUG
2255	{ PRISM2_PARAM_IO_DEBUG,
2256	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "io_debug" },
2257	{ PRISM2_PARAM_IO_DEBUG,
2258	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getio_debug" },
2259#endif /* PRISM2_IO_DEBUG */
2260	{ PRISM2_PARAM_BASIC_RATES,
2261	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "basic_rates" },
2262	{ PRISM2_PARAM_BASIC_RATES,
2263	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbasic_rates" },
2264	{ PRISM2_PARAM_OPER_RATES,
2265	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "oper_rates" },
2266	{ PRISM2_PARAM_OPER_RATES,
2267	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getoper_rates" },
2268	{ PRISM2_PARAM_HOSTAPD,
2269	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd" },
2270	{ PRISM2_PARAM_HOSTAPD,
2271	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd" },
2272	{ PRISM2_PARAM_HOSTAPD_STA,
2273	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd_sta" },
2274	{ PRISM2_PARAM_HOSTAPD_STA,
2275	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd_sta" },
2276	{ PRISM2_PARAM_WPA,
2277	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wpa" },
2278	{ PRISM2_PARAM_WPA,
2279	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwpa" },
2280	{ PRISM2_PARAM_PRIVACY_INVOKED,
2281	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "privacy_invoked" },
2282	{ PRISM2_PARAM_PRIVACY_INVOKED,
2283	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprivacy_invo" },
2284	{ PRISM2_PARAM_TKIP_COUNTERMEASURES,
2285	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "tkip_countermea" },
2286	{ PRISM2_PARAM_TKIP_COUNTERMEASURES,
2287	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettkip_counter" },
2288	{ PRISM2_PARAM_DROP_UNENCRYPTED,
2289	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "drop_unencrypte" },
2290	{ PRISM2_PARAM_DROP_UNENCRYPTED,
2291	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdrop_unencry" },
2292	{ PRISM2_PARAM_SCAN_CHANNEL_MASK,
2293	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "scan_channels" },
2294	{ PRISM2_PARAM_SCAN_CHANNEL_MASK,
2295	  0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getscan_channel" },
2296};
2297
2298
2299static int prism2_ioctl_priv_inquire(struct net_device *dev, int *i)
2300{
2301	struct hostap_interface *iface;
2302	local_info_t *local;
2303
2304	iface = netdev_priv(dev);
2305	local = iface->local;
2306
2307	if (local->func->cmd(dev, HFA384X_CMDCODE_INQUIRE, *i, NULL, NULL))
2308		return -EOPNOTSUPP;
2309
2310	return 0;
2311}
2312
2313
2314static int prism2_ioctl_priv_prism2_param(struct net_device *dev,
2315					  struct iw_request_info *info,
2316					  void *wrqu, char *extra)
2317{
2318	struct hostap_interface *iface;
2319	local_info_t *local;
2320	int *i = (int *) extra;
2321	int param = *i;
2322	int value = *(i + 1);
2323	int ret = 0;
2324	u16 val;
2325
2326	iface = netdev_priv(dev);
2327	local = iface->local;
2328
2329	switch (param) {
2330	case PRISM2_PARAM_TXRATECTRL:
2331		local->fw_tx_rate_control = value;
2332		break;
2333
2334	case PRISM2_PARAM_BEACON_INT:
2335		if (hostap_set_word(dev, HFA384X_RID_CNFBEACONINT, value) ||
2336		    local->func->reset_port(dev))
2337			ret = -EINVAL;
2338		else
2339			local->beacon_int = value;
2340		break;
2341
2342#ifndef PRISM2_NO_STATION_MODES
2343	case PRISM2_PARAM_PSEUDO_IBSS:
2344		if (value == local->pseudo_adhoc)
2345			break;
2346
2347		if (value != 0 && value != 1) {
2348			ret = -EINVAL;
2349			break;
2350		}
2351
2352		printk(KERN_DEBUG "prism2: %s: pseudo IBSS change %d -> %d\n",
2353		       dev->name, local->pseudo_adhoc, value);
2354		local->pseudo_adhoc = value;
2355		if (local->iw_mode != IW_MODE_ADHOC)
2356			break;
2357
2358		if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
2359				    hostap_get_porttype(local))) {
2360			ret = -EOPNOTSUPP;
2361			break;
2362		}
2363
2364		if (local->func->reset_port(dev))
2365			ret = -EINVAL;
2366		break;
2367#endif /* PRISM2_NO_STATION_MODES */
2368
2369	case PRISM2_PARAM_ALC:
2370		printk(KERN_DEBUG "%s: %s ALC\n", dev->name,
2371		       value == 0 ? "Disabling" : "Enabling");
2372		val = HFA384X_TEST_CFG_BIT_ALC;
2373		local->func->cmd(dev, HFA384X_CMDCODE_TEST |
2374				 (HFA384X_TEST_CFG_BITS << 8),
2375				 value == 0 ? 0 : 1, &val, NULL);
2376		break;
2377
2378	case PRISM2_PARAM_DUMP:
2379		local->frame_dump = value;
2380		break;
2381
2382	case PRISM2_PARAM_OTHER_AP_POLICY:
2383		if (value < 0 || value > 3) {
2384			ret = -EINVAL;
2385			break;
2386		}
2387		if (local->ap != NULL)
2388			local->ap->ap_policy = value;
2389		break;
2390
2391	case PRISM2_PARAM_AP_MAX_INACTIVITY:
2392		if (value < 0 || value > 7 * 24 * 60 * 60) {
2393			ret = -EINVAL;
2394			break;
2395		}
2396		if (local->ap != NULL)
2397			local->ap->max_inactivity = value * HZ;
2398		break;
2399
2400	case PRISM2_PARAM_AP_BRIDGE_PACKETS:
2401		if (local->ap != NULL)
2402			local->ap->bridge_packets = value;
2403		break;
2404
2405	case PRISM2_PARAM_DTIM_PERIOD:
2406		if (value < 0 || value > 65535) {
2407			ret = -EINVAL;
2408			break;
2409		}
2410		if (hostap_set_word(dev, HFA384X_RID_CNFOWNDTIMPERIOD, value)
2411		    || local->func->reset_port(dev))
2412			ret = -EINVAL;
2413		else
2414			local->dtim_period = value;
2415		break;
2416
2417	case PRISM2_PARAM_AP_NULLFUNC_ACK:
2418		if (local->ap != NULL)
2419			local->ap->nullfunc_ack = value;
2420		break;
2421
2422	case PRISM2_PARAM_MAX_WDS:
2423		local->wds_max_connections = value;
2424		break;
2425
2426	case PRISM2_PARAM_AP_AUTOM_AP_WDS:
2427		if (local->ap != NULL) {
2428			if (!local->ap->autom_ap_wds && value) {
2429				/* add WDS link to all APs in STA table */
2430				hostap_add_wds_links(local);
2431			}
2432			local->ap->autom_ap_wds = value;
2433		}
2434		break;
2435
2436	case PRISM2_PARAM_AP_AUTH_ALGS:
2437		local->auth_algs = value;
2438		if (hostap_set_auth_algs(local))
2439			ret = -EINVAL;
2440		break;
2441
2442	case PRISM2_PARAM_MONITOR_ALLOW_FCSERR:
2443		local->monitor_allow_fcserr = value;
2444		break;
2445
2446	case PRISM2_PARAM_HOST_ENCRYPT:
2447		local->host_encrypt = value;
2448		if (hostap_set_encryption(local) ||
2449		    local->func->reset_port(dev))
2450			ret = -EINVAL;
2451		break;
2452
2453	case PRISM2_PARAM_HOST_DECRYPT:
2454		local->host_decrypt = value;
2455		if (hostap_set_encryption(local) ||
2456		    local->func->reset_port(dev))
2457			ret = -EINVAL;
2458		break;
2459
2460#ifndef PRISM2_NO_STATION_MODES
2461	case PRISM2_PARAM_HOST_ROAMING:
2462		if (value < 0 || value > 2) {
2463			ret = -EINVAL;
2464			break;
2465		}
2466		local->host_roaming = value;
2467		if (hostap_set_roaming(local) || local->func->reset_port(dev))
2468			ret = -EINVAL;
2469		break;
2470#endif /* PRISM2_NO_STATION_MODES */
2471
2472	case PRISM2_PARAM_BCRX_STA_KEY:
2473		local->bcrx_sta_key = value;
2474		break;
2475
2476	case PRISM2_PARAM_IEEE_802_1X:
2477		local->ieee_802_1x = value;
2478		break;
2479
2480	case PRISM2_PARAM_ANTSEL_TX:
2481		if (value < 0 || value > HOSTAP_ANTSEL_HIGH) {
2482			ret = -EINVAL;
2483			break;
2484		}
2485		local->antsel_tx = value;
2486		hostap_set_antsel(local);
2487		break;
2488
2489	case PRISM2_PARAM_ANTSEL_RX:
2490		if (value < 0 || value > HOSTAP_ANTSEL_HIGH) {
2491			ret = -EINVAL;
2492			break;
2493		}
2494		local->antsel_rx = value;
2495		hostap_set_antsel(local);
2496		break;
2497
2498	case PRISM2_PARAM_MONITOR_TYPE:
2499		if (value != PRISM2_MONITOR_80211 &&
2500		    value != PRISM2_MONITOR_CAPHDR &&
2501		    value != PRISM2_MONITOR_PRISM &&
2502		    value != PRISM2_MONITOR_RADIOTAP) {
2503			ret = -EINVAL;
2504			break;
2505		}
2506		local->monitor_type = value;
2507		if (local->iw_mode == IW_MODE_MONITOR)
2508			hostap_monitor_set_type(local);
2509		break;
2510
2511	case PRISM2_PARAM_WDS_TYPE:
2512		local->wds_type = value;
2513		break;
2514
2515	case PRISM2_PARAM_HOSTSCAN:
2516	{
2517		struct hfa384x_hostscan_request scan_req;
2518		u16 rate;
2519
2520		memset(&scan_req, 0, sizeof(scan_req));
2521		scan_req.channel_list = cpu_to_le16(0x3fff);
2522		switch (value) {
2523		case 1: rate = HFA384X_RATES_1MBPS; break;
2524		case 2: rate = HFA384X_RATES_2MBPS; break;
2525		case 3: rate = HFA384X_RATES_5MBPS; break;
2526		case 4: rate = HFA384X_RATES_11MBPS; break;
2527		default: rate = HFA384X_RATES_1MBPS; break;
2528		}
2529		scan_req.txrate = cpu_to_le16(rate);
2530		/* leave SSID empty to accept all SSIDs */
2531
2532		if (local->iw_mode == IW_MODE_MASTER) {
2533			if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
2534					    HFA384X_PORTTYPE_BSS) ||
2535			    local->func->reset_port(dev))
2536				printk(KERN_DEBUG "Leaving Host AP mode "
2537				       "for HostScan failed\n");
2538		}
2539
2540		if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req,
2541					 sizeof(scan_req))) {
2542			printk(KERN_DEBUG "HOSTSCAN failed\n");
2543			ret = -EINVAL;
2544		}
2545		if (local->iw_mode == IW_MODE_MASTER) {
2546			wait_queue_t __wait;
2547			init_waitqueue_entry(&__wait, current);
2548			add_wait_queue(&local->hostscan_wq, &__wait);
2549			set_current_state(TASK_INTERRUPTIBLE);
2550			schedule_timeout(HZ);
2551			if (signal_pending(current))
2552				ret = -EINTR;
2553			set_current_state(TASK_RUNNING);
2554			remove_wait_queue(&local->hostscan_wq, &__wait);
2555
2556			if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
2557					    HFA384X_PORTTYPE_HOSTAP) ||
2558			    local->func->reset_port(dev))
2559				printk(KERN_DEBUG "Returning to Host AP mode "
2560				       "after HostScan failed\n");
2561		}
2562		break;
2563	}
2564
2565	case PRISM2_PARAM_AP_SCAN:
2566		local->passive_scan_interval = value;
2567		if (timer_pending(&local->passive_scan_timer))
2568			del_timer(&local->passive_scan_timer);
2569		if (value > 0) {
2570			local->passive_scan_timer.expires = jiffies +
2571				local->passive_scan_interval * HZ;
2572			add_timer(&local->passive_scan_timer);
2573		}
2574		break;
2575
2576	case PRISM2_PARAM_ENH_SEC:
2577		if (value < 0 || value > 3) {
2578			ret = -EINVAL;
2579			break;
2580		}
2581		local->enh_sec = value;
2582		if (hostap_set_word(dev, HFA384X_RID_CNFENHSECURITY,
2583				    local->enh_sec) ||
2584		    local->func->reset_port(dev)) {
2585			printk(KERN_INFO "%s: cnfEnhSecurity requires STA f/w "
2586			       "1.6.3 or newer\n", dev->name);
2587			ret = -EOPNOTSUPP;
2588		}
2589		break;
2590
2591#ifdef PRISM2_IO_DEBUG
2592	case PRISM2_PARAM_IO_DEBUG:
2593		local->io_debug_enabled = value;
2594		break;
2595#endif /* PRISM2_IO_DEBUG */
2596
2597	case PRISM2_PARAM_BASIC_RATES:
2598		if ((value & local->tx_rate_control) != value || value == 0) {
2599			printk(KERN_INFO "%s: invalid basic rate set - basic "
2600			       "rates must be in supported rate set\n",
2601			       dev->name);
2602			ret = -EINVAL;
2603			break;
2604		}
2605		local->basic_rates = value;
2606		if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES,
2607				    local->basic_rates) ||
2608		    local->func->reset_port(dev))
2609			ret = -EINVAL;
2610		break;
2611
2612	case PRISM2_PARAM_OPER_RATES:
2613		local->tx_rate_control = value;
2614		if (hostap_set_rate(dev))
2615			ret = -EINVAL;
2616		break;
2617
2618	case PRISM2_PARAM_HOSTAPD:
2619		ret = hostap_set_hostapd(local, value, 1);
2620		break;
2621
2622	case PRISM2_PARAM_HOSTAPD_STA:
2623		ret = hostap_set_hostapd_sta(local, value, 1);
2624		break;
2625
2626	case PRISM2_PARAM_WPA:
2627		local->wpa = value;
2628		if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
2629			ret = -EOPNOTSUPP;
2630		else if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE,
2631					 value ? 1 : 0))
2632			ret = -EINVAL;
2633		break;
2634
2635	case PRISM2_PARAM_PRIVACY_INVOKED:
2636		local->privacy_invoked = value;
2637		if (hostap_set_encryption(local) ||
2638		    local->func->reset_port(dev))
2639			ret = -EINVAL;
2640		break;
2641
2642	case PRISM2_PARAM_TKIP_COUNTERMEASURES:
2643		local->tkip_countermeasures = value;
2644		break;
2645
2646	case PRISM2_PARAM_DROP_UNENCRYPTED:
2647		local->drop_unencrypted = value;
2648		break;
2649
2650	case PRISM2_PARAM_SCAN_CHANNEL_MASK:
2651		local->scan_channel_mask = value;
2652		break;
2653
2654	default:
2655		printk(KERN_DEBUG "%s: prism2_param: unknown param %d\n",
2656		       dev->name, param);
2657		ret = -EOPNOTSUPP;
2658		break;
2659	}
2660
2661	return ret;
2662}
2663
2664
2665static int prism2_ioctl_priv_get_prism2_param(struct net_device *dev,
2666					      struct iw_request_info *info,
2667					      void *wrqu, char *extra)
2668{
2669	struct hostap_interface *iface;
2670	local_info_t *local;
2671	int *param = (int *) extra;
2672	int ret = 0;
2673
2674	iface = netdev_priv(dev);
2675	local = iface->local;
2676
2677	switch (*param) {
2678	case PRISM2_PARAM_TXRATECTRL:
2679		*param = local->fw_tx_rate_control;
2680		break;
2681
2682	case PRISM2_PARAM_BEACON_INT:
2683		*param = local->beacon_int;
2684		break;
2685
2686	case PRISM2_PARAM_PSEUDO_IBSS:
2687		*param = local->pseudo_adhoc;
2688		break;
2689
2690	case PRISM2_PARAM_ALC:
2691		ret = -EOPNOTSUPP; /* FIX */
2692		break;
2693
2694	case PRISM2_PARAM_DUMP:
2695		*param = local->frame_dump;
2696		break;
2697
2698	case PRISM2_PARAM_OTHER_AP_POLICY:
2699		if (local->ap != NULL)
2700			*param = local->ap->ap_policy;
2701		else
2702			ret = -EOPNOTSUPP;
2703		break;
2704
2705	case PRISM2_PARAM_AP_MAX_INACTIVITY:
2706		if (local->ap != NULL)
2707			*param = local->ap->max_inactivity / HZ;
2708		else
2709			ret = -EOPNOTSUPP;
2710		break;
2711
2712	case PRISM2_PARAM_AP_BRIDGE_PACKETS:
2713		if (local->ap != NULL)
2714			*param = local->ap->bridge_packets;
2715		else
2716			ret = -EOPNOTSUPP;
2717		break;
2718
2719	case PRISM2_PARAM_DTIM_PERIOD:
2720		*param = local->dtim_period;
2721		break;
2722
2723	case PRISM2_PARAM_AP_NULLFUNC_ACK:
2724		if (local->ap != NULL)
2725			*param = local->ap->nullfunc_ack;
2726		else
2727			ret = -EOPNOTSUPP;
2728		break;
2729
2730	case PRISM2_PARAM_MAX_WDS:
2731		*param = local->wds_max_connections;
2732		break;
2733
2734	case PRISM2_PARAM_AP_AUTOM_AP_WDS:
2735		if (local->ap != NULL)
2736			*param = local->ap->autom_ap_wds;
2737		else
2738			ret = -EOPNOTSUPP;
2739		break;
2740
2741	case PRISM2_PARAM_AP_AUTH_ALGS:
2742		*param = local->auth_algs;
2743		break;
2744
2745	case PRISM2_PARAM_MONITOR_ALLOW_FCSERR:
2746		*param = local->monitor_allow_fcserr;
2747		break;
2748
2749	case PRISM2_PARAM_HOST_ENCRYPT:
2750		*param = local->host_encrypt;
2751		break;
2752
2753	case PRISM2_PARAM_HOST_DECRYPT:
2754		*param = local->host_decrypt;
2755		break;
2756
2757	case PRISM2_PARAM_HOST_ROAMING:
2758		*param = local->host_roaming;
2759		break;
2760
2761	case PRISM2_PARAM_BCRX_STA_KEY:
2762		*param = local->bcrx_sta_key;
2763		break;
2764
2765	case PRISM2_PARAM_IEEE_802_1X:
2766		*param = local->ieee_802_1x;
2767		break;
2768
2769	case PRISM2_PARAM_ANTSEL_TX:
2770		*param = local->antsel_tx;
2771		break;
2772
2773	case PRISM2_PARAM_ANTSEL_RX:
2774		*param = local->antsel_rx;
2775		break;
2776
2777	case PRISM2_PARAM_MONITOR_TYPE:
2778		*param = local->monitor_type;
2779		break;
2780
2781	case PRISM2_PARAM_WDS_TYPE:
2782		*param = local->wds_type;
2783		break;
2784
2785	case PRISM2_PARAM_HOSTSCAN:
2786		ret = -EOPNOTSUPP;
2787		break;
2788
2789	case PRISM2_PARAM_AP_SCAN:
2790		*param = local->passive_scan_interval;
2791		break;
2792
2793	case PRISM2_PARAM_ENH_SEC:
2794		*param = local->enh_sec;
2795		break;
2796
2797#ifdef PRISM2_IO_DEBUG
2798	case PRISM2_PARAM_IO_DEBUG:
2799		*param = local->io_debug_enabled;
2800		break;
2801#endif /* PRISM2_IO_DEBUG */
2802
2803	case PRISM2_PARAM_BASIC_RATES:
2804		*param = local->basic_rates;
2805		break;
2806
2807	case PRISM2_PARAM_OPER_RATES:
2808		*param = local->tx_rate_control;
2809		break;
2810
2811	case PRISM2_PARAM_HOSTAPD:
2812		*param = local->hostapd;
2813		break;
2814
2815	case PRISM2_PARAM_HOSTAPD_STA:
2816		*param = local->hostapd_sta;
2817		break;
2818
2819	case PRISM2_PARAM_WPA:
2820		if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
2821			ret = -EOPNOTSUPP;
2822		*param = local->wpa;
2823		break;
2824
2825	case PRISM2_PARAM_PRIVACY_INVOKED:
2826		*param = local->privacy_invoked;
2827		break;
2828
2829	case PRISM2_PARAM_TKIP_COUNTERMEASURES:
2830		*param = local->tkip_countermeasures;
2831		break;
2832
2833	case PRISM2_PARAM_DROP_UNENCRYPTED:
2834		*param = local->drop_unencrypted;
2835		break;
2836
2837	case PRISM2_PARAM_SCAN_CHANNEL_MASK:
2838		*param = local->scan_channel_mask;
2839		break;
2840
2841	default:
2842		printk(KERN_DEBUG "%s: get_prism2_param: unknown param %d\n",
2843		       dev->name, *param);
2844		ret = -EOPNOTSUPP;
2845		break;
2846	}
2847
2848	return ret;
2849}
2850
2851
2852static int prism2_ioctl_priv_readmif(struct net_device *dev,
2853				     struct iw_request_info *info,
2854				     void *wrqu, char *extra)
2855{
2856	struct hostap_interface *iface;
2857	local_info_t *local;
2858	u16 resp0;
2859
2860	iface = netdev_priv(dev);
2861	local = iface->local;
2862
2863	if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF, *extra, NULL,
2864			     &resp0))
2865		return -EOPNOTSUPP;
2866	else
2867		*extra = resp0;
2868
2869	return 0;
2870}
2871
2872
2873static int prism2_ioctl_priv_writemif(struct net_device *dev,
2874				      struct iw_request_info *info,
2875				      void *wrqu, char *extra)
2876{
2877	struct hostap_interface *iface;
2878	local_info_t *local;
2879	u16 cr, val;
2880
2881	iface = netdev_priv(dev);
2882	local = iface->local;
2883
2884	cr = *extra;
2885	val = *(extra + 1);
2886	if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, cr, &val, NULL))
2887		return -EOPNOTSUPP;
2888
2889	return 0;
2890}
2891
2892
2893static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i)
2894{
2895	struct hostap_interface *iface;
2896	local_info_t *local;
2897	int ret = 0;
2898	u32 mode;
2899
2900	iface = netdev_priv(dev);
2901	local = iface->local;
2902
2903	printk(KERN_DEBUG "%s: process %d (%s) used deprecated iwpriv monitor "
2904	       "- update software to use iwconfig mode monitor\n",
2905	       dev->name, task_pid_nr(current), current->comm);
2906
2907	/* Backward compatibility code - this can be removed at some point */
2908
2909	if (*i == 0) {
2910		/* Disable monitor mode - old mode was not saved, so go to
2911		 * Master mode */
2912		mode = IW_MODE_MASTER;
2913		ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL);
2914	} else if (*i == 1) {
2915		/* netlink socket mode is not supported anymore since it did
2916		 * not separate different devices from each other and was not
2917		 * best method for delivering large amount of packets to
2918		 * user space */
2919		ret = -EOPNOTSUPP;
2920	} else if (*i == 2 || *i == 3) {
2921		switch (*i) {
2922		case 2:
2923			local->monitor_type = PRISM2_MONITOR_80211;
2924			break;
2925		case 3:
2926			local->monitor_type = PRISM2_MONITOR_PRISM;
2927			break;
2928		}
2929		mode = IW_MODE_MONITOR;
2930		ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL);
2931		hostap_monitor_mode_enable(local);
2932	} else
2933		ret = -EINVAL;
2934
2935	return ret;
2936}
2937
2938
2939static int prism2_ioctl_priv_reset(struct net_device *dev, int *i)
2940{
2941	struct hostap_interface *iface;
2942	local_info_t *local;
2943
2944	iface = netdev_priv(dev);
2945	local = iface->local;
2946
2947	printk(KERN_DEBUG "%s: manual reset request(%d)\n", dev->name, *i);
2948	switch (*i) {
2949	case 0:
2950		/* Disable and enable card */
2951		local->func->hw_shutdown(dev, 1);
2952		local->func->hw_config(dev, 0);
2953		break;
2954
2955	case 1:
2956		/* COR sreset */
2957		local->func->hw_reset(dev);
2958		break;
2959
2960	case 2:
2961		/* Disable and enable port 0 */
2962		local->func->reset_port(dev);
2963		break;
2964
2965	case 3:
2966		prism2_sta_deauth(local, WLAN_REASON_DEAUTH_LEAVING);
2967		if (local->func->cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL,
2968				     NULL))
2969			return -EINVAL;
2970		break;
2971
2972	case 4:
2973		if (local->func->cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL,
2974				     NULL))
2975			return -EINVAL;
2976		break;
2977
2978	default:
2979		printk(KERN_DEBUG "Unknown reset request %d\n", *i);
2980		return -EOPNOTSUPP;
2981	}
2982
2983	return 0;
2984}
2985
2986
2987static int prism2_ioctl_priv_set_rid_word(struct net_device *dev, int *i)
2988{
2989	int rid = *i;
2990	int value = *(i + 1);
2991
2992	printk(KERN_DEBUG "%s: Set RID[0x%X] = %d\n", dev->name, rid, value);
2993
2994	if (hostap_set_word(dev, rid, value))
2995		return -EINVAL;
2996
2997	return 0;
2998}
2999
3000
3001#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
3002static int ap_mac_cmd_ioctl(local_info_t *local, int *cmd)
3003{
3004	int ret = 0;
3005
3006	switch (*cmd) {
3007	case AP_MAC_CMD_POLICY_OPEN:
3008		local->ap->mac_restrictions.policy = MAC_POLICY_OPEN;
3009		break;
3010	case AP_MAC_CMD_POLICY_ALLOW:
3011		local->ap->mac_restrictions.policy = MAC_POLICY_ALLOW;
3012		break;
3013	case AP_MAC_CMD_POLICY_DENY:
3014		local->ap->mac_restrictions.policy = MAC_POLICY_DENY;
3015		break;
3016	case AP_MAC_CMD_FLUSH:
3017		ap_control_flush_macs(&local->ap->mac_restrictions);
3018		break;
3019	case AP_MAC_CMD_KICKALL:
3020		ap_control_kickall(local->ap);
3021		hostap_deauth_all_stas(local->dev, local->ap, 0);
3022		break;
3023	default:
3024		ret = -EOPNOTSUPP;
3025		break;
3026	}
3027
3028	return ret;
3029}
3030#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
3031
3032
3033#ifdef PRISM2_DOWNLOAD_SUPPORT
3034static int prism2_ioctl_priv_download(local_info_t *local, struct iw_point *p)
3035{
3036	struct prism2_download_param *param;
3037	int ret = 0;
3038
3039	if (p->length < sizeof(struct prism2_download_param) ||
3040	    p->length > 1024 || !p->pointer)
3041		return -EINVAL;
3042
3043	param = kmalloc(p->length, GFP_KERNEL);
3044	if (param == NULL)
3045		return -ENOMEM;
3046
3047	if (copy_from_user(param, p->pointer, p->length)) {
3048		ret = -EFAULT;
3049		goto out;
3050	}
3051
3052	if (p->length < sizeof(struct prism2_download_param) +
3053	    param->num_areas * sizeof(struct prism2_download_area)) {
3054		ret = -EINVAL;
3055		goto out;
3056	}
3057
3058	ret = local->func->download(local, param);
3059
3060 out:
3061	kfree(param);
3062	return ret;
3063}
3064#endif /* PRISM2_DOWNLOAD_SUPPORT */
3065
3066
3067static int prism2_set_genericelement(struct net_device *dev, u8 *elem,
3068				     size_t len)
3069{
3070	struct hostap_interface *iface = netdev_priv(dev);
3071	local_info_t *local = iface->local;
3072	u8 *buf;
3073
3074	/*
3075	 * Add 16-bit length in the beginning of the buffer because Prism2 RID
3076	 * includes it.
3077	 */
3078	buf = kmalloc(len + 2, GFP_KERNEL);
3079	if (buf == NULL)
3080		return -ENOMEM;
3081
3082	*((__le16 *) buf) = cpu_to_le16(len);
3083	memcpy(buf + 2, elem, len);
3084
3085	kfree(local->generic_elem);
3086	local->generic_elem = buf;
3087	local->generic_elem_len = len + 2;
3088
3089	return local->func->set_rid(local->dev, HFA384X_RID_GENERICELEMENT,
3090				    buf, len + 2);
3091}
3092
3093
3094static int prism2_ioctl_siwauth(struct net_device *dev,
3095				struct iw_request_info *info,
3096				struct iw_param *data, char *extra)
3097{
3098	struct hostap_interface *iface = netdev_priv(dev);
3099	local_info_t *local = iface->local;
3100
3101	switch (data->flags & IW_AUTH_INDEX) {
3102	case IW_AUTH_WPA_VERSION:
3103	case IW_AUTH_CIPHER_PAIRWISE:
3104	case IW_AUTH_CIPHER_GROUP:
3105	case IW_AUTH_KEY_MGMT:
3106		/*
3107		 * Host AP driver does not use these parameters and allows
3108		 * wpa_supplicant to control them internally.
3109		 */
3110		break;
3111	case IW_AUTH_TKIP_COUNTERMEASURES:
3112		local->tkip_countermeasures = data->value;
3113		break;
3114	case IW_AUTH_DROP_UNENCRYPTED:
3115		local->drop_unencrypted = data->value;
3116		break;
3117	case IW_AUTH_80211_AUTH_ALG:
3118		local->auth_algs = data->value;
3119		break;
3120	case IW_AUTH_WPA_ENABLED:
3121		if (data->value == 0) {
3122			local->wpa = 0;
3123			if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
3124				break;
3125			prism2_set_genericelement(dev, "", 0);
3126			local->host_roaming = 0;
3127			local->privacy_invoked = 0;
3128			if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE,
3129					    0) ||
3130			    hostap_set_roaming(local) ||
3131			    hostap_set_encryption(local) ||
3132			    local->func->reset_port(dev))
3133				return -EINVAL;
3134			break;
3135		}
3136		if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0))
3137			return -EOPNOTSUPP;
3138		local->host_roaming = 2;
3139		local->privacy_invoked = 1;
3140		local->wpa = 1;
3141		if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE, 1) ||
3142		    hostap_set_roaming(local) ||
3143		    hostap_set_encryption(local) ||
3144		    local->func->reset_port(dev))
3145			return -EINVAL;
3146		break;
3147	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
3148		local->ieee_802_1x = data->value;
3149		break;
3150	case IW_AUTH_PRIVACY_INVOKED:
3151		local->privacy_invoked = data->value;
3152		break;
3153	default:
3154		return -EOPNOTSUPP;
3155	}
3156	return 0;
3157}
3158
3159
3160static int prism2_ioctl_giwauth(struct net_device *dev,
3161				struct iw_request_info *info,
3162				struct iw_param *data, char *extra)
3163{
3164	struct hostap_interface *iface = netdev_priv(dev);
3165	local_info_t *local = iface->local;
3166
3167	switch (data->flags & IW_AUTH_INDEX) {
3168	case IW_AUTH_WPA_VERSION:
3169	case IW_AUTH_CIPHER_PAIRWISE:
3170	case IW_AUTH_CIPHER_GROUP:
3171	case IW_AUTH_KEY_MGMT:
3172		/*
3173		 * Host AP driver does not use these parameters and allows
3174		 * wpa_supplicant to control them internally.
3175		 */
3176		return -EOPNOTSUPP;
3177	case IW_AUTH_TKIP_COUNTERMEASURES:
3178		data->value = local->tkip_countermeasures;
3179		break;
3180	case IW_AUTH_DROP_UNENCRYPTED:
3181		data->value = local->drop_unencrypted;
3182		break;
3183	case IW_AUTH_80211_AUTH_ALG:
3184		data->value = local->auth_algs;
3185		break;
3186	case IW_AUTH_WPA_ENABLED:
3187		data->value = local->wpa;
3188		break;
3189	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
3190		data->value = local->ieee_802_1x;
3191		break;
3192	default:
3193		return -EOPNOTSUPP;
3194	}
3195	return 0;
3196}
3197
3198
3199static int prism2_ioctl_siwencodeext(struct net_device *dev,
3200				     struct iw_request_info *info,
3201				     struct iw_point *erq, char *extra)
3202{
3203	struct hostap_interface *iface = netdev_priv(dev);
3204	local_info_t *local = iface->local;
3205	struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
3206	int i, ret = 0;
3207	struct lib80211_crypto_ops *ops;
3208	struct lib80211_crypt_data **crypt;
3209	void *sta_ptr;
3210	u8 *addr;
3211	const char *alg, *module;
3212
3213	i = erq->flags & IW_ENCODE_INDEX;
3214	if (i > WEP_KEYS)
3215		return -EINVAL;
3216	if (i < 1 || i > WEP_KEYS)
3217		i = local->crypt_info.tx_keyidx;
3218	else
3219		i--;
3220	if (i < 0 || i >= WEP_KEYS)
3221		return -EINVAL;
3222
3223	addr = ext->addr.sa_data;
3224	if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
3225	    addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
3226		sta_ptr = NULL;
3227		crypt = &local->crypt_info.crypt[i];
3228	} else {
3229		if (i != 0)
3230			return -EINVAL;
3231		sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt);
3232		if (sta_ptr == NULL) {
3233			if (local->iw_mode == IW_MODE_INFRA) {
3234				/*
3235				 * TODO: add STA entry for the current AP so
3236				 * that unicast key can be used. For now, this
3237				 * is emulated by using default key idx 0.
3238				 */
3239				i = 0;
3240				crypt = &local->crypt_info.crypt[i];
3241			} else
3242				return -EINVAL;
3243		}
3244	}
3245
3246	if ((erq->flags & IW_ENCODE_DISABLED) ||
3247	    ext->alg == IW_ENCODE_ALG_NONE) {
3248		if (*crypt)
3249			lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
3250		goto done;
3251	}
3252
3253	switch (ext->alg) {
3254	case IW_ENCODE_ALG_WEP:
3255		alg = "WEP";
3256		module = "lib80211_crypt_wep";
3257		break;
3258	case IW_ENCODE_ALG_TKIP:
3259		alg = "TKIP";
3260		module = "lib80211_crypt_tkip";
3261		break;
3262	case IW_ENCODE_ALG_CCMP:
3263		alg = "CCMP";
3264		module = "lib80211_crypt_ccmp";
3265		break;
3266	default:
3267		printk(KERN_DEBUG "%s: unsupported algorithm %d\n",
3268		       local->dev->name, ext->alg);
3269		ret = -EOPNOTSUPP;
3270		goto done;
3271	}
3272
3273	ops = lib80211_get_crypto_ops(alg);
3274	if (ops == NULL) {
3275		request_module(module);
3276		ops = lib80211_get_crypto_ops(alg);
3277	}
3278	if (ops == NULL) {
3279		printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
3280		       local->dev->name, alg);
3281		ret = -EOPNOTSUPP;
3282		goto done;
3283	}
3284
3285	if (sta_ptr || ext->alg != IW_ENCODE_ALG_WEP) {
3286		/*
3287		 * Per station encryption and other than WEP algorithms
3288		 * require host-based encryption, so force them on
3289		 * automatically.
3290		 */
3291		local->host_decrypt = local->host_encrypt = 1;
3292	}
3293
3294	if (*crypt == NULL || (*crypt)->ops != ops) {
3295		struct lib80211_crypt_data *new_crypt;
3296
3297		lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
3298
3299		new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
3300				GFP_KERNEL);
3301		if (new_crypt == NULL) {
3302			ret = -ENOMEM;
3303			goto done;
3304		}
3305		new_crypt->ops = ops;
3306		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
3307			new_crypt->priv = new_crypt->ops->init(i);
3308		if (new_crypt->priv == NULL) {
3309			kfree(new_crypt);
3310			ret = -EINVAL;
3311			goto done;
3312		}
3313
3314		*crypt = new_crypt;
3315	}
3316
3317	/*
3318	 * TODO: if ext_flags does not have IW_ENCODE_EXT_RX_SEQ_VALID, the
3319	 * existing seq# should not be changed.
3320	 * TODO: if ext_flags has IW_ENCODE_EXT_TX_SEQ_VALID, next TX seq#
3321	 * should be changed to something else than zero.
3322	 */
3323	if ((!(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) || ext->key_len > 0)
3324	    && (*crypt)->ops->set_key &&
3325	    (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
3326				   (*crypt)->priv) < 0) {
3327		printk(KERN_DEBUG "%s: key setting failed\n",
3328		       local->dev->name);
3329		ret = -EINVAL;
3330		goto done;
3331	}
3332
3333	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
3334		if (!sta_ptr)
3335			local->crypt_info.tx_keyidx = i;
3336	}
3337
3338
3339	if (sta_ptr == NULL && ext->key_len > 0) {
3340		int first = 1, j;
3341		for (j = 0; j < WEP_KEYS; j++) {
3342			if (j != i && local->crypt_info.crypt[j]) {
3343				first = 0;
3344				break;
3345			}
3346		}
3347		if (first)
3348			local->crypt_info.tx_keyidx = i;
3349	}
3350
3351 done:
3352	if (sta_ptr)
3353		hostap_handle_sta_release(sta_ptr);
3354
3355	local->open_wep = erq->flags & IW_ENCODE_OPEN;
3356
3357	/*
3358	 * Do not reset port0 if card is in Managed mode since resetting will
3359	 * generate new IEEE 802.11 authentication which may end up in looping
3360	 * with IEEE 802.1X. Prism2 documentation seem to require port reset
3361	 * after WEP configuration. However, keys are apparently changed at
3362	 * least in Managed mode.
3363	 */
3364	if (ret == 0 &&
3365	    (hostap_set_encryption(local) ||
3366	     (local->iw_mode != IW_MODE_INFRA &&
3367	      local->func->reset_port(local->dev))))
3368		ret = -EINVAL;
3369
3370	return ret;
3371}
3372
3373
3374static int prism2_ioctl_giwencodeext(struct net_device *dev,
3375				     struct iw_request_info *info,
3376				     struct iw_point *erq, char *extra)
3377{
3378	struct hostap_interface *iface = netdev_priv(dev);
3379	local_info_t *local = iface->local;
3380	struct lib80211_crypt_data **crypt;
3381	void *sta_ptr;
3382	int max_key_len, i;
3383	struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
3384	u8 *addr;
3385
3386	max_key_len = erq->length - sizeof(*ext);
3387	if (max_key_len < 0)
3388		return -EINVAL;
3389
3390	i = erq->flags & IW_ENCODE_INDEX;
3391	if (i < 1 || i > WEP_KEYS)
3392		i = local->crypt_info.tx_keyidx;
3393	else
3394		i--;
3395
3396	addr = ext->addr.sa_data;
3397	if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
3398	    addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
3399		sta_ptr = NULL;
3400		crypt = &local->crypt_info.crypt[i];
3401	} else {
3402		i = 0;
3403		sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt);
3404		if (sta_ptr == NULL)
3405			return -EINVAL;
3406	}
3407	erq->flags = i + 1;
3408	memset(ext, 0, sizeof(*ext));
3409
3410	if (*crypt == NULL || (*crypt)->ops == NULL) {
3411		ext->alg = IW_ENCODE_ALG_NONE;
3412		ext->key_len = 0;
3413		erq->flags |= IW_ENCODE_DISABLED;
3414	} else {
3415		if (strcmp((*crypt)->ops->name, "WEP") == 0)
3416			ext->alg = IW_ENCODE_ALG_WEP;
3417		else if (strcmp((*crypt)->ops->name, "TKIP") == 0)
3418			ext->alg = IW_ENCODE_ALG_TKIP;
3419		else if (strcmp((*crypt)->ops->name, "CCMP") == 0)
3420			ext->alg = IW_ENCODE_ALG_CCMP;
3421		else
3422			return -EINVAL;
3423
3424		if ((*crypt)->ops->get_key) {
3425			ext->key_len =
3426				(*crypt)->ops->get_key(ext->key,
3427						       max_key_len,
3428						       ext->tx_seq,
3429						       (*crypt)->priv);
3430			if (ext->key_len &&
3431			    (ext->alg == IW_ENCODE_ALG_TKIP ||
3432			     ext->alg == IW_ENCODE_ALG_CCMP))
3433				ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
3434		}
3435	}
3436
3437	if (sta_ptr)
3438		hostap_handle_sta_release(sta_ptr);
3439
3440	return 0;
3441}
3442
3443
3444static int prism2_ioctl_set_encryption(local_info_t *local,
3445				       struct prism2_hostapd_param *param,
3446				       int param_len)
3447{
3448	int ret = 0;
3449	struct lib80211_crypto_ops *ops;
3450	struct lib80211_crypt_data **crypt;
3451	void *sta_ptr;
3452
3453	param->u.crypt.err = 0;
3454	param->u.crypt.alg[HOSTAP_CRYPT_ALG_NAME_LEN - 1] = '\0';
3455
3456	if (param_len !=
3457	    (int) ((char *) param->u.crypt.key - (char *) param) +
3458	    param->u.crypt.key_len)
3459		return -EINVAL;
3460
3461	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3462	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3463	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3464		if (param->u.crypt.idx >= WEP_KEYS)
3465			return -EINVAL;
3466		sta_ptr = NULL;
3467		crypt = &local->crypt_info.crypt[param->u.crypt.idx];
3468	} else {
3469		if (param->u.crypt.idx)
3470			return -EINVAL;
3471		sta_ptr = ap_crypt_get_ptrs(
3472			local->ap, param->sta_addr,
3473			(param->u.crypt.flags & HOSTAP_CRYPT_FLAG_PERMANENT),
3474			&crypt);
3475
3476		if (sta_ptr == NULL) {
3477			param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
3478			return -EINVAL;
3479		}
3480	}
3481
3482	if (strcmp(param->u.crypt.alg, "none") == 0) {
3483		if (crypt)
3484			lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
3485		goto done;
3486	}
3487
3488	ops = lib80211_get_crypto_ops(param->u.crypt.alg);
3489	if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
3490		request_module("lib80211_crypt_wep");
3491		ops = lib80211_get_crypto_ops(param->u.crypt.alg);
3492	} else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
3493		request_module("lib80211_crypt_tkip");
3494		ops = lib80211_get_crypto_ops(param->u.crypt.alg);
3495	} else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
3496		request_module("lib80211_crypt_ccmp");
3497		ops = lib80211_get_crypto_ops(param->u.crypt.alg);
3498	}
3499	if (ops == NULL) {
3500		printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
3501		       local->dev->name, param->u.crypt.alg);
3502		param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ALG;
3503		ret = -EINVAL;
3504		goto done;
3505	}
3506
3507	/* station based encryption and other than WEP algorithms require
3508	 * host-based encryption, so force them on automatically */
3509	local->host_decrypt = local->host_encrypt = 1;
3510
3511	if (*crypt == NULL || (*crypt)->ops != ops) {
3512		struct lib80211_crypt_data *new_crypt;
3513
3514		lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
3515
3516		new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
3517				GFP_KERNEL);
3518		if (new_crypt == NULL) {
3519			ret = -ENOMEM;
3520			goto done;
3521		}
3522		new_crypt->ops = ops;
3523		new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx);
3524		if (new_crypt->priv == NULL) {
3525			kfree(new_crypt);
3526			param->u.crypt.err =
3527				HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED;
3528			ret = -EINVAL;
3529			goto done;
3530		}
3531
3532		*crypt = new_crypt;
3533	}
3534
3535	if ((!(param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) ||
3536	     param->u.crypt.key_len > 0) && (*crypt)->ops->set_key &&
3537	    (*crypt)->ops->set_key(param->u.crypt.key,
3538				   param->u.crypt.key_len, param->u.crypt.seq,
3539				   (*crypt)->priv) < 0) {
3540		printk(KERN_DEBUG "%s: key setting failed\n",
3541		       local->dev->name);
3542		param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED;
3543		ret = -EINVAL;
3544		goto done;
3545	}
3546
3547	if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) {
3548		if (!sta_ptr)
3549			local->crypt_info.tx_keyidx = param->u.crypt.idx;
3550		else if (param->u.crypt.idx) {
3551			printk(KERN_DEBUG "%s: TX key idx setting failed\n",
3552			       local->dev->name);
3553			param->u.crypt.err =
3554				HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED;
3555			ret = -EINVAL;
3556			goto done;
3557		}
3558	}
3559
3560 done:
3561	if (sta_ptr)
3562		hostap_handle_sta_release(sta_ptr);
3563
3564	/* Do not reset port0 if card is in Managed mode since resetting will
3565	 * generate new IEEE 802.11 authentication which may end up in looping
3566	 * with IEEE 802.1X. Prism2 documentation seem to require port reset
3567	 * after WEP configuration. However, keys are apparently changed at
3568	 * least in Managed mode. */
3569	if (ret == 0 &&
3570	    (hostap_set_encryption(local) ||
3571	     (local->iw_mode != IW_MODE_INFRA &&
3572	      local->func->reset_port(local->dev)))) {
3573		param->u.crypt.err = HOSTAP_CRYPT_ERR_CARD_CONF_FAILED;
3574		return -EINVAL;
3575	}
3576
3577	return ret;
3578}
3579
3580
3581static int prism2_ioctl_get_encryption(local_info_t *local,
3582				       struct prism2_hostapd_param *param,
3583				       int param_len)
3584{
3585	struct lib80211_crypt_data **crypt;
3586	void *sta_ptr;
3587	int max_key_len;
3588
3589	param->u.crypt.err = 0;
3590
3591	max_key_len = param_len -
3592		(int) ((char *) param->u.crypt.key - (char *) param);
3593	if (max_key_len < 0)
3594		return -EINVAL;
3595
3596	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3597	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3598	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3599		sta_ptr = NULL;
3600		if (param->u.crypt.idx >= WEP_KEYS)
3601			param->u.crypt.idx = local->crypt_info.tx_keyidx;
3602		crypt = &local->crypt_info.crypt[param->u.crypt.idx];
3603	} else {
3604		param->u.crypt.idx = 0;
3605		sta_ptr = ap_crypt_get_ptrs(local->ap, param->sta_addr, 0,
3606					    &crypt);
3607
3608		if (sta_ptr == NULL) {
3609			param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
3610			return -EINVAL;
3611		}
3612	}
3613
3614	if (*crypt == NULL || (*crypt)->ops == NULL) {
3615		memcpy(param->u.crypt.alg, "none", 5);
3616		param->u.crypt.key_len = 0;
3617		param->u.crypt.idx = 0xff;
3618	} else {
3619		strncpy(param->u.crypt.alg, (*crypt)->ops->name,
3620			HOSTAP_CRYPT_ALG_NAME_LEN);
3621		param->u.crypt.key_len = 0;
3622
3623		memset(param->u.crypt.seq, 0, 8);
3624		if ((*crypt)->ops->get_key) {
3625			param->u.crypt.key_len =
3626				(*crypt)->ops->get_key(param->u.crypt.key,
3627						       max_key_len,
3628						       param->u.crypt.seq,
3629						       (*crypt)->priv);
3630		}
3631	}
3632
3633	if (sta_ptr)
3634		hostap_handle_sta_release(sta_ptr);
3635
3636	return 0;
3637}
3638
3639
3640static int prism2_ioctl_get_rid(local_info_t *local,
3641				struct prism2_hostapd_param *param,
3642				int param_len)
3643{
3644	int max_len, res;
3645
3646	max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN;
3647	if (max_len < 0)
3648		return -EINVAL;
3649
3650	res = local->func->get_rid(local->dev, param->u.rid.rid,
3651				   param->u.rid.data, param->u.rid.len, 0);
3652	if (res >= 0) {
3653		param->u.rid.len = res;
3654		return 0;
3655	}
3656
3657	return res;
3658}
3659
3660
3661static int prism2_ioctl_set_rid(local_info_t *local,
3662				struct prism2_hostapd_param *param,
3663				int param_len)
3664{
3665	int max_len;
3666
3667	max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN;
3668	if (max_len < 0 || max_len < param->u.rid.len)
3669		return -EINVAL;
3670
3671	return local->func->set_rid(local->dev, param->u.rid.rid,
3672				    param->u.rid.data, param->u.rid.len);
3673}
3674
3675
3676static int prism2_ioctl_set_assoc_ap_addr(local_info_t *local,
3677					  struct prism2_hostapd_param *param,
3678					  int param_len)
3679{
3680	printk(KERN_DEBUG "%ssta: associated as client with AP %pM\n",
3681	       local->dev->name, param->sta_addr);
3682	memcpy(local->assoc_ap_addr, param->sta_addr, ETH_ALEN);
3683	return 0;
3684}
3685
3686
3687static int prism2_ioctl_siwgenie(struct net_device *dev,
3688				 struct iw_request_info *info,
3689				 struct iw_point *data, char *extra)
3690{
3691	return prism2_set_genericelement(dev, extra, data->length);
3692}
3693
3694
3695static int prism2_ioctl_giwgenie(struct net_device *dev,
3696				 struct iw_request_info *info,
3697				 struct iw_point *data, char *extra)
3698{
3699	struct hostap_interface *iface = netdev_priv(dev);
3700	local_info_t *local = iface->local;
3701	int len = local->generic_elem_len - 2;
3702
3703	if (len <= 0 || local->generic_elem == NULL) {
3704		data->length = 0;
3705		return 0;
3706	}
3707
3708	if (data->length < len)
3709		return -E2BIG;
3710
3711	data->length = len;
3712	memcpy(extra, local->generic_elem + 2, len);
3713
3714	return 0;
3715}
3716
3717
3718static int prism2_ioctl_set_generic_element(local_info_t *local,
3719					    struct prism2_hostapd_param *param,
3720					    int param_len)
3721{
3722	int max_len, len;
3723
3724	len = param->u.generic_elem.len;
3725	max_len = param_len - PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN;
3726	if (max_len < 0 || max_len < len)
3727		return -EINVAL;
3728
3729	return prism2_set_genericelement(local->dev,
3730					 param->u.generic_elem.data, len);
3731}
3732
3733
3734static int prism2_ioctl_siwmlme(struct net_device *dev,
3735				struct iw_request_info *info,
3736				struct iw_point *data, char *extra)
3737{
3738	struct hostap_interface *iface = netdev_priv(dev);
3739	local_info_t *local = iface->local;
3740	struct iw_mlme *mlme = (struct iw_mlme *) extra;
3741	__le16 reason;
3742
3743	reason = cpu_to_le16(mlme->reason_code);
3744
3745	switch (mlme->cmd) {
3746	case IW_MLME_DEAUTH:
3747		return prism2_sta_send_mgmt(local, mlme->addr.sa_data,
3748					    IEEE80211_STYPE_DEAUTH,
3749					    (u8 *) &reason, 2);
3750	case IW_MLME_DISASSOC:
3751		return prism2_sta_send_mgmt(local, mlme->addr.sa_data,
3752					    IEEE80211_STYPE_DISASSOC,
3753					    (u8 *) &reason, 2);
3754	default:
3755		return -EOPNOTSUPP;
3756	}
3757}
3758
3759
3760static int prism2_ioctl_mlme(local_info_t *local,
3761			     struct prism2_hostapd_param *param)
3762{
3763	__le16 reason;
3764
3765	reason = cpu_to_le16(param->u.mlme.reason_code);
3766	switch (param->u.mlme.cmd) {
3767	case MLME_STA_DEAUTH:
3768		return prism2_sta_send_mgmt(local, param->sta_addr,
3769					    IEEE80211_STYPE_DEAUTH,
3770					    (u8 *) &reason, 2);
3771	case MLME_STA_DISASSOC:
3772		return prism2_sta_send_mgmt(local, param->sta_addr,
3773					    IEEE80211_STYPE_DISASSOC,
3774					    (u8 *) &reason, 2);
3775	default:
3776		return -EOPNOTSUPP;
3777	}
3778}
3779
3780
3781static int prism2_ioctl_scan_req(local_info_t *local,
3782				 struct prism2_hostapd_param *param)
3783{
3784#ifndef PRISM2_NO_STATION_MODES
3785	if ((local->iw_mode != IW_MODE_INFRA &&
3786	     local->iw_mode != IW_MODE_ADHOC) ||
3787	    (local->sta_fw_ver < PRISM2_FW_VER(1,3,1)))
3788		return -EOPNOTSUPP;
3789
3790	if (!local->dev_enabled)
3791		return -ENETDOWN;
3792
3793	return prism2_request_hostscan(local->dev, param->u.scan_req.ssid,
3794				       param->u.scan_req.ssid_len);
3795#else /* PRISM2_NO_STATION_MODES */
3796	return -EOPNOTSUPP;
3797#endif /* PRISM2_NO_STATION_MODES */
3798}
3799
3800
3801static int prism2_ioctl_priv_hostapd(local_info_t *local, struct iw_point *p)
3802{
3803	struct prism2_hostapd_param *param;
3804	int ret = 0;
3805	int ap_ioctl = 0;
3806
3807	if (p->length < sizeof(struct prism2_hostapd_param) ||
3808	    p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
3809		return -EINVAL;
3810
3811	param = kmalloc(p->length, GFP_KERNEL);
3812	if (param == NULL)
3813		return -ENOMEM;
3814
3815	if (copy_from_user(param, p->pointer, p->length)) {
3816		ret = -EFAULT;
3817		goto out;
3818	}
3819
3820	switch (param->cmd) {
3821	case PRISM2_SET_ENCRYPTION:
3822		ret = prism2_ioctl_set_encryption(local, param, p->length);
3823		break;
3824	case PRISM2_GET_ENCRYPTION:
3825		ret = prism2_ioctl_get_encryption(local, param, p->length);
3826		break;
3827	case PRISM2_HOSTAPD_GET_RID:
3828		ret = prism2_ioctl_get_rid(local, param, p->length);
3829		break;
3830	case PRISM2_HOSTAPD_SET_RID:
3831		ret = prism2_ioctl_set_rid(local, param, p->length);
3832		break;
3833	case PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR:
3834		ret = prism2_ioctl_set_assoc_ap_addr(local, param, p->length);
3835		break;
3836	case PRISM2_HOSTAPD_SET_GENERIC_ELEMENT:
3837		ret = prism2_ioctl_set_generic_element(local, param,
3838						       p->length);
3839		break;
3840	case PRISM2_HOSTAPD_MLME:
3841		ret = prism2_ioctl_mlme(local, param);
3842		break;
3843	case PRISM2_HOSTAPD_SCAN_REQ:
3844		ret = prism2_ioctl_scan_req(local, param);
3845		break;
3846	default:
3847		ret = prism2_hostapd(local->ap, param);
3848		ap_ioctl = 1;
3849		break;
3850	}
3851
3852	if (ret == 1 || !ap_ioctl) {
3853		if (copy_to_user(p->pointer, param, p->length)) {
3854			ret = -EFAULT;
3855			goto out;
3856		} else if (ap_ioctl)
3857			ret = 0;
3858	}
3859
3860 out:
3861	kfree(param);
3862	return ret;
3863}
3864
3865
3866static void prism2_get_drvinfo(struct net_device *dev,
3867			       struct ethtool_drvinfo *info)
3868{
3869	struct hostap_interface *iface;
3870	local_info_t *local;
3871
3872	iface = netdev_priv(dev);
3873	local = iface->local;
3874
3875	strlcpy(info->driver, "hostap", sizeof(info->driver));
3876	snprintf(info->fw_version, sizeof(info->fw_version),
3877		 "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
3878		 (local->sta_fw_ver >> 8) & 0xff,
3879		 local->sta_fw_ver & 0xff);
3880}
3881
3882const struct ethtool_ops prism2_ethtool_ops = {
3883	.get_drvinfo = prism2_get_drvinfo
3884};
3885
3886
3887/* Structures to export the Wireless Handlers */
3888
3889static const iw_handler prism2_handler[] =
3890{
3891	(iw_handler) NULL,				/* SIOCSIWCOMMIT */
3892	(iw_handler) prism2_get_name,			/* SIOCGIWNAME */
3893	(iw_handler) NULL,				/* SIOCSIWNWID */
3894	(iw_handler) NULL,				/* SIOCGIWNWID */
3895	(iw_handler) prism2_ioctl_siwfreq,		/* SIOCSIWFREQ */
3896	(iw_handler) prism2_ioctl_giwfreq,		/* SIOCGIWFREQ */
3897	(iw_handler) prism2_ioctl_siwmode,		/* SIOCSIWMODE */
3898	(iw_handler) prism2_ioctl_giwmode,		/* SIOCGIWMODE */
3899	(iw_handler) prism2_ioctl_siwsens,		/* SIOCSIWSENS */
3900	(iw_handler) prism2_ioctl_giwsens,		/* SIOCGIWSENS */
3901	(iw_handler) NULL /* not used */,		/* SIOCSIWRANGE */
3902	(iw_handler) prism2_ioctl_giwrange,		/* SIOCGIWRANGE */
3903	(iw_handler) NULL /* not used */,		/* SIOCSIWPRIV */
3904	(iw_handler) NULL /* kernel code */,		/* SIOCGIWPRIV */
3905	(iw_handler) NULL /* not used */,		/* SIOCSIWSTATS */
3906	(iw_handler) NULL /* kernel code */,		/* SIOCGIWSTATS */
3907	iw_handler_set_spy,				/* SIOCSIWSPY */
3908	iw_handler_get_spy,				/* SIOCGIWSPY */
3909	iw_handler_set_thrspy,				/* SIOCSIWTHRSPY */
3910	iw_handler_get_thrspy,				/* SIOCGIWTHRSPY */
3911	(iw_handler) prism2_ioctl_siwap,		/* SIOCSIWAP */
3912	(iw_handler) prism2_ioctl_giwap,		/* SIOCGIWAP */
3913	(iw_handler) prism2_ioctl_siwmlme,		/* SIOCSIWMLME */
3914	(iw_handler) prism2_ioctl_giwaplist,		/* SIOCGIWAPLIST */
3915	(iw_handler) prism2_ioctl_siwscan,		/* SIOCSIWSCAN */
3916	(iw_handler) prism2_ioctl_giwscan,		/* SIOCGIWSCAN */
3917	(iw_handler) prism2_ioctl_siwessid,		/* SIOCSIWESSID */
3918	(iw_handler) prism2_ioctl_giwessid,		/* SIOCGIWESSID */
3919	(iw_handler) prism2_ioctl_siwnickn,		/* SIOCSIWNICKN */
3920	(iw_handler) prism2_ioctl_giwnickn,		/* SIOCGIWNICKN */
3921	(iw_handler) NULL,				/* -- hole -- */
3922	(iw_handler) NULL,				/* -- hole -- */
3923	(iw_handler) prism2_ioctl_siwrate,		/* SIOCSIWRATE */
3924	(iw_handler) prism2_ioctl_giwrate,		/* SIOCGIWRATE */
3925	(iw_handler) prism2_ioctl_siwrts,		/* SIOCSIWRTS */
3926	(iw_handler) prism2_ioctl_giwrts,		/* SIOCGIWRTS */
3927	(iw_handler) prism2_ioctl_siwfrag,		/* SIOCSIWFRAG */
3928	(iw_handler) prism2_ioctl_giwfrag,		/* SIOCGIWFRAG */
3929	(iw_handler) prism2_ioctl_siwtxpow,		/* SIOCSIWTXPOW */
3930	(iw_handler) prism2_ioctl_giwtxpow,		/* SIOCGIWTXPOW */
3931	(iw_handler) prism2_ioctl_siwretry,		/* SIOCSIWRETRY */
3932	(iw_handler) prism2_ioctl_giwretry,		/* SIOCGIWRETRY */
3933	(iw_handler) prism2_ioctl_siwencode,		/* SIOCSIWENCODE */
3934	(iw_handler) prism2_ioctl_giwencode,		/* SIOCGIWENCODE */
3935	(iw_handler) prism2_ioctl_siwpower,		/* SIOCSIWPOWER */
3936	(iw_handler) prism2_ioctl_giwpower,		/* SIOCGIWPOWER */
3937	(iw_handler) NULL,				/* -- hole -- */
3938	(iw_handler) NULL,				/* -- hole -- */
3939	(iw_handler) prism2_ioctl_siwgenie,		/* SIOCSIWGENIE */
3940	(iw_handler) prism2_ioctl_giwgenie,		/* SIOCGIWGENIE */
3941	(iw_handler) prism2_ioctl_siwauth,		/* SIOCSIWAUTH */
3942	(iw_handler) prism2_ioctl_giwauth,		/* SIOCGIWAUTH */
3943	(iw_handler) prism2_ioctl_siwencodeext,		/* SIOCSIWENCODEEXT */
3944	(iw_handler) prism2_ioctl_giwencodeext,		/* SIOCGIWENCODEEXT */
3945	(iw_handler) NULL,				/* SIOCSIWPMKSA */
3946	(iw_handler) NULL,				/* -- hole -- */
3947};
3948
3949static const iw_handler prism2_private_handler[] =
3950{							/* SIOCIWFIRSTPRIV + */
3951	(iw_handler) prism2_ioctl_priv_prism2_param,	/* 0 */
3952	(iw_handler) prism2_ioctl_priv_get_prism2_param, /* 1 */
3953	(iw_handler) prism2_ioctl_priv_writemif,	/* 2 */
3954	(iw_handler) prism2_ioctl_priv_readmif,		/* 3 */
3955};
3956
3957const struct iw_handler_def hostap_iw_handler_def =
3958{
3959	.num_standard	= ARRAY_SIZE(prism2_handler),
3960	.num_private	= ARRAY_SIZE(prism2_private_handler),
3961	.num_private_args = ARRAY_SIZE(prism2_priv),
3962	.standard	= (iw_handler *) prism2_handler,
3963	.private	= (iw_handler *) prism2_private_handler,
3964	.private_args	= (struct iw_priv_args *) prism2_priv,
3965	.get_wireless_stats = hostap_get_wireless_stats,
3966};
3967
3968
3969int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
3970{
3971	struct iwreq *wrq = (struct iwreq *) ifr;
3972	struct hostap_interface *iface;
3973	local_info_t *local;
3974	int ret = 0;
3975
3976	iface = netdev_priv(dev);
3977	local = iface->local;
3978
3979	switch (cmd) {
3980		/* Private ioctls (iwpriv) that have not yet been converted
3981		 * into new wireless extensions API */
3982
3983	case PRISM2_IOCTL_INQUIRE:
3984		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
3985		else ret = prism2_ioctl_priv_inquire(dev, (int *) wrq->u.name);
3986		break;
3987
3988	case PRISM2_IOCTL_MONITOR:
3989		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
3990		else ret = prism2_ioctl_priv_monitor(dev, (int *) wrq->u.name);
3991		break;
3992
3993	case PRISM2_IOCTL_RESET:
3994		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
3995		else ret = prism2_ioctl_priv_reset(dev, (int *) wrq->u.name);
3996		break;
3997
3998	case PRISM2_IOCTL_WDS_ADD:
3999		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
4000		else ret = prism2_wds_add(local, wrq->u.ap_addr.sa_data, 1);
4001		break;
4002
4003	case PRISM2_IOCTL_WDS_DEL:
4004		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
4005		else ret = prism2_wds_del(local, wrq->u.ap_addr.sa_data, 1, 0);
4006		break;
4007
4008	case PRISM2_IOCTL_SET_RID_WORD:
4009		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
4010		else ret = prism2_ioctl_priv_set_rid_word(dev,
4011							  (int *) wrq->u.name);
4012		break;
4013
4014#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
4015	case PRISM2_IOCTL_MACCMD:
4016		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
4017		else ret = ap_mac_cmd_ioctl(local, (int *) wrq->u.name);
4018		break;
4019
4020	case PRISM2_IOCTL_ADDMAC:
4021		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
4022		else ret = ap_control_add_mac(&local->ap->mac_restrictions,
4023					      wrq->u.ap_addr.sa_data);
4024		break;
4025	case PRISM2_IOCTL_DELMAC:
4026		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
4027		else ret = ap_control_del_mac(&local->ap->mac_restrictions,
4028					      wrq->u.ap_addr.sa_data);
4029		break;
4030	case PRISM2_IOCTL_KICKMAC:
4031		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
4032		else ret = ap_control_kick_mac(local->ap, local->dev,
4033					       wrq->u.ap_addr.sa_data);
4034		break;
4035#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
4036
4037
4038		/* Private ioctls that are not used with iwpriv;
4039		 * in SIOCDEVPRIVATE range */
4040
4041#ifdef PRISM2_DOWNLOAD_SUPPORT
4042	case PRISM2_IOCTL_DOWNLOAD:
4043		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
4044		else ret = prism2_ioctl_priv_download(local, &wrq->u.data);
4045		break;
4046#endif /* PRISM2_DOWNLOAD_SUPPORT */
4047
4048	case PRISM2_IOCTL_HOSTAPD:
4049		if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
4050		else ret = prism2_ioctl_priv_hostapd(local, &wrq->u.data);
4051		break;
4052
4053	default:
4054		ret = -EOPNOTSUPP;
4055		break;
4056	}
4057
4058	return ret;
4059}
4060