1
0
Fork 0

Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream

wifi-calibration
Jeff Garzik 2006-06-08 15:48:25 -04:00
commit ba9b28d19a
15 changed files with 180 additions and 176 deletions

View File

@ -531,6 +531,23 @@ config PRISM54
say M here and read <file:Documentation/modules.txt>. The module
will be called prism54.ko.
config USB_ZD1201
tristate "USB ZD1201 based Wireless device support"
depends on USB && NET_RADIO
select FW_LOADER
---help---
Say Y if you want to use wireless LAN adapters based on the ZyDAS
ZD1201 chip.
This driver makes the adapter appear as a normal Ethernet interface,
typically on wlan0.
The zd1201 device requires external firmware to be loaded.
This can be found at http://linux-lc100020.sourceforge.net/
To compile this driver as a module, choose M here: the
module will be called zd1201.
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/bcm43xx/Kconfig"

View File

@ -40,3 +40,5 @@ obj-$(CONFIG_BCM43XX) += bcm43xx/
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o

View File

@ -3555,7 +3555,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
unsigned long flags;
int keyidx;
dprintk(KERN_INFO PFX "set security called\n");
dprintk(KERN_INFO PFX "set security called");
bcm43xx_lock_mmio(bcm, flags);
@ -3568,24 +3568,25 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
if (sec->flags & SEC_ACTIVE_KEY) {
secinfo->active_key = sec->active_key;
dprintk(KERN_INFO PFX " .active_key = %d\n", sec->active_key);
dprintk(", .active_key = %d", sec->active_key);
}
if (sec->flags & SEC_UNICAST_GROUP) {
secinfo->unicast_uses_group = sec->unicast_uses_group;
dprintk(KERN_INFO PFX " .unicast_uses_group = %d\n", sec->unicast_uses_group);
dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group);
}
if (sec->flags & SEC_LEVEL) {
secinfo->level = sec->level;
dprintk(KERN_INFO PFX " .level = %d\n", sec->level);
dprintk(", .level = %d", sec->level);
}
if (sec->flags & SEC_ENABLED) {
secinfo->enabled = sec->enabled;
dprintk(KERN_INFO PFX " .enabled = %d\n", sec->enabled);
dprintk(", .enabled = %d", sec->enabled);
}
if (sec->flags & SEC_ENCRYPT) {
secinfo->encrypt = sec->encrypt;
dprintk(KERN_INFO PFX " .encrypt = %d\n", sec->encrypt);
dprintk(", .encrypt = %d", sec->encrypt);
}
dprintk("\n");
if (bcm->initialized && !bcm->ieee->host_encrypt) {
if (secinfo->enabled) {
/* upload WEP keys to hardware */

View File

@ -33,7 +33,7 @@ static struct usb_device_id zd1201_table[] = {
{}
};
static int ap = 0; /* Are we an AP or a normal station? */
static int ap; /* Are we an AP or a normal station? */
#define ZD1201_VERSION "0.15"
@ -49,7 +49,7 @@ MODULE_DEVICE_TABLE(usb, zd1201_table);
static int zd1201_fw_upload(struct usb_device *dev, int apfw)
{
const struct firmware *fw_entry;
char* data;
char *data;
unsigned long len;
int err;
unsigned char ret;
@ -65,7 +65,7 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
if (err) {
dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile);
dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n");
dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info\n");
dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n");
return err;
}
@ -94,12 +94,12 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT);
if (err < 0)
goto exit;
err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
if (err < 0)
goto exit;
if (ret & 0x80) {
err = -EIO;
goto exit;
@ -166,13 +166,13 @@ static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0,
return -ENOMEM;
}
usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
command, 16, zd1201_usbfree, zd);
command, 16, zd1201_usbfree, zd);
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret) {
kfree(command);
usb_free_urb(urb);
}
return ret;
}
@ -316,7 +316,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
fc = le16_to_cpu(*(__le16 *)&data[datalen-16]);
seq = le16_to_cpu(*(__le16 *)&data[datalen-24]);
if(zd->monitor) {
if (zd->monitor) {
if (datalen < 24)
goto resubmit;
if (!(skb = dev_alloc_skb(datalen+24)))
@ -364,7 +364,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
goto resubmit;
}
hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
if(frag->seq == (seq&IEEE80211_SCTL_SEQ))
if (frag->seq == (seq&IEEE80211_SCTL_SEQ))
break;
if (!frag)
goto resubmit;
@ -376,7 +376,6 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
goto resubmit;
hlist_del_init(&frag->fnode);
kfree(frag);
/* Fallthrough */
} else {
if (datalen<14)
goto resubmit;
@ -422,7 +421,7 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
int rid_fid;
int length;
unsigned char *pdata;
zd->rxdatas = 0;
err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0);
if (err)
@ -471,11 +470,11 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
length = zd->rxlen;
do {
int actual_length;
int actual_length;
actual_length = (length > 64) ? 64 : length;
if(pdata[0] != 0x3) {
if (pdata[0] != 0x3) {
dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n",
pdata[0]);
return -EINVAL;
@ -487,11 +486,10 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
}
/* Skip the 4 bytes header (RID length and RID) */
if(i == 0) {
if (i == 0) {
pdata += 8;
actual_length -= 8;
}
else {
} else {
pdata += 4;
actual_length -= 4;
}
@ -620,7 +618,7 @@ static int zd1201_drvr_start(struct zd1201 *zd)
short max;
__le16 zdmax;
unsigned char *buffer;
buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
@ -632,7 +630,7 @@ static int zd1201_drvr_start(struct zd1201 *zd)
err = usb_submit_urb(zd->rx_urb, GFP_KERNEL);
if (err)
goto err_buffer;
err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
if (err)
goto err_urb;
@ -684,7 +682,7 @@ static int zd1201_enable(struct zd1201 *zd)
static int zd1201_disable(struct zd1201 *zd)
{
int err;
if (!zd->mac_enabled)
return 0;
if (zd->monitor) {
@ -764,7 +762,6 @@ static int zd1201_net_open(struct net_device *dev)
static int zd1201_net_stop(struct net_device *dev)
{
netif_stop_queue(dev);
return 0;
}
@ -915,7 +912,6 @@ static int zd1201_get_name(struct net_device *dev,
struct iw_request_info *info, char *name, char *extra)
{
strcpy(name, "IEEE 802.11b");
return 0;
}
@ -1013,11 +1009,10 @@ static int zd1201_set_mode(struct net_device *dev,
if (err)
return err;
}
zd->monitor=monitor;
zd->monitor = monitor;
/* If monitor mode is set we don't actually turn it on here since it
* is done during mac reset anyway (see zd1201_mac_enable).
*/
zd1201_mac_reset(zd);
return 0;
@ -1117,7 +1112,7 @@ static int zd1201_get_wap(struct net_device *dev,
zd->iwstats.qual.updated = 2;
}
return zd1201_getconfig(zd,ZD1201_RID_CURRENTBSSID,ap_addr->sa_data,6);
return zd1201_getconfig(zd, ZD1201_RID_CURRENTBSSID, ap_addr->sa_data, 6);
}
static int zd1201_set_scan(struct net_device *dev,
@ -1275,7 +1270,7 @@ static int zd1201_set_rate(struct net_device *dev,
if (!rrq->fixed) { /* Also enable all lower bitrates */
rate |= rate-1;
}
err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate);
if (err)
return err;
@ -1486,7 +1481,7 @@ static int zd1201_get_encode(struct net_device *dev,
return -EINVAL;
erq->flags |= i+1;
erq->length = zd->encode_keylen[i];
memcpy(key, zd->encode_keys[i], erq->length);
@ -1529,11 +1524,7 @@ static int zd1201_set_power(struct net_device *dev,
return -EINVAL;
}
out:
err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
if (err)
return err;
return 0;
return zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
}
static int zd1201_get_power(struct net_device *dev,
@ -1627,15 +1618,11 @@ static int zd1201_set_hostauth(struct net_device *dev,
struct iw_request_info *info, struct iw_param *rrq, char *extra)
{
struct zd1201 *zd = (struct zd1201 *)dev->priv;
int err;
if (!zd->ap)
return -EOPNOTSUPP;
err = zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
if (err)
return err;
return 0;
return zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
}
static int zd1201_get_hostauth(struct net_device *dev,
@ -1744,7 +1731,7 @@ static int zd1201_probe(struct usb_interface *interface,
{
struct zd1201 *zd;
struct usb_device *usb;
int i, err;
int err;
short porttype;
char buf[IW_ESSID_MAX_SIZE+2];
@ -1773,9 +1760,7 @@ static int zd1201_probe(struct usb_interface *interface,
if (!zd->rx_urb || !zd->tx_urb)
goto err_zd;
for(i = 0; i<100; i++)
udelay(1000);
mdelay(100);
err = zd1201_drvr_start(zd);
if (err)
goto err_zd;
@ -1833,7 +1818,7 @@ static int zd1201_probe(struct usb_interface *interface,
goto err_net;
dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n",
zd->dev->name);
usb_set_intfdata(interface, zd);
return 0;

View File

@ -301,21 +301,4 @@ config USB_NET_ZAURUS
some cases CDC MDLM) protocol, not "g_ether".
config USB_ZD1201
tristate "USB ZD1201 based Wireless device support"
depends on NET_RADIO
select FW_LOADER
---help---
Say Y if you want to use wireless LAN adapters based on the ZyDAS
ZD1201 chip.
This driver makes the adapter appear as a normal Ethernet interface,
typically on wlan0.
The zd1201 device requires external firmware to be loaded.
This can be found at http://linux-lc100020.sourceforge.net/
To compile this driver as a module, choose M here: the
module will be called zd1201.
endmenu

View File

@ -15,7 +15,6 @@ obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndis_host.o
obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o
obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o
obj-$(CONFIG_USB_USBNET) += usbnet.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
ifeq ($(CONFIG_USB_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG

View File

@ -1247,7 +1247,8 @@ extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
extern void ieee80211_txb_free(struct ieee80211_txb *);
extern int ieee80211_tx_frame(struct ieee80211_device *ieee,
struct ieee80211_hdr *frame, int len);
struct ieee80211_hdr *frame, int hdr_len,
int total_len, int encrypt_mpdu);
/* ieee80211_rx.c */
extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,

View File

@ -310,7 +310,7 @@ extern void ieee80211softmac_stop(struct net_device *dev);
* - context set to the context data you want passed
* The return value is 0, or an error.
*/
typedef void (*notify_function_ptr)(struct net_device *dev, void *context);
typedef void (*notify_function_ptr)(struct net_device *dev, int event_type, void *context);
#define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL);
#define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC);

View File

@ -555,7 +555,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
/* Incoming 802.11 strucure is converted to a TXB
* a block of 802.11 fragment packets (stored as skbs) */
int ieee80211_tx_frame(struct ieee80211_device *ieee,
struct ieee80211_hdr *frame, int len)
struct ieee80211_hdr *frame, int hdr_len, int total_len,
int encrypt_mpdu)
{
struct ieee80211_txb *txb = NULL;
unsigned long flags;
@ -565,6 +566,9 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
spin_lock_irqsave(&ieee->lock, flags);
if (encrypt_mpdu && !ieee->sec.encrypt)
encrypt_mpdu = 0;
/* If there is no driver handler to take the TXB, dont' bother
* creating it... */
if (!ieee->hard_start_xmit) {
@ -572,32 +576,41 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
goto success;
}
if (unlikely(len < 24)) {
if (unlikely(total_len < 24)) {
printk(KERN_WARNING "%s: skb too small (%d).\n",
ieee->dev->name, len);
ieee->dev->name, total_len);
goto success;
}
if (encrypt_mpdu)
frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
/* When we allocate the TXB we allocate enough space for the reserve
* and full fragment bytes (bytes_per_frag doesn't include prefix,
* postfix, header, FCS, etc.) */
txb = ieee80211_alloc_txb(1, len, ieee->tx_headroom, GFP_ATOMIC);
txb = ieee80211_alloc_txb(1, total_len, ieee->tx_headroom, GFP_ATOMIC);
if (unlikely(!txb)) {
printk(KERN_WARNING "%s: Could not allocate TXB\n",
ieee->dev->name);
goto failed;
}
txb->encrypted = 0;
txb->payload_size = len;
txb->payload_size = total_len;
skb_frag = txb->fragments[0];
memcpy(skb_put(skb_frag, len), frame, len);
memcpy(skb_put(skb_frag, total_len), frame, total_len);
if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
skb_put(skb_frag, 4);
/* To avoid overcomplicating things, we do the corner-case frame
* encryption in software. The only real situation where encryption is
* needed here is during software-based shared key authentication. */
if (encrypt_mpdu)
ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
success:
spin_unlock_irqrestore(&ieee->lock, flags);

View File

@ -2,6 +2,7 @@ config IEEE80211_SOFTMAC
tristate "Software MAC add-on to the IEEE 802.11 networking stack"
depends on IEEE80211 && EXPERIMENTAL
select WIRELESS_EXT
select IEEE80211_CRYPT_WEP
---help---
This option enables the hardware independent software MAC addon
for the IEEE 802.11 networking stack.

View File

@ -164,12 +164,28 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
}
static void
ieee80211softmac_assoc_notify(struct net_device *dev, void *context)
ieee80211softmac_assoc_notify_scan(struct net_device *dev, int event_type, void *context)
{
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
ieee80211softmac_assoc_work((void*)mac);
}
static void
ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void *context)
{
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
switch (event_type) {
case IEEE80211SOFTMAC_EVENT_AUTHENTICATED:
ieee80211softmac_assoc_work((void*)mac);
break;
case IEEE80211SOFTMAC_EVENT_AUTH_FAILED:
case IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT:
ieee80211softmac_disassoc(mac);
break;
}
}
/* This function is called to handle userspace requests (asynchronously) */
void
ieee80211softmac_assoc_work(void *d)
@ -249,7 +265,7 @@ ieee80211softmac_assoc_work(void *d)
* Maybe we can hope to have more memory after scanning finishes ;)
*/
dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify, NULL);
ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
if (ieee80211softmac_start_scan(mac))
dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
return;
@ -284,7 +300,7 @@ ieee80211softmac_assoc_work(void *d)
* otherwise adding the notification would be racy. */
if (!ieee80211softmac_auth_req(mac, found)) {
dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n");
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify, NULL, GFP_KERNEL);
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
} else {
printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);

View File

@ -107,6 +107,7 @@ ieee80211softmac_auth_queue(void *data)
printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid));
/* Remove this item from the queue */
spin_lock_irqsave(&mac->lock, flags);
net->authenticating = 0;
ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
cancel_delayed_work(&auth->work); /* just to make sure... */
list_del(&auth->list);
@ -212,13 +213,13 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
spin_unlock_irqrestore(&mac->lock, flags);
/* Switch to correct channel for this network */
mac->set_channel(mac->dev, net->channel);
/* Send our response (How to encrypt?) */
/* Send our response */
ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
break;
return 0;
case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
kfree(net->challenge);
net->challenge = NULL;
net->challenge_len = 0;
/* Check the status code of the response */
switch(auth->status) {
case WLAN_STATUS_SUCCESS:
@ -229,6 +230,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
spin_unlock_irqrestore(&mac->lock, flags);
printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n",
MAC_ARG(net->bssid));
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
break;
default:
printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n",

View File

@ -78,7 +78,7 @@ ieee80211softmac_notify_callback(void *d)
struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
kfree(d);
event.fun(event.mac->dev, event.context);
event.fun(event.mac->dev, event.event_type, event.context);
}
int
@ -167,6 +167,9 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve
if ((eventptr->event_type == event || eventptr->event_type == -1)
&& (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
list_del(&eventptr->list);
/* User may have subscribed to ANY event, so
* we tell them which event triggered it. */
eventptr->event_type = event;
schedule_work(&eventptr->work);
}
}

View File

@ -149,6 +149,56 @@ ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac,
* shouldn't the sequence number be in ieee80211? */
}
static u16
ieee80211softmac_capabilities(struct ieee80211softmac_device *mac,
struct ieee80211softmac_network *net)
{
u16 capability = 0;
/* ESS and IBSS bits are set according to the current mode */
switch (mac->ieee->iw_mode) {
case IW_MODE_INFRA:
capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
break;
case IW_MODE_ADHOC:
capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
break;
case IW_MODE_AUTO:
capability = net->capabilities &
(WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
break;
default:
/* bleh. we don't ever go to these modes */
printk(KERN_ERR PFX "invalid iw_mode!\n");
break;
}
/* CF Pollable / CF Poll Request */
/* Needs to be implemented, for now, the 0's == not supported */
/* Privacy Bit */
capability |= mac->ieee->sec.level ?
cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
/* Short Preamble */
/* Always supported: we probably won't ever be powering devices which
* dont support this... */
capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
/* PBCC */
/* Not widely used */
/* Channel Agility */
/* Not widely used */
/* Short Slot */
/* Will be implemented later */
/* DSSS-OFDM */
/* Not widely used */
return capability;
}
/*****************************************************************************
* Create Management packets
@ -179,27 +229,6 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
return 0;
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
/* Fill in capability Info */
switch (mac->ieee->iw_mode) {
case IW_MODE_INFRA:
(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
break;
case IW_MODE_ADHOC:
(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
break;
case IW_MODE_AUTO:
(*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
break;
default:
/* bleh. we don't ever go to these modes */
printk(KERN_ERR PFX "invalid iw_mode!\n");
break;
}
/* Need to add this
(*pkt)->capability |= mac->ieee->short_slot ?
cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
*/
(*pkt)->capability |= mac->ieee->sec.level ? cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
/* Fill in Listen Interval (?) */
(*pkt)->listen_interval = cpu_to_le16(10);
@ -239,17 +268,9 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
return 0;
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid);
/* Fill in capability Info */
(*pkt)->capability = mac->ieee->iw_mode == IW_MODE_MASTER ?
cpu_to_le16(WLAN_CAPABILITY_ESS) :
cpu_to_le16(WLAN_CAPABILITY_IBSS);
/*
(*pkt)->capability |= mac->ieee->short_slot ?
cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
*/
(*pkt)->capability |= mac->ieee->sec.level ?
cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
/* Fill in the capabilities */
(*pkt)->capability = ieee80211softmac_capabilities(mac, net);
/* Fill in Listen Interval (?) */
(*pkt)->listen_interval = cpu_to_le16(10);
/* Fill in the current AP MAC */
@ -268,26 +289,27 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
static u32
ieee80211softmac_auth(struct ieee80211_auth **pkt,
struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
u16 transaction, u16 status)
u16 transaction, u16 status, int *encrypt_mpdu)
{
u8 *data;
int auth_mode = mac->ieee->sec.auth_mode;
int is_shared_response = (auth_mode == WLAN_AUTH_SHARED_KEY
&& transaction == IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE);
/* Allocate Packet */
(*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt(
2 + /* Auth Algorithm */
2 + /* Auth Transaction Seq */
2 + /* Status Code */
/* Challenge Text IE */
mac->ieee->open_wep ? 0 :
1 + 1 + WLAN_AUTH_CHALLENGE_LEN
);
is_shared_response ? 0 : 1 + 1 + net->challenge_len
);
if (unlikely((*pkt) == NULL))
return 0;
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid);
/* Algorithm */
(*pkt)->algorithm = mac->ieee->open_wep ?
cpu_to_le16(WLAN_AUTH_OPEN) :
cpu_to_le16(WLAN_AUTH_SHARED_KEY);
(*pkt)->algorithm = cpu_to_le16(auth_mode);
/* Transaction */
(*pkt)->transaction = cpu_to_le16(transaction);
/* Status */
@ -295,18 +317,20 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt,
data = (u8 *)(*pkt)->info_element;
/* Challenge Text */
if(!mac->ieee->open_wep){
if (is_shared_response) {
*data = MFIE_TYPE_CHALLENGE;
data++;
/* Copy the challenge in */
// *data = challenge length
// data += sizeof(u16);
// memcpy(data, challenge, challenge length);
// data += challenge length;
/* Add the full size to the packet length */
}
*data = net->challenge_len;
data++;
memcpy(data, net->challenge, net->challenge_len);
data += net->challenge_len;
/* Make sure this frame gets encrypted with the shared key */
*encrypt_mpdu = 1;
} else
*encrypt_mpdu = 0;
/* Return the packet size */
return (data - (u8 *)(*pkt));
@ -396,6 +420,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
{
void *pkt = NULL;
u32 pkt_size = 0;
int encrypt_mpdu = 0;
switch(type) {
case IEEE80211_STYPE_ASSOC_REQ:
@ -405,7 +430,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
break;
case IEEE80211_STYPE_AUTH:
pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16));
pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16), &encrypt_mpdu);
break;
case IEEE80211_STYPE_DISASSOC:
case IEEE80211_STYPE_DEAUTH:
@ -434,52 +459,8 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
* or get rid of it alltogether?
* Does this work for you now?
*/
ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, pkt_size);
kfree(pkt);
return 0;
}
/* Create an rts/cts frame */
static u32
ieee80211softmac_rts_cts(struct ieee80211_hdr_2addr **pkt,
struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
u32 type)
{
/* Allocate Packet */
(*pkt) = kmalloc(IEEE80211_2ADDR_LEN, GFP_ATOMIC);
memset(*pkt, 0, IEEE80211_2ADDR_LEN);
if((*pkt) == NULL)
return 0;
ieee80211softmac_hdr_2addr(mac, (*pkt), type, net->bssid);
return IEEE80211_2ADDR_LEN;
}
/* Sends a control packet */
static int
ieee80211softmac_send_ctl_frame(struct ieee80211softmac_device *mac,
struct ieee80211softmac_network *net, u32 type, u32 arg)
{
void *pkt = NULL;
u32 pkt_size = 0;
switch(type) {
case IEEE80211_STYPE_RTS:
case IEEE80211_STYPE_CTS:
pkt_size = ieee80211softmac_rts_cts((struct ieee80211_hdr_2addr **)(&pkt), mac, net, type);
break;
default:
printkl(KERN_DEBUG PFX "Unsupported Control Frame type: %i\n", type);
return -EINVAL;
}
if(pkt_size == 0)
return -ENOMEM;
/* Send the packet to the ieee80211 layer for tx */
ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *) pkt, pkt_size);
ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt,
IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu);
kfree(pkt);
return 0;