libipw_module.c revision d5b3b9ae065d093fe0e1588a07f3ebd71c815f0b
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 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/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 "ieee80211.h" 54 55#define DRV_DESCRIPTION "802.11 data/management/control stack" 56#define DRV_NAME "ieee80211" 57#define DRV_VERSION IEEE80211_VERSION 58#define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>" 59 60MODULE_VERSION(DRV_VERSION); 61MODULE_DESCRIPTION(DRV_DESCRIPTION); 62MODULE_AUTHOR(DRV_COPYRIGHT); 63MODULE_LICENSE("GPL"); 64 65static int ieee80211_networks_allocate(struct ieee80211_device *ieee) 66{ 67 if (ieee->networks) 68 return 0; 69 70 ieee->networks = 71 kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network), 72 GFP_KERNEL); 73 if (!ieee->networks) { 74 printk(KERN_WARNING "%s: Out of memory allocating beacons\n", 75 ieee->dev->name); 76 return -ENOMEM; 77 } 78 79 return 0; 80} 81 82void ieee80211_network_reset(struct ieee80211_network *network) 83{ 84 if (!network) 85 return; 86 87 if (network->ibss_dfs) { 88 kfree(network->ibss_dfs); 89 network->ibss_dfs = NULL; 90 } 91} 92 93static inline void ieee80211_networks_free(struct ieee80211_device *ieee) 94{ 95 int i; 96 97 if (!ieee->networks) 98 return; 99 100 for (i = 0; i < MAX_NETWORK_COUNT; i++) 101 if (ieee->networks[i].ibss_dfs) 102 kfree(ieee->networks[i].ibss_dfs); 103 104 kfree(ieee->networks); 105 ieee->networks = NULL; 106} 107 108void ieee80211_networks_age(struct ieee80211_device *ieee, 109 unsigned long age_secs) 110{ 111 struct ieee80211_network *network = NULL; 112 unsigned long flags; 113 unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC); 114 115 spin_lock_irqsave(&ieee->lock, flags); 116 list_for_each_entry(network, &ieee->network_list, list) { 117 network->last_scanned -= age_jiffies; 118 } 119 spin_unlock_irqrestore(&ieee->lock, flags); 120} 121EXPORT_SYMBOL(ieee80211_networks_age); 122 123static void ieee80211_networks_initialize(struct ieee80211_device *ieee) 124{ 125 int i; 126 127 INIT_LIST_HEAD(&ieee->network_free_list); 128 INIT_LIST_HEAD(&ieee->network_list); 129 for (i = 0; i < MAX_NETWORK_COUNT; i++) 130 list_add_tail(&ieee->networks[i].list, 131 &ieee->network_free_list); 132} 133 134int ieee80211_change_mtu(struct net_device *dev, int new_mtu) 135{ 136 if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN)) 137 return -EINVAL; 138 dev->mtu = new_mtu; 139 return 0; 140} 141EXPORT_SYMBOL(ieee80211_change_mtu); 142 143struct net_device *alloc_ieee80211(int sizeof_priv) 144{ 145 struct ieee80211_device *ieee; 146 struct net_device *dev; 147 int err; 148 149 IEEE80211_DEBUG_INFO("Initializing...\n"); 150 151 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv); 152 if (!dev) { 153 IEEE80211_ERROR("Unable to allocate network device.\n"); 154 goto failed; 155 } 156 ieee = netdev_priv(dev); 157#ifdef CONFIG_COMPAT_NET_DEV_OPS 158 dev->hard_start_xmit = ieee80211_xmit; 159 dev->change_mtu = ieee80211_change_mtu; 160#endif 161 162 ieee->dev = dev; 163 164 err = ieee80211_networks_allocate(ieee); 165 if (err) { 166 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err); 167 goto failed_free_netdev; 168 } 169 ieee80211_networks_initialize(ieee); 170 171 /* Default fragmentation threshold is maximum payload size */ 172 ieee->fts = DEFAULT_FTS; 173 ieee->rts = DEFAULT_FTS; 174 ieee->scan_age = DEFAULT_MAX_SCAN_AGE; 175 ieee->open_wep = 1; 176 177 /* Default to enabling full open WEP with host based encrypt/decrypt */ 178 ieee->host_encrypt = 1; 179 ieee->host_decrypt = 1; 180 ieee->host_mc_decrypt = 1; 181 182 /* Host fragementation in Open mode. Default is enabled. 183 * Note: host fragmentation is always enabled if host encryption 184 * is enabled. For cards can do hardware encryption, they must do 185 * hardware fragmentation as well. So we don't need a variable 186 * like host_enc_frag. */ 187 ieee->host_open_frag = 1; 188 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ 189 190 spin_lock_init(&ieee->lock); 191 192 lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock); 193 194 ieee->wpa_enabled = 0; 195 ieee->drop_unencrypted = 0; 196 ieee->privacy_invoked = 0; 197 198 return dev; 199 200failed_free_netdev: 201 free_netdev(dev); 202failed: 203 return NULL; 204} 205 206void free_ieee80211(struct net_device *dev) 207{ 208 struct ieee80211_device *ieee = netdev_priv(dev); 209 210 lib80211_crypt_info_free(&ieee->crypt_info); 211 212 ieee80211_networks_free(ieee); 213 free_netdev(dev); 214} 215 216#ifdef CONFIG_LIBIPW_DEBUG 217 218static int debug = 0; 219u32 ieee80211_debug_level = 0; 220EXPORT_SYMBOL_GPL(ieee80211_debug_level); 221static struct proc_dir_entry *ieee80211_proc = NULL; 222 223static int show_debug_level(char *page, char **start, off_t offset, 224 int count, int *eof, void *data) 225{ 226 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level); 227} 228 229static int store_debug_level(struct file *file, const char __user * buffer, 230 unsigned long count, void *data) 231{ 232 char buf[] = "0x00000000\n"; 233 unsigned long len = min((unsigned long)sizeof(buf) - 1, count); 234 unsigned long val; 235 236 if (copy_from_user(buf, buffer, len)) 237 return count; 238 buf[len] = 0; 239 if (sscanf(buf, "%li", &val) != 1) 240 printk(KERN_INFO DRV_NAME 241 ": %s is not in hex or decimal form.\n", buf); 242 else 243 ieee80211_debug_level = val; 244 245 return strnlen(buf, len); 246} 247#endif /* CONFIG_LIBIPW_DEBUG */ 248 249static int __init ieee80211_init(void) 250{ 251#ifdef CONFIG_LIBIPW_DEBUG 252 struct proc_dir_entry *e; 253 254 ieee80211_debug_level = debug; 255 ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net); 256 if (ieee80211_proc == NULL) { 257 IEEE80211_ERROR("Unable to create " DRV_NAME 258 " proc directory\n"); 259 return -EIO; 260 } 261 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR, 262 ieee80211_proc); 263 if (!e) { 264 remove_proc_entry(DRV_NAME, init_net.proc_net); 265 ieee80211_proc = NULL; 266 return -EIO; 267 } 268 e->read_proc = show_debug_level; 269 e->write_proc = store_debug_level; 270 e->data = NULL; 271#endif /* CONFIG_LIBIPW_DEBUG */ 272 273 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); 274 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); 275 276 return 0; 277} 278 279static void __exit ieee80211_exit(void) 280{ 281#ifdef CONFIG_LIBIPW_DEBUG 282 if (ieee80211_proc) { 283 remove_proc_entry("debug_level", ieee80211_proc); 284 remove_proc_entry(DRV_NAME, init_net.proc_net); 285 ieee80211_proc = NULL; 286 } 287#endif /* CONFIG_LIBIPW_DEBUG */ 288} 289 290#ifdef CONFIG_LIBIPW_DEBUG 291#include <linux/moduleparam.h> 292module_param(debug, int, 0444); 293MODULE_PARM_DESC(debug, "debug output mask"); 294#endif /* CONFIG_LIBIPW_DEBUG */ 295 296module_exit(ieee80211_exit); 297module_init(ieee80211_init); 298 299EXPORT_SYMBOL(alloc_ieee80211); 300EXPORT_SYMBOL(free_ieee80211); 301