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 <linux/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 61 MODULE_VERSION(DRV_VERSION); 62 MODULE_DESCRIPTION(DRV_DESCRIPTION); 63 MODULE_AUTHOR(DRV_COPYRIGHT); 64 MODULE_LICENSE("GPL"); 65 66 static struct cfg80211_ops libipw_config_ops = { }; 67 static void *libipw_wiphy_privid = &libipw_wiphy_privid; 68 69 static 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 87 static 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 95 void 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 } 108 EXPORT_SYMBOL(libipw_networks_age); 109 110 static 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 121 struct net_device *alloc_libipw(int sizeof_priv, int monitor) 122 { 123 struct libipw_device *ieee; 124 struct net_device *dev; 125 int err; 126 127 LIBIPW_DEBUG_INFO("Initializing...\n"); 128 129 dev = alloc_etherdev(sizeof(struct libipw_device) + sizeof_priv); 130 if (!dev) 131 goto failed; 132 133 ieee = netdev_priv(dev); 134 135 ieee->dev = dev; 136 137 if (!monitor) { 138 ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0); 139 if (!ieee->wdev.wiphy) { 140 LIBIPW_ERROR("Unable to allocate wiphy.\n"); 141 goto failed_free_netdev; 142 } 143 144 ieee->dev->ieee80211_ptr = &ieee->wdev; 145 ieee->wdev.iftype = NL80211_IFTYPE_STATION; 146 147 /* Fill-out wiphy structure bits we know... Not enough info 148 here to call set_wiphy_dev or set MAC address or channel info 149 -- have to do that in ->ndo_init... */ 150 ieee->wdev.wiphy->privid = libipw_wiphy_privid; 151 152 ieee->wdev.wiphy->max_scan_ssids = 1; 153 ieee->wdev.wiphy->max_scan_ie_len = 0; 154 ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) 155 | BIT(NL80211_IFTYPE_ADHOC); 156 } 157 158 err = libipw_networks_allocate(ieee); 159 if (err) { 160 LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err); 161 goto failed_free_wiphy; 162 } 163 libipw_networks_initialize(ieee); 164 165 /* Default fragmentation threshold is maximum payload size */ 166 ieee->fts = DEFAULT_FTS; 167 ieee->rts = DEFAULT_FTS; 168 ieee->scan_age = DEFAULT_MAX_SCAN_AGE; 169 ieee->open_wep = 1; 170 171 /* Default to enabling full open WEP with host based encrypt/decrypt */ 172 ieee->host_encrypt = 1; 173 ieee->host_decrypt = 1; 174 ieee->host_mc_decrypt = 1; 175 176 /* Host fragmentation in Open mode. Default is enabled. 177 * Note: host fragmentation is always enabled if host encryption 178 * is enabled. For cards can do hardware encryption, they must do 179 * hardware fragmentation as well. So we don't need a variable 180 * like host_enc_frag. */ 181 ieee->host_open_frag = 1; 182 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ 183 184 spin_lock_init(&ieee->lock); 185 186 lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock); 187 188 ieee->wpa_enabled = 0; 189 ieee->drop_unencrypted = 0; 190 ieee->privacy_invoked = 0; 191 192 return dev; 193 194 failed_free_wiphy: 195 if (!monitor) 196 wiphy_free(ieee->wdev.wiphy); 197 failed_free_netdev: 198 free_netdev(dev); 199 failed: 200 return NULL; 201 } 202 EXPORT_SYMBOL(alloc_libipw); 203 204 void free_libipw(struct net_device *dev, int monitor) 205 { 206 struct libipw_device *ieee = netdev_priv(dev); 207 208 lib80211_crypt_info_free(&ieee->crypt_info); 209 210 libipw_networks_free(ieee); 211 212 /* free cfg80211 resources */ 213 if (!monitor) 214 wiphy_free(ieee->wdev.wiphy); 215 216 free_netdev(dev); 217 } 218 EXPORT_SYMBOL(free_libipw); 219 220 #ifdef CONFIG_LIBIPW_DEBUG 221 222 static int debug = 0; 223 u32 libipw_debug_level = 0; 224 EXPORT_SYMBOL_GPL(libipw_debug_level); 225 static struct proc_dir_entry *libipw_proc = NULL; 226 227 static int debug_level_proc_show(struct seq_file *m, void *v) 228 { 229 seq_printf(m, "0x%08X\n", libipw_debug_level); 230 return 0; 231 } 232 233 static int debug_level_proc_open(struct inode *inode, struct file *file) 234 { 235 return single_open(file, debug_level_proc_show, NULL); 236 } 237 238 static ssize_t debug_level_proc_write(struct file *file, 239 const char __user *buffer, size_t count, loff_t *pos) 240 { 241 char buf[] = "0x00000000\n"; 242 size_t len = min(sizeof(buf) - 1, count); 243 unsigned long val; 244 245 if (copy_from_user(buf, buffer, len)) 246 return count; 247 buf[len] = 0; 248 if (sscanf(buf, "%li", &val) != 1) 249 printk(KERN_INFO DRV_NAME 250 ": %s is not in hex or decimal form.\n", buf); 251 else 252 libipw_debug_level = val; 253 254 return strnlen(buf, len); 255 } 256 257 static const struct file_operations debug_level_proc_fops = { 258 .owner = THIS_MODULE, 259 .open = debug_level_proc_open, 260 .read = seq_read, 261 .llseek = seq_lseek, 262 .release = single_release, 263 .write = debug_level_proc_write, 264 }; 265 #endif /* CONFIG_LIBIPW_DEBUG */ 266 267 static int __init libipw_init(void) 268 { 269 #ifdef CONFIG_LIBIPW_DEBUG 270 struct proc_dir_entry *e; 271 272 libipw_debug_level = debug; 273 libipw_proc = proc_mkdir(DRV_PROCNAME, init_net.proc_net); 274 if (libipw_proc == NULL) { 275 LIBIPW_ERROR("Unable to create " DRV_PROCNAME 276 " proc directory\n"); 277 return -EIO; 278 } 279 e = proc_create("debug_level", S_IRUGO | S_IWUSR, libipw_proc, 280 &debug_level_proc_fops); 281 if (!e) { 282 remove_proc_entry(DRV_PROCNAME, init_net.proc_net); 283 libipw_proc = NULL; 284 return -EIO; 285 } 286 #endif /* CONFIG_LIBIPW_DEBUG */ 287 288 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); 289 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); 290 291 return 0; 292 } 293 294 static void __exit libipw_exit(void) 295 { 296 #ifdef CONFIG_LIBIPW_DEBUG 297 if (libipw_proc) { 298 remove_proc_entry("debug_level", libipw_proc); 299 remove_proc_entry(DRV_PROCNAME, init_net.proc_net); 300 libipw_proc = NULL; 301 } 302 #endif /* CONFIG_LIBIPW_DEBUG */ 303 } 304 305 #ifdef CONFIG_LIBIPW_DEBUG 306 #include <linux/moduleparam.h> 307 module_param(debug, int, 0444); 308 MODULE_PARM_DESC(debug, "debug output mask"); 309 #endif /* CONFIG_LIBIPW_DEBUG */ 310 311 module_exit(libipw_exit); 312 module_init(libipw_init); 313