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

📄 ieee80211_ioctl.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	data->length = 0;	return res;}static int ieee80211_ioctl_siwrate(struct net_device *dev,				  struct iw_request_info *info,				  struct iw_param *rate, char *extra){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct ieee80211_hw_mode *mode;	int i;	u32 target_rate = rate->value / 100000;	struct ieee80211_sub_if_data *sdata;	sdata = IEEE80211_DEV_TO_SUB_IF(dev);	if (!sdata->bss)		return -ENODEV;	mode = local->oper_hw_mode;	/* target_rate = -1, rate->fixed = 0 means auto only, so use all rates	 * target_rate = X, rate->fixed = 1 means only rate X	 * target_rate = X, rate->fixed = 0 means all rates <= X */	sdata->bss->max_ratectrl_rateidx = -1;	sdata->bss->force_unicast_rateidx = -1;	if (rate->value < 0)		return 0;	for (i=0; i < mode->num_rates; i++) {		struct ieee80211_rate *rates = &mode->rates[i];		int this_rate = rates->rate;		if (target_rate == this_rate) {			sdata->bss->max_ratectrl_rateidx = i;			if (rate->fixed)				sdata->bss->force_unicast_rateidx = i;			return 0;		}	}	return -EINVAL;}static int ieee80211_ioctl_giwrate(struct net_device *dev,				  struct iw_request_info *info,				  struct iw_param *rate, char *extra){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct sta_info *sta;	struct ieee80211_sub_if_data *sdata;	sdata = IEEE80211_DEV_TO_SUB_IF(dev);	if (sdata->type == IEEE80211_IF_TYPE_STA)		sta = sta_info_get(local, sdata->u.sta.bssid);	else		return -EOPNOTSUPP;	if (!sta)		return -ENODEV;	if (sta->txrate < local->oper_hw_mode->num_rates)		rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;	else		rate->value = 0;	sta_info_put(sta);	return 0;}static int ieee80211_ioctl_siwtxpower(struct net_device *dev,				      struct iw_request_info *info,				      union iwreq_data *data, char *extra){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	bool need_reconfig = 0;	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)		return -EINVAL;	if (data->txpower.flags & IW_TXPOW_RANGE)		return -EINVAL;	if (!data->txpower.fixed)		return -EINVAL;	if (local->hw.conf.power_level != data->txpower.value) {		local->hw.conf.power_level = data->txpower.value;		need_reconfig = 1;	}	if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {		local->hw.conf.radio_enabled = !(data->txpower.disabled);		need_reconfig = 1;	}	if (need_reconfig) {		ieee80211_hw_config(local);		/* The return value of hw_config is not of big interest here,		 * as it doesn't say that it failed because of _this_ config		 * change or something else. Ignore it. */	}	return 0;}static int ieee80211_ioctl_giwtxpower(struct net_device *dev,				   struct iw_request_info *info,				   union iwreq_data *data, char *extra){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	data->txpower.fixed = 1;	data->txpower.disabled = !(local->hw.conf.radio_enabled);	data->txpower.value = local->hw.conf.power_level;	data->txpower.flags = IW_TXPOW_DBM;	return 0;}static int ieee80211_ioctl_siwrts(struct net_device *dev,				  struct iw_request_info *info,				  struct iw_param *rts, char *extra){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	if (rts->disabled)		local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;	else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)		return -EINVAL;	else		local->rts_threshold = rts->value;	/* If the wlan card performs RTS/CTS in hardware/firmware,	 * configure it here */	if (local->ops->set_rts_threshold)		local->ops->set_rts_threshold(local_to_hw(local),					     local->rts_threshold);	return 0;}static int ieee80211_ioctl_giwrts(struct net_device *dev,				  struct iw_request_info *info,				  struct iw_param *rts, char *extra){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	rts->value = local->rts_threshold;	rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);	rts->fixed = 1;	return 0;}static int ieee80211_ioctl_siwfrag(struct net_device *dev,				   struct iw_request_info *info,				   struct iw_param *frag, char *extra){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	if (frag->disabled)		local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;	else if (frag->value < 256 ||		 frag->value > IEEE80211_MAX_FRAG_THRESHOLD)		return -EINVAL;	else {		/* Fragment length must be even, so strip LSB. */		local->fragmentation_threshold = frag->value & ~0x1;	}	/* If the wlan card performs fragmentation in hardware/firmware,	 * configure it here */	if (local->ops->set_frag_threshold)		local->ops->set_frag_threshold(			local_to_hw(local),			local->fragmentation_threshold);	return 0;}static int ieee80211_ioctl_giwfrag(struct net_device *dev,				   struct iw_request_info *info,				   struct iw_param *frag, char *extra){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	frag->value = local->fragmentation_threshold;	frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);	frag->fixed = 1;	return 0;}static int ieee80211_ioctl_siwretry(struct net_device *dev,				    struct iw_request_info *info,				    struct iw_param *retry, char *extra){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	if (retry->disabled ||	    (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)		return -EINVAL;	if (retry->flags & IW_RETRY_MAX)		local->long_retry_limit = retry->value;	else if (retry->flags & IW_RETRY_MIN)		local->short_retry_limit = retry->value;	else {		local->long_retry_limit = retry->value;		local->short_retry_limit = retry->value;	}	if (local->ops->set_retry_limit) {		return local->ops->set_retry_limit(			local_to_hw(local),			local->short_retry_limit,			local->long_retry_limit);	}	return 0;}static int ieee80211_ioctl_giwretry(struct net_device *dev,				    struct iw_request_info *info,				    struct iw_param *retry, char *extra){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	retry->disabled = 0;	if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {		/* first return min value, iwconfig will ask max value		 * later if needed */		retry->flags |= IW_RETRY_LIMIT;		retry->value = local->short_retry_limit;		if (local->long_retry_limit != local->short_retry_limit)			retry->flags |= IW_RETRY_MIN;		return 0;	}	if (retry->flags & IW_RETRY_MAX) {		retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;		retry->value = local->long_retry_limit;	}	return 0;}static int ieee80211_ioctl_siwmlme(struct net_device *dev,				   struct iw_request_info *info,				   struct iw_point *data, char *extra){	struct ieee80211_sub_if_data *sdata;	struct iw_mlme *mlme = (struct iw_mlme *) extra;	sdata = IEEE80211_DEV_TO_SUB_IF(dev);	if (sdata->type != IEEE80211_IF_TYPE_STA &&	    sdata->type != IEEE80211_IF_TYPE_IBSS)		return -EINVAL;	switch (mlme->cmd) {	case IW_MLME_DEAUTH:		/* TODO: mlme->addr.sa_data */		return ieee80211_sta_deauthenticate(dev, mlme->reason_code);	case IW_MLME_DISASSOC:		/* TODO: mlme->addr.sa_data */		return ieee80211_sta_disassociate(dev, mlme->reason_code);	default:		return -EOPNOTSUPP;	}}static int ieee80211_ioctl_siwencode(struct net_device *dev,				     struct iw_request_info *info,				     struct iw_point *erq, char *keybuf){	struct ieee80211_sub_if_data *sdata;	int idx, i, alg = ALG_WEP;	u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };	int remove = 0;	sdata = IEEE80211_DEV_TO_SUB_IF(dev);	idx = erq->flags & IW_ENCODE_INDEX;	if (idx == 0) {		if (sdata->default_key)			for (i = 0; i < NUM_DEFAULT_KEYS; i++) {				if (sdata->default_key == sdata->keys[i]) {					idx = i;					break;				}			}	} else if (idx < 1 || idx > 4)		return -EINVAL;	else		idx--;	if (erq->flags & IW_ENCODE_DISABLED)		remove = 1;	else if (erq->length == 0) {		/* No key data - just set the default TX key index */		ieee80211_set_default_key(sdata, idx);		return 0;	}	return ieee80211_set_encryption(		dev, bcaddr,		idx, alg, remove,		!sdata->default_key,		keybuf, erq->length);}static int ieee80211_ioctl_giwencode(struct net_device *dev,				     struct iw_request_info *info,				     struct iw_point *erq, char *key){	struct ieee80211_sub_if_data *sdata;	int idx, i;	sdata = IEEE80211_DEV_TO_SUB_IF(dev);	idx = erq->flags & IW_ENCODE_INDEX;	if (idx < 1 || idx > 4) {		idx = -1;		if (!sdata->default_key)			idx = 0;		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {			if (sdata->default_key == sdata->keys[i]) {				idx = i;				break;			}		}		if (idx < 0)			return -EINVAL;	} else		idx--;	erq->flags = idx + 1;	if (!sdata->keys[idx]) {		erq->length = 0;		erq->flags |= IW_ENCODE_DISABLED;		return 0;	}	memcpy(key, sdata->keys[idx]->conf.key,	       min_t(int, erq->length, sdata->keys[idx]->conf.keylen));	erq->length = sdata->keys[idx]->conf.keylen;	erq->flags |= IW_ENCODE_ENABLED;	return 0;}static int ieee80211_ioctl_siwauth(struct net_device *dev,				   struct iw_request_info *info,				   struct iw_param *data, char *extra){	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);	int ret = 0;	switch (data->flags & IW_AUTH_INDEX) {	case IW_AUTH_WPA_VERSION:	case IW_AUTH_CIPHER_PAIRWISE:	case IW_AUTH_CIPHER_GROUP:	case IW_AUTH_WPA_ENABLED:	case IW_AUTH_RX_UNENCRYPTED_EAPOL:	case IW_AUTH_KEY_MGMT:		break;	case IW_AUTH_PRIVACY_INVOKED:		if (sdata->type != IEEE80211_IF_TYPE_STA)			ret = -EINVAL;		else {			sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;			/*			 * Privacy invoked by wpa_supplicant, store the			 * value and allow associating to a protected			 * network without having a key up front.			 */			if (data->value)				sdata->u.sta.flags |=					IEEE80211_STA_PRIVACY_INVOKED;		}		break;	case IW_AUTH_80211_AUTH_ALG:		if (sdata->type == IEEE80211_IF_TYPE_STA ||		    sdata->type == IEEE80211_IF_TYPE_IBSS)			sdata->u.sta.auth_algs = data->value;		else			ret = -EOPNOTSUPP;		break;	default:		ret = -EOPNOTSUPP;		break;	}	return ret;}/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct iw_statistics *wstats = &local->wstats;	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);	struct sta_info *sta = NULL;	if (sdata->type == IEEE80211_IF_TYPE_STA ||	    sdata->type == IEEE80211_IF_TYPE_IBSS)		sta = sta_info_get(local, sdata->u.sta.bssid);	if (!sta) {		wstats->discard.fragment = 0;		wstats->discard.misc = 0;		wstats->qual.qual = 0;		wstats->qual.level = 0;		wstats->qual.noise = 0;		wstats->qual.updated = IW_QUAL_ALL_INVALID;	} else {		wstats->qual.level = sta->last_rssi;		wstats->qual.qual = sta->last_signal;		wstats->qual.noise = sta->last_noise;		wstats->qual.updated = local->wstats_flags;		sta_info_put(sta);	}	return wstats;}static int ieee80211_ioctl_giwauth(struct net_device *dev,				   struct iw_request_info *info,				   struct iw_param *data, char *extra){	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);	int ret = 0;	switch (data->flags & IW_AUTH_INDEX) {	case IW_AUTH_80211_AUTH_ALG:		if (sdata->type == IEEE80211_IF_TYPE_STA ||		    sdata->type == IEEE80211_IF_TYPE_IBSS)			data->value = sdata->u.sta.auth_algs;		else			ret = -EOPNOTSUPP;		break;	default:		ret = -EOPNOTSUPP;		break;	}	return ret;}static int ieee80211_ioctl_siwencodeext(struct net_device *dev,					struct iw_request_info *info,					struct iw_point *erq, char *extra){	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);	struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;	int uninitialized_var(alg), idx, i, remove = 0;	switch (ext->alg) {	case IW_ENCODE_ALG_NONE:		remove = 1;		break;	case IW_ENCODE_ALG_WEP:		alg = ALG_WEP;		break;	case IW_ENCODE_ALG_TKIP:		alg = ALG_TKIP;		break;	case IW_ENCODE_ALG_CCMP:		alg = ALG_CCMP;		break;	default:		return -EOPNOTSUPP;	}	if (erq->flags & IW_ENCODE_DISABLED)		remove = 1;	idx = erq->flags & IW_ENCODE_INDEX;	if (idx < 1 || idx > 4) {		idx = -1;		if (!sdata->default_key)			idx = 0;		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {			if (sdata->default_key == sdata->keys[i]) {				idx = i;				break;			}		}		if (idx < 0)			return -EINVAL;	} else		idx--;	return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,					remove,					ext->ext_flags &					IW_ENCODE_EXT_SET_TX_KEY,					ext->key, ext->key_len);}/* Structures to export the Wireless Handlers */static const iw_handler ieee80211_handler[] ={	(iw_handler) NULL,				/* SIOCSIWCOMMIT */	(iw_handler) ieee80211_ioctl_giwname,		/* SIOCGIWNAME */	(iw_handler) NULL,				/* SIOCSIWNWID */	(iw_handler) NULL,				/* SIOCGIWNWID */	(iw_handler) ieee80211_ioctl_siwfreq,		/* SIOCSIWFREQ */	(iw_handler) ieee80211_ioctl_giwfreq,		/* SIOCGIWFREQ */	(iw_handler) ieee80211_ioctl_siwmode,		/* SIOCSIWMODE */	(iw_handler) ieee80211_ioctl_giwmode,		/* SIOCGIWMODE */	(iw_handler) NULL,				/* SIOCSIWSENS */	(iw_handler) NULL,				/* SIOCGIWSENS */	(iw_handler) NULL /* not used */,		/* SIOCSIWRANGE */	(iw_handler) ieee80211_ioctl_giwrange,		/* SIOCGIWRANGE */	(iw_handler) NULL /* not used */,		/* SIOCSIWPRIV */	(iw_handler) NULL /* kernel code */,		/* SIOCGIWPRIV */	(iw_handler) NULL /* not used */,		/* SIOCSIWSTATS */	(iw_handler) NULL /* kernel code */,		/* SIOCGIWSTATS */	(iw_handler) NULL,				/* SIOCSIWSPY */	(iw_handler) NULL,				/* SIOCGIWSPY */	(iw_handler) NULL,				/* SIOCSIWTHRSPY */	(iw_handler) NULL,				/* SIOCGIWTHRSPY */	(iw_handler) ieee80211_ioctl_siwap,		/* SIOCSIWAP */	(iw_handler) ieee80211_ioctl_giwap,		/* SIOCGIWAP */	(iw_handler) ieee80211_ioctl_siwmlme,		/* SIOCSIWMLME */	(iw_handler) NULL,				/* SIOCGIWAPLIST */	(iw_handler) ieee80211_ioctl_siwscan,		/* SIOCSIWSCAN */	(iw_handler) ieee80211_ioctl_giwscan,		/* SIOCGIWSCAN */	(iw_handler) ieee80211_ioctl_siwessid,		/* SIOCSIWESSID */	(iw_handler) ieee80211_ioctl_giwessid,		/* SIOCGIWESSID */	(iw_handler) NULL,				/* SIOCSIWNICKN */	(iw_handler) NULL,				/* SIOCGIWNICKN */	(iw_handler) NULL,				/* -- hole -- */	(iw_handler) NULL,				/* -- hole -- */	(iw_handler) ieee80211_ioctl_siwrate,		/* SIOCSIWRATE */	(iw_handler) ieee80211_ioctl_giwrate,		/* SIOCGIWRATE */	(iw_handler) ieee80211_ioctl_siwrts,		/* SIOCSIWRTS */	(iw_handler) ieee80211_ioctl_giwrts,		/* SIOCGIWRTS */	(iw_handler) ieee80211_ioctl_siwfrag,		/* SIOCSIWFRAG */	(iw_handler) ieee80211_ioctl_giwfrag,		/* SIOCGIWFRAG */	(iw_handler) ieee80211_ioctl_siwtxpower,	/* SIOCSIWTXPOW */	(iw_handler) ieee80211_ioctl_giwtxpower,	/* SIOCGIWTXPOW */	(iw_handler) ieee80211_ioctl_siwretry,		/* SIOCSIWRETRY */	(iw_handler) ieee80211_ioctl_giwretry,		/* SIOCGIWRETRY */	(iw_handler) ieee80211_ioctl_siwencode,		/* SIOCSIWENCODE */	(iw_handler) ieee80211_ioctl_giwencode,		/* SIOCGIWENCODE */	(iw_handler) NULL,				/* SIOCSIWPOWER */	(iw_handler) NULL,				/* SIOCGIWPOWER */	(iw_handler) NULL,				/* -- hole -- */	(iw_handler) NULL,				/* -- hole -- */	(iw_handler) ieee80211_ioctl_siwgenie,		/* SIOCSIWGENIE */	(iw_handler) NULL,				/* SIOCGIWGENIE */	(iw_handler) ieee80211_ioctl_siwauth,		/* SIOCSIWAUTH */	(iw_handler) ieee80211_ioctl_giwauth,		/* SIOCGIWAUTH */	(iw_handler) ieee80211_ioctl_siwencodeext,	/* SIOCSIWENCODEEXT */	(iw_handler) NULL,				/* SIOCGIWENCODEEXT */	(iw_handler) NULL,				/* SIOCSIWPMKSA */	(iw_handler) NULL,				/* -- hole -- */};const struct iw_handler_def ieee80211_iw_handler_def ={	.num_standard	= ARRAY_SIZE(ieee80211_handler),	.standard	= (iw_handler *) ieee80211_handler,	.get_wireless_stats = ieee80211_get_wireless_stats,};

⌨️ 快捷键说明

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