From owner-svn-src-head@FreeBSD.ORG Sat Apr 10 13:54:00 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7089F106566B; Sat, 10 Apr 2010 13:54:00 +0000 (UTC) (envelope-from bschmidt@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 5D2088FC08; Sat, 10 Apr 2010 13:54:00 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o3ADs0sO098255; Sat, 10 Apr 2010 13:54:00 GMT (envelope-from bschmidt@svn.freebsd.org) Received: (from bschmidt@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o3ADs05a098248; Sat, 10 Apr 2010 13:54:00 GMT (envelope-from bschmidt@svn.freebsd.org) Message-Id: <201004101354.o3ADs05a098248@svn.freebsd.org> From: Bernhard Schmidt Date: Sat, 10 Apr 2010 13:54:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r206457 - in head: sys/dev/ath sys/net80211 usr.sbin/wpa/wpa_supplicant X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 10 Apr 2010 13:54:00 -0000 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