linux/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
<<
>>
Prefs
   1/*******************************************************************************
   2
   3  Copyright(c) 2004 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  <jkmaline@cc.hut.fi>
   9  Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.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  James P. Ketrenos <ipw2100-admin@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/config.h>
  35#include <linux/errno.h>
  36#include <linux/if_arp.h>
  37#include <linux/in6.h>
  38#include <linux/in.h>
  39#include <linux/ip.h>
  40#include <linux/kernel.h>
  41#include <linux/module.h>
  42#include <linux/netdevice.h>
  43#include <linux/pci.h>
  44#include <linux/proc_fs.h>
  45#include <linux/skbuff.h>
  46#include <linux/slab.h>
  47#include <linux/tcp.h>
  48#include <linux/types.h>
  49#include <linux/version.h>
  50#include <linux/wireless.h>
  51#include <linux/etherdevice.h>
  52#include <asm/uaccess.h>
  53#include <net/arp.h>
  54
  55#include "ieee80211.h"
  56
  57MODULE_DESCRIPTION("802.11 data/management/control stack");
  58MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
  59MODULE_LICENSE("GPL");
  60
  61#define DRV_NAME "ieee80211"
  62
  63static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
  64{
  65        if (ieee->networks)
  66                return 0;
  67
  68        ieee->networks = kmalloc(
  69                MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
  70                GFP_KERNEL);
  71        if (!ieee->networks) {
  72                printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
  73                       ieee->dev->name);
  74                return -ENOMEM;
  75        }
  76
  77        memset(ieee->networks, 0,
  78               MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
  79
  80        return 0;
  81}
  82
  83static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
  84{
  85        if (!ieee->networks)
  86                return;
  87        kfree(ieee->networks);
  88        ieee->networks = NULL;
  89}
  90
  91static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
  92{
  93        int i;
  94
  95        INIT_LIST_HEAD(&ieee->network_free_list);
  96        INIT_LIST_HEAD(&ieee->network_list);
  97        for (i = 0; i < MAX_NETWORK_COUNT; i++)
  98                list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
  99}
 100
 101
 102struct net_device *alloc_ieee80211(int sizeof_priv)
 103{
 104        struct ieee80211_device *ieee;
 105        struct net_device *dev;
 106        int i,err;
 107
 108        IEEE80211_DEBUG_INFO("Initializing...\n");
 109
 110        dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
 111        if (!dev) {
 112                IEEE80211_ERROR("Unable to network device.\n");
 113                goto failed;
 114        }
 115
 116#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
 117        ieee = netdev_priv(dev);
 118#else
 119        ieee = (struct ieee80211_device *)dev->priv;
 120#endif
 121#if 0
 122        dev->hard_start_xmit = ieee80211_xmit;
 123#endif
 124
 125        memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv);
 126        ieee->dev = dev;
 127
 128        err = ieee80211_networks_allocate(ieee);
 129        if (err) {
 130                IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
 131                                err);
 132                goto failed;
 133        }
 134        ieee80211_networks_initialize(ieee);
 135
 136
 137        /* Default fragmentation threshold is maximum payload size */
 138        ieee->fts = DEFAULT_FTS;
 139        ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
 140        ieee->open_wep = 1;
 141
 142        /* Default to enabling full open WEP with host based encrypt/decrypt */
 143        ieee->host_encrypt = 1;
 144        ieee->host_decrypt = 1;
 145        ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
 146
 147        INIT_LIST_HEAD(&ieee->crypt_deinit_list);
 148        init_timer(&ieee->crypt_deinit_timer);
 149        ieee->crypt_deinit_timer.data = (unsigned long)ieee;
 150        ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
 151
 152        spin_lock_init(&ieee->lock);
 153        spin_lock_init(&ieee->wpax_suitlist_lock);
 154        spin_lock_init(&ieee->bw_spinlock);
 155        spin_lock_init(&ieee->reorder_spinlock);
 156        //added by WB
 157        atomic_set(&(ieee->atm_chnlop), 0);
 158        atomic_set(&(ieee->atm_swbw), 0);
 159
 160        ieee->wpax_type_set = 0;
 161        ieee->wpa_enabled = 0;
 162        ieee->tkip_countermeasures = 0;
 163        ieee->drop_unencrypted = 0;
 164        ieee->privacy_invoked = 0;
 165        ieee->ieee802_1x = 1;
 166        ieee->raw_tx = 0;
 167        //ieee->hwsec_support = 1; //defalt support hw security. //use module_param instead.
 168        ieee->hwsec_active = 0; //disable hwsec, switch it on when necessary.
 169
 170        ieee80211_softmac_init(ieee);
 171
 172#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
 173        ieee->pHTInfo = (RT_HIGH_THROUGHPUT*)kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
 174#else
 175        ieee->pHTInfo = (RT_HIGH_THROUGHPUT*)kmalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
 176        memset(ieee->pHTInfo,0,sizeof(RT_HIGH_THROUGHPUT));
 177#endif
 178        if (ieee->pHTInfo == NULL)
 179        {
 180                IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for HTInfo\n");
 181                return NULL;
 182        }
 183        HTUpdateDefaultSetting(ieee);
 184        HTInitializeHTInfo(ieee); //may move to other place.
 185        TSInitialize(ieee);
 186#if 0
 187#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
 188        INIT_WORK(&ieee->ht_onAssRsp, (void(*)(void*)) HTOnAssocRsp_wq);
 189#else
 190        INIT_WORK(&ieee->ht_onAssRsp, (void(*)(void*)) HTOnAssocRsp_wq, ieee);
 191#endif
 192#endif
 193        for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
 194                INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
 195
 196        for (i = 0; i < 17; i++) {
 197          ieee->last_rxseq_num[i] = -1;
 198          ieee->last_rxfrag_num[i] = -1;
 199          ieee->last_packet_time[i] = 0;
 200        }
 201
 202//These function were added to load crypte module autoly
 203        ieee80211_tkip_null();
 204        ieee80211_wep_null();
 205        ieee80211_ccmp_null();
 206
 207        return dev;
 208
 209 failed:
 210        if (dev)
 211#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
 212                free_netdev(dev);
 213#else
 214                kfree(dev);
 215#endif
 216        return NULL;
 217}
 218
 219
 220void free_ieee80211(struct net_device *dev)
 221{
 222#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
 223        struct ieee80211_device *ieee = netdev_priv(dev);
 224#else
 225        struct ieee80211_device *ieee = (struct ieee80211_device *)dev->priv;
 226#endif
 227        int i;
 228        //struct list_head *p, *q;
 229//      del_timer_sync(&ieee->SwBwTimer);
 230#if 1
 231        if (ieee->pHTInfo != NULL)
 232        {
 233                kfree(ieee->pHTInfo);
 234                ieee->pHTInfo = NULL;
 235        }
 236#endif
 237        RemoveAllTS(ieee);
 238        ieee80211_softmac_free(ieee);
 239        del_timer_sync(&ieee->crypt_deinit_timer);
 240        ieee80211_crypt_deinit_entries(ieee, 1);
 241
 242        for (i = 0; i < WEP_KEYS; i++) {
 243                struct ieee80211_crypt_data *crypt = ieee->crypt[i];
 244                if (crypt) {
 245                        if (crypt->ops)
 246                                crypt->ops->deinit(crypt->priv);
 247                        kfree(crypt);
 248                        ieee->crypt[i] = NULL;
 249                }
 250        }
 251
 252        ieee80211_networks_free(ieee);
 253#if 0
 254        for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) {
 255                list_for_each_safe(p, q, &ieee->ibss_mac_hash[i]) {
 256                        kfree(list_entry(p, struct ieee_ibss_seq, list));
 257                        list_del(p);
 258                }
 259        }
 260
 261#endif
 262#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
 263        free_netdev(dev);
 264#else
 265        kfree(dev);
 266#endif
 267}
 268
 269#ifdef CONFIG_IEEE80211_DEBUG
 270
 271u32 ieee80211_debug_level = 0;
 272static int debug = \
 273        //                  IEEE80211_DL_INFO   |
 274        //                  IEEE80211_DL_WX     |
 275        //                  IEEE80211_DL_SCAN   |
 276        //                  IEEE80211_DL_STATE  |
 277        //                  IEEE80211_DL_MGMT   |
 278        //                  IEEE80211_DL_FRAG   |
 279        //                  IEEE80211_DL_EAP    |
 280        //                  IEEE80211_DL_DROP   |
 281        //                  IEEE80211_DL_TX     |
 282        //                  IEEE80211_DL_RX     |
 283                            //IEEE80211_DL_QOS    |
 284        //                  IEEE80211_DL_HT     |
 285        //                  IEEE80211_DL_TS     |
 286//                          IEEE80211_DL_BA     |
 287        //                  IEEE80211_DL_REORDER|
 288//                          IEEE80211_DL_TRACE  |
 289                            //IEEE80211_DL_DATA |
 290                            IEEE80211_DL_ERR      //awayls open this flags to show error out
 291                            ;
 292struct proc_dir_entry *ieee80211_proc = NULL;
 293
 294static int show_debug_level(char *page, char **start, off_t offset,
 295                            int count, int *eof, void *data)
 296{
 297        return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
 298}
 299
 300static int store_debug_level(struct file *file, const char *buffer,
 301                             unsigned long count, void *data)
 302{
 303        char buf[] = "0x00000000";
 304        unsigned long len = min(sizeof(buf) - 1, (u32)count);
 305        char *p = (char *)buf;
 306        unsigned long val;
 307
 308        if (copy_from_user(buf, buffer, len))
 309                return count;
 310        buf[len] = 0;
 311        if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
 312                p++;
 313                if (p[0] == 'x' || p[0] == 'X')
 314                        p++;
 315                val = simple_strtoul(p, &p, 16);
 316        } else
 317                val = simple_strtoul(p, &p, 10);
 318        if (p == buf)
 319                printk(KERN_INFO DRV_NAME
 320                       ": %s is not in hex or decimal form.\n", buf);
 321        else
 322                ieee80211_debug_level = val;
 323
 324        return strnlen(buf, count);
 325}
 326
 327extern int ieee80211_crypto_init(void);
 328extern void ieee80211_crypto_deinit(void);
 329extern int ieee80211_crypto_tkip_init(void);
 330extern void ieee80211_crypto_tkip_exit(void);
 331extern int ieee80211_crypto_ccmp_init(void);
 332extern void ieee80211_crypto_ccmp_exit(void);
 333extern int ieee80211_crypto_wep_init(void);
 334extern void ieee80211_crypto_wep_exit(void);
 335
 336int __init ieee80211_init(void)
 337{
 338        struct proc_dir_entry *e;
 339        int retval;
 340
 341        retval = ieee80211_crypto_init();
 342        if (retval)
 343                return retval;
 344        retval = ieee80211_crypto_tkip_init();
 345        if (retval) {
 346                ieee80211_crypto_deinit();
 347                return retval;
 348        }
 349        retval = ieee80211_crypto_ccmp_init();
 350        if (retval) {
 351                ieee80211_crypto_tkip_exit();
 352                ieee80211_crypto_deinit();
 353                return retval;
 354        }
 355        retval = ieee80211_crypto_wep_init();
 356        if (retval) {
 357                ieee80211_crypto_ccmp_exit();
 358                ieee80211_crypto_tkip_exit();
 359                ieee80211_crypto_deinit();
 360                return retval;
 361        }
 362
 363        ieee80211_debug_level = debug;
 364#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
 365        ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
 366#else
 367        ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
 368#endif
 369        if (ieee80211_proc == NULL) {
 370                IEEE80211_ERROR("Unable to create " DRV_NAME
 371                                " proc directory\n");
 372                return -EIO;
 373        }
 374        e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
 375                              ieee80211_proc);
 376        if (!e) {
 377#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
 378                remove_proc_entry(DRV_NAME, proc_net);
 379#else
 380                remove_proc_entry(DRV_NAME, init_net.proc_net);
 381#endif
 382                ieee80211_proc = NULL;
 383                return -EIO;
 384        }
 385        e->read_proc = show_debug_level;
 386        e->write_proc = store_debug_level;
 387        e->data = NULL;
 388
 389        return 0;
 390}
 391
 392void __exit ieee80211_exit(void)
 393{
 394        if (ieee80211_proc) {
 395                remove_proc_entry("debug_level", ieee80211_proc);
 396#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
 397                remove_proc_entry(DRV_NAME, proc_net);
 398#else
 399                remove_proc_entry(DRV_NAME, init_net.proc_net);
 400#endif
 401                ieee80211_proc = NULL;
 402        }
 403        ieee80211_crypto_wep_exit();
 404        ieee80211_crypto_ccmp_exit();
 405        ieee80211_crypto_tkip_exit();
 406        ieee80211_crypto_deinit();
 407}
 408
 409#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 410#include <linux/moduleparam.h>
 411module_param(debug, int, 0444);
 412MODULE_PARM_DESC(debug, "debug output mask");
 413
 414
 415//module_exit(ieee80211_exit);
 416//module_init(ieee80211_init);
 417#endif
 418#endif
 419
 420#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 421//EXPORT_SYMBOL(alloc_ieee80211);
 422//EXPORT_SYMBOL(free_ieee80211);
 423#else
 424EXPORT_SYMBOL_NOVERS(alloc_ieee80211);
 425EXPORT_SYMBOL_NOVERS(free_ieee80211);
 426#endif
 427