📄 ieee80211_wx.c
字号:
/****************************************************************************** Copyright(c) 2004 Intel Corporation. All rights reserved. Portions of this file are based on the WEP enablement code provided by the Host AP project hostap-drivers v0.1.3 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen <jkmaline@cc.hut.fi> Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> Association logic, scanning WX and logics added by Andrea Merello <andreamrl@tiscali.it> This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The full GNU General Public License is included in this distribution in the file called LICENSE. Contact Information: James P. Ketrenos <ipw2100-admin@linux.intel.com> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497******************************************************************************/#include <linux/wireless.h>#include <linux/version.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)#include <linux/kmod.h> /* request_module */#include <linux/kernel.h>#include <linux/module.h>#endif#include "ieee80211.h"#include <linux/if_arp.h>#define RSSI2DBM(x) 98-(x)static inline char *wlan_translate_scan(char *start, char *stop, struct ieee80211_beacon *beacon){ struct iw_event iwe; int i; /* First entry *MUST* be the AP MAC address */ iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, beacon->bssid, ETH_ALEN); start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN); /* Remaining entries will be displayed in the order we provide them */ /* Add the ESSID */ iwe.u.data.length = beacon->ssid_len; if (iwe.u.data.length > 32) iwe.u.data.length = 32; iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; start = iwe_stream_add_point(start, stop, &iwe, beacon->ssid); /* Add mode */ iwe.cmd = SIOCGIWMODE; if (beacon->capability & (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) { if (beacon->capability & WLAN_CAPABILITY_BSS) iwe.u.mode = IW_MODE_MASTER; else iwe.u.mode = IW_MODE_ADHOC; start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN); } /* Add frequency */ iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = wlan_frequencies[beacon->channel -1] * 100000; iwe.u.freq.e = 1; start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN); /* Add rates */ iwe.cmd = SIOCGIWRATE; iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; for (i = 0; i < beacon->rates_len; i++) { iwe.u.bitrate.value = (beacon->rates[i] & 0x7F) * 500000; start = iwe_stream_add_event(start, stop, &iwe, IW_EV_PARAM_LEN); } /* Add quality statistics */ iwe.cmd = IWEVQUAL; iwe.u.qual.qual = beacon->quality ; iwe.u.qual.level = beacon->rssi ; iwe.u.qual.noise = 0; iwe.u.qual.updated = 7; start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); /* Add encryption capability */ iwe.cmd = SIOCGIWENCODE; if (beacon->capability & WLAN_CAPABILITY_PRIVACY) iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; start = iwe_stream_add_point(start, stop, &iwe, beacon->ssid); return start;} int ieee80211_r8180_wx_get_scan(struct ieee80211_device *ieee,struct iw_request_info *a,union iwreq_data *wrqu,char *extra){ struct ieee80211_beacon *beacon; struct list_head *b,*delprev,*prev,*next; unsigned long flags; char *ev = extra; char *stop = ev + IW_SCAN_MAX_DATA; delprev = NULL; spin_lock_irqsave(&ieee->irq_lock, flags); list_for_each(b,&ieee->beacons){ if (delprev){ kfree(list_entry(delprev,struct ieee80211_beacon,list)); delprev=NULL; } beacon=list_entry(b,struct ieee80211_beacon,list); if(beacon->last_scanned + SCAN_JIFFI < jiffies){ prev = b->prev; next = b->next; next->prev = prev; prev->next = next; delprev=b; }else{ ev = wlan_translate_scan(ev, stop, beacon); /* printk("cell %s : %x %x %x %x %x %x\n",beacon->ssid,beacon->bssid[0], beacon->bssid[1],beacon->bssid[2],beacon->bssid[3],beacon->bssid[4], beacon->bssid[5]);*/ } } spin_unlock_irqrestore(&ieee->irq_lock, flags); wrqu->data.length = ev - extra; wrqu->data.flags = 0; return 0; }#ifndef CONFIG_IEEE80211_NOWEPstatic void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, struct ieee80211_crypt_data **crypt){ struct ieee80211_crypt_data *tmp; unsigned long flags; if (*crypt == NULL) return; tmp = *crypt; *crypt = NULL; /* must not run ops->deinit() while there may be pending encrypt or * decrypt operations. Use a list of delayed deinits to avoid needing * locking. */ spin_lock_irqsave(&ieee->lock, flags); list_add(&tmp->list, &ieee->crypt_deinit_list); if (!timer_pending(&ieee->crypt_deinit_timer)) { ieee->crypt_deinit_timer.expires = jiffies + HZ; add_timer(&ieee->crypt_deinit_timer); } spin_unlock_irqrestore(&ieee->lock, flags);}#endifint ieee80211_r8180_wx_set_encode(struct ieee80211_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *keybuf){ struct iw_point *erq = &(wrqu->encoding);#ifdef CONFIG_IEEE80211_NOWEP if (erq->flags & IW_ENCODE_DISABLED) return 0; return -EOPNOTSUPP;#else struct net_device *dev = ieee->dev; struct ieee80211_security sec = { .flags = 0 }; int key; struct ieee80211_crypt_data **crypt; key = erq->flags & IW_ENCODE_INDEX; if (key) { if (key > 4) return -EINVAL; else key--; if (key >= WEP_KEYS) return -EINVAL; } else key = ieee->tx_keyidx; crypt = &ieee->crypt[key]; if (erq->flags & IW_ENCODE_DISABLED) { if (*crypt) { sec.enabled = 0; sec.level = SEC_LEVEL_0; sec.flags |= SEC_ENABLED | SEC_LEVEL; ieee80211_crypt_delayed_deinit(ieee, crypt); } goto done; } sec.enabled = 1; sec.flags |= SEC_ENABLED; if (*crypt != NULL && (*crypt)->ops != NULL && strcmp((*crypt)->ops->name, "WEP") != 0) { /* changing to use WEP; deinit previously used algorithm */ ieee80211_crypt_delayed_deinit(ieee, crypt); } if (*crypt == NULL) { struct ieee80211_crypt_data *new_crypt; /* take WEP into use */ new_crypt = (struct ieee80211_crypt_data *) kmalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL); if (new_crypt == NULL) return -ENOMEM; memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ieee80211_r8180_get_crypto_ops("WEP"); if (!new_crypt->ops) { request_module("ieee80211_crypt_wep-r8180"); new_crypt->ops = ieee80211_r8180_get_crypto_ops("WEP"); } if (new_crypt->ops) new_crypt->priv = new_crypt->ops->init(key); if (!new_crypt->ops || !new_crypt->priv) { kfree(new_crypt); new_crypt = NULL; printk(KERN_WARNING "%s: could not initialize WEP: " "load module ieee80211_crypt_wep_r8180.o\n", dev->name); return -EOPNOTSUPP; } *crypt = new_crypt; } if (erq->length > 0) { int len = erq->length <= 5 ? 5 : 13; int first = 1, j; if (len > erq->length) memset(keybuf + erq->length, 0, len - erq->length); (*crypt)->ops->set_key(keybuf, len, NULL, (*crypt)->priv); memcpy(sec.keys[key], keybuf, len); sec.key_sizes[key] = len; sec.flags |= (1 << key); for (j = 0; j < WEP_KEYS; j++) { if (j != key && ieee->crypt[j]) { first = 0; break; } } if (first) ieee->tx_keyidx = key; sec.active_key = key; sec.flags |= SEC_ACTIVE_KEY; } else { /* No key data - just set the default TX key index */ ieee->tx_keyidx = key; sec.active_key = key; sec.flags |= SEC_ACTIVE_KEY; } done: ieee->open_wep = erq->flags & IW_ENCODE_OPEN; sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; sec.flags |= SEC_AUTH_MODE; /* For now we just support WEP, so only set that security level... * TODO: When WPA is added this is one place that needs to change */ sec.flags |= SEC_LEVEL; sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */ if (ieee->func && ieee->func->set_security) ieee->func->set_security(ieee, &sec); /* Do not reset port if card is in Managed mode since resetting will * generate new IEEE 802.11 authentication which may end up in looping * with IEEE 802.1X. If your hardware requires a reset after WEP * configuration (for example... Prism2), implement the reset_port in * the callbacks structures used to initialize the 802.11 stack. */ if (ieee->reset_on_keychange && ieee->iw_mode != IW_MODE_INFRA && ieee->func->reset_port && ieee->func->reset_port(dev)) { printk(KERN_DEBUG "%s: reset_port failed\n", dev->name); return -EINVAL; } return 0;#endif}#if 0int ieee80211_wx_set_encode(struct ieee80211_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *key){ struct iw_point *erq = &(wrqu->encoding);#ifdef CONFIG_IEEE80211_NOWEP if (erq->flags & IW_ENCODE_DISABLED) return 0; return -EOPNOTSUPP;#else struct net_device *dev = ieee->dev; struct ieee80211_security sec = { .flags = 0 }; int first = 0; int i; if (erq->flags & IW_ENCODE_DISABLED) { sec.enabled = 0; sec.flags |= SEC_ENABLED; ieee80211_crypt_delayed_deinit(ieee, &ieee->crypt); goto done; } sec.enabled = 1; sec.flags |= SEC_ENABLED; if (ieee->crypt != NULL && ieee->crypt->ops != NULL && strcmp(ieee->crypt->ops->name, "WEP") != 0) { /* changing to use WEP; deinit previously used algorithm */ ieee80211_crypt_delayed_deinit(ieee, &ieee->crypt);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -