/* Wireless extensions support.
*
* See copyright notice in main.c
*/
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/if_arp.h>
#include <linux/wireless.h>
#include <linux/ieee80211.h>
#include <net/iw_handler.h>
#include <net/cfg80211.h>
#include <net/cfg80211-wext.h>
#include "hermes.h"
#include "hermes_rid.h"
#include "orinoco.h"
#include "hw.h"
#include "mic.h"
#include "scan.h"
#include "main.h"
#include "wext.h"
#define MAX_RID_LEN 1024
/* Helper routine to record keys
* It is called under orinoco_lock so it may not sleep */
static int orinoco_set_key(struct orinoco_private *priv, int index,
enum orinoco_alg alg, const u8 *key, int key_len,
const u8 *seq, int seq_len)
{
kzfree(priv->keys[index].key);
kzfree(priv->keys[index].seq);
if (key_len) {
priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC);
if (!priv->keys[index].key)
goto nomem;
} else
priv->keys[index].key = NULL;
if (seq_len) {
priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC);
if (!priv->keys[index].seq)
goto free_key;
} else
priv->keys[index].seq = NULL;
priv->keys[index].key_len = key_len;
priv->keys[index].seq_len = seq_len;
if (key_len)
memcpy(priv->keys[index].key, key, key_len);
if (seq_len)
memcpy(priv->keys[index].seq, seq, seq_len);
switch (alg) {
case ORINOCO_ALG_TKIP:
priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
break;
case ORINOCO_ALG_WEP:
priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
break;
case ORINOCO_ALG_NONE:
default:
priv->keys[index].cipher = 0;
break;
}
return 0;
free_key:
kfree(priv->keys[index].key);
priv->keys[index].key = NULL;
nomem:
priv->keys[index].key_len = 0;
priv->keys[index].seq_len = 0;
priv->keys[index].cipher = 0;
return -ENOMEM;
}
static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
{
struct orinoco_private *priv = ndev_priv(dev);
struct hermes *hw = &priv->hw;
struct iw_statistics *wstats = &priv->wstats;
int err;
unsigned long flags;
if (!netif_device_present(dev)) {
printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
dev->name);
return NULL; /* FIXME: Can we do better than this? */
}
/* If busy, return the old stats. Returning NULL may cause
* the interface to disappear from /proc/net/wireless */
if (orinoco_lock(priv, &flags) != 0)
return wstats;
/* We can't really wait for the tallies inquiry command to
* complete, so we just use the previous results and trigger
* a new tallies inquiry command for next time - Jean II */
/* FIXME: Really we should wait for the inquiry to come back -
* as it is the stats we give don't make a whole lot of sense.
* Unfortunately, it's not clear how to do that within the
* wireless extensions framework: I think we're in user
* context, but a lock seems to be held by the time we get in
* here so we're not safe to sleep here. */
hermes_inquire
|