Add WPA-None support:
* WPA-None requires ap_scan=2: The major difference between ap_scan=1 (default) and 2 is, that no IEEE80211_IOC_SCAN* ioctls/functions are called, though, there is a dependency on those. For example the call to wpa_driver_bsd_scan() sets the interface UP, this never happens, therefore the interface must be marked up in wpa_driver_bsd_associate(). IEEE80211_IOC_SSID also is not called, which means that the SSID has not been set prior to the IEEE80211_MLME_ASSOC call. * WPA-None has no support for sequence number updates, it doesn't make sense to check for replay violations.. * I had some crashes right after the switch to RUN state, issue is that sc->sc_lastrs was not yet defined. Approved by: rpaulo (mentor) MFC after: 3 weeks
This commit is contained in:
parent
9c251892c0
commit
632ee7e3a4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=206457
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
@ -1494,6 +1497,36 @@ setmlme_assoc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN],
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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;
|
||||
int i;
|
||||
|
||||
/* 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;
|
||||
/* 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,24 +2454,43 @@ 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)
|
||||
{
|
||||
|
@ -396,7 +396,7 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
|
||||
{
|
||||
struct wpa_driver_bsd_data *drv = priv;
|
||||
struct ieee80211req_mlme mlme;
|
||||
int privacy;
|
||||
int flags, privacy;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
|
||||
@ -408,6 +408,17 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
|
||||
, params->key_mgmt_suite
|
||||
);
|
||||
|
||||
/* NB: interface must be marked UP to associate */
|
||||
if (getifflags(drv, &flags) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "%s did not mark interface UP", __func__);
|
||||
return -1;
|
||||
}
|
||||
if ((flags & IFF_UP) == 0 && setifflags(drv, flags | IFF_UP) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "%s unable to mark interface UP",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX error handling is wrong but unclear what to do... */
|
||||
if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
|
||||
return -1;
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 8, 2007
|
||||
.Dd April 10, 2010
|
||||
.Dt WPA_SUPPLICANT.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -153,7 +153,27 @@ Note that IBSS (adhoc) mode can only be used with
|
||||
.Va key_mgmt
|
||||
set to
|
||||
.Li NONE
|
||||
(plaintext and static WEP).
|
||||
(plaintext and static WEP), or
|
||||
.Va key_mgmt
|
||||
set to
|
||||
.Li WPA-NONE
|
||||
(fixed group key TKIP/CCMP).
|
||||
In addition,
|
||||
.Va ap_scan
|
||||
has to be set to 2 for IBSS.
|
||||
.Li WPA-NONE
|
||||
requires
|
||||
.Va proto
|
||||
set to WPA,
|
||||
.Va key_mgmt
|
||||
set to WPA-NONE,
|
||||
.Va pairwise
|
||||
set to NONE,
|
||||
.Va group
|
||||
set to either
|
||||
CCMP or TKIP (but not both), and
|
||||
.Va psk
|
||||
must also be set.
|
||||
.It Va proto
|
||||
List of acceptable protocols; one or more of:
|
||||
.Li WPA
|
||||
|
Loading…
Reference in New Issue
Block a user