summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ath/if_ath.c10
-rw-r--r--sys/net80211/ieee80211_crypto_ccmp.c9
-rw-r--r--sys/net80211/ieee80211_crypto_tkip.c9
-rw-r--r--sys/net80211/ieee80211_ioctl.c166
-rw-r--r--usr.sbin/wpa/wpa_supplicant/driver_freebsd.c13
-rw-r--r--usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.524
6 files changed, 164 insertions, 67 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;
diff --git a/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c b/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
index ec8ae98..65989c2 100644
--- a/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
+++ b/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
@@ -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;
diff --git a/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5 b/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5
index a7a1698..7e25391 100644
--- a/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5
+++ b/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5
@@ -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
OpenPOWER on IntegriCloud