ic->ic_stats.is_rx_mgtdiscard++; goto out; } } else { if (ic->ic_opmode != IEEE80211_M_IBSS && subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,	int rssi, u_int32_t rstamp){	struct ieee80211com *ic = (void *)ifp;	struct ieee80211_frame *wh;	struct ether_header *eh;	struct mbuf *m1;	int error, len;	u_int8_t dir, type, subtype;	u_int8_t *bssid;	u_int16_t rxseq;#if !defined(__OpenBSD__)	ALTQ_DECL(struct altq_pktattr pktattr;)#endif	IASSERT(ni != NULL, ("null node"));	/* trim CRC here so WEP can find its own CRC at the end of packet. */	if (m->m_flags & M_HASFCS) {		m_adj(m, -IEEE80211_CRC_LEN);		m->m_flags &= ~M_HASFCS;	}	/*	 * In monitor mode, send everything directly to bpf.	 * Also do not process frames w/o i_addr2 any further.	 * XXX may want to include the CRC	 */	if (ic->ic_opmode == IEEE80211_M_MONITOR ||	    m->m_pkthdr.len < sizeof(struct ieee80211_frame_min))		goto out;	wh = mtod(m, struct ieee80211_frame *);	if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=	    IEEE80211_FC0_VERSION_0) {		if (ifp->if_flags & IFF_DEBUG)			if_printf(ifp, "receive packet with wrong version: %x\n",			    wh->i_fc[0]);		ic->ic_stats.is_rx_badversion++;		goto err;	}	dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;	/*	 * NB: We are not yet prepared to handle control frames,	 *     but permitting drivers to send them to us allows	 *     them to go through bpf tapping at the 802.11 layer.	 */	if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {		/* XXX statistic */		IEEE80211_DPRINTF2(("%s: frame too short, len %u\n",			__func__, m->m_pkthdr.len));		ic->ic_stats.is_rx_tooshort++;		goto out;		/* XXX */	}	if (ic->ic_state != IEEE80211_S_SCAN) {		switch (ic->ic_opmode) {		case IEEE80211_M_STA:			if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {				/* not interested in */				IEEE80211_DPRINTF2(("%s: discard frame from "					"bss %s\n", __func__,					ether_sprintf(wh->i_addr2)));				ic->ic_stats.is_rx_wrongbss++;				goto out;			}			break;		case IEEE80211_M_IBSS:		case IEEE80211_M_AHDEMO:		case IEEE80211_M_HOSTAP:			if (dir == IEEE80211_FC1_DIR_NODS)				bssid = wh->i_addr3;			else				bssid = wh->i_addr1;			if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->ni_bssid) &&#ifdef __OpenBSD__			    !IEEE80211_ADDR_EQ(bssid, etherbroadcastaddr) &&#else			    !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr) &&#endif			    (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==			    IEEE80211_FC0_TYPE_DATA) {				/* not interested in */				IEEE80211_DPRINTF2(("%s: discard frame from "					"bss %s\n", __func__,					ether_sprintf(bssid)));				ic->ic_stats.is_rx_wrongbss++;				goto out;			}			break;		case IEEE80211_M_MONITOR:			goto out;		default:			/* XXX catch bad values */			break;		}		ni->ni_rssi = rssi;		ni->ni_rstamp = rstamp;		rxseq = ni->ni_rxseq;		ni->ni_rxseq =		    letoh16(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;		/* TODO: fragment */		if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&		    rxseq == ni->ni_rxseq) {			/* duplicate, silently discarded */			ic->ic_stats.is_rx_dup++; /* XXX per-station stat */			goto out;		}		ni->ni_inact = 0;	}	if (ic->ic_set_tim != NULL &&	    (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT)	    && ni->ni_pwrsave == 0) {		/* turn on power save mode */		if (ifp->if_flags & IFF_DEBUG)			printf("%s: power save mode on for %s\n",			    ifp->if_xname, ether_sprintf(wh->i_addr2));		ni->ni_pwrsave = IEEE80211_PS_SLEEP;	}	if (ic->ic_set_tim != NULL &&	    (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) == 0 &&	    ni->ni_pwrsave != 0) {		/* turn off power save mode, dequeue stored packets */		ni->ni_pwrsave = 0;		if (ic->ic_set_tim)			ic->ic_set_tim(ic, ni->ni_associd, 0);		if (ifp->if_flags & IFF_DEBUG)			printf("%s: power save mode off for %s\n",			    ifp->if_xname, ether_sprintf(wh->i_addr2));		while (!IF_IS_EMPTY(&ni->ni_savedq)) {			struct mbuf *m;			IF_DEQUEUE(&ni->ni_savedq, m);			IF_ENQUEUE(&ic->ic_pwrsaveq, m);			(*ifp->if_start)(ifp);		}	}	switch (type) {	case IEEE80211_FC0_TYPE_DATA:		switch (ic->ic_opmode) {		case IEEE80211_M_STA:			if (dir != IEEE80211_FC1_DIR_FROMDS) {				ic->ic_stats.is_rx_wrongdir++;				goto out;			}			if ((ifp->if_flags & IFF_SIMPLEX) &&			    IEEE80211_IS_MULTICAST(wh->i_addr1) &&			    IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) {				/*				 * In IEEE802.11 network, multicast packet				 * sent from me is broadcasted from AP.				 * It should be silently discarded for				 * SIMPLEX interface.				 */				ic->ic_stats.is_rx_mcastecho++;				goto out;			}			break;		case IEEE80211_M_IBSS:		case IEEE80211_M_AHDEMO:			if (dir != IEEE80211_FC1_DIR_NODS) {				ic->ic_stats.is_rx_wrongdir++;				goto out;			}			break;		case IEEE80211_M_HOSTAP:			if (dir != IEEE80211_FC1_DIR_TODS) {				ic->ic_stats.is_rx_wrongdir++;				goto out;			}			/* check if source STA is associated */			if (ni == ic->ic_bss) {				IEEE80211_DPRINTF(("%s: data from unknown src "					"%s\n", __func__,					ether_sprintf(wh->i_addr2)));				/* NB: caller deals with reference */				ni = ieee80211_dup_bss(ic, wh->i_addr2);				if (ni != NULL) {					IEEE80211_SEND_MGMT(ic, ni,					    IEEE80211_FC0_SUBTYPE_DEAUTH,					    IEEE80211_REASON_NOT_AUTHED);					ieee80211_free_node(ic, ni);				}				ic->ic_stats.is_rx_notassoc++;				goto err;			}			if (ni->ni_associd == 0) {				IEEE80211_DPRINTF(("ieee80211_input: "				    "data from unassoc src %s\n",				    ether_sprintf(wh->i_addr2)));				IEEE80211_SEND_MGMT(ic, ni,				    IEEE80211_FC0_SUBTYPE_DISASSOC,				    IEEE80211_REASON_NOT_ASSOCED);				ieee80211_unref_node(&ni);				ic->ic_stats.is_rx_notassoc++;				goto err;			}			break;		case IEEE80211_M_MONITOR:			break;		}		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {			if (ic->ic_flags & IEEE80211_F_WEPON) {				m = ieee80211_wep_crypt(ifp, m, 0);				if (m == NULL) {					ic->ic_stats.is_rx_wepfail++;					goto err;				}				wh = mtod(m, struct ieee80211_frame *);			} else {				ic->ic_stats.is_rx_nowep++;				goto out;			}		}#if NBPFILTER > 0		/* copy to listener after decrypt */		if (ic->ic_rawbpf)			BPF_MTAP(ic->ic_rawbpf, m);#endif		m = ieee80211_decap(ifp, m);		if (m == NULL) {			IEEE80211_DPRINTF(("ieee80211_input: "			    "decapsulation error for src %s\n",			    ether_sprintf(wh->i_addr2)));			ic->ic_stats.is_rx_decap++;			goto err;		}		ifp->if_ipackets++;		/* perform as a bridge within the AP */		m1 = NULL;		if (ic->ic_opmode == IEEE80211_M_HOSTAP) {			eh = mtod(m, struct ether_header *);			if (ETHER_IS_MULTICAST(eh->ether_dhost)) {				m1 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);				if (m1 == NULL)					ifp->if_oerrors++;				else					m1->m_flags |= M_MCAST;			} else {				ni = ieee80211_find_node(ic, eh->ether_dhost);				if (ni != NULL) {					if (ni->ni_associd != 0) {						m1 = m;						m = NULL;					}					ieee80211_free_node(ic, ni);				}			}			if (m1 != NULL) {#if !defined(__OpenBSD__)#ifdef ALTQ				if (ALTQ_IS_ENABLED(&ifp->if_snd))					altq_etherclassify(&ifp->if_snd, m1,					    &pktattr);#endif#endif				len = m1->m_pkthdr.len;				IFQ_ENQUEUE(&ifp->if_snd, m1, NULL, error);				if (error)					ifp->if_oerrors++;				else {					if (m != NULL)						ifp->if_omcasts++;					ifp->if_obytes += len;				}			}		}		if (m != NULL) {#if NBPFILTER > 0			/*			 * If we forward packet into transmitter of the AP,			 * we don't need to duplicate for DLT_EN10MB.			 */			if (ifp->if_bpf && m1 == NULL)				BPF_MTAP(ifp->if_bpf, m);#endif#if defined(__OpenBSD__) 			ether_input_mbuf(ifp, m);#else			(*ifp->if_input)(ifp, m);#endif		}		return;	case IEEE80211_FC0_TYPE_MGT:		if (dir != IEEE80211_FC1_DIR_NODS) {			ic->ic_stats.is_rx_wrongdir++;			goto err;		}		if (ic->ic_opmode == IEEE80211_M_AHDEMO) {			ic->ic_stats.is_rx_ahdemo_mgt++;			goto out;		}		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;		/* drop frames without interest */		if (ic->ic_state == IEEE80211_S_SCAN) {			if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&			    subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP) {				ic->ic_stats.is_rx_mgtdiscard++;				goto out;			}		} else {			if (ic->ic_opmode != IEEE80211_M_IBSS &&			    subtype == IEEE80211_FC0_SUBTYPE_BEACON) {				ic->ic_stats.is_rx_mgtdiscard++;				goto out;			}		}		if (ifp->if_flags & IFF_DEBUG) {			/* avoid to print too many frames */			int doprint = 0;			switch (subtype) {			case IEEE80211_FC0_SUBTYPE_BEACON:				if (ic->ic_state == IEEE80211_S_SCAN)					doprint = 1;				break;			case IEEE80211_FC0_SUBTYPE_PROBE_REQ:				if (ic->ic_opmode == IEEE80211_M_IBSS)					doprint = 1;				break;			default:				doprint = 1;				break;			}#ifdef IEEE80211_DEBUG			doprint += ieee80211_debug;#endif			if (doprint)				if_printf(ifp, "received %s from %s rssi %d\n",				    ieee80211_mgt_subtype_name[subtype				    >> IEEE80211_FC0_SUBTYPE_SHIFT],				    ether_sprintf(wh->i_addr2), rssi);		}#if NBPFILTER > 0		if (ic->ic_rawbpf)			BPF_MTAP(ic->ic_rawbpf, m);#endif		(*ic->ic_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);		m_freem(m);		return;	case IEEE80211_FC0_TYPE_CTL:		ic->ic_stats.is_rx_ctl++;		if (ic->ic_opmode != IEEE80211_M_HOSTAP)			goto out;		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;		if (subtype == IEEE80211_FC0_SUBTYPE_PS_POLL) {			/* XXX statistic */			/* Dump out a single packet from the host */			if (ifp->if_flags & IFF_DEBUG)				printf("%s: got power save probe from %s\n",				    ifp->if_xname,				    ether_sprintf(wh->i_addr2));			ieee80211_recv_pspoll(ic, m, rssi, rstamp);		}		goto out;	default:		IEEE80211_DPRINTF(("%s: bad type %x\n", __func__, type));		/* should not come here */		break;	}  err:	ifp->if_ierrors++;  out:	if (m != NULL) {#if NBPFILTER > 0		if (ic->ic_rawbpf)			BPF_MTAP(ic->ic_rawbpf, m);#endif		m_freem(m);	}}