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

📄 ieee80211_rx.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN))					is_packet_for_us = 1;			}		}		break;	default:		/* ? */		break;	}	if (is_packet_for_us)		if (!ieee80211_rx(ieee, skb, stats))			dev_kfree_skb_irq(skb);	return;drop_free:	dev_kfree_skb_irq(skb);	ieee->stats.rx_dropped++;	return;}#define MGMT_FRAME_FIXED_PART_LENGTH		0x24static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };/** Make ther structure we read from the beacon packet has* the right values*/static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element				     *info_element, int sub_type){	if (info_element->qui_subtype != sub_type)		return -1;	if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))		return -1;	if (info_element->qui_type != QOS_OUI_TYPE)		return -1;	if (info_element->version != QOS_VERSION_1)		return -1;	return 0;}/* * Parse a QoS parameter element */static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info					    *element_param, struct ieee80211_info_element					    *info_element){	int ret = 0;	u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;	if ((info_element == NULL) || (element_param == NULL))		return -1;	if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {		memcpy(element_param->info_element.qui, info_element->data,		       info_element->len);		element_param->info_element.elementID = info_element->id;		element_param->info_element.length = info_element->len;	} else		ret = -1;	if (ret == 0)		ret = ieee80211_verify_qos_info(&element_param->info_element,						QOS_OUI_PARAM_SUB_TYPE);	return ret;}/* * Parse a QoS information element */static int ieee80211_read_qos_info_element(struct					   ieee80211_qos_information_element					   *element_info, struct ieee80211_info_element					   *info_element){	int ret = 0;	u16 size = sizeof(struct ieee80211_qos_information_element) - 2;	if (element_info == NULL)		return -1;	if (info_element == NULL)		return -1;	if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {		memcpy(element_info->qui, info_element->data,		       info_element->len);		element_info->elementID = info_element->id;		element_info->length = info_element->len;	} else		ret = -1;	if (ret == 0)		ret = ieee80211_verify_qos_info(element_info,						QOS_OUI_INFO_SUB_TYPE);	return ret;}/* * Write QoS parameters from the ac parameters. */static int ieee80211_qos_convert_ac_to_parameters(struct						  ieee80211_qos_parameter_info						  *param_elm, struct						  ieee80211_qos_parameters						  *qos_param){	int rc = 0;	int i;	struct ieee80211_qos_ac_parameter *ac_params;	u32 txop;	u8 cw_min;	u8 cw_max;	for (i = 0; i < QOS_QUEUE_NUM; i++) {		ac_params = &(param_elm->ac_params_record[i]);		qos_param->aifs[i] = (ac_params->aci_aifsn) & 0x0F;		qos_param->aifs[i] -= (qos_param->aifs[i] < 2) ? 0 : 2;		cw_min = ac_params->ecw_min_max & 0x0F;		qos_param->cw_min[i] = (u16) ((1 << cw_min) - 1);		cw_max = (ac_params->ecw_min_max & 0xF0) >> 4;		qos_param->cw_max[i] = (u16) ((1 << cw_max) - 1);		qos_param->flag[i] =		    (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;		txop = le16_to_cpu(ac_params->tx_op_limit) * 32;		qos_param->tx_op_limit[i] = (u16) txop;	}	return rc;}/* * we have a generic data element which it may contain QoS information or * parameters element. check the information element length to decide * which type to read */static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element					     *info_element,					     struct ieee80211_network *network){	int rc = 0;	struct ieee80211_qos_parameters *qos_param = NULL;	struct ieee80211_qos_information_element qos_info_element;	rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);	if (rc == 0) {		network->qos_data.param_count = qos_info_element.ac_info & 0x0F;		network->flags |= NETWORK_HAS_QOS_INFORMATION;	} else {		struct ieee80211_qos_parameter_info param_element;		rc = ieee80211_read_qos_param_element(&param_element,						      info_element);		if (rc == 0) {			qos_param = &(network->qos_data.parameters);			ieee80211_qos_convert_ac_to_parameters(&param_element,							       qos_param);			network->flags |= NETWORK_HAS_QOS_PARAMETERS;			network->qos_data.param_count =			    param_element.info_element.ac_info & 0x0F;		}	}	if (rc == 0) {		IEEE80211_DEBUG_QOS("QoS is supported\n");		network->qos_data.supported = 1;	}	return rc;}#ifdef CONFIG_IEEE80211_DEBUG#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #xstatic const char *get_info_element_string(u16 id){	switch (id) {		MFIE_STRING(SSID);		MFIE_STRING(RATES);		MFIE_STRING(FH_SET);		MFIE_STRING(DS_SET);		MFIE_STRING(CF_SET);		MFIE_STRING(TIM);		MFIE_STRING(IBSS_SET);		MFIE_STRING(COUNTRY);		MFIE_STRING(HOP_PARAMS);		MFIE_STRING(HOP_TABLE);		MFIE_STRING(REQUEST);		MFIE_STRING(CHALLENGE);		MFIE_STRING(POWER_CONSTRAINT);		MFIE_STRING(POWER_CAPABILITY);		MFIE_STRING(TPC_REQUEST);		MFIE_STRING(TPC_REPORT);		MFIE_STRING(SUPP_CHANNELS);		MFIE_STRING(CSA);		MFIE_STRING(MEASURE_REQUEST);		MFIE_STRING(MEASURE_REPORT);		MFIE_STRING(QUIET);		MFIE_STRING(IBSS_DFS);		MFIE_STRING(ERP_INFO);		MFIE_STRING(RSN);		MFIE_STRING(RATES_EX);		MFIE_STRING(GENERIC);		MFIE_STRING(QOS_PARAMETER);	default:		return "UNKNOWN";	}}#endifstatic int ieee80211_parse_info_param(struct ieee80211_info_element				      *info_element, u16 length,				      struct ieee80211_network *network){	u8 i;#ifdef CONFIG_IEEE80211_DEBUG	char rates_str[64];	char *p;#endif	while (length >= sizeof(*info_element)) {		if (sizeof(*info_element) + info_element->len > length) {			IEEE80211_DEBUG_MGMT("Info elem: parse failed: "					     "info_element->len + 2 > left : "					     "info_element->len+2=%zd left=%d, id=%d.\n",					     info_element->len +					     sizeof(*info_element),					     length, info_element->id);			/* We stop processing but don't return an error here			 * because some misbehaviour APs break this rule. ie.			 * Orinoco AP1000. */			break;		}		switch (info_element->id) {		case MFIE_TYPE_SSID:			if (ieee80211_is_empty_essid(info_element->data,						     info_element->len)) {				network->flags |= NETWORK_EMPTY_ESSID;				break;			}			network->ssid_len = min(info_element->len,						(u8) IW_ESSID_MAX_SIZE);			memcpy(network->ssid, info_element->data,			       network->ssid_len);			if (network->ssid_len < IW_ESSID_MAX_SIZE)				memset(network->ssid + network->ssid_len, 0,				       IW_ESSID_MAX_SIZE - network->ssid_len);			IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",					     network->ssid, network->ssid_len);			break;		case MFIE_TYPE_RATES:#ifdef CONFIG_IEEE80211_DEBUG			p = rates_str;#endif			network->rates_len = min(info_element->len,						 MAX_RATES_LENGTH);			for (i = 0; i < network->rates_len; i++) {				network->rates[i] = info_element->data[i];#ifdef CONFIG_IEEE80211_DEBUG				p += snprintf(p, sizeof(rates_str) -					      (p - rates_str), "%02X ",					      network->rates[i]);#endif				if (ieee80211_is_ofdm_rate				    (info_element->data[i])) {					network->flags |= NETWORK_HAS_OFDM;					if (info_element->data[i] &					    IEEE80211_BASIC_RATE_MASK)						network->flags &=						    ~NETWORK_HAS_CCK;				}			}			IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",					     rates_str, network->rates_len);			break;		case MFIE_TYPE_RATES_EX:#ifdef CONFIG_IEEE80211_DEBUG			p = rates_str;#endif			network->rates_ex_len = min(info_element->len,						    MAX_RATES_EX_LENGTH);			for (i = 0; i < network->rates_ex_len; i++) {				network->rates_ex[i] = info_element->data[i];#ifdef CONFIG_IEEE80211_DEBUG				p += snprintf(p, sizeof(rates_str) -					      (p - rates_str), "%02X ",					      network->rates[i]);#endif				if (ieee80211_is_ofdm_rate				    (info_element->data[i])) {					network->flags |= NETWORK_HAS_OFDM;					if (info_element->data[i] &					    IEEE80211_BASIC_RATE_MASK)						network->flags &=						    ~NETWORK_HAS_CCK;				}			}			IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",					     rates_str, network->rates_ex_len);			break;		case MFIE_TYPE_DS_SET:			IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",					     info_element->data[0]);			network->channel = info_element->data[0];			break;		case MFIE_TYPE_FH_SET:			IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");			break;		case MFIE_TYPE_CF_SET:			IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");			break;		case MFIE_TYPE_TIM:			network->tim.tim_count = info_element->data[0];			network->tim.tim_period = info_element->data[1];			IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n");			break;		case MFIE_TYPE_ERP_INFO:			network->erp_value = info_element->data[0];			network->flags |= NETWORK_HAS_ERP_VALUE;			IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",					     network->erp_value);			break;		case MFIE_TYPE_IBSS_SET:			network->atim_window = info_element->data[0];			IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",					     network->atim_window);			break;		case MFIE_TYPE_CHALLENGE:			IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");			break;		case MFIE_TYPE_GENERIC:			IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",					     info_element->len);			if (!ieee80211_parse_qos_info_param_IE(info_element,							       network))				break;			if (info_element->len >= 4 &&			    info_element->data[0] == 0x00 &&			    info_element->data[1] == 0x50 &&			    info_element->data[2] == 0xf2 &&			    info_element->data[3] == 0x01) {				network->wpa_ie_len = min(info_element->len + 2,							  MAX_WPA_IE_LEN);				memcpy(network->wpa_ie, info_element,				       network->wpa_ie_len);			}			break;		case MFIE_TYPE_RSN:			IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",					     info_element->len);			network->rsn_ie_len = min(info_element->len + 2,						  MAX_WPA_IE_LEN);			memcpy(network->rsn_ie, info_element,			       network->rsn_ie_len);			break;		case MFIE_TYPE_QOS_PARAMETER:			printk(KERN_ERR			       "QoS Error need to parse QOS_PARAMETER IE\n");			break;			/* 802.11h */		case MFIE_TYPE_POWER_CONSTRAINT:			network->power_constraint = info_element->data[0];			network->flags |= NETWORK_HAS_POWER_CONSTRAINT;			break;		case MFIE_TYPE_CSA:			network->power_constraint = info_element->data[0];			network->flags |= NETWORK_HAS_CSA;			break;		case MFIE_TYPE_QUIET:			network->quiet.count = info_element->data[0];			network->quiet.period = info_element->data[1];			network->quiet.duration = info_element->data[2];			network->quiet.offset = info_element->data[3];			network->flags |= NETWORK_HAS_QUIET;			break;		case MFIE_TYPE_IBSS_DFS:			if (network->ibss_dfs)				break;			network->ibss_dfs = kmemdup(info_element->data,						    info_element->len,						    GFP_ATOMIC);			if (!network->ibss_dfs)				return 1;			network->flags |= NETWORK_HAS_IBSS_DFS;			break;		case MFIE_TYPE_TPC_REPORT:			network->tpc_report.transmit_power =			    info_element->data[0];			network->tpc_report.link_margin = info_element->data[1];			network->flags |= NETWORK_HAS_TPC_REPORT;			break;		default:			IEEE80211_DEBUG_MGMT			    ("Unsupported info element: %s (%d)\n",			     get_info_element_string(info_element->id),			     info_element->id);			break;		}		length -= sizeof(*info_element) + info_element->len;		info_element =		    (struct ieee80211_info_element *)&info_element->		    data[info_element->len];	}	return 0;}static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response				       *frame, struct ieee80211_rx_stats *stats){	struct ieee80211_network network_resp = {		.ibss_dfs = NULL,	};	struct ieee80211_network *network = &network_resp;	struct net_device *dev = ieee->dev;	network->flags = 0;	network->qos_data.active = 0;	network->qos_data.supported = 0;	network->qos_data.param_count = 0;	network->qos_data.old_param_count = 0;	//network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);	network->atim_window = le16_to_cpu(frame->aid);

⌨️ 快捷键说明

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