⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iw_ndis.c

📁 linux下安装无线网卡启动的程式
💻 C
📖 第 1 页 / 共 4 页
字号:
 /* *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  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. * */#include <linux/version.h>#include <linux/wireless.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/ethtool.h>#include <linux/if_arp.h>#include <linux/usb.h>#include <linux/random.h>#include <net/iw_handler.h>#include <linux/rtnetlink.h>#include <asm/uaccess.h>#include "iw_ndis.h"#include "wrapndis.h"static int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,			   2447, 2452, 2457, 2462, 2467, 2472, 2484 };static const char *network_names[] = {"IEEE 802.11FH", "IEEE 802.11b",				      "IEEE 802.11a", "IEEE 802.11g", "Auto"};int set_essid(struct wrap_ndis_device *wnd, const char *ssid, int ssid_len){	NDIS_STATUS res;	struct ndis_essid req;	if (ssid_len > NDIS_ESSID_MAX_SIZE)		return -EINVAL;	memset(&req, 0, sizeof(req));	req.length = ssid_len;	if (ssid_len)		memcpy(&req.essid, ssid, ssid_len);	DBG_BLOCK(2) {		char buf[NDIS_ESSID_MAX_SIZE+1];		memcpy(buf, ssid, ssid_len);		buf[ssid_len] = 0;		TRACE2("ssid = '%s'", buf);	}	res = mp_set(wnd, OID_802_11_SSID, &req, sizeof(req));	if (res) {		WARNING("setting essid failed (%08X)", res);		EXIT2(return -EINVAL);	}	memcpy(&wnd->essid, &req, sizeof(req));	EXIT2(return 0);}static int set_assoc_params(struct wrap_ndis_device *wnd){#if WIRELESS_EXT > 17	TRACE2("wpa_version=0x%x auth_alg=0x%x key_mgmt=0x%x "	       "cipher_pairwise=0x%x cipher_group=0x%x",	       wnd->iw_auth_wpa_version, wnd->iw_auth_80211_alg,	       wnd->iw_auth_key_mgmt, wnd->iw_auth_cipher_pairwise,	       wnd->iw_auth_cipher_group);	set_auth_mode(wnd);	set_priv_filter(wnd);	set_encr_mode(wnd);#endif	return 0;}static int iw_set_essid(struct net_device *dev, struct iw_request_info *info,			union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	char ssid[NDIS_ESSID_MAX_SIZE];	int length;	ENTER2("");	memset(ssid, 0, sizeof(ssid));	/* there is no way to turn off essid other than to set to	 * random bytes; instead, we use off to mean any */	if (wrqu->essid.flags) {		/* wireless-tools prior to version 20 add extra 1, and		 * later than 20 don't! Deal with that mess */		length = wrqu->essid.length - 1;		if (length > 0)			length--;		while (length < wrqu->essid.length && extra[length])			length++;		TRACE2("%d", length);		if (length <= 0 || length > NDIS_ESSID_MAX_SIZE)			EXIT2(return -EINVAL);	} else		length = 0;	set_assoc_params(wnd);	memcpy(ssid, extra, length);	if (set_essid(wnd, ssid, length))		EXIT2(return -EINVAL);	EXIT2(return 0);}static int iw_get_essid(struct net_device *dev, struct iw_request_info *info,			union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	NDIS_STATUS res;	struct ndis_essid req;	ENTER2("");	memset(&req, 0, sizeof(req));	res = mp_query(wnd, OID_802_11_SSID, &req, sizeof(req));	if (res) {		WARNING("getting essid failed (%08X)", res);		EXIT2(return -EOPNOTSUPP);	}	memcpy(extra, req.essid, req.length);	extra[req.length] = 0;	if (req.length > 0)		wrqu->essid.flags  = 1;	else		wrqu->essid.flags = 0;	wrqu->essid.length = req.length;	EXIT2(return 0);}int set_infra_mode(struct wrap_ndis_device *wnd,		   enum ndis_infrastructure_mode mode){	NDIS_STATUS res;	unsigned int i;	ENTER2("%d", mode);	res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE,			   &wnd->infrastructure_mode);	if (res != NDIS_STATUS_SUCCESS) {		WARNING("getting operating mode to failed (%08X)", res);		EXIT2(return -EINVAL);	}	if (wnd->infrastructure_mode == mode)		EXIT2(return 0);	res = mp_set_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, mode);	if (res) {		WARNING("setting operating mode to %d failed (%08X)",			mode, res);		EXIT2(return -EINVAL);	}	/* NDIS drivers clear keys when infrastructure mode is	 * changed. But Linux tools assume otherwise. So set the	 * keys */	if (wnd->iw_auth_key_mgmt == 0 ||	    wnd->iw_auth_key_mgmt == IW_AUTH_KEY_MGMT_802_1X) {		for (i = 0; i < MAX_ENCR_KEYS; i++) {			if (wnd->encr_info.keys[i].length > 0)				add_wep_key(wnd, wnd->encr_info.keys[i].key,					    wnd->encr_info.keys[i].length, i);		}	}	wnd->infrastructure_mode = mode;	EXIT2(return 0);}static int iw_set_infra_mode(struct net_device *dev,			     struct iw_request_info *info,			     union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	enum ndis_infrastructure_mode ndis_mode;	ENTER2("%d", wrqu->mode);	switch (wrqu->mode) {	case IW_MODE_ADHOC:		ndis_mode = Ndis802_11IBSS;		break;	case IW_MODE_INFRA:		ndis_mode = Ndis802_11Infrastructure;		break;	case IW_MODE_AUTO:		ndis_mode = Ndis802_11AutoUnknown;		break;	default:		EXIT2(return -EINVAL);	}	if (set_infra_mode(wnd, ndis_mode))		EXIT2(return -EINVAL);	EXIT2(return 0);}static int iw_get_infra_mode(struct net_device *dev,			     struct iw_request_info *info,			     union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	int ndis_mode, iw_mode;	NDIS_STATUS res;	ENTER2("");	res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, &ndis_mode);	if (res) {		WARNING("getting operating mode failed (%08X)", res);		EXIT2(return -EOPNOTSUPP);	}	switch(ndis_mode) {	case Ndis802_11IBSS:		iw_mode = IW_MODE_ADHOC;		break;	case Ndis802_11Infrastructure:		iw_mode = IW_MODE_INFRA;		break;	case Ndis802_11AutoUnknown:		iw_mode = IW_MODE_AUTO;		break;	default:		ERROR("invalid operating mode (%u)", ndis_mode);		EXIT2(return -EINVAL);	}	wrqu->mode = iw_mode;	EXIT2(return 0);}static const char *network_type_to_name(int net_type){	if (net_type >= 0 &&	    net_type < (sizeof(network_names)/sizeof(network_names[0])))		return network_names[net_type];	else		return network_names[sizeof(network_names) /				     sizeof(network_names[0]) - 1];}static int iw_get_network_type(struct net_device *dev,			       struct iw_request_info *info,			       union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	unsigned int network_type;	NDIS_STATUS res;	ENTER2("");	res = mp_query_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE,			   &network_type);	if (res) {		WARNING("getting network type failed: %08X", res);		network_type = -1;	}	strncpy(wrqu->name, network_type_to_name(network_type),	        sizeof(wrqu->name) - 1);	wrqu->name[sizeof(wrqu->name)-1] = 0;	return 0;}static int iw_get_freq(struct net_device *dev, struct iw_request_info *info,		       union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	NDIS_STATUS res;	struct ndis_configuration req;	ENTER2("");	memset(&req, 0, sizeof(req));	res = mp_query(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req));	if (res) {		WARNING("getting configuration failed (%08X)", res);		EXIT2(return -EOPNOTSUPP);	}	memset(&(wrqu->freq), 0, sizeof(struct iw_freq));	/* see comment in wireless.h above the "struct iw_freq"	   definition for an explanation of this if	   NOTE: 1000000 is due to the kHz	*/	if (req.ds_config > 1000000) {		wrqu->freq.m = req.ds_config / 10;		wrqu->freq.e = 1;	}	else		wrqu->freq.m = req.ds_config;	/* convert from kHz to Hz */	wrqu->freq.e += 3;	return 0;}static int iw_set_freq(struct net_device *dev, struct iw_request_info *info,		       union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	NDIS_STATUS res;	struct ndis_configuration req;	ENTER2("");	/* this OID is valid only when not associated */	if (netif_carrier_ok(wnd->net_dev))		EXIT2(return 0);	memset(&req, 0, sizeof(req));	res = mp_query(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req));	if (res) {		WARNING("getting configuration failed (%08X)", res);		EXIT2(return 0);	}	if (wrqu->freq.m < 1000 && wrqu->freq.e == 0) {		if (wrqu->freq.m >= 1 &&		    wrqu->freq.m <= (sizeof(freq_chan) / sizeof(freq_chan[0])))			req.ds_config = freq_chan[wrqu->freq.m - 1] * 1000;		else			return -EINVAL;	} else {		int i;		req.ds_config = wrqu->freq.m;		for (i = wrqu->freq.e; i > 0; i--)			req.ds_config *= 10;		req.ds_config /= 1000;	}	res = mp_set(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req));	if (res)		WARNING("setting configuration failed (%08X)", res);	return 0;}static int iw_get_tx_power(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	ndis_tx_power_level ndis_power;	NDIS_STATUS res;	ENTER2("");	res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL,		       &ndis_power, sizeof(ndis_power));	if (res)		return -EOPNOTSUPP;	wrqu->txpower.flags = IW_TXPOW_MWATT;	wrqu->txpower.disabled = 0;	wrqu->txpower.fixed = 0;	wrqu->txpower.value = ndis_power;	return 0;}static int iw_set_tx_power(struct net_device *dev, struct iw_request_info *info,			   union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	ndis_tx_power_level ndis_power;	NDIS_STATUS res;	ENTER2("");	if (wrqu->txpower.disabled)		ndis_power = 0;	else {		if (wrqu->txpower.flags == IW_TXPOW_MWATT)			ndis_power = wrqu->txpower.value;		else { // wrqu->txpower.flags == IW_TXPOW_DBM			if (wrqu->txpower.value > 20)				ndis_power = 128;			else if (wrqu->txpower.value < -43)				ndis_power = 127;			else {				signed char tmp;				tmp = wrqu->txpower.value;				tmp = -12 - tmp;				tmp <<= 2;				ndis_power = (unsigned char)tmp;			}		}	}	TRACE2("%d", ndis_power);	res = mp_set(wnd, OID_802_11_TX_POWER_LEVEL,		     &ndis_power, sizeof(ndis_power));	if (res)		EXIT2(return -EOPNOTSUPP);	if (ndis_power == 0)		res = disassociate(wnd, 0);	EXIT2(return 0);}static int iw_get_bitrate(struct net_device *dev, struct iw_request_info *info,			  union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	ULONG ndis_rate;	int res;	ENTER2("");	res = mp_query(wnd, OID_GEN_LINK_SPEED, &ndis_rate, sizeof(ndis_rate));	if (res) {		WARNING("getting bitrate failed (%08X)", res);		ndis_rate = 0;	}	wrqu->bitrate.value = ndis_rate * 100;	return 0;}static int iw_set_bitrate(struct net_device *dev, struct iw_request_info *info,			  union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	int i, n;	NDIS_STATUS res;	ndis_rates_ex rates;	ENTER2("");	if (wrqu->bitrate.fixed == 0)		EXIT2(return 0);	res = mp_query_info(wnd, OID_802_11_SUPPORTED_RATES, &rates,			    sizeof(rates), &n, NULL);	if (res) {		WARNING("getting bit rate failed (%08X)", res);		EXIT2(return 0);	}	for (i = 0; i < n; i++) {		if (rates[i] & 0x80)			continue;		if ((rates[i] & 0x7f) * 500000 > wrqu->bitrate.value) {			TRACE2("setting rate %d to 0",			       (rates[i] & 0x7f) * 500000);			rates[i] = 0;		}	}	res = mp_set(wnd, OID_802_11_DESIRED_RATES, &rates, n);	if (res) {		WARNING("setting bit rate failed (%08X)", res);		EXIT2(return 0);	}	return 0;}static int iw_set_dummy(struct net_device *dev, struct iw_request_info *info,			union iwreq_data *wrqu, char *extra){	/* Do nothing. Used for ioctls that are not implemented. */	return 0;}static int iw_get_rts_threshold(struct net_device *dev,				struct iw_request_info *info,				union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	ndis_rts_threshold threshold;	NDIS_STATUS res;	ENTER2("");	res = mp_query(wnd, OID_802_11_RTS_THRESHOLD,		       &threshold, sizeof(threshold));	if (res)		return -EOPNOTSUPP;	wrqu->rts.value = threshold;	return 0;}static int iw_set_rts_threshold(struct net_device *dev,				struct iw_request_info *info,				union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	ndis_rts_threshold threshold;	NDIS_STATUS res;	ENTER2("");	threshold = wrqu->rts.value;	res = mp_set(wnd, OID_802_11_RTS_THRESHOLD,		     &threshold, sizeof(threshold));	if (res == NDIS_STATUS_INVALID_DATA)		return -EINVAL;	if (res)		return -EOPNOTSUPP;	return 0;}static int iw_get_frag_threshold(struct net_device *dev,				 struct iw_request_info *info,				 union iwreq_data *wrqu, char *extra){	struct wrap_ndis_device *wnd = netdev_priv(dev);	ndis_fragmentation_threshold frag_threshold;	NDIS_STATUS res;	ENTER2("");	res = mp_query(wnd, OID_802_11_FRAGMENTATION_THRESHOLD,		       &frag_threshold, sizeof(frag_threshold));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -