?? p80211wext.c
字號:
/* src/p80211/p80211wext.c* * Glue code to make linux-wlan-ng a happy wireless extension camper.* * original author: Reyk Floeter <reyk@synack.de>* Completely re-written by Solomon Peachy <solomon@linux-wlan.com>** Copyright (C) 2002 AbsoluteValue Systems, Inc. All Rights Reserved.* --------------------------------------------------------------------** linux-wlan** The contents of this file are subject to the Mozilla Public* License Version 1.1 (the "License"); you may not use this file* except in compliance with the License. You may obtain a copy of* the License at http://www.mozilla.org/MPL/** Software distributed under the License is distributed on an "AS* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or* implied. See the License for the specific language governing* rights and limitations under the License.** Alternatively, the contents of this file may be used under the* terms of the GNU Public License version 2 (the "GPL"), in which* case the provisions of the GPL are applicable instead of the* above. If you wish to allow the use of your version of this file* only under the terms of the GPL and not to allow others to use* your version of this file under the MPL, indicate your decision* by deleting the provisions above and replace them with the notice* and other provisions required by the GPL. If you do not delete* the provisions above, a recipient may use your version of this* file under either the MPL or the GPL.** --------------------------------------------------------------------*//*================================================================*//* System Includes */#include <linux/config.h>#include <linux/version.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/wireless.h>#if WIRELESS_EXT > 12#include <net/iw_handler.h>#endif#include <linux/if_arp.h>#include <asm/bitops.h>#include <asm/uaccess.h>#include <asm/byteorder.h>/*================================================================*//* Project Includes */#include <wlan/version.h>#include <wlan/wlan_compat.h>#include <wlan/p80211types.h>#include <wlan/p80211hdr.h>#include <wlan/p80211conv.h>#include <wlan/p80211mgmt.h>#include <wlan/p80211msg.h>#include <wlan/p80211metastruct.h>#include <wlan/p80211metadef.h>#include <wlan/p80211netdev.h>#include <wlan/p80211ioctl.h>#include <wlan/p80211req.h>static int p80211wext_giwrate(netdevice_t *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra);static int p80211wext_giwessid(netdevice_t *dev, struct iw_request_info *info, struct iw_point *data, char *essid);/* compatibility to wireless extensions */#ifdef WIRELESS_EXTUINT8 p80211_mhz_to_channel(UINT16 mhz){ if (mhz >= 5000) { return ((mhz - 5000) / 5); } if (mhz == 2482) return 14; if (mhz >= 2407) { return ((mhz - 2407) / 5); } return 0;}UINT16 p80211_channel_to_mhz(UINT8 ch, int dot11a){ if (ch == 0) return 0; if (ch > 200) return 0; /* 5G */ if (dot11a) { return (5000 + (5 * ch)); } /* 2.4G */ if (ch == 14) return 2484; if ((ch < 14) && (ch > 0)) { return (2407 + (5 * ch)); } return 0;}/* taken from orinoco.c ;-) */const long p80211wext_channel_freq[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484};#define NUM_CHANNELS (sizeof(p80211wext_channel_freq) / sizeof(p80211wext_channel_freq[0])) /** function declarations =============== */static int p80211wext_dorequest(wlandevice_t *wlandev, UINT32 did, UINT32 data){ p80211msg_dot11req_mibset_t msg; p80211item_uint32_t mibitem; int result; DBFENTER; msg.msgcode = DIDmsg_dot11req_mibset; mibitem.did = did; mibitem.data = data; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); result = p80211req_dorequest(wlandev, (UINT8*)&msg); DBFEXIT; return result;}static int p80211wext_autojoin(wlandevice_t *wlandev){ p80211msg_lnxreq_autojoin_t msg; struct iw_point data; char ssid[IW_ESSID_MAX_SIZE]; int result; int err = 0; DBFENTER; /* Get ESSID */ result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid); if (result) { err = -EFAULT; goto exit; }#warning "make a smarter sharedkey/opensystem auth decision" /* Get WEPDef */ if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED || wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) { msg.authtype.data = P80211ENUM_authalg_sharedkey; } else { msg.authtype.data = P80211ENUM_authalg_opensystem; } msg.msgcode = DIDmsg_lnxreq_autojoin; /* Trim the last '\0' to fit the SSID format */ if (ssid[data.length-1] == '\0') { data.length = data.length - 1; } memcpy(msg.ssid.data.data, ssid, data.length); msg.ssid.data.len = data.length; result = p80211req_dorequest(wlandev, (UINT8*)&msg); if (result) { err = -EFAULT; goto exit; }exit: DBFEXIT; return err; }/* called by /proc/net/wireless */struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev) { p80211msg_lnxreq_commsquality_t quality; wlandevice_t *wlandev = (wlandevice_t*)dev->priv; struct iw_statistics* wstats = &wlandev->wstats; int retval; DBFENTER; /* Check */ if ( (wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING) ) return NULL; /* XXX Only valid in station mode */ wstats->status = 0; /* build request message */ quality.msgcode = DIDmsg_lnxreq_commsquality; quality.dbm.data = P80211ENUM_truth_true; quality.dbm.status = P80211ENUM_msgitem_status_data_ok; /* send message to nsd */ if ( wlandev->mlmerequest == NULL ) return NULL; retval = wlandev->mlmerequest(wlandev, (p80211msg_t*) &quality); wstats->qual.qual = quality.link.data; /* overall link quality */ wstats->qual.level = quality.level.data; /* instant signal level */ wstats->qual.noise = quality.noise.data; /* instant noise level */ wstats->qual.updated = 7; wstats->discard.code = wlandev->rx.decrypt_err; wstats->discard.nwid = 0; wstats->discard.misc = 0;#if WIRELESS_EXT > 11 wstats->discard.fragment = 0; // incomplete fragments wstats->discard.retries = 0; // tx retries. wstats->miss.beacon = 0;#endif DBFEXIT; return wstats;}static int p80211wext_giwname(netdevice_t *dev, struct iw_request_info *info, char *name, char *extra){ struct iw_param rate; int result; int err = 0; DBFENTER; result = p80211wext_giwrate(dev, NULL, &rate, NULL); if (result) { err = -EFAULT; goto exit; } switch (rate.value) { case 1000000: case 2000000: strcpy(name, "IEEE 802.11-DS"); break; case 5500000: case 11000000: strcpy(name, "IEEE 802.11-b"); break; }exit: DBFEXIT; return err;}static int p80211wext_giwfreq(netdevice_t *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra){ wlandevice_t *wlandev = (wlandevice_t*)dev->priv; p80211item_uint32_t mibitem; p80211msg_dot11req_mibset_t msg; int result; int err = 0; DBFENTER; msg.msgcode = DIDmsg_dot11req_mibget; mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); result = p80211req_dorequest(wlandev, (UINT8*)&msg); if (result) { err = -EFAULT; goto exit; } memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); if (mibitem.data > NUM_CHANNELS) { err = -EFAULT; goto exit; } /* convert into frequency instead of a channel */ freq->e = 1; freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000; exit: DBFEXIT; return err;}static int p80211wext_siwfreq(netdevice_t *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra){ wlandevice_t *wlandev = (wlandevice_t*)dev->priv; p80211item_uint32_t mibitem; p80211msg_dot11req_mibset_t msg; int result; int err = 0; DBFENTER; if (!wlan_wext_write) { err = (-EOPNOTSUPP); goto exit; } msg.msgcode = DIDmsg_dot11req_mibset; mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel; mibitem.status = P80211ENUM_msgitem_status_data_ok; if ( (freq->e == 0) && (freq->m <= 1000) ) mibitem.data = freq->m; else mibitem.data = p80211_mhz_to_channel(freq->m); memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); result = p80211req_dorequest(wlandev, (UINT8*)&msg); if (result) { err = -EFAULT; goto exit; } exit: DBFEXIT; return err;}#if WIRELESS_EXT > 8static int p80211wext_giwmode(netdevice_t *dev, struct iw_request_info *info, __u32 *mode, char *extra){ wlandevice_t *wlandev = (wlandevice_t*)dev->priv; DBFENTER; switch (wlandev->macmode) { case WLAN_MACMODE_IBSS_STA: *mode = IW_MODE_ADHOC; break; case WLAN_MACMODE_ESS_STA: *mode = IW_MODE_INFRA; break; case WLAN_MACMODE_ESS_AP: *mode = IW_MODE_MASTER; break; default: /* Not set yet. */ *mode = IW_MODE_AUTO; } DBFEXIT; return 0;}static int p80211wext_siwmode(netdevice_t *dev, struct iw_request_info *info, __u32 *mode, char *extra){ wlandevice_t *wlandev = (wlandevice_t*)dev->priv; p80211item_uint32_t mibitem; p80211msg_dot11req_mibset_t msg; int result; int err = 0; DBFENTER; if (!wlan_wext_write) { err = (-EOPNOTSUPP); goto exit; } if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA && *mode != IW_MODE_MASTER) { err = (-EOPNOTSUPP); goto exit; } /* Operation mode is the same with current mode */ if (*mode == wlandev->macmode) goto exit; switch (*mode) { case IW_MODE_ADHOC: wlandev->macmode = WLAN_MACMODE_IBSS_STA; break; case IW_MODE_INFRA: wlandev->macmode = WLAN_MACMODE_ESS_STA; break; case IW_MODE_MASTER: wlandev->macmode = WLAN_MACMODE_ESS_AP; break; default: /* Not set yet. */ WLAN_LOG_INFO("Operation mode: %d not support\n", *mode); return -EOPNOTSUPP; } /* Set Operation mode to the PORT TYPE RID */#warning "get rid of p2mib here" msg.msgcode = DIDmsg_dot11req_mibset; mibitem.did = DIDmib_p2_p2Static_p2CnfPortType; mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); result = p80211req_dorequest(wlandev, (UINT8*)&msg); if (result) err = -EFAULT; exit: DBFEXIT; return err;}static int p80211wext_giwrange(netdevice_t *dev, struct iw_request_info *info, struct iw_point *data, char *extra){ struct iw_range *range = (struct iw_range *) extra; int i, val; DBFENTER;#if WIRELESS_EXT > 9 range->txpower_capa = IW_TXPOW_DBM; // XXX what about min/max_pmp, min/max_pmt, etc.#endif#if WIRELESS_EXT > 10 range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 13; range->retry_capa = IW_RETRY_LIMIT; range->retry_flags = IW_RETRY_LIMIT; range->min_retry = 0; range->max_retry = 255;#endif /* WIRELESS_EXT > 10 */#if WIRELESS_EXT > 16 range->event_capa[0] = (IW_EVENT_CAPA_K_0 | //mode/freq/ssid IW_EVENT_CAPA_MASK(SIOCGIWAP) | IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); range->event_capa[1] = IW_EVENT_CAPA_K_1; //encode range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) | IW_EVENT_CAPA_MASK(IWEVCUSTOM) );#endif range->num_channels = NUM_CHANNELS; /* XXX need to filter against the regulatory domain &| active set */ val = 0; for (i = 0; i < NUM_CHANNELS ; i++) { range->freq[val].i = i + 1; range->freq[val].m = p80211wext_channel_freq[i] * 100000; range->freq[val].e = 1; val++; } range->num_frequency = val; /* Max of /proc/net/wireless */ range->max_qual.qual = 92; range->max_qual.level = 154; range->max_qual.noise = 154; range->sensitivity = 3; // XXX these need to be nsd-specific! range->min_rts = 0; range->max_rts = 2347; range->min_frag = 256; range->max_frag = 2346; range->max_encoding_tokens = NUM_WEPKEYS; range->num_encoding_sizes = 2; range->encoding_size[0] = 5; range->encoding_size[1] = 13; // XXX what about num_bitrates/throughput? range->num_bitrates = 0; /* estimated max throughput */ range->throughput = 5500000; DBFEXIT; return 0;}#endifstatic int p80211wext_giwap(netdevice_t *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra){ wlandevice_t *wlandev = (wlandevice_t*)dev->priv; DBFENTER; memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN); ap_addr->sa_family = ARPHRD_ETHER; DBFEXIT; return 0;}#if WIRELESS_EXT > 8static int p80211wext_giwencode(netdevice_t *dev, struct iw_request_info *info, struct iw_point *erq, char *key){ wlandevice_t *wlandev = (wlandevice_t*)dev->priv; int err = 0; int i; DBFENTER; if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) erq->flags = IW_ENCODE_ENABLED; else erq->flags = IW_ENCODE_DISABLED; if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) erq->flags |= IW_ENCODE_RESTRICTED; else erq->flags |= IW_ENCODE_OPEN; i = (erq->flags & IW_ENCODE_INDEX) - 1; if (i == -1) i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; if ((i < 0) || (i >= NUM_WEPKEYS)) { err = -EINVAL; goto exit; } erq->flags |= i + 1; /* copy the key from the driver cache as the keys are read-only MIBs */ erq->length = wlandev->wep_keylens[i]; memcpy(key, wlandev->wep_keys[i], erq->length); exit: DBFEXIT; return err;}static int p80211wext_siwencode(netdevice_t *dev, struct iw_request_info *info, struct iw_point *erq, char *key){ wlandevice_t *wlandev = (wlandevice_t*)dev->priv; p80211msg_dot11req_mibset_t msg; p80211item_pstr32_t pstr;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -