Date: Thu, 20 Nov 2003 09:02:02 -0800 (PST) From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 42808 for review Message-ID: <200311201702.hAKH2247081905@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=42808 Change 42808 by sam@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) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200311201702.hAKH2247081905>