Commit ba9b28d1 authored by Jeff Garzik's avatar Jeff Garzik

Merge branch 'upstream' of...

Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream
parents 862fc81b 5c601d0c
...@@ -531,6 +531,23 @@ config PRISM54 ...@@ -531,6 +531,23 @@ config PRISM54
say M here and read <file:Documentation/modules.txt>. The module say M here and read <file:Documentation/modules.txt>. The module
will be called prism54.ko. 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/hostap/Kconfig"
source "drivers/net/wireless/bcm43xx/Kconfig" source "drivers/net/wireless/bcm43xx/Kconfig"
......
...@@ -40,3 +40,5 @@ obj-$(CONFIG_BCM43XX) += bcm43xx/ ...@@ -40,3 +40,5 @@ obj-$(CONFIG_BCM43XX) += bcm43xx/
# 16-bit wireless PCMCIA client drivers # 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
...@@ -3555,7 +3555,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, ...@@ -3555,7 +3555,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
unsigned long flags; unsigned long flags;
int keyidx; int keyidx;
dprintk(KERN_INFO PFX "set security called\n"); dprintk(KERN_INFO PFX "set security called");
bcm43xx_lock_mmio(bcm, flags); bcm43xx_lock_mmio(bcm, flags);
...@@ -3568,24 +3568,25 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, ...@@ -3568,24 +3568,25 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
if (sec->flags & SEC_ACTIVE_KEY) { if (sec->flags & SEC_ACTIVE_KEY) {
secinfo->active_key = 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) { if (sec->flags & SEC_UNICAST_GROUP) {
secinfo->unicast_uses_group = sec->unicast_uses_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) { if (sec->flags & SEC_LEVEL) {
secinfo->level = 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) { if (sec->flags & SEC_ENABLED) {
secinfo->enabled = 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) { if (sec->flags & SEC_ENCRYPT) {
secinfo->encrypt = 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 (bcm->initialized && !bcm->ieee->host_encrypt) {
if (secinfo->enabled) { if (secinfo->enabled) {
/* upload WEP keys to hardware */ /* upload WEP keys to hardware */
......
...@@ -33,7 +33,7 @@ static struct usb_device_id zd1201_table[] = { ...@@ -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" #define ZD1201_VERSION "0.15"
...@@ -49,7 +49,7 @@ MODULE_DEVICE_TABLE(usb, zd1201_table); ...@@ -49,7 +49,7 @@ MODULE_DEVICE_TABLE(usb, zd1201_table);
static int zd1201_fw_upload(struct usb_device *dev, int apfw) static int zd1201_fw_upload(struct usb_device *dev, int apfw)
{ {
const struct firmware *fw_entry; const struct firmware *fw_entry;
char* data; char *data;
unsigned long len; unsigned long len;
int err; int err;
unsigned char ret; unsigned char ret;
...@@ -65,7 +65,7 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw) ...@@ -65,7 +65,7 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
if (err) { if (err) {
dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile); 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, "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; return err;
} }
...@@ -94,12 +94,12 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw) ...@@ -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); USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT);
if (err < 0) if (err < 0)
goto exit; goto exit;
err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4, err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT); USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
if (err < 0) if (err < 0)
goto exit; goto exit;
if (ret & 0x80) { if (ret & 0x80) {
err = -EIO; err = -EIO;
goto exit; goto exit;
...@@ -166,13 +166,13 @@ static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0, ...@@ -166,13 +166,13 @@ static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0,
return -ENOMEM; return -ENOMEM;
} }
usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), 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); ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret) { if (ret) {
kfree(command); kfree(command);
usb_free_urb(urb); usb_free_urb(urb);
} }
return ret; return ret;
} }
...@@ -316,7 +316,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs) ...@@ -316,7 +316,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
fc = le16_to_cpu(*(__le16 *)&data[datalen-16]); fc = le16_to_cpu(*(__le16 *)&data[datalen-16]);
seq = le16_to_cpu(*(__le16 *)&data[datalen-24]); seq = le16_to_cpu(*(__le16 *)&data[datalen-24]);
if(zd->monitor) { if (zd->monitor) {
if (datalen < 24) if (datalen < 24)
goto resubmit; goto resubmit;
if (!(skb = dev_alloc_skb(datalen+24))) if (!(skb = dev_alloc_skb(datalen+24)))
...@@ -364,7 +364,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs) ...@@ -364,7 +364,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
goto resubmit; goto resubmit;
} }
hlist_for_each_entry(frag, node, &zd->fraglist, fnode) hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
if(frag->seq == (seq&IEEE80211_SCTL_SEQ)) if (frag->seq == (seq&IEEE80211_SCTL_SEQ))
break; break;
if (!frag) if (!frag)
goto resubmit; goto resubmit;
...@@ -376,7 +376,6 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs) ...@@ -376,7 +376,6 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
goto resubmit; goto resubmit;
hlist_del_init(&frag->fnode); hlist_del_init(&frag->fnode);
kfree(frag); kfree(frag);
/* Fallthrough */
} else { } else {
if (datalen<14) if (datalen<14)
goto resubmit; goto resubmit;
...@@ -422,7 +421,7 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata, ...@@ -422,7 +421,7 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
int rid_fid; int rid_fid;
int length; int length;
unsigned char *pdata; unsigned char *pdata;
zd->rxdatas = 0; zd->rxdatas = 0;
err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0); err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0);
if (err) if (err)
...@@ -471,11 +470,11 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata, ...@@ -471,11 +470,11 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
length = zd->rxlen; length = zd->rxlen;
do { do {
int actual_length; int actual_length;
actual_length = (length > 64) ? 64 : 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", dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n",
pdata[0]); pdata[0]);
return -EINVAL; return -EINVAL;
...@@ -487,11 +486,10 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata, ...@@ -487,11 +486,10 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
} }
/* Skip the 4 bytes header (RID length and RID) */ /* Skip the 4 bytes header (RID length and RID) */
if(i == 0) { if (i == 0) {
pdata += 8; pdata += 8;
actual_length -= 8; actual_length -= 8;
} } else {
else {
pdata += 4; pdata += 4;
actual_length -= 4; actual_length -= 4;
} }
...@@ -620,7 +618,7 @@ static int zd1201_drvr_start(struct zd1201 *zd) ...@@ -620,7 +618,7 @@ static int zd1201_drvr_start(struct zd1201 *zd)
short max; short max;
__le16 zdmax; __le16 zdmax;
unsigned char *buffer; unsigned char *buffer;
buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL); buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL);
if (!buffer) if (!buffer)
return -ENOMEM; return -ENOMEM;
...@@ -632,7 +630,7 @@ static int zd1201_drvr_start(struct zd1201 *zd) ...@@ -632,7 +630,7 @@ static int zd1201_drvr_start(struct zd1201 *zd)
err = usb_submit_urb(zd->rx_urb, GFP_KERNEL); err = usb_submit_urb(zd->rx_urb, GFP_KERNEL);
if (err) if (err)
goto err_buffer; goto err_buffer;
err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
if (err) if (err)
goto err_urb; goto err_urb;
...@@ -684,7 +682,7 @@ static int zd1201_enable(struct zd1201 *zd) ...@@ -684,7 +682,7 @@ static int zd1201_enable(struct zd1201 *zd)
static int zd1201_disable(struct zd1201 *zd) static int zd1201_disable(struct zd1201 *zd)
{ {
int err; int err;
if (!zd->mac_enabled) if (!zd->mac_enabled)
return 0; return 0;
if (zd->monitor) { if (zd->monitor) {
...@@ -764,7 +762,6 @@ static int zd1201_net_open(struct net_device *dev) ...@@ -764,7 +762,6 @@ static int zd1201_net_open(struct net_device *dev)
static int zd1201_net_stop(struct net_device *dev) static int zd1201_net_stop(struct net_device *dev)
{ {
netif_stop_queue(dev); netif_stop_queue(dev);
return 0; return 0;
} }
...@@ -915,7 +912,6 @@ static int zd1201_get_name(struct net_device *dev, ...@@ -915,7 +912,6 @@ static int zd1201_get_name(struct net_device *dev,
struct iw_request_info *info, char *name, char *extra) struct iw_request_info *info, char *name, char *extra)
{ {
strcpy(name, "IEEE 802.11b"); strcpy(name, "IEEE 802.11b");
return 0; return 0;
} }
...@@ -1013,11 +1009,10 @@ static int zd1201_set_mode(struct net_device *dev, ...@@ -1013,11 +1009,10 @@ static int zd1201_set_mode(struct net_device *dev,
if (err) if (err)
return err; return err;
} }
zd->monitor=monitor; zd->monitor = monitor;
/* If monitor mode is set we don't actually turn it on here since it /* 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). * is done during mac reset anyway (see zd1201_mac_enable).
*/ */
zd1201_mac_reset(zd); zd1201_mac_reset(zd);
return 0; return 0;
...@@ -1117,7 +1112,7 @@ static int zd1201_get_wap(struct net_device *dev, ...@@ -1117,7 +1112,7 @@ static int zd1201_get_wap(struct net_device *dev,
zd->iwstats.qual.updated = 2; 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, static int zd1201_set_scan(struct net_device *dev,
...@@ -1275,7 +1270,7 @@ static int zd1201_set_rate(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 */ if (!rrq->fixed) { /* Also enable all lower bitrates */
rate |= rate-1; rate |= rate-1;
} }
err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate); err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate);
if (err) if (err)
return err; return err;
...@@ -1486,7 +1481,7 @@ static int zd1201_get_encode(struct net_device *dev, ...@@ -1486,7 +1481,7 @@ static int zd1201_get_encode(struct net_device *dev,
return -EINVAL; return -EINVAL;
erq->flags |= i+1; erq->flags |= i+1;
erq->length = zd->encode_keylen[i]; erq->length = zd->encode_keylen[i];
memcpy(key, zd->encode_keys[i], erq->length); memcpy(key, zd->encode_keys[i], erq->length);
...@@ -1529,11 +1524,7 @@ static int zd1201_set_power(struct net_device *dev, ...@@ -1529,11 +1524,7 @@ static int zd1201_set_power(struct net_device *dev,
return -EINVAL; return -EINVAL;
} }
out: out:
err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled); return zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
if (err)
return err;
return 0;
} }
static int zd1201_get_power(struct net_device *dev, static int zd1201_get_power(struct net_device *dev,
...@@ -1627,15 +1618,11 @@ static int zd1201_set_hostauth(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 iw_request_info *info, struct iw_param *rrq, char *extra)
{ {
struct zd1201 *zd = (struct zd1201 *)dev->priv; struct zd1201 *zd = (struct zd1201 *)dev->priv;
int err;
if (!zd->ap) if (!zd->ap)
return -EOPNOTSUPP; return -EOPNOTSUPP;
err = zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value); return zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
if (err)
return err;
return 0;
} }
static int zd1201_get_hostauth(struct net_device *dev, static int zd1201_get_hostauth(struct net_device *dev,
...@@ -1744,7 +1731,7 @@ static int zd1201_probe(struct usb_interface *interface, ...@@ -1744,7 +1731,7 @@ static int zd1201_probe(struct usb_interface *interface,
{ {
struct zd1201 *zd; struct zd1201 *zd;
struct usb_device *usb; struct usb_device *usb;
int i, err; int err;
short porttype; short porttype;
char buf[IW_ESSID_MAX_SIZE+2]; char buf[IW_ESSID_MAX_SIZE+2];
...@@ -1773,9 +1760,7 @@ static int zd1201_probe(struct usb_interface *interface, ...@@ -1773,9 +1760,7 @@ static int zd1201_probe(struct usb_interface *interface,
if (!zd->rx_urb || !zd->tx_urb) if (!zd->rx_urb || !zd->tx_urb)
goto err_zd; goto err_zd;
for(i = 0; i<100; i++) mdelay(100);
udelay(1000);
err = zd1201_drvr_start(zd); err = zd1201_drvr_start(zd);
if (err) if (err)
goto err_zd; goto err_zd;
...@@ -1833,7 +1818,7 @@ static int zd1201_probe(struct usb_interface *interface, ...@@ -1833,7 +1818,7 @@ static int zd1201_probe(struct usb_interface *interface,
goto err_net; goto err_net;
dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n", dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n",
zd->dev->name); zd->dev->name);
usb_set_intfdata(interface, zd); usb_set_intfdata(interface, zd);
return 0; return 0;
......
...@@ -301,21 +301,4 @@ config USB_NET_ZAURUS ...@@ -301,21 +301,4 @@ config USB_NET_ZAURUS
some cases CDC MDLM) protocol, not "g_ether". 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 endmenu
...@@ -15,7 +15,6 @@ obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndis_host.o ...@@ -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_CDC_SUBSET) += cdc_subset.o
obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o
obj-$(CONFIG_USB_USBNET) += usbnet.o obj-$(CONFIG_USB_USBNET) += usbnet.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
ifeq ($(CONFIG_USB_DEBUG),y) ifeq ($(CONFIG_USB_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG
......
...@@ -1247,7 +1247,8 @@ extern int ieee80211_set_encryption(struct ieee80211_device *ieee); ...@@ -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 int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
extern void ieee80211_txb_free(struct ieee80211_txb *); extern void ieee80211_txb_free(struct ieee80211_txb *);
extern int ieee80211_tx_frame(struct ieee80211_device *ieee, 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 */ /* ieee80211_rx.c */
extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
......
...@@ -310,7 +310,7 @@ extern void ieee80211softmac_stop(struct net_device *dev); ...@@ -310,7 +310,7 @@ extern void ieee80211softmac_stop(struct net_device *dev);
* - context set to the context data you want passed * - context set to the context data you want passed
* The return value is 0, or an error. * 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(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); #define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC);
......
...@@ -555,7 +555,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -555,7 +555,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
/* Incoming 802.11 strucure is converted to a TXB /* Incoming 802.11 strucure is converted to a TXB
* a block of 802.11 fragment packets (stored as skbs) */ * a block of 802.11 fragment packets (stored as skbs) */
int ieee80211_tx_frame(struct ieee80211_device *ieee, 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; struct ieee80211_txb *txb = NULL;
unsigned long flags; unsigned long flags;
...@@ -565,6 +566,9 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee, ...@@ -565,6 +566,9 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
spin_lock_irqsave(&ieee->lock, flags); 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 /* If there is no driver handler to take the TXB, dont' bother
* creating it... */ * creating it... */
if (!ieee->hard_start_xmit) { if (!ieee->hard_start_xmit) {
...@@ -572,32 +576,41 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee, ...@@ -572,32 +576,41 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
goto success; goto success;
} }
if (unlikely(len < 24)) { if (unlikely(total_len < 24)) {
printk(KERN_WARNING "%s: skb too small (%d).\n", printk(KERN_WARNING "%s: skb too small (%d).\n",
ieee->dev->name, len); ieee->dev->name, total_len);
goto success; 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 /* When we allocate the TXB we allocate enough space for the reserve
* and full fragment bytes (bytes_per_frag doesn't include prefix, * and full fragment bytes (bytes_per_frag doesn't include prefix,
* postfix, header, FCS, etc.) */ * 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)) { if (unlikely(!txb)) {
printk(KERN_WARNING "%s: Could not allocate TXB\n", printk(KERN_WARNING "%s: Could not allocate TXB\n",
ieee->dev->name); ieee->dev->name);
goto failed; goto failed;
} }
txb->encrypted = 0; txb->encrypted = 0;
txb->payload_size = len; txb->payload_size = total_len;
skb_frag = txb->fragments[0]; 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 & if (ieee->config &
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
skb_put(skb_frag, 4); 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: success:
spin_unlock_irqrestore(&ieee->lock, flags); spin_unlock_irqrestore(&ieee->lock, flags);
......
...@@ -2,6 +2,7 @@ config IEEE80211_SOFTMAC ...@@ -2,6 +2,7 @@ config IEEE80211_SOFTMAC
tristate "Software MAC add-on to the IEEE 802.11 networking stack" tristate "Software MAC add-on to the IEEE 802.11 networking stack"
depends on IEEE80211 && EXPERIMENTAL depends on IEEE80211 && EXPERIMENTAL
select WIRELESS_EXT select WIRELESS_EXT
select IEEE80211_CRYPT_WEP
---help--- ---help---
This option enables the hardware independent software MAC addon This option enables the hardware independent software MAC addon
for the IEEE 802.11 networking stack. for the IEEE 802.11 networking stack.
......
...@@ -164,12 +164,28 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne ...@@ -164,12 +164,28 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
} }
static void 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); struct ieee80211softmac_device *mac = ieee80211_priv(dev);
ieee80211softmac_assoc_work((void*)mac); 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) */ /* This function is called to handle userspace requests (asynchronously) */
void void
ieee80211softmac_assoc_work(void *d) ieee80211softmac_assoc_work(void *d)
...@@ -249,7 +265,7 @@ 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 ;) * Maybe we can hope to have more memory after scanning finishes ;)
*/ */
dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n"); 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)) if (ieee80211softmac_start_scan(mac))
dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
return; return;
...@@ -284,7 +300,7 @@ ieee80211softmac_assoc_work(void *d) ...@@ -284,7 +300,7 @@ ieee80211softmac_assoc_work(void *d)
* otherwise adding the notification would be racy. */ * otherwise adding the notification would be racy. */
if (!ieee80211softmac_auth_req(mac, found)) { if (!ieee80211softmac_auth_req(mac, found)) {
dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n"); 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 { } else {
printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n"); printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
......
...@@ -107,6 +107,7 @@ ieee80211softmac_auth_queue(void *data) ...@@ -107,6 +107,7 @@ ieee80211softmac_auth_queue(void *data)
printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid)); printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid));
/* Remove this item from the queue */ /* Remove this item from the queue */
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
net->authenticating = 0;
ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net); ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
cancel_delayed_work(&auth->work); /* just to make sure... */ cancel_delayed_work(&auth->work); /* just to make sure... */
list_del(&auth->list); list_del(&auth->list);
...@@ -212,13 +213,13 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) ...@@ -212,13 +213,13 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
spin_unlock_irqrestore(&mac->lock, flags); spin_unlock_irqrestore(&mac->lock, flags);
/* Switch to correct channel for this network */ /* Send our response */
mac->set_channel(mac->dev, net->channel);
/* Send our response (How to encrypt?) */
ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
break; return 0;
case IEEE80211SOFTMAC_AUTH_SHARED_PASS: case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
kfree(net->challenge);
net->challenge = NULL;
net->challenge_len = 0;
/* Check the status code of the response */ /* Check the status code of the response */
switch(auth->status) { switch(auth->status) {
case WLAN_STATUS_SUCCESS: case WLAN_STATUS_SUCCESS:
...@@ -229,6 +230,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) ...@@ -229,6 +230,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
spin_unlock_irqrestore(&mac->lock, flags); spin_unlock_irqrestore(&mac->lock, flags);
printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n", printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n",
MAC_ARG(net->bssid)); MAC_ARG(net->bssid));
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
break; break;
default: default:
printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n", printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n",
......
...@@ -78,7 +78,7 @@ ieee80211softmac_notify_callback(void *d) ...@@ -78,7 +78,7 @@ ieee80211softmac_notify_callback(void *d)
struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d; struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
kfree(d); kfree(d);
event.fun(event.mac->dev, event.context); event.fun(event.mac->dev, event.event_type, event.context);
} }
int int
...@@ -167,6 +167,9 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve ...@@ -167,6 +167,9 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve
if ((eventptr->event_type == event || eventptr->event_type == -1) if ((eventptr->event_type == event || eventptr->event_type == -1)
&& (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) { && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
list_del(&eventptr->list); 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); schedule_work(&eventptr->work);
} }
} }
......
...@@ -149,6 +149,56 @@ ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac, ...@@ -149,6 +149,56 @@ ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac,
* shouldn't the sequence number be in ieee80211? */ * 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 * Create Management packets
...@@ -179,27 +229,6 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt, ...@@ -179,27 +229,6 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
return 0; return 0;
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); 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 (?) */ /* Fill in Listen Interval (?) */
(*pkt)->listen_interval = cpu_to_le16(10); (*pkt)->listen_interval = cpu_to_le16(10);
...@@ -239,17 +268,9 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt, ...@@ -239,17 +268,9 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
return 0; return 0;
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid); ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid);
/* Fill in capability Info */ /* Fill in the capabilities */
(*pkt)->capability = mac->ieee->iw_mode == IW_MODE_MASTER ? (*pkt)->capability = ieee80211softmac_capabilities(mac, net);
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 Listen Interval (?) */ /* Fill in Listen Interval (?) */
(*pkt)->listen_interval = cpu_to_le16(10); (*pkt)->listen_interval = cpu_to_le16(10);
/* Fill in the current AP MAC */ /* Fill in the current AP MAC */
...@@ -268,26 +289,27 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt, ...@@ -268,26 +289,27 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
static u32 static u32
ieee80211softmac_auth(struct ieee80211_auth **pkt, ieee80211softmac_auth(struct ieee80211_auth **pkt,
struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
u16 transaction, u16 status) u16 transaction, u16 status, int *encrypt_mpdu)
{ {
u8 *data; 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 */ /* Allocate Packet */
(*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt( (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt(
2 + /* Auth Algorithm */ 2 + /* Auth Algorithm */
2 + /* Auth Transaction Seq */ 2 + /* Auth Transaction Seq */
2 + /* Status Code */ 2 + /* Status Code */
/* Challenge Text IE */ /* Challenge Text IE */
mac->ieee->open_wep ? 0 : is_shared_response ? 0 : 1 + 1 + net->challenge_len
1 + 1 + WLAN_AUTH_CHALLENGE_LEN );
);
if (unlikely((*pkt) == NULL)) if (unlikely((*pkt) == NULL))
return 0; return 0;
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid); ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid);
/* Algorithm */ /* Algorithm */
(*pkt)->algorithm = mac->ieee->open_wep ? (*pkt)->algorithm = cpu_to_le16(auth_mode);
cpu_to_le16(WLAN_AUTH_OPEN) :
cpu_to_le16(WLAN_AUTH_SHARED_KEY);
/* Transaction */ /* Transaction */
(*pkt)->transaction = cpu_to_le16(transaction); (*pkt)->transaction = cpu_to_le16(transaction);
/* Status */ /* Status */
...@@ -295,18 +317,20 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt, ...@@ -295,18 +317,20 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt,
data = (u8 *)(*pkt)->info_element; data = (u8 *)(*pkt)->info_element;
/* Challenge Text */ /* Challenge Text */
if(!mac->ieee->open_wep){ if (is_shared_response) {
*data = MFIE_TYPE_CHALLENGE; *data = MFIE_TYPE_CHALLENGE;
data++; data++;
/* Copy the challenge in */ /* Copy the challenge in */
// *data = challenge length *data = net->challenge_len;
// data += sizeof(u16); data++;
// memcpy(data, challenge, challenge length); memcpy(data, net->challenge, net->challenge_len);
// data += challenge length; data += net->challenge_len;
/* Add the full size to the packet length */ /* Make sure this frame gets encrypted with the shared key */
} *encrypt_mpdu = 1;
} else
*encrypt_mpdu = 0;
/* Return the packet size */ /* Return the packet size */
return (data - (u8 *)(*pkt)); return (data - (u8 *)(*pkt));
...@@ -396,6 +420,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, ...@@ -396,6 +420,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
{ {
void *pkt = NULL; void *pkt = NULL;
u32 pkt_size = 0; u32 pkt_size = 0;
int encrypt_mpdu = 0;
switch(type) { switch(type) {
case IEEE80211_STYPE_ASSOC_REQ: case IEEE80211_STYPE_ASSOC_REQ:
...@@ -405,7 +430,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, ...@@ -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); pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
break; break;
case IEEE80211_STYPE_AUTH: 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; break;
case IEEE80211_STYPE_DISASSOC: case IEEE80211_STYPE_DISASSOC:
case IEEE80211_STYPE_DEAUTH: case IEEE80211_STYPE_DEAUTH:
...@@ -434,52 +459,8 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, ...@@ -434,52 +459,8 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
* or get rid of it alltogether? * or get rid of it alltogether?
* Does this work for you now? * Does this work for you now?
*/ */
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;
}
/* 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);
kfree(pkt); kfree(pkt);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment