svn commit: r206457 - in head: sys/dev/ath sys/net80211 usr.sbin/wpa/wpa_supplicant

Bernhard Schmidt bschmidt at FreeBSD.org
Sat Apr 10 13:54:00 UTC 2010


Author: bschmidt
Date: Sat Apr 10 13:54:00 2010
New Revision: 206457
URL: http://svn.freebsd.org/changeset/base/206457

Log:
  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

Modified:
  head/sys/dev/ath/if_ath.c
  head/sys/net80211/ieee80211_crypto_ccmp.c
  head/sys/net80211/ieee80211_crypto_tkip.c
  head/sys/net80211/ieee80211_ioctl.c
  head/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
  head/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Sat Apr 10 12:47:06 2010	(r206456)
+++ head/sys/dev/ath/if_ath.c	Sat Apr 10 13:54:00 2010	(r206457)
@@ -3654,8 +3654,14 @@ ath_recv_mgmt(struct ieee80211_node *ni,
 	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

Modified: head/sys/net80211/ieee80211_crypto_ccmp.c
==============================================================================
--- head/sys/net80211/ieee80211_crypto_ccmp.c	Sat Apr 10 12:47:06 2010	(r206456)
+++ head/sys/net80211/ieee80211_crypto_ccmp.c	Sat Apr 10 13:54:00 2010	(r206457)
@@ -226,7 +226,14 @@ ccmp_decap(struct ieee80211_key *k, stru
 	}
 	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.
 		 */

Modified: head/sys/net80211/ieee80211_crypto_tkip.c
==============================================================================
--- head/sys/net80211/ieee80211_crypto_tkip.c	Sat Apr 10 12:47:06 2010	(r206456)
+++ head/sys/net80211/ieee80211_crypto_tkip.c	Sat Apr 10 13:54:00 2010	(r206457)
@@ -281,7 +281,14 @@ tkip_decap(struct ieee80211_key *k, stru
 
 	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.
 		 */

Modified: head/sys/net80211/ieee80211_ioctl.c
==============================================================================
--- head/sys/net80211/ieee80211_ioctl.c	Sat Apr 10 12:47:06 2010	(r206456)
+++ head/sys/net80211/ieee80211_ioctl.c	Sat Apr 10 13:54:00 2010	(r206457)
@@ -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 ieee8
 }
 
 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, 
 }
 
 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 ieee80211
 	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 ieee80
 	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 ieee80211
 	 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_maxdwell != 0) {
-		sr.sr_maxdwell = msecs_to_ticks(sr.sr_maxdwell);
-		if (sr.sr_maxdwell < 1)
-			sr.sr_maxdwell = 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;
 	}
 	/* 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 ieee80211
 	 * 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 ieee80211
 	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 ieee80211
 		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;

Modified: head/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c
==============================================================================
--- head/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c	Sat Apr 10 12:47:06 2010	(r206456)
+++ head/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c	Sat Apr 10 13:54:00 2010	(r206457)
@@ -396,7 +396,7 @@ wpa_driver_bsd_associate(void *priv, str
 {
 	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, str
 		, 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;

Modified: head/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5
==============================================================================
--- head/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5	Sat Apr 10 12:47:06 2010	(r206456)
+++ head/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5	Sat Apr 10 13:54:00 2010	(r206457)
@@ -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 
 .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


More information about the svn-src-all mailing list