Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/net80211 Start splitting ieee80211_recv_mgmt.
details: https://anonhg.NetBSD.org/src/rev/e06375f5ee43
branches: trunk
changeset: 829086:e06375f5ee43
user: maxv <maxv%NetBSD.org@localhost>
date: Tue Jan 16 15:42:52 2018 +0000
description:
Start splitting ieee80211_recv_mgmt.
diffstat:
sys/net80211/ieee80211_input.c | 727 +++++++++++++++++++++-------------------
1 files changed, 380 insertions(+), 347 deletions(-)
diffs (truncated from 772 to 300 lines):
diff -r 6198fbd5f5a0 -r e06375f5ee43 sys/net80211/ieee80211_input.c
--- a/sys/net80211/ieee80211_input.c Tue Jan 16 15:18:37 2018 +0000
+++ b/sys/net80211/ieee80211_input.c Tue Jan 16 15:42:52 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ieee80211_input.c,v 1.97 2018/01/16 15:18:37 maxv Exp $ */
+/* $NetBSD: ieee80211_input.c,v 1.98 2018/01/16 15:42:52 maxv Exp $ */
/*
* Copyright (c) 2001 Atsushi Onoe
@@ -37,7 +37,7 @@
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_input.c,v 1.81 2005/08/10 16:22:29 sam Exp $");
#endif
#ifdef __NetBSD__
-__KERNEL_RCSID(0, "$NetBSD: ieee80211_input.c,v 1.97 2018/01/16 15:18:37 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ieee80211_input.c,v 1.98 2018/01/16 15:42:52 maxv Exp $");
#endif
#ifdef _KERNEL_OPT
@@ -2001,16 +2001,387 @@
}
}
+/* -------------------------------------------------------------------------- */
+
+static void
+ieee80211_recv_mgmt_beacon(struct ieee80211com *ic, struct mbuf *m0,
+ struct ieee80211_node *ni, int subtype, int rssi, u_int32_t rstamp)
+{
+ struct ieee80211_frame *wh;
+ u_int8_t *frm, *efrm;
+ IEEE80211_DEBUGVAR(char ebuf[3 * ETHER_ADDR_LEN]);
+ struct ieee80211_scanparams scan;
+
+ wh = mtod(m0, struct ieee80211_frame *);
+ frm = (u_int8_t *)(wh + 1);
+ efrm = mtod(m0, u_int8_t *) + m0->m_len;
+
+ /*
+ * We process beacon/probe response frames:
+ * o when scanning, or
+ * o station mode when associated (to collect state
+ * updates such as 802.11g slot time), or
+ * o adhoc mode (to discover neighbors)
+ * Frames otherwise received are discarded.
+ */
+ if (!((ic->ic_flags & IEEE80211_F_SCAN) ||
+ (ic->ic_opmode == IEEE80211_M_STA && ni->ni_associd) ||
+ ic->ic_opmode == IEEE80211_M_IBSS)) {
+ ic->ic_stats.is_rx_mgtdiscard++;
+ return;
+ }
+
+ /*
+ * beacon/probe response frame format
+ * [8] time stamp
+ * [2] beacon interval
+ * [2] capability information
+ * [tlv] ssid
+ * [tlv] supported rates
+ * [tlv] country information
+ * [tlv] parameter set (FH/DS)
+ * [tlv] erp information
+ * [tlv] extended supported rates
+ * [tlv] WME
+ * [tlv] WPA or RSN
+ */
+ IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
+ memset(&scan, 0, sizeof(scan));
+ scan.tstamp = frm; frm += 8;
+ scan.bintval = le16toh(*(u_int16_t *)frm); frm += 2;
+ scan.capinfo = le16toh(*(u_int16_t *)frm); frm += 2;
+ scan.bchan = ieee80211_chan2ieee(ic, ic->ic_curchan);
+ scan.chan = scan.bchan;
+
+ while (frm + 1 < efrm) {
+ IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2);
+
+ switch (*frm) {
+ case IEEE80211_ELEMID_SSID:
+ scan.ssid = frm;
+ break;
+ case IEEE80211_ELEMID_RATES:
+ scan.rates = frm;
+ break;
+ case IEEE80211_ELEMID_COUNTRY:
+ scan.country = frm;
+ break;
+ case IEEE80211_ELEMID_FHPARMS:
+ IEEE80211_VERIFY_LENGTH(frm[1], 5);
+ if (ic->ic_phytype == IEEE80211_T_FH) {
+ scan.fhdwell = LE_READ_2(&frm[2]);
+ scan.chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
+ scan.fhindex = frm[6];
+ }
+ break;
+ case IEEE80211_ELEMID_DSPARMS:
+ /*
+ * XXX hack this since depending on phytype
+ * is problematic for multi-mode devices.
+ */
+ IEEE80211_VERIFY_LENGTH(frm[1], 1);
+ if (ic->ic_phytype != IEEE80211_T_FH)
+ scan.chan = frm[2];
+ break;
+ case IEEE80211_ELEMID_TIM:
+ /* XXX ATIM? */
+ IEEE80211_VERIFY_LENGTH(frm[1], 5);
+ scan.tim = frm;
+ scan.timoff = frm - mtod(m0, u_int8_t *);
+ break;
+ case IEEE80211_ELEMID_IBSSPARMS:
+ break;
+ case IEEE80211_ELEMID_XRATES:
+ scan.xrates = frm;
+ break;
+ case IEEE80211_ELEMID_ERP:
+ if (frm[1] != 1) {
+ IEEE80211_DISCARD_IE(ic,
+ IEEE80211_MSG_ELEMID, wh, "ERP",
+ "bad len %u", frm[1]);
+ ic->ic_stats.is_rx_elem_toobig++;
+ break;
+ }
+ scan.erp = frm[2];
+ break;
+ case IEEE80211_ELEMID_RSN:
+ scan.wpa = frm;
+ break;
+ case IEEE80211_ELEMID_VENDOR:
+ if (iswpaoui(frm))
+ scan.wpa = frm;
+ else if (iswmeparam(frm) || iswmeinfo(frm))
+ scan.wme = frm;
+ /* XXX Atheros OUI support */
+ break;
+ default:
+ IEEE80211_DISCARD_IE(ic, IEEE80211_MSG_ELEMID,
+ wh, "unhandled",
+ "id %u, len %u", *frm, frm[1]);
+ ic->ic_stats.is_rx_elem_unknown++;
+ break;
+ }
+
+ frm += frm[1] + 2;
+ }
+
+ IEEE80211_VERIFY_ELEMENT(scan.rates, IEEE80211_RATE_MAXSIZE);
+ IEEE80211_VERIFY_ELEMENT(scan.ssid, IEEE80211_NWID_LEN);
+
+ if (
+#if IEEE80211_CHAN_MAX < 255
+ scan.chan > IEEE80211_CHAN_MAX ||
+#endif
+ isclr(ic->ic_chan_active, scan.chan)) {
+ IEEE80211_DISCARD(ic,
+ IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
+ wh, ieee80211_mgt_subtype_name[subtype >>
+ IEEE80211_FC0_SUBTYPE_SHIFT],
+ "invalid channel %u", scan.chan);
+ ic->ic_stats.is_rx_badchan++;
+ return;
+ }
+ if (scan.chan != scan.bchan &&
+ ic->ic_phytype != IEEE80211_T_FH) {
+ /*
+ * Frame was received on a channel different from the
+ * one indicated in the DS params element id;
+ * silently discard it.
+ *
+ * NB: this can happen due to signal leakage.
+ * But we should take it for FH phy because
+ * the rssi value should be correct even for
+ * different hop pattern in FH.
+ */
+ IEEE80211_DISCARD(ic,
+ IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
+ wh, ieee80211_mgt_subtype_name[subtype >>
+ IEEE80211_FC0_SUBTYPE_SHIFT],
+ "for off-channel %u", scan.chan);
+ ic->ic_stats.is_rx_chanmismatch++;
+ return;
+ }
+ if (!(IEEE80211_BINTVAL_MIN <= scan.bintval &&
+ scan.bintval <= IEEE80211_BINTVAL_MAX)) {
+ IEEE80211_DISCARD(ic,
+ IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
+ wh, ieee80211_mgt_subtype_name[subtype >>
+ IEEE80211_FC0_SUBTYPE_SHIFT],
+ "bogus beacon interval", scan.bintval);
+ ic->ic_stats.is_rx_badbintval++;
+ return;
+ }
+
+ if (ni != ic->ic_bss) {
+ ni = ieee80211_refine_node_for_beacon(ic, ni,
+ &ic->ic_channels[scan.chan], scan.ssid);
+ }
+ /*
+ * Count frame now that we know it's to be processed.
+ */
+ if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
+ ic->ic_stats.is_rx_beacon++; /* XXX remove */
+ IEEE80211_NODE_STAT(ni, rx_beacons);
+ } else
+ IEEE80211_NODE_STAT(ni, rx_proberesp);
+
+ /*
+ * When operating in station mode, check for state updates.
+ * Be careful to ignore beacons received while doing a
+ * background scan. We consider only 11g/WMM stuff right now.
+ */
+ if (ic->ic_opmode == IEEE80211_M_STA &&
+ ni->ni_associd != 0 &&
+ ((ic->ic_flags & IEEE80211_F_SCAN) == 0 ||
+ IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid))) {
+ /* record tsf of last beacon */
+ memcpy(ni->ni_tstamp.data, scan.tstamp,
+ sizeof(ni->ni_tstamp));
+ if (ni->ni_erp != scan.erp) {
+ IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
+ "[%s] erp change: was 0x%x, now 0x%x\n",
+ ether_snprintf(ebuf, sizeof(ebuf),
+ wh->i_addr2), ni->ni_erp, scan.erp);
+ if (ic->ic_curmode == IEEE80211_MODE_11G &&
+ (ni->ni_erp & IEEE80211_ERP_USE_PROTECTION))
+ ic->ic_flags |= IEEE80211_F_USEPROT;
+ else
+ ic->ic_flags &= ~IEEE80211_F_USEPROT;
+ ni->ni_erp = scan.erp;
+ /* XXX statistic */
+ }
+ if ((ni->ni_capinfo ^ scan.capinfo) & IEEE80211_CAPINFO_SHORT_SLOTTIME) {
+ IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
+ "[%s] capabilities change: before 0x%x,"
+ " now 0x%x\n",
+ ether_snprintf(ebuf, sizeof(ebuf),
+ wh->i_addr2),
+ ni->ni_capinfo, scan.capinfo);
+ /*
+ * NB: we assume short preamble doesn't
+ * change dynamically
+ */
+ ieee80211_set_shortslottime(ic,
+ ic->ic_curmode == IEEE80211_MODE_11A ||
+ (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));
+ ni->ni_capinfo = scan.capinfo;
+ /* XXX statistic */
+ }
+ if (scan.wme != NULL &&
+ (ni->ni_flags & IEEE80211_NODE_QOS) &&
+ ieee80211_parse_wmeparams(ic, scan.wme, wh) > 0)
+ ieee80211_wme_updateparams(ic);
+ if (scan.tim != NULL) {
+ struct ieee80211_tim_ie *ie =
+ (struct ieee80211_tim_ie *) scan.tim;
+
+ ni->ni_dtim_count = ie->tim_count;
+ ni->ni_dtim_period = ie->tim_period;
+ }
+ if (ic->ic_flags & IEEE80211_F_SCAN)
+ ieee80211_add_scan(ic, &scan, wh,
+ subtype, rssi, rstamp);
+ ic->ic_bmiss_count = 0;
+ return;
+ }
+
+ /*
+ * If scanning, just pass information to the scan module.
+ */
+ if (ic->ic_flags & IEEE80211_F_SCAN) {
+ if (ic->ic_flags_ext & IEEE80211_FEXT_PROBECHAN) {
+ /*
+ * Actively scanning a channel marked passive;
+ * send a probe request now that we know there
+ * is 802.11 traffic present.
+ *
+ * XXX check if the beacon we recv'd gives
+ * us what we need and suppress the probe req
+ */
+ ieee80211_probe_curchan(ic, 1);
+ ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
+ }
+ ieee80211_add_scan(ic, &scan, wh,
+ subtype, rssi, rstamp);
+ return;
+ }
+ if (scan.capinfo & IEEE80211_CAPINFO_IBSS)
+ ieee80211_update_adhoc_node(ic, ni, wh, &scan, rssi, rstamp);
+}
+
+static void
+ieee80211_recv_mgmt_probe_req(struct ieee80211com *ic, struct mbuf *m0,
+ struct ieee80211_node *ni, int subtype, int rssi, u_int32_t rstamp)
+{
+ struct ieee80211_frame *wh;
+ u_int8_t *frm, *efrm;
+ u_int8_t *ssid, *rates, *xrates;
+ int allocbs;
+ u_int8_t rate;
+ IEEE80211_DEBUGVAR(char ebuf[3 * ETHER_ADDR_LEN]);
Home |
Main Index |
Thread Index |
Old Index