linux/drivers/net/wireless/intel/ipw2x00/libipw_module.c
<<
>>
Prefs
   1/*******************************************************************************
   2
   3  Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
   4
   5  Portions of this file are based on the WEP enablement code provided by the
   6  Host AP project hostap-drivers v0.1.3
   7  Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
   8  <j@w1.fi>
   9  Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
  10
  11  This program is free software; you can redistribute it and/or modify it
  12  under the terms of version 2 of the GNU General Public License as
  13  published by the Free Software Foundation.
  14
  15  This program is distributed in the hope that it will be useful, but WITHOUT
  16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  17  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  18  more details.
  19
  20  You should have received a copy of the GNU General Public License along with
  21  this program; if not, write to the Free Software Foundation, Inc., 59
  22  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  23
  24  The full GNU General Public License is included in this distribution in the
  25  file called LICENSE.
  26
  27  Contact Information:
  28  Intel Linux Wireless <ilw@linux.intel.com>
  29  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  30
  31*******************************************************************************/
  32
  33#include <linux/compiler.h>
  34#include <linux/errno.h>
  35#include <linux/if_arp.h>
  36#include <linux/in6.h>
  37#include <linux/in.h>
  38#include <linux/ip.h>
  39#include <linux/kernel.h>
  40#include <linux/module.h>
  41#include <linux/netdevice.h>
  42#include <linux/proc_fs.h>
  43#include <linux/skbuff.h>
  44#include <linux/slab.h>
  45#include <linux/tcp.h>
  46#include <linux/types.h>
  47#include <linux/wireless.h>
  48#include <linux/etherdevice.h>
  49#include <asm/uaccess.h>
  50#include <net/net_namespace.h>
  51#include <net/arp.h>
  52
  53#include "libipw.h"
  54
  55#define DRV_DESCRIPTION "802.11 data/management/control stack"
  56#define DRV_NAME        "libipw"
  57#define DRV_PROCNAME    "ieee80211"
  58#define DRV_VERSION     LIBIPW_VERSION
  59#define DRV_COPYRIGHT   "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
  60
  61MODULE_VERSION(DRV_VERSION);
  62MODULE_DESCRIPTION(DRV_DESCRIPTION);
  63MODULE_AUTHOR(DRV_COPYRIGHT);
  64MODULE_LICENSE("GPL");
  65
  66static struct cfg80211_ops libipw_config_ops = { };
  67static void *libipw_wiphy_privid = &libipw_wiphy_privid;
  68
  69static int libipw_networks_allocate(struct libipw_device *ieee)
  70{
  71        int i, j;
  72
  73        for (i = 0; i < MAX_NETWORK_COUNT; i++) {
  74                ieee->networks[i] = kzalloc(sizeof(struct libipw_network),
  75                                            GFP_KERNEL);
  76                if (!ieee->networks[i]) {
  77                        LIBIPW_ERROR("Out of memory allocating beacons\n");
  78                        for (j = 0; j < i; j++)
  79                                kfree(ieee->networks[j]);
  80                        return -ENOMEM;
  81                }
  82        }
  83
  84        return 0;
  85}
  86
  87static inline void libipw_networks_free(struct libipw_device *ieee)
  88{
  89        int i;
  90
  91        for (i = 0; i < MAX_NETWORK_COUNT; i++)
  92                kfree(ieee->networks[i]);
  93}
  94
  95void libipw_networks_age(struct libipw_device *ieee,
  96                            unsigned long age_secs)
  97{
  98        struct libipw_network *network = NULL;
  99        unsigned long flags;
 100        unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
 101
 102        spin_lock_irqsave(&ieee->lock, flags);
 103        list_for_each_entry(network, &ieee->network_list, list) {
 104                network->last_scanned -= age_jiffies;
 105        }
 106        spin_unlock_irqrestore(&ieee->lock, flags);
 107}
 108EXPORT_SYMBOL(libipw_networks_age);
 109
 110static void libipw_networks_initialize(struct libipw_device *ieee)
 111{
 112        int i;
 113
 114        INIT_LIST_HEAD(&ieee->network_free_list);
 115        INIT_LIST_HEAD(&ieee->network_list);
 116        for (i = 0; i < MAX_NETWORK_COUNT; i++)
 117                list_add_tail(&ieee->networks[i]->list,
 118                              &ieee->network_free_list);
 119}
 120
 121int libipw_change_mtu(struct net_device *dev, int new_mtu)
 122{
 123        if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN))
 124                return -EINVAL;
 125        dev->mtu = new_mtu;
 126        return 0;
 127}
 128EXPORT_SYMBOL(libipw_change_mtu);
 129
 130struct net_device *alloc_libipw(int sizeof_priv, int monitor)
 131{
 132        struct libipw_device *ieee;
 133        struct net_device *dev;
 134        int err;
 135
 136        LIBIPW_DEBUG_INFO("Initializing...\n");
 137
 138        dev = alloc_etherdev(sizeof(struct libipw_device) + sizeof_priv);
 139        if (!dev)
 140                goto failed;
 141
 142        ieee = netdev_priv(dev);
 143
 144        ieee->dev = dev;
 145
 146        if (!monitor) {
 147                ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0);
 148                if (!ieee->wdev.wiphy) {
 149                        LIBIPW_ERROR("Unable to allocate wiphy.\n");
 150                        goto failed_free_netdev;
 151                }
 152
 153                ieee->dev->ieee80211_ptr = &ieee->wdev;
 154                ieee->wdev.iftype = NL80211_IFTYPE_STATION;
 155
 156                /* Fill-out wiphy structure bits we know...  Not enough info
 157                   here to call set_wiphy_dev or set MAC address or channel info
 158                   -- have to do that in ->ndo_init... */
 159                ieee->wdev.wiphy->privid = libipw_wiphy_privid;
 160
 161                ieee->wdev.wiphy->max_scan_ssids = 1;
 162                ieee->wdev.wiphy->max_scan_ie_len = 0;
 163                ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
 164                                                | BIT(NL80211_IFTYPE_ADHOC);
 165        }
 166
 167        err = libipw_networks_allocate(ieee);
 168        if (err) {
 169                LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
 170                goto failed_free_wiphy;
 171        }
 172        libipw_networks_initialize(ieee);
 173
 174        /* Default fragmentation threshold is maximum payload size */
 175        ieee->fts = DEFAULT_FTS;
 176        ieee->rts = DEFAULT_FTS;
 177        ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
 178        ieee->open_wep = 1;
 179
 180        /* Default to enabling full open WEP with host based encrypt/decrypt */
 181        ieee->host_encrypt = 1;
 182        ieee->host_decrypt = 1;
 183        ieee->host_mc_decrypt = 1;
 184
 185        /* Host fragmentation in Open mode. Default is enabled.
 186         * Note: host fragmentation is always enabled if host encryption
 187         * is enabled. For cards can do hardware encryption, they must do
 188         * hardware fragmentation as well. So we don't need a variable
 189         * like host_enc_frag. */
 190        ieee->host_open_frag = 1;
 191        ieee->ieee802_1x = 1;   /* Default to supporting 802.1x */
 192
 193        spin_lock_init(&ieee->lock);
 194
 195        lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
 196
 197        ieee->wpa_enabled = 0;
 198        ieee->drop_unencrypted = 0;
 199        ieee->privacy_invoked = 0;
 200
 201        return dev;
 202
 203failed_free_wiphy:
 204        if (!monitor)
 205                wiphy_free(ieee->wdev.wiphy);
 206failed_free_netdev:
 207        free_netdev(dev);
 208failed:
 209        return NULL;
 210}
 211EXPORT_SYMBOL(alloc_libipw);
 212
 213void free_libipw(struct net_device *dev, int monitor)
 214{
 215        struct libipw_device *ieee = netdev_priv(dev);
 216
 217        lib80211_crypt_info_free(&ieee->crypt_info);
 218
 219        libipw_networks_free(ieee);
 220
 221        /* free cfg80211 resources */
 222        if (!monitor)
 223                wiphy_free(ieee->wdev.wiphy);
 224
 225        free_netdev(dev);
 226}
 227EXPORT_SYMBOL(free_libipw);
 228
 229#ifdef CONFIG_LIBIPW_DEBUG
 230
 231static int debug = 0;
 232u32 libipw_debug_level = 0;
 233EXPORT_SYMBOL_GPL(libipw_debug_level);
 234static struct proc_dir_entry *libipw_proc = NULL;
 235
 236static int debug_level_proc_show(struct seq_file *m, void *v)
 237{
 238        seq_printf(m, "0x%08X\n", libipw_debug_level);
 239        return 0;
 240}
 241
 242static int debug_level_proc_open(struct inode *inode, struct file *file)
 243{
 244        return single_open(file, debug_level_proc_show, NULL);
 245}
 246
 247static ssize_t debug_level_proc_write(struct file *file,
 248                const char __user *buffer, size_t count, loff_t *pos)
 249{
 250        char buf[] = "0x00000000\n";
 251        size_t len = min(sizeof(buf) - 1, count);
 252        unsigned long val;
 253
 254        if (copy_from_user(buf, buffer, len))
 255                return count;
 256        buf[len] = 0;
 257        if (sscanf(buf, "%li", &val) != 1)
 258                printk(KERN_INFO DRV_NAME
 259                       ": %s is not in hex or decimal form.\n", buf);
 260        else
 261                libipw_debug_level = val;
 262
 263        return strnlen(buf, len);
 264}
 265
 266static const struct file_operations debug_level_proc_fops = {
 267        .owner          = THIS_MODULE,
 268        .open           = debug_level_proc_open,
 269        .read           = seq_read,
 270        .llseek         = seq_lseek,
 271        .release        = single_release,
 272        .write          = debug_level_proc_write,
 273};
 274#endif                          /* CONFIG_LIBIPW_DEBUG */
 275
 276static int __init libipw_init(void)
 277{
 278#ifdef CONFIG_LIBIPW_DEBUG
 279        struct proc_dir_entry *e;
 280
 281        libipw_debug_level = debug;
 282        libipw_proc = proc_mkdir(DRV_PROCNAME, init_net.proc_net);
 283        if (libipw_proc == NULL) {
 284                LIBIPW_ERROR("Unable to create " DRV_PROCNAME
 285                                " proc directory\n");
 286                return -EIO;
 287        }
 288        e = proc_create("debug_level", S_IRUGO | S_IWUSR, libipw_proc,
 289                        &debug_level_proc_fops);
 290        if (!e) {
 291                remove_proc_entry(DRV_PROCNAME, init_net.proc_net);
 292                libipw_proc = NULL;
 293                return -EIO;
 294        }
 295#endif                          /* CONFIG_LIBIPW_DEBUG */
 296
 297        printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
 298        printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
 299
 300        return 0;
 301}
 302
 303static void __exit libipw_exit(void)
 304{
 305#ifdef CONFIG_LIBIPW_DEBUG
 306        if (libipw_proc) {
 307                remove_proc_entry("debug_level", libipw_proc);
 308                remove_proc_entry(DRV_PROCNAME, init_net.proc_net);
 309                libipw_proc = NULL;
 310        }
 311#endif                          /* CONFIG_LIBIPW_DEBUG */
 312}
 313
 314#ifdef CONFIG_LIBIPW_DEBUG
 315#include <linux/moduleparam.h>
 316module_param(debug, int, 0444);
 317MODULE_PARM_DESC(debug, "debug output mask");
 318#endif                          /* CONFIG_LIBIPW_DEBUG */
 319
 320module_exit(libipw_exit);
 321module_init(libipw_init);
 322