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

📄 hostap_80211_rx.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	u8 *ssid = NULL, *wpa = NULL, *rsn = NULL;	size_t ssid_len = 0, wpa_len = 0, rsn_len = 0;	struct hostap_bss_info *bss;	if (skb->len < IEEE80211_MGMT_HDR_LEN + sizeof(mgmt->u.beacon))		return;	mgmt = (struct hostap_ieee80211_mgmt *) skb->data;	pos = mgmt->u.beacon.variable;	left = skb->len - (pos - skb->data);	while (left >= 2) {		if (2 + pos[1] > left)			return; /* parse failed */		switch (*pos) {		case WLAN_EID_SSID:			ssid = pos + 2;			ssid_len = pos[1];			break;		case WLAN_EID_GENERIC:			if (pos[1] >= 4 &&			    pos[2] == 0x00 && pos[3] == 0x50 &&			    pos[4] == 0xf2 && pos[5] == 1) {				wpa = pos;				wpa_len = pos[1] + 2;			}			break;		case WLAN_EID_RSN:			rsn = pos;			rsn_len = pos[1] + 2;			break;		case WLAN_EID_DS_PARAMS:			if (pos[1] >= 1)				chan = pos[2];			break;		}		left -= 2 + pos[1];		pos += 2 + pos[1];	}	if (wpa_len > MAX_WPA_IE_LEN)		wpa_len = MAX_WPA_IE_LEN;	if (rsn_len > MAX_WPA_IE_LEN)		rsn_len = MAX_WPA_IE_LEN;	if (ssid_len > sizeof(bss->ssid))		ssid_len = sizeof(bss->ssid);	spin_lock(&local->lock);	bss = __hostap_get_bss(local, mgmt->bssid, ssid, ssid_len);	if (bss == NULL)		bss = __hostap_add_bss(local, mgmt->bssid, ssid, ssid_len);	if (bss) {		bss->last_update = jiffies;		bss->count++;		bss->capab_info = le16_to_cpu(mgmt->u.beacon.capab_info);		if (wpa) {			memcpy(bss->wpa_ie, wpa, wpa_len);			bss->wpa_ie_len = wpa_len;		} else			bss->wpa_ie_len = 0;		if (rsn) {			memcpy(bss->rsn_ie, rsn, rsn_len);			bss->rsn_ie_len = rsn_len;		} else			bss->rsn_ie_len = 0;		bss->chan = chan;	}	__hostap_expire_bss(local);	spin_unlock(&local->lock);}static inline inthostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,		     struct hostap_80211_rx_status *rx_stats, u16 type,		     u16 stype){	if (local->iw_mode == IW_MODE_MASTER) {		hostap_update_sta_ps(local, (struct ieee80211_hdr_4addr *)				     skb->data);	}	if (local->hostapd && type == IEEE80211_FTYPE_MGMT) {		if (stype == IEEE80211_STYPE_BEACON &&		    local->iw_mode == IW_MODE_MASTER) {			struct sk_buff *skb2;			/* Process beacon frames also in kernel driver to			 * update STA(AP) table statistics */			skb2 = skb_clone(skb, GFP_ATOMIC);			if (skb2)				hostap_rx(skb2->dev, skb2, rx_stats);		}		/* send management frames to the user space daemon for		 * processing */		local->apdevstats.rx_packets++;		local->apdevstats.rx_bytes += skb->len;		if (local->apdev == NULL)			return -1;		prism2_rx_80211(local->apdev, skb, rx_stats, PRISM2_RX_MGMT);		return 0;	}	if (local->iw_mode == IW_MODE_MASTER) {		if (type != IEEE80211_FTYPE_MGMT &&		    type != IEEE80211_FTYPE_CTL) {			printk(KERN_DEBUG "%s: unknown management frame "			       "(type=0x%02x, stype=0x%02x) dropped\n",			       skb->dev->name, type >> 2, stype >> 4);			return -1;		}		hostap_rx(skb->dev, skb, rx_stats);		return 0;	} else if (type == IEEE80211_FTYPE_MGMT &&		   (stype == IEEE80211_STYPE_BEACON ||		    stype == IEEE80211_STYPE_PROBE_RESP)) {		hostap_rx_sta_beacon(local, skb, stype);		return -1;	} else if (type == IEEE80211_FTYPE_MGMT &&		   (stype == IEEE80211_STYPE_ASSOC_RESP ||		    stype == IEEE80211_STYPE_REASSOC_RESP)) {		/* Ignore (Re)AssocResp silently since these are not currently		 * needed but are still received when WPA/RSN mode is enabled.		 */		return -1;	} else {		printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: dropped unhandled"		       " management frame in non-Host AP mode (type=%d:%d)\n",		       skb->dev->name, type >> 2, stype >> 4);		return -1;	}}/* Called only as a tasklet (software IRQ) */static inline struct net_device *prism2_rx_get_wds(local_info_t *local,						   u8 *addr){	struct hostap_interface *iface = NULL;	struct list_head *ptr;	read_lock_bh(&local->iface_lock);	list_for_each(ptr, &local->hostap_interfaces) {		iface = list_entry(ptr, struct hostap_interface, list);		if (iface->type == HOSTAP_INTERFACE_WDS &&		    memcmp(iface->u.wds.remote_addr, addr, ETH_ALEN) == 0)			break;		iface = NULL;	}	read_unlock_bh(&local->iface_lock);	return iface ? iface->dev : NULL;}static inline inthostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,		    u16 fc, struct net_device **wds){	/* FIX: is this really supposed to accept WDS frames only in Master	 * mode? What about Repeater or Managed with WDS frames? */	if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) !=	    (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS) &&	    (local->iw_mode != IW_MODE_MASTER || !(fc & IEEE80211_FCTL_TODS)))		return 0; /* not a WDS frame */	/* Possible WDS frame: either IEEE 802.11 compliant (if FromDS)	 * or own non-standard frame with 4th address after payload */	if (memcmp(hdr->addr1, local->dev->dev_addr, ETH_ALEN) != 0 &&	    (hdr->addr1[0] != 0xff || hdr->addr1[1] != 0xff ||	     hdr->addr1[2] != 0xff || hdr->addr1[3] != 0xff ||	     hdr->addr1[4] != 0xff || hdr->addr1[5] != 0xff)) {		/* RA (or BSSID) is not ours - drop */		PDEBUG(DEBUG_EXTRA, "%s: received WDS frame with "		       "not own or broadcast %s=" MACSTR "\n",		       local->dev->name,		       fc & IEEE80211_FCTL_FROMDS ? "RA" : "BSSID",		       MAC2STR(hdr->addr1));		return -1;	}	/* check if the frame came from a registered WDS connection */	*wds = prism2_rx_get_wds(local, hdr->addr2);	if (*wds == NULL && fc & IEEE80211_FCTL_FROMDS &&	    (local->iw_mode != IW_MODE_INFRA ||	     !(local->wds_type & HOSTAP_WDS_AP_CLIENT) ||	     memcmp(hdr->addr2, local->bssid, ETH_ALEN) != 0)) {		/* require that WDS link has been registered with TA or the		 * frame is from current AP when using 'AP client mode' */		PDEBUG(DEBUG_EXTRA, "%s: received WDS[4 addr] frame "		       "from unknown TA=" MACSTR "\n",		       local->dev->name, MAC2STR(hdr->addr2));		if (local->ap && local->ap->autom_ap_wds)			hostap_wds_link_oper(local, hdr->addr2, WDS_ADD);		return -1;	}	if (*wds && !(fc & IEEE80211_FCTL_FROMDS) && local->ap &&	    hostap_is_sta_assoc(local->ap, hdr->addr2)) {		/* STA is actually associated with us even though it has a		 * registered WDS link. Assume it is in 'AP client' mode.		 * Since this is a 3-addr frame, assume it is not (bogus) WDS		 * frame and process it like any normal ToDS frame from		 * associated STA. */		*wds = NULL;	}	return 0;}static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb){	struct net_device *dev = local->dev;	u16 fc, ethertype;	struct ieee80211_hdr_4addr *hdr;	u8 *pos;	if (skb->len < 24)		return 0;	hdr = (struct ieee80211_hdr_4addr *) skb->data;	fc = le16_to_cpu(hdr->frame_ctl);	/* check that the frame is unicast frame to us */	if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==	    IEEE80211_FCTL_TODS &&	    memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&	    memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {		/* ToDS frame with own addr BSSID and DA */	} else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==		   IEEE80211_FCTL_FROMDS &&		   memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {		/* FromDS frame with own addr as DA */	} else		return 0;	if (skb->len < 24 + 8)		return 0;	/* check for port access entity Ethernet type */	pos = skb->data + 24;	ethertype = (pos[6] << 8) | pos[7];	if (ethertype == ETH_P_PAE)		return 1;	return 0;}/* Called only as a tasklet (software IRQ) */static inline inthostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,			struct ieee80211_crypt_data *crypt){	struct ieee80211_hdr_4addr *hdr;	int res, hdrlen;	if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)		return 0;	hdr = (struct ieee80211_hdr_4addr *) skb->data;	hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));	if (local->tkip_countermeasures &&	    strcmp(crypt->ops->name, "TKIP") == 0) {		if (net_ratelimit()) {			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "			       "received packet from " MACSTR "\n",			       local->dev->name, MAC2STR(hdr->addr2));		}		return -1;	}	atomic_inc(&crypt->refcnt);	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);	atomic_dec(&crypt->refcnt);	if (res < 0) {		printk(KERN_DEBUG "%s: decryption failed (SA=" MACSTR		       ") res=%d\n",		       local->dev->name, MAC2STR(hdr->addr2), res);		local->comm_tallies.rx_discards_wep_undecryptable++;		return -1;	}	return res;}/* Called only as a tasklet (software IRQ) */static inline inthostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,			     int keyidx, struct ieee80211_crypt_data *crypt){	struct ieee80211_hdr_4addr *hdr;	int res, hdrlen;	if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)		return 0;	hdr = (struct ieee80211_hdr_4addr *) skb->data;	hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));	atomic_inc(&crypt->refcnt);	res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);	atomic_dec(&crypt->refcnt);	if (res < 0) {		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"		       " (SA=" MACSTR " keyidx=%d)\n",		       local->dev->name, MAC2STR(hdr->addr2), keyidx);		return -1;	}	return 0;}/* All received frames are sent to this function. @skb contains the frame in * IEEE 802.11 format, i.e., in the format it was sent over air. * This function is called only as a tasklet (software IRQ). */void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,		     struct hostap_80211_rx_status *rx_stats){	struct hostap_interface *iface;	local_info_t *local;	struct ieee80211_hdr_4addr *hdr;	size_t hdrlen;	u16 fc, type, stype, sc;	struct net_device *wds = NULL;	struct net_device_stats *stats;	unsigned int frag;	u8 *payload;	struct sk_buff *skb2 = NULL;	u16 ethertype;	int frame_authorized = 0;	int from_assoc_ap = 0;	u8 dst[ETH_ALEN];	u8 src[ETH_ALEN];	struct ieee80211_crypt_data *crypt = NULL;	void *sta = NULL;	int keyidx = 0;	iface = netdev_priv(dev);	local = iface->local;	iface->stats.rx_packets++;	iface->stats.rx_bytes += skb->len;	/* dev is the master radio device; change this to be the default	 * virtual interface (this may be changed to WDS device below) */	dev = local->ddev;	iface = netdev_priv(dev);	hdr = (struct ieee80211_hdr_4addr *) skb->data;	stats = hostap_get_stats(dev);	if (skb->len < 10)		goto rx_dropped;	fc = le16_to_cpu(hdr->frame_ctl);	type = WLAN_FC_GET_TYPE(fc);	stype = WLAN_FC_GET_STYPE(fc);	sc = le16_to_cpu(hdr->seq_ctl);	frag = WLAN_GET_SEQ_FRAG(sc);	hdrlen = hostap_80211_get_hdrlen(fc);

⌨️ 快捷键说明

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