PERFORCE change 42808 for review
Sam Leffler
sam at FreeBSD.org
Thu Nov 20 09:02:05 PST 2003
http://perforce.freebsd.org/chv.cgi?CH=42808
Change 42808 by sam at sam_ebb on 2003/11/20 09:01:40
First pass at integrating netbsd work:
o os portability changes
o pspoll support
o shared key authentication support
o manage assigned aid's to avoid duplicate assignment
o support for FH phy's
o change IFM_* constants from values to bitmasks
o minor (but ABI-changing) mods to radiotap definitions
Still need to go over changes in populating the node table
that are supposed to fix adhoc mode.
Affected files ...
.. //depot/projects/netperf/sys/net80211/ieee80211.c#6 edit
.. //depot/projects/netperf/sys/net80211/ieee80211.h#3 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_compat.c#1 add
.. //depot/projects/netperf/sys/net80211/ieee80211_compat.h#1 add
.. //depot/projects/netperf/sys/net80211/ieee80211_input.c#14 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_node.c#16 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_node.h#11 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_output.c#11 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_proto.c#8 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_radiotap.h#4 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_var.h#10 edit
Differences ...
==== //depot/projects/netperf/sys/net80211/ieee80211.c#6 (text+ko) ====
@@ -84,7 +84,8 @@
"11a", /* IEEE80211_MODE_11A */
"11b", /* IEEE80211_MODE_11B */
"11g", /* IEEE80211_MODE_11G */
- "turbo", /* IEEE80211_MODE_TURBO */
+ "FH", /* IEEE80211_MODE_FH */
+ "turbo", /* IEEE80211_MODE_TURBO */
};
void
@@ -129,6 +130,8 @@
ic->ic_modecaps |= 1<<IEEE80211_MODE_11B;
if (IEEE80211_IS_CHAN_PUREG(c))
ic->ic_modecaps |= 1<<IEEE80211_MODE_11G;
+ if (IEEE80211_IS_CHAN_FHSS(c))
+ ic->ic_modecaps |= 1<<IEEE80211_MODE_FH;
if (IEEE80211_IS_CHAN_T(c))
ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO;
}
@@ -266,10 +269,11 @@
for (mode = IEEE80211_MODE_AUTO; mode < IEEE80211_MODE_MAX; mode++) {
static const u_int mopts[] = {
IFM_AUTO,
- IFM_MAKEMODE(IFM_IEEE80211_11A),
- IFM_MAKEMODE(IFM_IEEE80211_11B),
- IFM_MAKEMODE(IFM_IEEE80211_11G),
- IFM_MAKEMODE(IFM_IEEE80211_11A) | IFM_IEEE80211_TURBO,
+ IFM_IEEE80211_11A,
+ IFM_IEEE80211_11B,
+ IFM_IEEE80211_11G,
+ IFM_IEEE80211_FH,
+ IFM_IEEE80211_11A | IFM_IEEE80211_TURBO,
};
if ((ic->ic_modecaps & (1<<mode)) == 0)
continue;
@@ -343,6 +347,9 @@
if (maxrate)
ifp->if_baudrate = IF_Mbps(maxrate);
+
+ if (ic->ic_max_aid == 0)
+ ic->ic_max_aid = IEEE80211_MAX_AID;
#undef ADD
}
@@ -385,6 +392,9 @@
case IFM_IEEE80211_11G:
newphymode = IEEE80211_MODE_11G;
break;
+ case IFM_IEEE80211_FH:
+ newphymode = IEEE80211_MODE_FH;
+ break;
case IFM_AUTO:
newphymode = IEEE80211_MODE_AUTO;
break;
@@ -555,17 +565,19 @@
}
switch (ic->ic_curmode) {
case IEEE80211_MODE_11A:
- imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A);
+ imr->ifm_active |= IFM_IEEE80211_11A;
break;
case IEEE80211_MODE_11B:
- imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11B);
+ imr->ifm_active |= IFM_IEEE80211_11B;
break;
case IEEE80211_MODE_11G:
- imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11G);
+ imr->ifm_active |= IFM_IEEE80211_11G;
+ break;
+ case IEEE80211_MODE_FH:
+ imr->ifm_active |= IFM_IEEE80211_FH;
break;
case IEEE80211_MODE_TURBO:
- imr->ifm_active |= IFM_MAKEMODE(IFM_IEEE80211_11A)
- | IFM_IEEE80211_TURBO;
+ imr->ifm_active |= IFM_IEEE80211_11A | IFM_IEEE80211_TURBO;
break;
}
}
@@ -598,6 +610,7 @@
{ 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */
{ 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11B */
{ 7, { 2, 4, 11, 22, 12, 24, 48 } },/* IEEE80211_MODE_11G */
+ { 0 }, /* IEEE80211_MODE_FH */
{ 0 }, /* IEEE80211_MODE_TURBO */
};
int i, j;
@@ -627,6 +640,7 @@
IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */
IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */
IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */
+ IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */
IEEE80211_CHAN_T, /* IEEE80211_MODE_TURBO */
};
struct ieee80211_channel *c;
@@ -691,6 +705,11 @@
ic->ic_ibss_chan = &ic->ic_channels[i];
break;
}
+ KASSERT(ic->ic_ibss_chan != NULL &&
+ isset(ic->ic_chan_active,
+ ieee80211_chan2ieee(ic, ic->ic_ibss_chan)),
+ ("Bad IBSS channel %u",
+ ieee80211_chan2ieee(ic, ic->ic_ibss_chan)));
}
/*
@@ -719,6 +738,8 @@
* Return the phy mode for with the specified channel so the
* caller can select a rate set. This is problematic and the
* work here assumes how things work elsewhere in this code.
+ *
+ * XXX never returns turbo modes -dcy
*/
enum ieee80211_phymode
ieee80211_chan2mode(struct ieee80211com *ic, struct ieee80211_channel *chan)
@@ -736,6 +757,8 @@
*/
if (IEEE80211_IS_CHAN_5GHZ(chan))
return IEEE80211_MODE_11A;
+ else if (IEEE80211_IS_CHAN_FHSS(chan))
+ return IEEE80211_MODE_FH;
else if (chan->ic_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN))
return IEEE80211_MODE_11G;
else
@@ -754,31 +777,31 @@
u_int m; /* rate + mode */
u_int r; /* if_media rate */
} rates[] = {
- { 2 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS1 },
- { 4 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS2 },
- { 11 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS5 },
- { 22 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS11 },
- { 44 | IFM_MAKEMODE(IFM_IEEE80211_11B), IFM_IEEE80211_DS22 },
- { 12 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM6 },
- { 18 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM9 },
- { 24 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM12 },
- { 36 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM18 },
- { 48 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM24 },
- { 72 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM36 },
- { 96 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM48 },
- { 108 | IFM_MAKEMODE(IFM_IEEE80211_11A), IFM_IEEE80211_OFDM54 },
- { 2 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS1 },
- { 4 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS2 },
- { 11 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS5 },
- { 22 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_DS11 },
- { 12 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM6 },
- { 18 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM9 },
- { 24 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM12 },
- { 36 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM18 },
- { 48 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM24 },
- { 72 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM36 },
- { 96 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM48 },
- { 108 | IFM_MAKEMODE(IFM_IEEE80211_11G), IFM_IEEE80211_OFDM54 },
+ { 2 | IFM_IEEE80211_11B, IFM_IEEE80211_DS1 },
+ { 4 | IFM_IEEE80211_11B, IFM_IEEE80211_DS2 },
+ { 11 | IFM_IEEE80211_11B, IFM_IEEE80211_DS5 },
+ { 22 | IFM_IEEE80211_11B, IFM_IEEE80211_DS11 },
+ { 44 | IFM_IEEE80211_11B, IFM_IEEE80211_DS22 },
+ { 12 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM6 },
+ { 18 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM9 },
+ { 24 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM12 },
+ { 36 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM18 },
+ { 48 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM24 },
+ { 72 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM36 },
+ { 96 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM48 },
+ { 108 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM54 },
+ { 2 | IFM_IEEE80211_11G, IFM_IEEE80211_DS1 },
+ { 4 | IFM_IEEE80211_11G, IFM_IEEE80211_DS2 },
+ { 11 | IFM_IEEE80211_11G, IFM_IEEE80211_DS5 },
+ { 22 | IFM_IEEE80211_11G, IFM_IEEE80211_DS11 },
+ { 12 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM6 },
+ { 18 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM9 },
+ { 24 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM12 },
+ { 36 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM18 },
+ { 48 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM24 },
+ { 72 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM36 },
+ { 96 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM48 },
+ { 108 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM54 },
/* NB: OFDM72 doesn't realy exist so we don't handle it */
};
u_int mask, i;
@@ -787,10 +810,13 @@
switch (mode) {
case IEEE80211_MODE_11A:
case IEEE80211_MODE_TURBO:
- mask |= IFM_MAKEMODE(IFM_IEEE80211_11A);
+ mask |= IFM_IEEE80211_11A;
break;
case IEEE80211_MODE_11B:
- mask |= IFM_MAKEMODE(IFM_IEEE80211_11B);
+ mask |= IFM_IEEE80211_11B;
+ break;
+ case IEEE80211_MODE_FH:
+ mask |= IFM_IEEE80211_FH;
break;
case IEEE80211_MODE_AUTO:
/* NB: ic may be NULL for some drivers */
@@ -805,7 +831,7 @@
/* NB: hack, 11g matches both 11b+11a rates */
/* fall thru... */
case IEEE80211_MODE_11G:
- mask |= IFM_MAKEMODE(IFM_IEEE80211_11G);
+ mask |= IFM_IEEE80211_11G;
break;
}
for (i = 0; i < N(rates); i++)
@@ -845,6 +871,7 @@
#undef N
}
+#ifdef __FreeBSD__
/*
* Module glue.
*
@@ -873,3 +900,4 @@
DECLARE_MODULE(wlan, ieee80211_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
MODULE_VERSION(wlan, 1);
MODULE_DEPEND(wlan, rc4, 1, 1, 1);
+#endif /* __FreeBSD__ */
==== //depot/projects/netperf/sys/net80211/ieee80211.h#3 (text+ko) ====
@@ -51,6 +51,9 @@
u_int16_t i_crc;
} __attribute__((__packed__));
+#define IEEE80211_PLCP_SFD 0xF3A0
+#define IEEE80211_PLCP_SERVICE 0x00
+
/*
* generic definitions for IEEE 802.11 frames
*/
@@ -272,6 +275,8 @@
IEEE80211_ELEMID_XRATES = 50,
};
+#define IEEE80211_CHALLENGE_LEN 128
+
#define IEEE80211_RATE_BASIC 0x80
#define IEEE80211_RATE_VAL 0x7f
@@ -366,6 +371,15 @@
#define IEEE80211_MIN_LEN \
(sizeof(struct ieee80211_frame_min) + IEEE80211_CRC_LEN)
+#define IEEE80211_MAX_AID 2007
+
+#define IEEE80211_AID_SET(b, w) \
+ ((w)[((b) & ~0xc000) / 32] |= (1 << (((b) & ~0xc000) % 32)))
+#define IEEE80211_AID_CLR(b, w) \
+ ((w)[((b) & ~0xc000) / 32] &= ~(1 << (((b) & ~0xc000) % 32)))
+#define IEEE80211_AID_ISSET(b, w) \
+ ((w)[((b) & ~0xc000) / 32] & (1 << (((b) & ~0xc000) % 32)))
+
/*
* RTS frame length parameters. The default is specified in
* the 802.11 spec. The max may be wrong for jumbo frames.
==== //depot/projects/netperf/sys/net80211/ieee80211_input.c#14 (text+ko) ====
@@ -68,6 +68,8 @@
static struct mbuf *ieee80211_reass(struct ieee80211com *,
struct ieee80211_node *, struct mbuf *);
+static void ieee80211_recv_pspoll(struct ieee80211com *,
+ struct mbuf *, int, u_int32_t);
/*
* Process a received frame. The node associated with the sender
@@ -138,10 +140,10 @@
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)));
+ /* not interested in */
ic->ic_stats.is_rx_wrongbss++;
goto out;
}
@@ -184,6 +186,35 @@
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)
+ if_printf(ifp, "power save mode on for %s\n",
+ 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)
+ if_printf(ifp, "power save mode off for %s\n",
+ ether_sprintf(wh->i_addr2));
+ for (;;) {
+ struct mbuf *m;
+ IF_DEQUEUE(&ni->ni_savedq, m);
+ if (!m)
+ break;
+ IF_ENQUEUE(&ic->ic_pwrsaveq, m);
+ (*ifp->if_start)(ifp);
+ }
+ }
+
switch (type) {
case IEEE80211_FC0_TYPE_DATA:
switch (ic->ic_opmode) {
@@ -307,8 +338,15 @@
ifp->if_obytes += len;
}
}
- if (m != NULL)
+ if (m != NULL) {
+ /*
+ * 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);
(*ifp->if_input)(ifp, m);
+ }
return;
case IEEE80211_FC0_TYPE_MGT:
@@ -374,6 +412,17 @@
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) {
+ /* 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));
@@ -620,6 +669,233 @@
} \
} while (0)
+static void
+ieee80211_auth_open(struct ieee80211com *ic, struct ieee80211_frame *wh,
+ struct ieee80211_node *ni, int rssi, u_int32_t rstamp, u_int16_t seq,
+ u_int16_t status)
+{
+ struct ifnet *ifp = &ic->ic_if;
+ int allocbs;
+
+ switch (ic->ic_opmode) {
+ case IEEE80211_M_IBSS:
+ if (ic->ic_state != IEEE80211_S_RUN ||
+ seq != IEEE80211_AUTH_OPEN_REQUEST) {
+ ic->ic_stats.is_rx_bad_auth++;
+ return;
+ }
+ ieee80211_new_state(ic, IEEE80211_S_AUTH,
+ wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
+ break;
+
+ case IEEE80211_M_AHDEMO:
+ /* should not come here */
+ break;
+
+ case IEEE80211_M_HOSTAP:
+ if (ic->ic_state != IEEE80211_S_RUN ||
+ seq != IEEE80211_AUTH_OPEN_REQUEST) {
+ ic->ic_stats.is_rx_bad_auth++;
+ return;
+ }
+ if (ni == ic->ic_bss) {
+ ni = ieee80211_alloc_node(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;
+ IEEE80211_SEND_MGMT(ic, ni,
+ IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
+ if (ifp->if_flags & IFF_DEBUG)
+ if_printf(ifp, "station %s %s authenticated\n",
+ ether_sprintf(ni->ni_macaddr),
+ (allocbs ? "newly" : "already"));
+ break;
+
+ case IEEE80211_M_STA:
+ if (ic->ic_state != IEEE80211_S_AUTH ||
+ seq != IEEE80211_AUTH_OPEN_RESPONSE) {
+ ic->ic_stats.is_rx_bad_auth++;
+ return;
+ }
+ if (status != 0) {
+ if_printf(&ic->ic_if,
+ "authentication failed (reason %d) for %s\n",
+ status,
+ ether_sprintf(wh->i_addr3));
+ if (ni != ic->ic_bss)
+ ni->ni_fails++;
+ ic->ic_stats.is_rx_auth_fail++;
+ return;
+ }
+ ieee80211_new_state(ic, IEEE80211_S_ASSOC,
+ wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
+ break;
+ case IEEE80211_M_MONITOR:
+ break;
+ }
+}
+
+/* TBD send appropriate responses on error? */
+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)
+{
+ struct ifnet *ifp = &ic->ic_if;
+ u_int8_t *challenge = NULL;
+ int allocbs, i;
+
+ if ((ic->ic_flags & IEEE80211_F_WEPON) == 0) {
+ IEEE80211_DPRINTF(("%s: WEP is off\n", __func__));
+ return;
+ }
+
+ if (frm + 1 < efrm) {
+ if ((frm[1] + 2) > (efrm - frm)) {
+ IEEE80211_DPRINTF(("elt %d %d bytes too long\n",
+ frm[0], (frm[1] + 2) - (efrm - frm)));
+ return;
+ }
+ if (*frm == IEEE80211_ELEMID_CHALLENGE)
+ challenge = frm;
+ frm += frm[1] + 2;
+ }
+ switch (seq) {
+ case IEEE80211_AUTH_SHARED_CHALLENGE:
+ case IEEE80211_AUTH_SHARED_RESPONSE:
+ if (challenge == NULL) {
+ IEEE80211_DPRINTF(("%s: no challenge sent\n",
+ __func__));
+ return;
+ }
+ if (challenge[1] != IEEE80211_CHALLENGE_LEN) {
+ IEEE80211_DPRINTF(("%s: bad challenge len %d\n",
+ __func__, challenge[1]));
+ return;
+ }
+ default:
+ break;
+ }
+ switch (ic->ic_opmode) {
+ case IEEE80211_M_MONITOR:
+ case IEEE80211_M_AHDEMO:
+ case IEEE80211_M_IBSS:
+ IEEE80211_DPRINTF(("%s: unexpected operating mode\n",
+ __func__));
+ return;
+ case IEEE80211_M_HOSTAP:
+ if (ic->ic_state != IEEE80211_S_RUN) {
+ IEEE80211_DPRINTF(("%s: not running\n", __func__));
+ return;
+ }
+ switch (seq) {
+ case IEEE80211_AUTH_SHARED_REQUEST:
+ if (ni == ic->ic_bss) {
+ ni = ieee80211_alloc_node(ic, wh->i_addr2);
+ if (ni == NULL) {
+ ic->ic_stats.is_rx_nodealloc++;
+ 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)
+ ni->ni_challenge = (u_int32_t*)malloc(
+ IEEE80211_CHALLENGE_LEN, M_DEVBUF,
+ M_NOWAIT);
+ if (ni->ni_challenge == NULL) {
+ IEEE80211_DPRINTF(("challenge alloc failed\n"));
+ return;
+ }
+ for (i = IEEE80211_CHALLENGE_LEN / sizeof(u_int32_t);
+ --i >= 0; )
+ ni->ni_challenge[i] = arc4random();
+ break;
+ case IEEE80211_AUTH_SHARED_RESPONSE:
+ if (ni == ic->ic_bss) {
+ IEEE80211_DPRINTF(("%s: unknown STA\n",
+ __func__));
+ return;
+ }
+ allocbs = 1;
+ if (ni->ni_challenge == NULL) {
+ IEEE80211_DPRINTF((
+ "%s: no challenge recorded\n", __func__));
+ return;
+ }
+ if (memcmp(ni->ni_challenge, &challenge[2],
+ challenge[1]) != 0) {
+ IEEE80211_DPRINTF(("%s: challenge mismatch\n",
+ __func__));
+ return;
+ }
+ break;
+ default:
+ IEEE80211_DPRINTF(("%s: bad seq %d from %s\n",
+ __func__, seq, ether_sprintf(wh->i_addr2)));
+ return;
+ }
+ IEEE80211_SEND_MGMT(ic, ni,
+ IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
+ if (ifp->if_flags & IFF_DEBUG)
+ if_printf(ifp, "station %s %s authenticated\n",
+ ether_sprintf(ni->ni_macaddr),
+ (allocbs ? "newly" : "already"));
+ break;
+
+ case IEEE80211_M_STA:
+ if (ic->ic_state != IEEE80211_S_AUTH)
+ return;
+ switch (seq) {
+ case IEEE80211_AUTH_SHARED_PASS:
+ if (ni->ni_challenge != NULL) {
+ free(ni->ni_challenge, M_DEVBUF);
+ ni->ni_challenge = NULL;
+ }
+ if (status != 0) {
+ if_printf(&ic->ic_if,
+ "%s: auth failed (reason %d) for %s\n",
+ __func__, status,
+ ether_sprintf(wh->i_addr3));
+ if (ni != ic->ic_bss)
+ ni->ni_fails++;
+ ic->ic_stats.is_rx_auth_fail++;
+ return;
+ }
+ ieee80211_new_state(ic, IEEE80211_S_ASSOC,
+ wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
+ break;
+ case IEEE80211_AUTH_SHARED_CHALLENGE:
+ if (ni->ni_challenge == NULL)
+ ni->ni_challenge = (u_int32_t*)malloc(
+ challenge[1], M_DEVBUF, M_NOWAIT);
+ if (ni->ni_challenge == NULL) {
+ IEEE80211_DPRINTF((
+ "%s: challenge alloc failed\n", __func__));
+ return;
+ }
+ memcpy(ni->ni_challenge, &challenge[2], challenge[1]);
+ break;
+ default:
+ IEEE80211_DPRINTF(("%s: bad seq %d from %s\n",
+ __func__, seq, ether_sprintf(wh->i_addr2)));
+ return;
+ }
+ break;
+ }
+}
+
void
ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
struct ieee80211_node *ni,
@@ -904,86 +1180,19 @@
algo = le16toh(*(u_int16_t *)frm);
seq = le16toh(*(u_int16_t *)(frm + 2));
status = le16toh(*(u_int16_t *)(frm + 4));
- if (algo != IEEE80211_AUTH_ALG_OPEN) {
- /* TODO: shared key auth */
+
+ if (algo == IEEE80211_AUTH_ALG_SHARED)
+ ieee80211_auth_shared(ic, wh, frm + 6, efrm, ni, rssi,
+ rstamp, seq, status);
+ else if (algo == IEEE80211_AUTH_ALG_OPEN)
+ ieee80211_auth_open(ic, wh, ni, rssi, rstamp, seq,
+ status);
+ else {
IEEE80211_DPRINTF(("%s: unsupported auth %d from %s\n",
__func__, algo, ether_sprintf(wh->i_addr2)));
ic->ic_stats.is_rx_auth_unsupported++;
return;
- }
- switch (ic->ic_opmode) {
- case IEEE80211_M_IBSS:
- if (ic->ic_state != IEEE80211_S_RUN || seq != 1) {
- IEEE80211_DPRINTF(("%s: discard auth from %s; "
- "state %u, seq %u\n", __func__,
- ether_sprintf(wh->i_addr2),
- ic->ic_state, seq));
- ic->ic_stats.is_rx_bad_auth++;
- break;
- }
- ieee80211_new_state(ic, IEEE80211_S_AUTH,
- wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
- break;
-
- case IEEE80211_M_AHDEMO:
- /* should not come here */
- break;
-
- case IEEE80211_M_HOSTAP:
- if (ic->ic_state != IEEE80211_S_RUN || seq != 1) {
- IEEE80211_DPRINTF(("%s: discard auth from %s; "
- "state %u, seq %u\n", __func__,
- ether_sprintf(wh->i_addr2),
- ic->ic_state, seq));
- ic->ic_stats.is_rx_bad_auth++;
- break;
- }
- if (ni == ic->ic_bss) {
- ni = ieee80211_alloc_node(ic, wh->i_addr2);
- if (ni == NULL) {
- ic->ic_stats.is_rx_nodealloc++;
- 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;
- IEEE80211_SEND_MGMT(ic, ni,
- IEEE80211_FC0_SUBTYPE_AUTH, 2);
- if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "station %s %s authenticated\n",
- (allocbs ? "newly" : "already"),
- ether_sprintf(ni->ni_macaddr));
- break;
-
- case IEEE80211_M_STA:
- if (ic->ic_state != IEEE80211_S_AUTH || seq != 2) {
- IEEE80211_DPRINTF(("%s: discard auth from %s; "
- "state %u, seq %u\n", __func__,
- ether_sprintf(wh->i_addr2),
- ic->ic_state, seq));
- ic->ic_stats.is_rx_bad_auth++;
- break;
- }
- if (status != 0) {
- if_printf(&ic->ic_if,
- "authentication failed (reason %d) for %s\n",
- status,
- ether_sprintf(wh->i_addr3));
- if (ni != ic->ic_bss)
- ni->ni_fails++;
- ic->ic_stats.is_rx_auth_fail++;
- return;
- }
- ieee80211_new_state(ic, IEEE80211_S_ASSOC,
- wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
- break;
- case IEEE80211_M_MONITOR:
- break;
- }
+ }
break;
}
@@ -1064,6 +1273,11 @@
ic->ic_stats.is_rx_assoc_notauth++;
return;
}
+ /* discard challenge after association */
+ if (ni->ni_challenge != NULL) {
+ free(ni->ni_challenge, M_DEVBUF);
+ ni->ni_challenge = NULL;
+ }
/* XXX per-node cipher suite */
/* XXX some stations use the privacy bit for handling APs
that suport both encrypted and unencrypted traffic */
@@ -1073,6 +1287,7 @@
IEEE80211_CAPINFO_PRIVACY : 0)) {
IEEE80211_DPRINTF(("%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);
@@ -1099,19 +1314,39 @@
ni->ni_fhdwell = ic->ic_bss->ni_fhdwell;
ni->ni_fhindex = ic->ic_bss->ni_fhindex;
if (ni->ni_associd == 0) {
- /* XXX handle rollover at 2007 */
- /* XXX guarantee uniqueness */
- ni->ni_associd = 0xc000 | ic->ic_bss->ni_associd++;
- newassoc = 1;
+ u_int16_t aid;
+
+ /*
+ * It would be clever to search the bitmap
+ * more efficiently, but this will do for now.
+ */
+ for (aid = 1; aid < ic->ic_max_aid; aid++) {
+ if (!IEEE80211_AID_ISSET(aid,
+ ic->ic_aid_bitmap))
+ break;
+ }
+
+ if (ic->ic_bss->ni_associd >= ic->ic_max_aid) {
+ IEEE80211_SEND_MGMT(ic, ni, resp,
+ IEEE80211_REASON_ASSOC_TOOMANY);
+ /* XXX statistic */
+ return;
+ } else {
+ ni->ni_associd = aid | 0xc000;
+ IEEE80211_AID_SET(ni->ni_associd,
+ ic->ic_aid_bitmap);
+ newassoc = 1;
+ }
} else
newassoc = 0;
/* XXX for 11g must turn off short slot time if long
slot time sta associates */
IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
if (ifp->if_flags & IFF_DEBUG)
- if_printf(ifp, "station %s %s associated\n",
+ if_printf(ifp, "station %s %s associated at aid %d\n",
(newassoc ? "newly" : "already"),
- ether_sprintf(ni->ni_macaddr));
+ ether_sprintf(ni->ni_macaddr),
+ ni->ni_associd & ~0xc000);
/* give driver a chance to setup state like ni_txrate */
if (ic->ic_newassoc)
(*ic->ic_newassoc)(ic, ni, newassoc);
@@ -1142,8 +1377,10 @@
status = le16toh(*(u_int16_t *)frm);
frm += 2;
if (status != 0) {
- if_printf(ifp, "association failed (reason %d) for %s\n",
- status, ether_sprintf(wh->i_addr3));
+ if (ifp->if_flags & IFF_DEBUG)
+ if_printf(ifp,
+ "association failed (reason %d) for %s\n",
+ status, ether_sprintf(wh->i_addr3));
if (ni != ic->ic_bss)
ni->ni_fails++;
ic->ic_stats.is_rx_auth_fail++;
@@ -1225,6 +1462,8 @@
if_printf(ifp, "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;
/* XXX node reclaimed how? */
}
@@ -1242,5 +1481,76 @@
}
#undef ISPROBE
}
+
+static void
+ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m0, int rssi,
+ u_int32_t rstamp)
+{
+ struct ifnet *ifp = &ic->ic_if;
+ struct ieee80211_frame *wh;
+ struct ieee80211_node *ni;
+ 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 (ifp->if_flags & IFF_DEBUG)
+ if_printf(ifp, "unknown station %s sent "
+ "power save poll\n",
+ ether_sprintf(wh->i_addr2));
+ return;
+ }
+
+ memcpy(&aid, wh->i_dur, sizeof(wh->i_dur));
+ if ((aid & 0xc000) != 0xc000) {
+ if (ifp->if_flags & IFF_DEBUG)
+ if_printf(ifp, "station %s sent bogus aid %x\n",
+ ether_sprintf(wh->i_addr2), aid);
+ return;
+ }
+
+ if (aid != ni->ni_associd) {
+ if (ifp->if_flags & IFF_DEBUG)
+ if_printf(ifp, "station %s aid %x doesn't match pspoll "
+ "aid %x\n",
+ ether_sprintf(wh->i_addr2), ni->ni_associd, aid);
+ return;
+ }
+
+ /* Okay, take the first queued packet and put it out... */
+
+ IF_DEQUEUE(&ni->ni_savedq, m);
+ if (m == NULL) {
+ if (ifp->if_flags & IFF_DEBUG)
+ if_printf(ifp, "station %s sent pspoll, "
+ "but no packets are saved\n",
+ ether_sprintf(wh->i_addr2));
+ return;
+ }
+ wh = mtod(m, struct ieee80211_frame *);
+
+ /*
+ * If this is the last packet, turn off the TIM fields.
+ * If there are more packets, set the more packets bit.
+ */
+
+ if (_IF_QLEN(&ni->ni_savedq) == 0) {
+ if (ic->ic_set_tim)
+ ic->ic_set_tim(ic, ni->ni_associd, 0);
+ } else {
+ wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
+ }
+
+ if (ifp->if_flags & IFF_DEBUG)
+ if_printf(ifp, "enqueued power saving packet for station %s\n",
+ ether_sprintf(ni->ni_macaddr));
+
+ IF_ENQUEUE(&ic->ic_pwrsaveq, m);
+ (*ifp->if_start)(ifp);
+}
#undef IEEE80211_VERIFY_LENGTH
#undef IEEE80211_VERIFY_ELEMENT
==== //depot/projects/netperf/sys/net80211/ieee80211_node.c#16 (text+ko) ====
@@ -241,6 +241,68 @@
ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
}
+static int
+ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
+{
+ struct ifnet *ifp = &ic->ic_if;
+ u_int8_t rate;
+ int fail;
+
+ fail = 0;
+ if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
+ fail |= 0x01;
+ if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
+ ni->ni_chan != ic->ic_des_chan)
+ fail |= 0x01;
+ if (ic->ic_opmode == IEEE80211_M_IBSS) {
+ if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
+ fail |= 0x02;
+ } else {
+ if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
+ fail |= 0x02;
+ }
+ if (ic->ic_flags & IEEE80211_F_WEPON) {
+ if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
+ fail |= 0x04;
+ } else {
+ if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
+ fail |= 0x04;
+ }
+ rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO);
+ if (rate & IEEE80211_RATE_BASIC)
+ fail |= 0x08;
+ if (ic->ic_des_esslen != 0 &&
+ (ni->ni_esslen != ic->ic_des_esslen ||
+ memcmp(ni->ni_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0))
+ fail |= 0x10;
+ if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
+ !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
+ fail |= 0x20;
+ if (ifp->if_flags & IFF_DEBUG) {
+ printf(" %c %s", fail ? '-' : '+',
+ ether_sprintf(ni->ni_macaddr));
+ printf(" %s%c", ether_sprintf(ni->ni_bssid),
+ fail & 0x20 ? '!' : ' ');
+ printf(" %3d%c", ieee80211_chan2ieee(ic, ni->ni_chan),
+ fail & 0x01 ? '!' : ' ');
+ printf(" %+4d", ni->ni_rssi);
+ printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
+ fail & 0x08 ? '!' : ' ');
+ printf(" %4s%c",
+ (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
+ (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
+ "????",
+ fail & 0x02 ? '!' : ' ');
+ printf(" %3s%c ",
+ (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
+ "wep" : "no",
+ fail & 0x04 ? '!' : ' ');
+ ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
+ printf("%s\n", fail & 0x10 ? "!" : "");
+ }
+ return fail;
+}
+
/*
* Complete a scan of potential channels.
*/
@@ -249,7 +311,6 @@
{
struct ieee80211com *ic = (void *)ifp;
struct ieee80211_node *ni, *nextbs, *selbs;
- u_int8_t rate;
int i, fail;
ic->ic_flags &= ~IEEE80211_F_ASCAN;
@@ -315,59 +376,7 @@
ieee80211_free_node(ic, ni);
continue;
}
- fail = 0;
- if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
- fail |= 0x01;
- if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
- ni->ni_chan != ic->ic_des_chan)
- fail |= 0x01;
- if (ic->ic_opmode == IEEE80211_M_IBSS) {
- if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
- fail |= 0x02;
- } else {
- if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
- fail |= 0x02;
- }
- if (ic->ic_flags & IEEE80211_F_WEPON) {
- if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
- fail |= 0x04;
- } else {
- if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
- fail |= 0x04;
- }
- rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO);
- if (rate & IEEE80211_RATE_BASIC)
- fail |= 0x08;
- if (ic->ic_des_esslen != 0 &&
- (ni->ni_esslen != ic->ic_des_esslen ||
- memcmp(ni->ni_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0))
- fail |= 0x10;
- if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
- !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
- fail |= 0x20;
- if (ifp->if_flags & IFF_DEBUG) {
- printf(" %c %s", fail ? '-' : '+',
- ether_sprintf(ni->ni_macaddr));
- printf(" %s%c", ether_sprintf(ni->ni_bssid),
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list