Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/net80211 Split ieee80211_input into three sub-functions, ...
details: https://anonhg.NetBSD.org/src/rev/be6bf3b08599
branches: trunk
changeset: 358774:be6bf3b08599
user: maxv <maxv%NetBSD.org@localhost>
date: Tue Jan 16 08:39:29 2018 +0000
description:
Split ieee80211_input into three sub-functions, that parse received
packets depending on their type:
DATA -> ieee80211_input_data
MANAGEMENT -> ieee80211_input_management
CONTROL -> ieee80211_input_control
No real functional change, but makes the code much clearer.
diffstat:
sys/net80211/ieee80211_input.c | 639 +++++++++++++++++++++++-----------------
1 files changed, 364 insertions(+), 275 deletions(-)
diffs (truncated from 693 to 300 lines):
diff -r fef63f610ed4 -r be6bf3b08599 sys/net80211/ieee80211_input.c
--- a/sys/net80211/ieee80211_input.c Tue Jan 16 08:37:43 2018 +0000
+++ b/sys/net80211/ieee80211_input.c Tue Jan 16 08:39:29 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ieee80211_input.c,v 1.92 2018/01/16 07:53:02 maxv Exp $ */
+/* $NetBSD: ieee80211_input.c,v 1.93 2018/01/16 08:39:29 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.92 2018/01/16 07:53:02 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ieee80211_input.c,v 1.93 2018/01/16 08:39:29 maxv Exp $");
#endif
#ifdef _KERNEL_OPT
@@ -148,6 +148,359 @@
struct ieee80211_node *, struct ieee80211_frame *,
struct ieee80211_scanparams *, int, u_int32_t);
+/* -------------------------------------------------------------------------- */
+
+/*
+ * Input code for a DATA frame.
+ */
+static int
+ieee80211_input_data(struct ieee80211com *ic, struct mbuf **mp,
+ struct ieee80211_node *ni)
+{
+ struct ifnet *ifp = ic->ic_ifp;
+ struct ieee80211_key *key;
+ struct ieee80211_frame *wh;
+ u_int8_t dir, subtype;
+ struct ether_header *eh;
+ struct mbuf *m = *mp;
+ int hdrspace;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
+ subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+
+ hdrspace = ieee80211_hdrspace(ic, wh);
+
+ if (m->m_len < hdrspace &&
+ (m = m_pullup(m, hdrspace)) == NULL) {
+ IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
+ ni->ni_macaddr, NULL,
+ "data too short: expecting %u", hdrspace);
+ ic->ic_stats.is_rx_tooshort++;
+ goto out; /* XXX */
+ }
+ wh = mtod(m, struct ieee80211_frame *);
+
+ switch (ic->ic_opmode) {
+ case IEEE80211_M_STA:
+ if (dir != IEEE80211_FC1_DIR_FROMDS) {
+ IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
+ wh, "data", "%s", "unknown dir 0x%x", dir);
+ 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 broadcast from AP.
+ * It should be silently discarded for
+ * SIMPLEX interface.
+ */
+ IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
+ wh, NULL, "%s", "multicast echo");
+ ic->ic_stats.is_rx_mcastecho++;
+ goto out;
+ }
+ break;
+
+ case IEEE80211_M_IBSS:
+ case IEEE80211_M_AHDEMO:
+ if (dir != IEEE80211_FC1_DIR_NODS) {
+ IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
+ wh, "data", "%s", "unknown dir 0x%x", dir);
+ ic->ic_stats.is_rx_wrongdir++;
+ goto out;
+ }
+ /* XXX no power-save support */
+ break;
+
+ case IEEE80211_M_HOSTAP:
+#ifndef IEEE80211_NO_HOSTAP
+ if (dir != IEEE80211_FC1_DIR_TODS) {
+ IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
+ wh, "data", "%s", "unknown dir 0x%x", dir);
+ ic->ic_stats.is_rx_wrongdir++;
+ goto out;
+ }
+ /* check if source STA is associated */
+ if (ni == ic->ic_bss) {
+ IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
+ wh, "data", "%s", "unknown src");
+ ieee80211_send_error(ic, ni, wh->i_addr2,
+ IEEE80211_FC0_SUBTYPE_DEAUTH,
+ IEEE80211_REASON_NOT_AUTHED);
+ ic->ic_stats.is_rx_notassoc++;
+ goto err;
+ }
+ if (ni->ni_associd == 0) {
+ IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
+ wh, "data", "%s", "unassoc src");
+ IEEE80211_SEND_MGMT(ic, ni,
+ IEEE80211_FC0_SUBTYPE_DISASSOC,
+ IEEE80211_REASON_NOT_ASSOCED);
+ ic->ic_stats.is_rx_notassoc++;
+ goto err;
+ }
+
+ /*
+ * Check for power save state change.
+ */
+ if (((wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) ^
+ (ni->ni_flags & IEEE80211_NODE_PWR_MGT)))
+ ieee80211_node_pwrsave(ni,
+ wh->i_fc[1] & IEEE80211_FC1_PWR_MGT);
+#endif /* !IEEE80211_NO_HOSTAP */
+ break;
+
+ default:
+ /* XXX here to keep compiler happy */
+ goto out;
+ }
+
+ /*
+ * Handle privacy requirements. Note that we
+ * must not be preempted from here until after
+ * we (potentially) call ieee80211_crypto_demic;
+ * otherwise we may violate assumptions in the
+ * crypto cipher modules used to do delayed update
+ * of replay sequence numbers.
+ */
+ if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
+ if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) {
+ /*
+ * Discard encrypted frames when privacy is off.
+ */
+ IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
+ wh, "WEP", "%s", "PRIVACY off");
+ ic->ic_stats.is_rx_noprivacy++;
+ IEEE80211_NODE_STAT(ni, rx_noprivacy);
+ goto out;
+ }
+ key = ieee80211_crypto_decap(ic, ni, &m, hdrspace);
+ if (key == NULL) {
+ /* NB: stats+msgs handled in crypto_decap */
+ IEEE80211_NODE_STAT(ni, rx_wepfail);
+ goto out;
+ }
+ wh = mtod(m, struct ieee80211_frame *);
+ wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
+ } else {
+ key = NULL;
+ }
+
+ /*
+ * Next up, any fragmentation.
+ */
+ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ m = ieee80211_defrag(ic, ni, m, hdrspace);
+ if (m == NULL) {
+ /* Fragment dropped or frame not complete yet */
+ goto out;
+ }
+ }
+ wh = NULL; /* no longer valid, catch any uses */
+
+ /*
+ * Next strip any MSDU crypto bits.
+ */
+ if (key != NULL && !ieee80211_crypto_demic(ic, key, m, 0)) {
+ IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_INPUT,
+ ni->ni_macaddr, "data", "%s", "demic error");
+ IEEE80211_NODE_STAT(ni, rx_demicfail);
+ goto out;
+ }
+
+ /* copy to listener after decrypt */
+ bpf_mtap3(ic->ic_rawbpf, m);
+
+ /*
+ * Finally, strip the 802.11 header.
+ */
+ m = ieee80211_decap(ic, m, hdrspace);
+ if (m == NULL) {
+ /* don't count Null data frames as errors */
+ if (subtype == IEEE80211_FC0_SUBTYPE_NODATA)
+ goto out;
+ IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_INPUT,
+ ni->ni_macaddr, "data", "%s", "decap error");
+ ic->ic_stats.is_rx_decap++;
+ IEEE80211_NODE_STAT(ni, rx_decap);
+ goto err;
+ }
+
+ eh = mtod(m, struct ether_header *);
+ if (!ieee80211_node_is_authorized(ni)) {
+ /*
+ * 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 until the handshake has completed.
+ */
+ if (eh->ether_type != htons(ETHERTYPE_PAE)) {
+ IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_INPUT,
+ eh->ether_shost, "data",
+ "unauthorized port: ether type 0x%x len %u",
+ eh->ether_type, m->m_pkthdr.len);
+ ic->ic_stats.is_rx_unauth++;
+ IEEE80211_NODE_STAT(ni, rx_unauth);
+ goto err;
+ }
+ } else {
+ /*
+ * When denying unencrypted frames, discard
+ * any non-PAE frames received without encryption.
+ */
+ if ((ic->ic_flags & IEEE80211_F_DROPUNENC) &&
+ key == NULL &&
+ eh->ether_type != htons(ETHERTYPE_PAE)) {
+ /*
+ * Drop unencrypted frames.
+ */
+ ic->ic_stats.is_rx_unencrypted++;
+ IEEE80211_NODE_STAT(ni, rx_unencrypted);
+ goto out;
+ }
+ }
+
+ ifp->if_ipackets++;
+ IEEE80211_NODE_STAT(ni, rx_data);
+ IEEE80211_NODE_STAT_ADD(ni, rx_bytes, m->m_pkthdr.len);
+
+ ieee80211_deliver_data(ic, ni, m);
+
+ *mp = NULL;
+ return 0;
+
+err:
+ ifp->if_ierrors++;
+out:
+ *mp = m;
+ return -1;
+}
+
+/*
+ * Input code for a MANAGEMENT frame.
+ */
+static int
+ieee80211_input_management(struct ieee80211com *ic, struct mbuf **mp,
+ struct ieee80211_node *ni, int rssi, u_int32_t rstamp)
+{
+ IEEE80211_DEBUGVAR(char ebuf[3 * ETHER_ADDR_LEN]);
+ struct ifnet *ifp = ic->ic_ifp;
+ struct ieee80211_key *key;
+ struct ieee80211_frame *wh;
+ u_int8_t dir, subtype;
+ struct mbuf *m = *mp;
+ int hdrspace;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
+ subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+
+ IEEE80211_NODE_STAT(ni, rx_mgmt);
+ if (dir != IEEE80211_FC1_DIR_NODS) {
+ IEEE80211_DISCARD(ic, IEEE80211_MSG_INPUT,
+ wh, "data", "%s", "unknown dir 0x%x", dir);
+ ic->ic_stats.is_rx_wrongdir++;
+ goto err;
+ }
+ if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
+ IEEE80211_DISCARD_MAC(ic, IEEE80211_MSG_ANY,
+ ni->ni_macaddr, "mgt", "too short: len %u",
+ 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(ic->ic_ifp, "received %s from %s rssi %d\n",
+ ieee80211_mgt_subtype_name[subtype >>
+ IEEE80211_FC0_SUBTYPE_SHIFT],
+ ether_snprintf(ebuf, sizeof(ebuf), wh->i_addr2),
+ rssi);
+ }
+#endif
+
Home |
Main Index |
Thread Index |
Old Index