Linux Audio

Check our new training course

Loading...
   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}