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:
Bernhard Schmidt 2010-04-10 13:54:00 +00:00
parent 9c251892c0
commit 632ee7e3a4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=206457
6 changed files with 164 additions and 67 deletions

View File

@ -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

View File

@ -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.
*/

View File

@ -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.
*/

View File

@ -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)
{

View File

@ -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;

View File

@ -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