[net80211] turn the default TX key configuration (for WEP) into a vap callback.
The ath10k firmware supports hardware WEP offload, and in native wifi mode (or 802.3 ethernet mode, for that matter) the WEP key isn't actually included in the TX payload from net80211. Instead, a separate firmware command is issued that sets the default TX key to be the specified key. However, net80211 doesn't at all inform the driver layer that this is occuring - it just "expects" to be inserting WEP header information when doing WEP TX, even with hardware encryption. So, to better support the newer world order, turn the default TX key assignment into a VAP method that can be overridden by the driver and ensure its wrapped in a crypto begin/end set. That way it should be correctly atomic from the point of view of keychanges (as long as the driver does the right thing.) It'd be nice if we passed through to the key_set call a flag that says "also make this the default key" - that's captured here by calling the deftxkey method after the key_set method. Maybe I can do that later. Note: this is a net80211 ABI change, and will require a kernel+modules recompile. Happy Holidays, etc. Tested: * ath10k driver port * rtwn_usb, WEP station
This commit is contained in:
parent
7105995c64
commit
781487cfc6
@ -432,6 +432,22 @@ default_reset(struct ieee80211vap *vap, u_long cmd)
|
||||
return ENETRESET;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default for updating the VAP default TX key index.
|
||||
*
|
||||
* Drivers that support TX offload as well as hardware encryption offload
|
||||
* may need to be informed of key index changes separate from the key
|
||||
* update.
|
||||
*/
|
||||
static void
|
||||
default_update_deftxkey(struct ieee80211vap *vap, ieee80211_keyix kid)
|
||||
{
|
||||
|
||||
/* XXX assert validity */
|
||||
/* XXX assert we're in a key update block */
|
||||
vap->iv_def_txkey = kid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add underlying device errors to vap errors.
|
||||
*/
|
||||
@ -561,6 +577,12 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
|
||||
*/
|
||||
vap->iv_reset = default_reset;
|
||||
|
||||
/*
|
||||
* Install a default crypto key update method, the driver
|
||||
* can override this.
|
||||
*/
|
||||
vap->iv_update_deftxkey = default_update_deftxkey;
|
||||
|
||||
ieee80211_sysctl_vattach(vap);
|
||||
ieee80211_crypto_vattach(vap);
|
||||
ieee80211_node_vattach(vap);
|
||||
|
@ -787,3 +787,18 @@ ieee80211_crypto_reload_keys(struct ieee80211com *ic)
|
||||
*/
|
||||
ieee80211_iterate_nodes(&ic->ic_sta, load_ucastkey, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the default key index for WEP, or KEYIX_NONE for no default TX key.
|
||||
*
|
||||
* This should be done as part of a key update block (iv_key_update_begin /
|
||||
* iv_key_update_end.)
|
||||
*/
|
||||
void
|
||||
ieee80211_crypto_set_deftxkey(struct ieee80211vap *vap, ieee80211_keyix kid)
|
||||
{
|
||||
|
||||
/* XXX TODO: assert we're in a key update block */
|
||||
|
||||
vap->iv_update_deftxkey(vap, kid);
|
||||
}
|
||||
|
@ -171,6 +171,8 @@ int ieee80211_crypto_delkey(struct ieee80211vap *,
|
||||
int ieee80211_crypto_setkey(struct ieee80211vap *, struct ieee80211_key *);
|
||||
void ieee80211_crypto_delglobalkeys(struct ieee80211vap *);
|
||||
void ieee80211_crypto_reload_keys(struct ieee80211com *);
|
||||
void ieee80211_crypto_set_deftxkey(struct ieee80211vap *,
|
||||
ieee80211_keyix kid);
|
||||
|
||||
/*
|
||||
* Template for a supported cipher. Ciphers register with the
|
||||
|
@ -855,6 +855,8 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
|
||||
* Tx power limit is the min of max regulatory
|
||||
* power, any user-set limit, and the max the
|
||||
* radio can do.
|
||||
*
|
||||
* TODO: methodize this
|
||||
*/
|
||||
ireq->i_val = 2*ic->ic_curchan->ic_maxregpower;
|
||||
if (ireq->i_val > ic->ic_txpowlimit)
|
||||
@ -1013,6 +1015,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
|
||||
ireq->i_val |= 2;
|
||||
break;
|
||||
case IEEE80211_IOC_AMPDU_LIMIT:
|
||||
/* XXX TODO: make this a per-node thing; and leave this as global */
|
||||
if (vap->iv_opmode == IEEE80211_M_HOSTAP)
|
||||
ireq->i_val = vap->iv_ampdu_rxmax;
|
||||
else if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)
|
||||
@ -1026,6 +1029,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
|
||||
ireq->i_val = vap->iv_ampdu_limit;
|
||||
break;
|
||||
case IEEE80211_IOC_AMPDU_DENSITY:
|
||||
/* XXX TODO: make this a per-node thing; and leave this as global */
|
||||
if (vap->iv_opmode == IEEE80211_M_STA &&
|
||||
(vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP))
|
||||
/*
|
||||
@ -1204,7 +1208,15 @@ ieee80211_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
|
||||
if (!ieee80211_crypto_setkey(vap, wk))
|
||||
error = EIO;
|
||||
else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT))
|
||||
vap->iv_def_txkey = kid;
|
||||
/*
|
||||
* Inform the driver that this is the default
|
||||
* transmit key. Now, ideally we'd just set
|
||||
* a flag in the key update that would
|
||||
* say "yes, we're the default key", but
|
||||
* that currently isn't the way the ioctl ->
|
||||
* key interface works.
|
||||
*/
|
||||
ieee80211_crypto_set_deftxkey(vap, kid);
|
||||
} else
|
||||
error = ENXIO;
|
||||
ieee80211_key_update_end(vap);
|
||||
@ -2687,7 +2699,17 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
|
||||
if (kid >= IEEE80211_WEP_NKID &&
|
||||
(uint16_t) kid != IEEE80211_KEYIX_NONE)
|
||||
return EINVAL;
|
||||
vap->iv_def_txkey = kid;
|
||||
/*
|
||||
* Firmware devices may need to be told about an explicit
|
||||
* key index here, versus just inferring it from the
|
||||
* key set / change. Since we may also need to pause
|
||||
* things like transmit before the key is updated,
|
||||
* give the driver a chance to flush things by tying
|
||||
* into key update begin/end.
|
||||
*/
|
||||
ieee80211_key_update_begin(vap);
|
||||
ieee80211_crypto_set_deftxkey(vap, kid);
|
||||
ieee80211_key_update_end(vap);
|
||||
break;
|
||||
case IEEE80211_IOC_AUTHMODE:
|
||||
switch (ireq->i_val) {
|
||||
@ -3094,6 +3116,7 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
|
||||
error = ERESTART;
|
||||
break;
|
||||
case IEEE80211_IOC_AMPDU_LIMIT:
|
||||
/* XXX TODO: figure out ampdu_limit versus ampdu_rxmax */
|
||||
if (!(IEEE80211_HTCAP_MAXRXAMPDU_8K <= ireq->i_val &&
|
||||
ireq->i_val <= IEEE80211_HTCAP_MAXRXAMPDU_64K))
|
||||
return EINVAL;
|
||||
|
@ -470,6 +470,8 @@ struct ieee80211vap {
|
||||
struct ieee80211_appie *iv_appie_wpa;
|
||||
uint8_t *iv_wpa_ie;
|
||||
uint8_t *iv_rsn_ie;
|
||||
|
||||
/* Key management */
|
||||
uint16_t iv_max_keyix; /* max h/w key index */
|
||||
ieee80211_keyix iv_def_txkey; /* default/group tx key index */
|
||||
struct ieee80211_key iv_nw_keys[IEEE80211_WEP_NKID];
|
||||
@ -482,6 +484,8 @@ struct ieee80211vap {
|
||||
const struct ieee80211_key *);
|
||||
void (*iv_key_update_begin)(struct ieee80211vap *);
|
||||
void (*iv_key_update_end)(struct ieee80211vap *);
|
||||
void (*iv_update_deftxkey)(struct ieee80211vap *,
|
||||
ieee80211_keyix deftxkey);
|
||||
|
||||
const struct ieee80211_authenticator *iv_auth; /* authenticator glue */
|
||||
void *iv_ec; /* private auth state */
|
||||
@ -536,6 +540,7 @@ struct ieee80211vap {
|
||||
/* 802.3 output method for raw frame xmit */
|
||||
int (*iv_output)(struct ifnet *, struct mbuf *,
|
||||
const struct sockaddr *, struct route *);
|
||||
|
||||
uint64_t iv_spare[6];
|
||||
};
|
||||
MALLOC_DECLARE(M_80211_VAP);
|
||||
|
Loading…
Reference in New Issue
Block a user