diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ath/if_ath.c | 10 | ||||
-rw-r--r-- | sys/net80211/ieee80211_crypto_ccmp.c | 9 | ||||
-rw-r--r-- | sys/net80211/ieee80211_crypto_tkip.c | 9 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ioctl.c | 166 |
4 files changed, 130 insertions, 64 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index d1ddb2d..5847489 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -3654,8 +3654,14 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, case IEEE80211_FC0_SUBTYPE_PROBE_RESP: if (vap->iv_opmode == IEEE80211_M_IBSS && vap->iv_state == IEEE80211_S_RUN) { - uint32_t rstamp = sc->sc_lastrs->rs_tstamp; - u_int64_t tsf = ath_extend_tsf(rstamp, + uint32_t rstamp; + uint64_t tsf; + + if (sc->sc_lastrs == NULL) + break; + + rstamp = sc->sc_lastrs->rs_tstamp; + tsf = ath_extend_tsf(rstamp, ath_hal_gettsf64(sc->sc_ah)); /* * Handle ibss merge as needed; check the tsf on the diff --git a/sys/net80211/ieee80211_crypto_ccmp.c b/sys/net80211/ieee80211_crypto_ccmp.c index 79df266..9ad2409 100644 --- a/sys/net80211/ieee80211_crypto_ccmp.c +++ b/sys/net80211/ieee80211_crypto_ccmp.c @@ -226,7 +226,14 @@ ccmp_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) } tid = ieee80211_gettid(wh); pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]); - if (pn <= k->wk_keyrsc[tid]) { + /* + * NB: Multiple stations are using the same key in + * IBSS mode, there is currently no way to sync keyrsc + * counters without discarding too many frames. + */ + if (vap->iv_opmode != IEEE80211_M_IBSS && + vap->iv_opmode != IEEE80211_M_AHDEMO && + pn <= k->wk_keyrsc[tid]) { /* * Replay violation. */ diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c index 6e1fda1..0f17c17 100644 --- a/sys/net80211/ieee80211_crypto_tkip.c +++ b/sys/net80211/ieee80211_crypto_tkip.c @@ -281,7 +281,14 @@ tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) tid = ieee80211_gettid(wh); ctx->rx_rsc = READ_6(ivp[2], ivp[0], ivp[4], ivp[5], ivp[6], ivp[7]); - if (ctx->rx_rsc <= k->wk_keyrsc[tid]) { + /* + * NB: Multiple stations are using the same key in + * IBSS mode, there is currently no way to sync keyrsc + * counters without discarding too many frames. + */ + if (vap->iv_opmode != IEEE80211_M_IBSS && + vap->iv_opmode != IEEE80211_M_AHDEMO && + ctx->rx_rsc <= k->wk_keyrsc[tid]) { /* * Replay violation; notify upper layer. */ diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 237e556..3c913cc 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -70,6 +70,8 @@ __FBSDID("$FreeBSD$"); static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; static struct ieee80211_channel *findchannel(struct ieee80211com *, int ieee, int mode); +static int ieee80211_scanreq(struct ieee80211vap *, + struct ieee80211_scan_req *); static __noinline int ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq) @@ -1471,14 +1473,15 @@ mlmelookup(void *arg, const struct ieee80211_scan_entry *se) } static __noinline int -setmlme_assoc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], - int ssid_len, const uint8_t ssid[IEEE80211_NWID_LEN]) +setmlme_assoc_sta(struct ieee80211vap *vap, + const uint8_t mac[IEEE80211_ADDR_LEN], int ssid_len, + const uint8_t ssid[IEEE80211_NWID_LEN]) { struct scanlookup lookup; - /* XXX ibss/ahdemo */ - if (vap->iv_opmode != IEEE80211_M_STA) - return EINVAL; + KASSERT(vap->iv_opmode == IEEE80211_M_STA, + ("expected opmode STA not %s", + ieee80211_opmode_name[vap->iv_opmode])); /* NB: this is racey if roaming is !manual */ lookup.se = NULL; @@ -1495,6 +1498,36 @@ setmlme_assoc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], } static __noinline int +setmlme_assoc_adhoc(struct ieee80211vap *vap, + const uint8_t mac[IEEE80211_ADDR_LEN], int ssid_len, + const uint8_t ssid[IEEE80211_NWID_LEN]) +{ + struct ieee80211_scan_req sr; + + KASSERT(vap->iv_opmode == IEEE80211_M_IBSS || + vap->iv_opmode == IEEE80211_M_AHDEMO, + ("expected opmode IBSS or AHDEMO not %s", + ieee80211_opmode_name[vap->iv_opmode])); + + if (ssid_len == 0) + return EINVAL; + + /* NB: IEEE80211_IOC_SSID call missing for ap_scan=2. */ + memset(vap->iv_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN); + vap->iv_des_ssid[0].len = ssid_len; + memcpy(vap->iv_des_ssid[0].ssid, ssid, ssid_len); + vap->iv_des_nssid = 1; + + sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE; + sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER; + memcpy(sr.sr_ssid[0].ssid, ssid, ssid_len); + sr.sr_ssid[0].len = ssid_len; + sr.sr_nssid = 1; + + return ieee80211_scanreq(vap, &sr); +} + +static __noinline int ieee80211_ioctl_setmlme(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211req_mlme mlme; @@ -1505,9 +1538,13 @@ ieee80211_ioctl_setmlme(struct ieee80211vap *vap, struct ieee80211req *ireq) error = copyin(ireq->i_data, &mlme, sizeof(mlme)); if (error) return error; - if (mlme.im_op == IEEE80211_MLME_ASSOC) - return setmlme_assoc(vap, mlme.im_macaddr, + if (vap->iv_opmode == IEEE80211_M_STA && + mlme.im_op == IEEE80211_MLME_ASSOC) + return setmlme_assoc_sta(vap, mlme.im_macaddr, vap->iv_des_ssid[0].len, vap->iv_des_ssid[0].ssid); + else if (mlme.im_op == IEEE80211_MLME_ASSOC) + return setmlme_assoc_adhoc(vap, mlme.im_macaddr, + mlme.im_ssid_len, mlme.im_ssid); else return setmlme_common(vap, mlme.im_op, mlme.im_macaddr, mlme.im_reason); @@ -2332,8 +2369,8 @@ ieee80211_ioctl_chanswitch(struct ieee80211vap *vap, struct ieee80211req *ireq) return error; } -static __noinline int -ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) +static int +ieee80211_scanreq(struct ieee80211vap *vap, struct ieee80211_scan_req *sr) { #define IEEE80211_IOC_SCAN_FLAGS \ (IEEE80211_IOC_SCAN_NOPICK | IEEE80211_IOC_SCAN_ACTIVE | \ @@ -2342,48 +2379,38 @@ ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) IEEE80211_IOC_SCAN_NOJOIN | IEEE80211_IOC_SCAN_FLUSH | \ IEEE80211_IOC_SCAN_CHECK) struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_req sr; /* XXX off stack? */ - int error, i; - - /* NB: parent must be running */ - if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return ENXIO; + int i; - if (ireq->i_len != sizeof(sr)) - return EINVAL; - error = copyin(ireq->i_data, &sr, sizeof(sr)); - if (error != 0) - return error; /* convert duration */ - if (sr.sr_duration == IEEE80211_IOC_SCAN_FOREVER) - sr.sr_duration = IEEE80211_SCAN_FOREVER; + if (sr->sr_duration == IEEE80211_IOC_SCAN_FOREVER) + sr->sr_duration = IEEE80211_SCAN_FOREVER; else { - if (sr.sr_duration < IEEE80211_IOC_SCAN_DURATION_MIN || - sr.sr_duration > IEEE80211_IOC_SCAN_DURATION_MAX) + if (sr->sr_duration < IEEE80211_IOC_SCAN_DURATION_MIN || + sr->sr_duration > IEEE80211_IOC_SCAN_DURATION_MAX) return EINVAL; - sr.sr_duration = msecs_to_ticks(sr.sr_duration); - if (sr.sr_duration < 1) - sr.sr_duration = 1; + sr->sr_duration = msecs_to_ticks(sr->sr_duration); + if (sr->sr_duration < 1) + sr->sr_duration = 1; } /* convert min/max channel dwell */ - if (sr.sr_mindwell != 0) { - sr.sr_mindwell = msecs_to_ticks(sr.sr_mindwell); - if (sr.sr_mindwell < 1) - sr.sr_mindwell = 1; + if (sr->sr_mindwell != 0) { + sr->sr_mindwell = msecs_to_ticks(sr->sr_mindwell); + if (sr->sr_mindwell < 1) + sr->sr_mindwell = 1; } - if (sr.sr_maxdwell != 0) { - sr.sr_maxdwell = msecs_to_ticks(sr.sr_maxdwell); - if (sr.sr_maxdwell < 1) - sr.sr_maxdwell = 1; + if (sr->sr_maxdwell != 0) { + sr->sr_maxdwell = msecs_to_ticks(sr->sr_maxdwell); + if (sr->sr_maxdwell < 1) + sr->sr_maxdwell = 1; } /* NB: silently reduce ssid count to what is supported */ - if (sr.sr_nssid > IEEE80211_SCAN_MAX_SSID) - sr.sr_nssid = IEEE80211_SCAN_MAX_SSID; - for (i = 0; i < sr.sr_nssid; i++) - if (sr.sr_ssid[i].len > IEEE80211_NWID_LEN) + if (sr->sr_nssid > IEEE80211_SCAN_MAX_SSID) + sr->sr_nssid = IEEE80211_SCAN_MAX_SSID; + for (i = 0; i < sr->sr_nssid; i++) + if (sr->sr_ssid[i].len > IEEE80211_NWID_LEN) return EINVAL; /* cleanse flags just in case, could reject if invalid flags */ - sr.sr_flags &= IEEE80211_IOC_SCAN_FLAGS; + sr->sr_flags &= IEEE80211_IOC_SCAN_FLAGS; /* * Add an implicit NOPICK if the vap is not marked UP. This * allows applications to scan without joining a bss (or picking @@ -2391,13 +2418,13 @@ ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) * roaming mode--you just need to mark the parent device UP. */ if ((vap->iv_ifp->if_flags & IFF_UP) == 0) - sr.sr_flags |= IEEE80211_IOC_SCAN_NOPICK; + sr->sr_flags |= IEEE80211_IOC_SCAN_NOPICK; IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: flags 0x%x%s duration 0x%x mindwell %u maxdwell %u nssid %d\n", - __func__, sr.sr_flags, + __func__, sr->sr_flags, (vap->iv_ifp->if_flags & IFF_UP) == 0 ? " (!IFF_UP)" : "", - sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell, sr.sr_nssid); + sr->sr_duration, sr->sr_mindwell, sr->sr_maxdwell, sr->sr_nssid); /* * If we are in INIT state then the driver has never had a chance * to setup hardware state to do a scan; we must use the state @@ -2412,13 +2439,13 @@ ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) IEEE80211_LOCK(ic); if (vap->iv_state == IEEE80211_S_INIT) { /* NB: clobbers previous settings */ - vap->iv_scanreq_flags = sr.sr_flags; - vap->iv_scanreq_duration = sr.sr_duration; - vap->iv_scanreq_nssid = sr.sr_nssid; - for (i = 0; i < sr.sr_nssid; i++) { - vap->iv_scanreq_ssid[i].len = sr.sr_ssid[i].len; - memcpy(vap->iv_scanreq_ssid[i].ssid, sr.sr_ssid[i].ssid, - sr.sr_ssid[i].len); + vap->iv_scanreq_flags = sr->sr_flags; + vap->iv_scanreq_duration = sr->sr_duration; + vap->iv_scanreq_nssid = sr->sr_nssid; + for (i = 0; i < sr->sr_nssid; i++) { + vap->iv_scanreq_ssid[i].len = sr->sr_ssid[i].len; + memcpy(vap->iv_scanreq_ssid[i].ssid, + sr->sr_ssid[i].ssid, sr->sr_ssid[i].len); } vap->iv_flags_ext |= IEEE80211_FEXT_SCANREQ; IEEE80211_UNLOCK(ic); @@ -2427,25 +2454,44 @@ ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ; IEEE80211_UNLOCK(ic); /* XXX neeed error return codes */ - if (sr.sr_flags & IEEE80211_IOC_SCAN_CHECK) { - (void) ieee80211_check_scan(vap, sr.sr_flags, - sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell, - sr.sr_nssid, + if (sr->sr_flags & IEEE80211_IOC_SCAN_CHECK) { + (void) ieee80211_check_scan(vap, sr->sr_flags, + sr->sr_duration, sr->sr_mindwell, sr->sr_maxdwell, + sr->sr_nssid, /* NB: cheat, we assume structures are compatible */ - (const struct ieee80211_scan_ssid *) &sr.sr_ssid[0]); + (const struct ieee80211_scan_ssid *) &sr->sr_ssid[0]); } else { - (void) ieee80211_start_scan(vap, sr.sr_flags, - sr.sr_duration, sr.sr_mindwell, sr.sr_maxdwell, - sr.sr_nssid, + (void) ieee80211_start_scan(vap, sr->sr_flags, + sr->sr_duration, sr->sr_mindwell, sr->sr_maxdwell, + sr->sr_nssid, /* NB: cheat, we assume structures are compatible */ - (const struct ieee80211_scan_ssid *) &sr.sr_ssid[0]); + (const struct ieee80211_scan_ssid *) &sr->sr_ssid[0]); } } - return error; + return 0; #undef IEEE80211_IOC_SCAN_FLAGS } static __noinline int +ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) +{ + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_scan_req sr; /* XXX off stack? */ + int error; + + /* NB: parent must be running */ + if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return ENXIO; + + if (ireq->i_len != sizeof(sr)) + return EINVAL; + error = copyin(ireq->i_data, &sr, sizeof(sr)); + if (error != 0) + return error; + return ieee80211_scanreq(vap, &sr); +} + +static __noinline int ieee80211_ioctl_setstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211_node *ni; |