Date: Mon, 16 Feb 2004 14:44:24 -0800 (PST) From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 47057 for review Message-ID: <200402162244.i1GMiOwl069264@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=47057 Change 47057 by sam@sam_ebb on 2004/02/16 14:44:05 backport madwifi work for 802.1x and 11g: o redo pspoll receive handling to eliminate extra node lookup (already had the node in hand) o pull out doprint logic into a separate function o redo input path so pspoll control frames are not discarded because of frame length o correct authorized port check o correct refcnt reclamation when doing internal bridge work o replace uess of ieee80211_alloc_node with ieee80211_dup_bss so new nodes properly inherit state o correct problem where existing nodes weren't having their rssi+rstamp updated on reassociation and the like o pull out shared key challenge allocation work into a routine o replace explicit arc4random usage with get_random_bytes portability wrapper o move is_rx_nodealloc counter to the node allocation routines o use new privacy capability flag instead of WEP usage o move aid management code to ieee80211_node_leave o correct check for running out of aid's o add callbacks to the authenticator when stations associate and deassociate (this kicks the 802.1x state machine) o fix two refcnt leaks that could occur in error conditions Affected files ... .. //depot/projects/netperf+sockets/sys/net80211/ieee80211_input.c#17 edit Differences ... ==== //depot/projects/netperf+sockets/sys/net80211/ieee80211_input.c#17 (text+ko) ==== @@ -73,8 +73,28 @@ static struct mbuf *ieee80211_defrag(struct ieee80211com *, struct ieee80211_node *, struct mbuf *); static struct mbuf *ieee80211_decap(struct ieee80211com *, struct mbuf *); -static void ieee80211_recv_pspoll(struct ieee80211com *, struct mbuf *, - int rssi, u_int32_t rstamp); +static void ieee80211_recv_pspoll(struct ieee80211com *, + struct ieee80211_node *, struct mbuf *); + +#ifdef IEEE80211_DEBUG +/* + * Decide if a received frame management frame should + * printed when debugging is enabled. This filters some + * of the less interesting frames that come frequently + * (e.g. beacons). + */ +static __inline int +doprint(struct ieee80211com *ic, int subtype) +{ + switch (subtype) { + case IEEE80211_FC0_SUBTYPE_BEACON: + return (ic->ic_state == IEEE80211_S_SCAN); + case IEEE80211_FC0_SUBTYPE_PROBE_REQ: + return (ic->ic_opmode == IEEE80211_M_IBSS); + } + return 1; +} +#endif /* * Process a received frame. The node associated with the sender @@ -93,7 +113,6 @@ struct ifnet *ifp = ic->ic_ifp; struct ieee80211_frame *wh; struct ether_header *eh; - struct mbuf *m1; int len; u_int8_t dir, type, subtype; u_int8_t *bssid; @@ -109,16 +128,30 @@ KASSERT(m->m_pkthdr.len >= sizeof(struct ieee80211_frame_min), ("frame length too short: %u", m->m_pkthdr.len)); + /* * 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)) + if (ic->ic_opmode == IEEE80211_M_MONITOR) goto out; + if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) { + IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, + ("%s: frame too short, len %u\n", + __func__, m->m_pkthdr.len)); + ic->ic_stats.is_rx_tooshort++; + goto out; + } + /* + * Bit of a cheat here, we use a pointer for a 3-address + * frame format but don't reference fields past outside + * ieee80211_frame_min w/o first validating the data is + * present. + */ wh = mtod(m, struct ieee80211_frame *); + if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != IEEE80211_FC0_VERSION_0) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, @@ -130,19 +163,7 @@ 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_DPRINTF(ic, IEEE80211_MSG_ANY, - ("%s: frame too short, len %u\n", - __func__, m->m_pkthdr.len)); - ic->ic_stats.is_rx_tooshort++; - goto out; /* XXX */ - } + subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; if (ic->ic_state != IEEE80211_S_SCAN) { switch (ic->ic_opmode) { case IEEE80211_M_STA: @@ -160,9 +181,17 @@ case IEEE80211_M_IBSS: case IEEE80211_M_AHDEMO: case IEEE80211_M_HOSTAP: - if (dir == IEEE80211_FC1_DIR_NODS) + if (dir == IEEE80211_FC1_DIR_NODS) { + if (m->m_pkthdr.len < + sizeof(struct ieee80211_frame)) { + IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, + ("%s: frame too short, len %u\n", + __func__, m->m_pkthdr.len)); + ic->ic_stats.is_rx_tooshort++; + goto out; + } bssid = wh->i_addr3; - else + } else bssid = wh->i_addr1; if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->ni_bssid) && !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr) && @@ -170,15 +199,13 @@ IEEE80211_FC0_TYPE_DATA) { /* not interested in */ IEEE80211_DPRINTF(ic, IEEE80211_MSG_INPUT, - ("[%s] discard frame from bss %s\n", - ieee80211_state_name[ic->ic_state], - ether_sprintf(bssid))); + ("[%s] discard frame from bss %s\n", + ieee80211_state_name[ic->ic_state], + ether_sprintf(bssid))); ic->ic_stats.is_rx_wrongbss++; goto out; } break; - case IEEE80211_M_MONITOR: - goto out; default: /* XXX catch bad values */ goto out; @@ -202,7 +229,7 @@ ic->ic_stats.is_rx_dup++; /* XXX per-station stat */ goto out; } - ni->ni_inact = 0; + ni->ni_inact = 0; /* XXX move up? */ } /* @@ -237,6 +264,13 @@ switch (type) { case IEEE80211_FC0_TYPE_DATA: + if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) { + IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, + ("%s: data frame too short, len %u\n", + __func__, m->m_pkthdr.len)); + ic->ic_stats.is_rx_tooshort++; + goto out; /* XXX */ + } switch (ic->ic_opmode) { case IEEE80211_M_STA: if (dir != IEEE80211_FC1_DIR_FROMDS) { @@ -275,7 +309,7 @@ IEEE80211_DPRINTF(ic, IEEE80211_MSG_INPUT, ("%s: data from unknown src %s\n", __func__, ether_sprintf(wh->i_addr2))); - /* NB: caller deals with reference */ + /* NB: caller deals with reference to ic_bss */ ni = ieee80211_dup_bss(ic, wh->i_addr2); if (ni != NULL) { IEEE80211_SEND_MGMT(ic, ni, @@ -296,22 +330,9 @@ ic->ic_stats.is_rx_notassoc++; goto err; } - /* - * When station is to be authenticated with 802.1x - * deny any data frames until authentication has - * been completed. - */ - if (ni->ni_authmode == IEEE80211_AUTH_8021X && - (ni->ni_flags & IEEE80211_NODE_AUTH) == 0) { - IEEE80211_DPRINTF(ic, IEEE80211_MSG_INPUT, - ("%s: data from unauthenticated src %s\n", - __func__, ether_sprintf(wh->i_addr2))); - ic->ic_stats.is_rx_not1xauth++; - /* XXX node statistic */ - goto err; - } break; - case IEEE80211_M_MONITOR: + default: + /* XXX here to keep compiler happy */ break; } if (wh->i_fc[1] & IEEE80211_FC1_WEP) { @@ -351,12 +372,28 @@ ic->ic_stats.is_rx_decap++; goto err; } + eh = mtod(m, struct ether_header *); + /* + * Deny any non-PAE frames received prior to authorization. + * For open/shared-key authentication the port is mark + * authorized after authentication completes. For 802.1x + * the port is not marked authorized by the authenticator. + */ + if ((ni->ni_flags & IEEE80211_NODE_AUTH) == 0 && + eh->ether_type != htons(ETHERTYPE_PAE)) { + IEEE80211_DPRINTF(ic, IEEE80211_MSG_INPUT, + ("%s: discard data from %s on unauthorized port\n", + __func__, ether_sprintf(wh->i_addr2))); + ic->ic_stats.is_rx_unauth++; + /* XXX node statistic */ + 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 *); + struct mbuf *m1 = NULL; + if (ETHER_IS_MULTICAST(eh->ether_dhost)) { m1 = m_copypacket(m, M_DONTWAIT); if (m1 == NULL) @@ -364,6 +401,8 @@ else m1->m_flags |= M_MCAST; } else { + /* XXX this dups work done in ieee80211_encap */ + /* check if destination is associated */ struct ieee80211_node *ni1 = ieee80211_find_node(ic, eh->ether_dhost); if (ni1 != NULL) { @@ -371,7 +410,8 @@ m1 = m; m = NULL; } - ieee80211_unref_node(&ni1); + /* XXX statistic? */ + ieee80211_free_node(ic, ni1); } } if (m1 != NULL) { @@ -405,7 +445,6 @@ 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) { @@ -421,30 +460,22 @@ goto out; } } - - if (ieee80211_msg_debug(ic)) { - /* 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; - } - if (doprint || ieee80211_msg_dumppkts(ic)) - 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 (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) { + IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, + ("%s: mgt data frame too short, len %u\n", + __func__, m->m_pkthdr.len)); + ic->ic_stats.is_rx_tooshort++; + goto out; + } +#ifdef IEEE80211_DEBUG + if ((ieee80211_msg_debug(ic) && doprint(ic, subtype)) || + ieee80211_msg_dumppkts(ic)) { + 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); } +#endif if (ic->ic_rawbpf) bpf_mtap(ic->ic_rawbpf, m); (*ic->ic_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp); @@ -455,19 +486,18 @@ 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 */ IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER, ("got power save probe from %s\n", ether_sprintf(wh->i_addr2))); - ieee80211_recv_pspoll(ic, m, rssi, rstamp); + ieee80211_recv_pspoll(ic, ni, m); } goto out; default: IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, - ("%s: bad type %x\n", __func__, type)); + ("%s: bad frame type %x\n", __func__, type)); /* should not come here */ break; } @@ -736,19 +766,17 @@ ic->ic_stats.is_rx_bad_auth++; return; } + /* always accept open authentication requests */ if (ni == ic->ic_bss) { - ni = ieee80211_alloc_node(ic, wh->i_addr2); - if (ni == NULL) { - ic->ic_stats.is_rx_nodealloc++; + ni = ieee80211_dup_bss(ic, wh->i_addr2); + if (ni == NULL) return; - } IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid); - ni->ni_rssi = rssi; - ni->ni_rstamp = rstamp; - ni->ni_chan = ic->ic_bss->ni_chan; allocbs = 1; } else allocbs = 0; + ni->ni_rssi = rssi; + ni->ni_rstamp = rstamp; IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, seq + 1); IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, @@ -782,14 +810,28 @@ } } +static int +alloc_challenge(struct ieee80211com *ic, struct ieee80211_node *ni) +{ + if (ni->ni_challenge == NULL) + MALLOC(ni->ni_challenge, u_int32_t*, IEEE80211_CHALLENGE_LEN, + M_DEVBUF, M_NOWAIT); + if (ni->ni_challenge == NULL) { + IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, + ("%s: challenge alloc failed\n", __func__)); + /* XXX statistic */ + } + return (ni->ni_challenge != NULL); +} + /* XXX TODO: add statistics */ static void ieee80211_auth_shared(struct ieee80211com *ic, struct ieee80211_frame *wh, u_int8_t *frm, u_int8_t *efrm, struct ieee80211_node *ni, int rssi, u_int32_t rstamp, u_int16_t seq, u_int16_t status) { - u_int8_t *challenge = NULL; - int allocbs, i, estatus; + u_int8_t *challenge; + int allocbs, estatus; /* * NB: this can happen as we allow pre-shared key @@ -820,6 +862,7 @@ goto bad; } + challenge = NULL; if (frm + 1 < efrm) { if ((frm[1] + 2) > (efrm - frm)) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH, @@ -871,35 +914,24 @@ switch (seq) { case IEEE80211_AUTH_SHARED_REQUEST: if (ni == ic->ic_bss) { - ni = ieee80211_alloc_node(ic, wh->i_addr2); + ni = ieee80211_dup_bss(ic, wh->i_addr2); if (ni == NULL) { - ic->ic_stats.is_rx_nodealloc++; /* NB: no way to return an error */ return; } IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid); - ni->ni_rssi = rssi; - ni->ni_rstamp = rstamp; - ni->ni_chan = ic->ic_bss->ni_chan; allocbs = 1; } else allocbs = 0; - if (ni->ni_challenge == NULL) - MALLOC(ni->ni_challenge, u_int32_t*, - IEEE80211_CHALLENGE_LEN, - M_DEVBUF, M_NOWAIT); - if (ni->ni_challenge == NULL) { - IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH, - ("%s: challenge alloc failed\n", - __func__)); - /* XXX statistic */ + ni->ni_rssi = rssi; + ni->ni_rstamp = rstamp; + if (!alloc_challenge(ic, ni)) { /* NB: don't return error so they rexmit */ return; } - for (i = IEEE80211_CHALLENGE_LEN / sizeof(u_int32_t); - --i >= 0; ) - ni->ni_challenge[i] = arc4random(); + get_random_bytes(ni->ni_challenge, + IEEE80211_CHALLENGE_LEN); IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, ("shared key %sauth request from station %s\n", @@ -913,7 +945,6 @@ /* NB: don't send a response */ return; } - allocbs = 1; if (ni->ni_challenge == NULL) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_AUTH, ("%s: no challenge recorded\n", __func__)); @@ -961,6 +992,7 @@ ("%s: auth failed (reason %d) for %s\n", __func__, status, ether_sprintf(wh->i_addr3))); + /* XXX can this happen? */ if (ni != ic->ic_bss) ni->ni_fails++; ic->ic_stats.is_rx_auth_fail++; @@ -970,16 +1002,9 @@ wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); break; case IEEE80211_AUTH_SHARED_CHALLENGE: - if (ni->ni_challenge == NULL) - MALLOC(ni->ni_challenge, u_int32_t *, - challenge[1], M_DEVBUF, M_NOWAIT); - if (ni->ni_challenge == NULL) { - IEEE80211_DPRINTF(ic, - IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, - ("%s: challenge alloc failed\n", __func__)); - /* XXX statistic */ + if (!alloc_challenge(ic, ni)) return; - } + /* XXX could optimize by passing recvd challenge */ memcpy(ni->ni_challenge, &challenge[2], challenge[1]); IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, seq + 1); @@ -1216,10 +1241,8 @@ #endif if (ni == NULL) { ni = ieee80211_alloc_node(ic, wh->i_addr2); - if (ni == NULL) { - ic->ic_stats.is_rx_nodealloc++; + if (ni == NULL) return; - } ni->ni_esslen = ssid[1]; memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); memcpy(ni->ni_essid, ssid + 2, ssid[1]); @@ -1260,7 +1283,7 @@ } /* NB: must be after ni_chan is setup */ ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT); - ieee80211_unref_node(&ni); + ieee80211_unref_node(&ni); /* NB: do not free */ break; } @@ -1311,12 +1334,10 @@ if (ni == ic->ic_bss) { ni = ieee80211_dup_bss(ic, wh->i_addr2); - if (ni == NULL) { - ic->ic_stats.is_rx_nodealloc++; + if (ni == NULL) return; - } IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC, - ("%s: new req from %s\n", + ("%s: new probe req from %s\n", __func__, ether_sprintf(wh->i_addr2))); allocbs = 1; } else @@ -1335,7 +1356,18 @@ IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0); } if (allocbs) { - /* XXX just use free? */ + /* + * When operating as an AP we discard the node's + * state until the station requests authentication. + * This may be better done by holding it and setting + * a short timer for reclaiming it but reduces the + * possibility of stations flooding us with probe + * requests causing our memory use to grow quickly + * (though this can still happen if they send + * authentication requests). When operating in ibss + * mode we hold the node but with a zero reference + * count; this is the current convention (XXX). + */ if (ic->ic_opmode == IEEE80211_M_HOSTAP) ieee80211_free_node(ic, ni); else @@ -1388,7 +1420,7 @@ u_int16_t capinfo, bintval; if (ic->ic_opmode != IEEE80211_M_HOSTAP || - (ic->ic_state != IEEE80211_S_RUN)) + ic->ic_state != IEEE80211_S_RUN) return; if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) { @@ -1410,7 +1442,8 @@ IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4)); if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, - ("%s: ignore assoc request from other bss %s\n", + ("%s: ignore assoc request with bss %s not " + "our own\n", __func__, ether_sprintf(wh->i_addr2))); ic->ic_stats.is_rx_assoc_bss++; return; @@ -1470,17 +1503,16 @@ /* XXX per-node cipher suite */ /* XXX some stations use the privacy bit for handling APs that suport both encrypted and unencrypted traffic */ + /* NB: PRIVACY flag bits are assumed to match */ if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 || - (capinfo & IEEE80211_CAPINFO_PRIVACY) != - ((ic->ic_flags & IEEE80211_F_WEPON) ? - IEEE80211_CAPINFO_PRIVACY : 0)) { + (capinfo & IEEE80211_CAPINFO_PRIVACY) ^ + (ic->ic_flags & IEEE80211_F_PRIVACY)) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, ("%s: capability mismatch %x for %s\n", __func__, capinfo, ether_sprintf(wh->i_addr2))); - IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap); - ni->ni_associd = 0; IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_CAPINFO); + ieee80211_node_leave(ic, ni); ic->ic_stats.is_rx_assoc_capmismatch++; return; } @@ -1491,10 +1523,9 @@ IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY, ("%s: rate mismatch for %s\n", __func__, ether_sprintf(wh->i_addr2))); - IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap); - ni->ni_associd = 0; IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_BASIC_RATE); + ieee80211_node_leave(ic, ni); ic->ic_stats.is_rx_assoc_norate++; return; } @@ -1509,7 +1540,7 @@ u_int16_t aid; /* - * It would be clever to search the bitmap + * It would be good to search the bitmap * more efficiently, but this will do for now. */ for (aid = 1; aid < ic->ic_max_aid; aid++) { @@ -1517,10 +1548,10 @@ ic->ic_aid_bitmap)) break; } - - if (ic->ic_bss->ni_associd >= ic->ic_max_aid) { + if (aid >= ic->ic_max_aid) { IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_REASON_ASSOC_TOOMANY); + ieee80211_node_leave(ic, ni); return; } ni->ni_associd = aid | 0xc000; @@ -1574,7 +1605,6 @@ ni->ni_flags |= IEEE80211_NODE_ERP; } else newassoc = 0; - IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS); IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ("station %s %s associated at aid %d\n", (newassoc ? "newly" : "already"), @@ -1583,6 +1613,11 @@ /* give driver a chance to setup state like ni_txrate */ if (ic->ic_newassoc) (*ic->ic_newassoc)(ic, ni, newassoc); + IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS); + /* XXX may need a delay here? */ + /* tell the authenticator about new station */ + if (ni->ni_authmode == IEEE80211_AUTH_8021X) + (*ic->ic_node_join)(ic, ni); break; } @@ -1605,6 +1640,7 @@ IEEE80211_VERIFY_LENGTH(efrm - frm, 6); ni = ic->ic_bss; ni->ni_capinfo = le16toh(*(u_int16_t *)frm); + frm += 2; if (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) ic->ic_flags |= IEEE80211_F_SHPREAMBLE; else @@ -1613,7 +1649,6 @@ ic->ic_flags |= IEEE80211_F_SHSLOT; else ic->ic_flags &= ~IEEE80211_F_SHSLOT; - frm += 2; status = le16toh(*(u_int16_t *)frm); frm += 2; @@ -1673,8 +1708,6 @@ "peer (reason %d)\n", ether_sprintf(ni->ni_macaddr), reason)); ieee80211_node_leave(ic, ni); - /* node will be free'd on return */ - ieee80211_unref_node(&ni); } break; default: @@ -1703,11 +1736,7 @@ ("station %s disassociated by " "peer (reason %d)\n", ether_sprintf(ni->ni_macaddr), reason)); - IEEE80211_AID_CLR(ni->ni_associd, - ic->ic_aid_bitmap); - ni->ni_associd = 0; ieee80211_node_leave(ic, ni); - ieee80211_unref_node(&ni); /* XXX??? */ } break; default: @@ -1728,27 +1757,25 @@ #undef IEEE80211_VERIFY_ELEMENT static void -ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m0, int rssi, - u_int32_t rstamp) +ieee80211_recv_pspoll(struct ieee80211com *ic, + struct ieee80211_node *ni, struct mbuf *m0) { struct ifnet *ifp = ic->ic_ifp; - struct ieee80211_frame *wh; - struct ieee80211_node *ni; + struct ieee80211_frame_min *wh; struct mbuf *m; u_int16_t aid; if (ic->ic_set_tim == NULL) /* No powersaving functionality */ return; - - wh = mtod(m0, struct ieee80211_frame *); - - if ((ni = ieee80211_find_node(ic, wh->i_addr2)) == NULL) { + if (ni == ic->ic_bss) { + wh = mtod(m0, struct ieee80211_frame_min *); IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER | IEEE80211_MSG_DEBUG, ("station %s sent bogus power save poll\n", ether_sprintf(wh->i_addr2))); - /* XXX statistic */ return; } + + wh = mtod(m0, struct ieee80211_frame_min *); memcpy(&aid, wh->i_dur, sizeof(wh->i_dur)); if ((aid & 0xc000) != 0xc000) { IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER | IEEE80211_MSG_DEBUG, @@ -1774,7 +1801,7 @@ /* XXX statistic */ return; } - wh = mtod(m, struct ieee80211_frame *); + wh = mtod(m, struct ieee80211_frame_min *); /* * If this is the last packet, turn off the TIM fields.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200402162244.i1GMiOwl069264>