Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/net80211 Introduce ieee80211_recv_mgmt_assoc_req.
details: https://anonhg.NetBSD.org/src/rev/2efbf464b709
branches: trunk
changeset: 358787:2efbf464b709
user: maxv <maxv%NetBSD.org@localhost>
date: Tue Jan 16 15:55:14 2018 +0000
description:
Introduce ieee80211_recv_mgmt_assoc_req.
diffstat:
sys/net80211/ieee80211_input.c | 434 +++++++++++++++++++++-------------------
1 files changed, 225 insertions(+), 209 deletions(-)
diffs (truncated from 469 to 300 lines):
diff -r 416d2b4fabc3 -r 2efbf464b709 sys/net80211/ieee80211_input.c
--- a/sys/net80211/ieee80211_input.c Tue Jan 16 15:48:32 2018 +0000
+++ b/sys/net80211/ieee80211_input.c Tue Jan 16 15:55:14 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ieee80211_input.c,v 1.99 2018/01/16 15:48:32 maxv Exp $ */
+/* $NetBSD: ieee80211_input.c,v 1.100 2018/01/16 15:55:14 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.99 2018/01/16 15:48:32 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ieee80211_input.c,v 1.100 2018/01/16 15:55:14 maxv Exp $");
#endif
#ifdef _KERNEL_OPT
@@ -2449,6 +2449,225 @@
}
}
+static void
+ieee80211_recv_mgmt_assoc_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, *wpa, *wme;
+ int reassoc, resp;
+ u_int8_t rate;
+ IEEE80211_DEBUGVAR(char ebuf[3 * ETHER_ADDR_LEN]);
+
+ wh = mtod(m0, struct ieee80211_frame *);
+ frm = (u_int8_t *)(wh + 1);
+ efrm = mtod(m0, u_int8_t *) + m0->m_len;
+
+ u_int16_t capinfo, lintval;
+ struct ieee80211_rsnparms rsn;
+ u_int8_t reason;
+
+ if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
+ ic->ic_state != IEEE80211_S_RUN) {
+ ic->ic_stats.is_rx_mgtdiscard++;
+ return;
+ }
+
+ if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
+ reassoc = 1;
+ resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
+ } else {
+ reassoc = 0;
+ resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
+ }
+ /*
+ * asreq frame format
+ * [2] capability information
+ * [2] listen interval
+ * [6*] current AP address (reassoc only)
+ * [tlv] ssid
+ * [tlv] supported rates
+ * [tlv] extended supported rates
+ * [tlv] WPA or RSN
+ */
+ IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4));
+ if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
+ IEEE80211_DISCARD(ic, IEEE80211_MSG_ANY,
+ wh, ieee80211_mgt_subtype_name[subtype >>
+ IEEE80211_FC0_SUBTYPE_SHIFT],
+ "%s", "wrong bssid");
+ ic->ic_stats.is_rx_assoc_bss++;
+ return;
+ }
+ capinfo = le16toh(*(u_int16_t *)frm); frm += 2;
+ lintval = le16toh(*(u_int16_t *)frm); frm += 2;
+ if (reassoc)
+ frm += 6; /* ignore current AP info */
+ ssid = rates = xrates = wpa = wme = NULL;
+ while (frm < efrm) {
+ switch (*frm) {
+ case IEEE80211_ELEMID_SSID:
+ ssid = frm;
+ break;
+ case IEEE80211_ELEMID_RATES:
+ rates = frm;
+ break;
+ case IEEE80211_ELEMID_XRATES:
+ xrates = frm;
+ break;
+ /* XXX verify only one of RSN and WPA ie's? */
+ case IEEE80211_ELEMID_RSN:
+ wpa = frm;
+ break;
+ case IEEE80211_ELEMID_VENDOR:
+ if (iswpaoui(frm))
+ wpa = frm;
+ else if (iswmeinfo(frm))
+ wme = frm;
+ /* XXX Atheros OUI support */
+ break;
+ }
+ frm += frm[1] + 2;
+ }
+ IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
+ IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
+ IEEE80211_VERIFY_SSID(ic->ic_bss, ssid);
+
+ if (ni == ic->ic_bss) {
+ IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
+ "[%s] deny %s request, sta not authenticated\n",
+ ether_snprintf(ebuf, sizeof(ebuf), wh->i_addr2),
+ reassoc ? "reassoc" : "assoc");
+ ieee80211_send_error(ic, ni, wh->i_addr2,
+ IEEE80211_FC0_SUBTYPE_DEAUTH,
+ IEEE80211_REASON_ASSOC_NOT_AUTHED);
+ ic->ic_stats.is_rx_assoc_notauth++;
+ return;
+ }
+ /* assert right associstion security credentials */
+ if (wpa == NULL && (ic->ic_flags & IEEE80211_F_WPA)) {
+ IEEE80211_DPRINTF(ic,
+ IEEE80211_MSG_ASSOC | IEEE80211_MSG_WPA,
+ "[%s] no WPA/RSN IE in association request\n",
+ ether_snprintf(ebuf, sizeof(ebuf), wh->i_addr2));
+ IEEE80211_SEND_MGMT(ic, ni,
+ IEEE80211_FC0_SUBTYPE_DEAUTH,
+ IEEE80211_REASON_RSN_REQUIRED);
+ ieee80211_node_leave(ic, ni);
+ /* XXX distinguish WPA/RSN? */
+ ic->ic_stats.is_rx_assoc_badwpaie++;
+ return;
+ }
+ if (wpa != NULL) {
+ /*
+ * Parse WPA information element. Note that
+ * we initialize the param block from the node
+ * state so that information in the IE overrides
+ * our defaults. The resulting parameters are
+ * installed below after the association is assured.
+ */
+ rsn = ni->ni_rsn;
+ if (wpa[0] != IEEE80211_ELEMID_RSN)
+ reason = ieee80211_parse_wpa(ic, wpa, &rsn, wh);
+ else
+ reason = ieee80211_parse_rsn(ic, wpa, &rsn, wh);
+ if (reason != 0) {
+ IEEE80211_SEND_MGMT(ic, ni,
+ IEEE80211_FC0_SUBTYPE_DEAUTH, reason);
+ ieee80211_node_leave(ic, ni);
+ /* XXX distinguish WPA/RSN? */
+ ic->ic_stats.is_rx_assoc_badwpaie++;
+ return;
+ }
+ IEEE80211_DPRINTF(ic,
+ IEEE80211_MSG_ASSOC | IEEE80211_MSG_WPA,
+ "[%s] %s ie: mc %u/%u uc %u/%u key %u caps 0x%x\n",
+ ether_snprintf(ebuf, sizeof(ebuf), wh->i_addr2),
+ wpa[0] != IEEE80211_ELEMID_RSN ? "WPA" : "RSN",
+ rsn.rsn_mcastcipher, rsn.rsn_mcastkeylen,
+ rsn.rsn_ucastcipher, rsn.rsn_ucastkeylen,
+ rsn.rsn_keymgmt, rsn.rsn_caps);
+ }
+ /* discard challenge after association */
+ if (ni->ni_challenge != NULL) {
+ free(ni->ni_challenge, M_DEVBUF);
+ ni->ni_challenge = NULL;
+ }
+ /* NB: 802.11 spec says to ignore station's privacy bit */
+ if ((capinfo & IEEE80211_CAPINFO_ESS) == 0) {
+ IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
+ "[%s] deny %s request, capability mismatch 0x%x\n",
+ ether_snprintf(ebuf, sizeof(ebuf), wh->i_addr2),
+ reassoc ? "reassoc" : "assoc", capinfo);
+ IEEE80211_SEND_MGMT(ic, ni, resp,
+ IEEE80211_STATUS_CAPINFO);
+ ieee80211_node_leave(ic, ni);
+ ic->ic_stats.is_rx_assoc_capmismatch++;
+ return;
+ }
+ rate = ieee80211_setup_rates(ni, rates, xrates,
+ IEEE80211_R_DOSORT | IEEE80211_R_DOFRATE |
+ IEEE80211_R_DONEGO | IEEE80211_R_DODEL);
+ /*
+ * If constrained to 11g-only stations reject an
+ * 11b-only station. We cheat a bit here by looking
+ * at the max negotiated xmit rate and assuming anyone
+ * with a best rate <24Mb/s is an 11b station.
+ */
+ if ((rate & IEEE80211_RATE_BASIC) ||
+ ((ic->ic_flags & IEEE80211_F_PUREG) && rate < 48)) {
+ IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
+ "[%s] deny %s request, rate set mismatch\n",
+ ether_snprintf(ebuf, sizeof(ebuf), wh->i_addr2),
+ reassoc ? "reassoc" : "assoc");
+ IEEE80211_SEND_MGMT(ic, ni, resp,
+ IEEE80211_STATUS_BASIC_RATE);
+ ieee80211_node_leave(ic, ni);
+ ic->ic_stats.is_rx_assoc_norate++;
+ return;
+ }
+ ni->ni_rssi = rssi;
+ ni->ni_rstamp = rstamp;
+ ni->ni_intval = lintval;
+ ni->ni_capinfo = capinfo;
+ ni->ni_chan = ic->ic_bss->ni_chan;
+ ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
+ ni->ni_fhindex = ic->ic_bss->ni_fhindex;
+ if (wpa != NULL) {
+ /*
+ * Record WPA/RSN parameters for station, mark
+ * node as using WPA and record information element
+ * for applications that require it.
+ */
+ ni->ni_rsn = rsn;
+ ieee80211_saveie(&ni->ni_wpa_ie, wpa);
+ } else if (ni->ni_wpa_ie != NULL) {
+ /*
+ * Flush any state from a previous association.
+ */
+ free(ni->ni_wpa_ie, M_DEVBUF);
+ ni->ni_wpa_ie = NULL;
+ }
+ if (wme != NULL) {
+ /*
+ * Record WME parameters for station, mark node
+ * as capable of QoS and record information
+ * element for applications that require it.
+ */
+ ieee80211_saveie(&ni->ni_wme_ie, wme);
+ ni->ni_flags |= IEEE80211_NODE_QOS;
+ } else if (ni->ni_wme_ie != NULL) {
+ /*
+ * Flush any state from a previous association.
+ */
+ free(ni->ni_wme_ie, M_DEVBUF);
+ ni->ni_wme_ie = NULL;
+ ni->ni_flags &= ~IEEE80211_NODE_QOS;
+ }
+ ieee80211_node_join(ic, ni, resp);
+}
+
/* -------------------------------------------------------------------------- */
void
@@ -2458,8 +2677,7 @@
#define ISREASSOC(_st) ((_st) == IEEE80211_FC0_SUBTYPE_REASSOC_RESP)
struct ieee80211_frame *wh;
u_int8_t *frm, *efrm;
- u_int8_t *ssid, *rates, *xrates, *wpa, *wme;
- int reassoc, resp;
+ u_int8_t *rates, *xrates, *wpa, *wme;
u_int8_t rate;
IEEE80211_DEBUGVAR(char ebuf[3 * ETHER_ADDR_LEN]);
@@ -2482,211 +2700,9 @@
return;
case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
- case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: {
- u_int16_t capinfo, lintval;
- struct ieee80211_rsnparms rsn;
- u_int8_t reason;
-
- if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
- ic->ic_state != IEEE80211_S_RUN) {
- ic->ic_stats.is_rx_mgtdiscard++;
- return;
- }
-
- if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
- reassoc = 1;
- resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP;
- } else {
- reassoc = 0;
- resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
- }
- /*
- * asreq frame format
- * [2] capability information
- * [2] listen interval
- * [6*] current AP address (reassoc only)
- * [tlv] ssid
- * [tlv] supported rates
- * [tlv] extended supported rates
- * [tlv] WPA or RSN
- */
- IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4));
- if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
- IEEE80211_DISCARD(ic, IEEE80211_MSG_ANY,
- wh, ieee80211_mgt_subtype_name[subtype >>
- IEEE80211_FC0_SUBTYPE_SHIFT],
- "%s", "wrong bssid");
- ic->ic_stats.is_rx_assoc_bss++;
- return;
- }
- capinfo = le16toh(*(u_int16_t *)frm); frm += 2;
- lintval = le16toh(*(u_int16_t *)frm); frm += 2;
- if (reassoc)
- frm += 6; /* ignore current AP info */
- ssid = rates = xrates = wpa = wme = NULL;
Home |
Main Index |
Thread Index |
Old Index