libipw_module.c revision c3d72b968129ad4aec86c5fc8d2380f01ebebc53
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 134static int 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} 141 142static struct net_device_stats *ieee80211_generic_get_stats( 143 struct net_device *dev) 144{ 145 struct ieee80211_device *ieee = netdev_priv(dev); 146 return &ieee->stats; 147} 148 149struct net_device *alloc_ieee80211(int sizeof_priv) 150{ 151 struct ieee80211_device *ieee; 152 struct net_device *dev; 153 int err; 154 155 IEEE80211_DEBUG_INFO("Initializing...\n"); 156 157 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv); 158 if (!dev) { 159 IEEE80211_ERROR("Unable to allocate network device.\n"); 160 goto failed; 161 } 162 ieee = netdev_priv(dev); 163 dev->hard_start_xmit = ieee80211_xmit; 164 dev->change_mtu = ieee80211_change_mtu; 165 166 /* Drivers are free to override this if the generic implementation 167 * does not meet their needs. */ 168 dev->get_stats = ieee80211_generic_get_stats; 169 170 ieee->dev = dev; 171 172 err = ieee80211_networks_allocate(ieee); 173 if (err) { 174 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err); 175 goto failed_free_netdev; 176 } 177 ieee80211_networks_initialize(ieee); 178 179 /* Default fragmentation threshold is maximum payload size */ 180 ieee->fts = DEFAULT_FTS; 181 ieee->rts = DEFAULT_FTS; 182 ieee->scan_age = DEFAULT_MAX_SCAN_AGE; 183 ieee->open_wep = 1; 184 185 /* Default to enabling full open WEP with host based encrypt/decrypt */ 186 ieee->host_encrypt = 1; 187 ieee->host_decrypt = 1; 188 ieee->host_mc_decrypt = 1; 189 190 /* Host fragementation in Open mode. Default is enabled. 191 * Note: host fragmentation is always enabled if host encryption 192 * is enabled. For cards can do hardware encryption, they must do 193 * hardware fragmentation as well. So we don't need a variable 194 * like host_enc_frag. */ 195 ieee->host_open_frag = 1; 196 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ 197 198 spin_lock_init(&ieee->lock); 199 200 lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock); 201 202 ieee->wpa_enabled = 0; 203 ieee->drop_unencrypted = 0; 204 ieee->privacy_invoked = 0; 205 206 return dev; 207 208failed_free_netdev: 209 free_netdev(dev); 210failed: 211 return NULL; 212} 213 214void free_ieee80211(struct net_device *dev) 215{ 216 struct ieee80211_device *ieee = netdev_priv(dev); 217 218 lib80211_crypt_info_free(&ieee->crypt_info); 219 220 ieee80211_networks_free(ieee); 221 free_netdev(dev); 222} 223 224#ifdef CONFIG_IEEE80211_DEBUG 225 226static int debug = 0; 227u32 ieee80211_debug_level = 0; 228EXPORT_SYMBOL_GPL(ieee80211_debug_level); 229static struct proc_dir_entry *ieee80211_proc = NULL; 230 231static int show_debug_level(char *page, char **start, off_t offset, 232 int count, int *eof, void *data) 233{ 234 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level); 235} 236 237static int store_debug_level(struct file *file, const char __user * buffer, 238 unsigned long count, void *data) 239{ 240 char buf[] = "0x00000000\n"; 241 unsigned long len = min((unsigned long)sizeof(buf) - 1, count); 242 unsigned long val; 243 244 if (copy_from_user(buf, buffer, len)) 245 return count; 246 buf[len] = 0; 247 if (sscanf(buf, "%li", &val) != 1) 248 printk(KERN_INFO DRV_NAME 249 ": %s is not in hex or decimal form.\n", buf); 250 else 251 ieee80211_debug_level = val; 252 253 return strnlen(buf, len); 254} 255#endif /* CONFIG_IEEE80211_DEBUG */ 256 257static int __init ieee80211_init(void) 258{ 259#ifdef CONFIG_IEEE80211_DEBUG 260 struct proc_dir_entry *e; 261 262 ieee80211_debug_level = debug; 263 ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net); 264 if (ieee80211_proc == NULL) { 265 IEEE80211_ERROR("Unable to create " DRV_NAME 266 " proc directory\n"); 267 return -EIO; 268 } 269 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR, 270 ieee80211_proc); 271 if (!e) { 272 remove_proc_entry(DRV_NAME, init_net.proc_net); 273 ieee80211_proc = NULL; 274 return -EIO; 275 } 276 e->read_proc = show_debug_level; 277 e->write_proc = store_debug_level; 278 e->data = NULL; 279#endif /* CONFIG_IEEE80211_DEBUG */ 280 281 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); 282 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); 283 284 return 0; 285} 286 287static void __exit ieee80211_exit(void) 288{ 289#ifdef CONFIG_IEEE80211_DEBUG 290 if (ieee80211_proc) { 291 remove_proc_entry("debug_level", ieee80211_proc); 292 remove_proc_entry(DRV_NAME, init_net.proc_net); 293 ieee80211_proc = NULL; 294 } 295#endif /* CONFIG_IEEE80211_DEBUG */ 296} 297 298#ifdef CONFIG_IEEE80211_DEBUG 299#include <linux/moduleparam.h> 300module_param(debug, int, 0444); 301MODULE_PARM_DESC(debug, "debug output mask"); 302#endif /* CONFIG_IEEE80211_DEBUG */ 303 304module_exit(ieee80211_exit); 305module_init(ieee80211_init); 306 307EXPORT_SYMBOL(alloc_ieee80211); 308EXPORT_SYMBOL(free_ieee80211); 309