diff --git a/sys/net80211/_ieee80211.h b/sys/net80211/_ieee80211.h --- a/sys/net80211/_ieee80211.h +++ b/sys/net80211/_ieee80211.h @@ -487,7 +487,7 @@ #define IEEE80211_C_SWSLEEP 0x00080000 /* CAPABILITY: do sleep here */ #define IEEE80211_C_SWAMSDUTX 0x00100000 /* CAPABILITY: software A-MSDU TX */ #define IEEE80211_C_UAPSD 0x00200000 /* CAPABILITY: U-APSD */ -/* 0x7c0000 available */ +#define IEEE80211_C_MFP 0x00400000 /* CAPABILITY: MFP */ #define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ #define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ #define IEEE80211_C_WPA 0x01800000 /* CAPABILITY: WPA1+WPA2 avail*/ @@ -651,4 +651,10 @@ struct ieee80211_rx_stats params; }; +enum ieee80211_mfp_mode { + IEEE80211_MFP_PROTMODE_DISABLED = 0, + IEEE80211_MFP_PROTMODE_OPTIONAL = 1, + IEEE80211_MFP_PROTMODE_REQUIRED = 2, +}; + #endif /* _NET80211__IEEE80211_H_ */ diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -592,6 +592,7 @@ vap->iv_opmode = opmode; vap->iv_caps |= ieee80211_opcap[opmode]; + vap->iv_mfp_cfg = IEEE80211_MFP_PROTMODE_DISABLED; IEEE80211_ADDR_COPY(vap->iv_myaddr, ic->ic_macaddr); switch (opmode) { case IEEE80211_M_WDS: diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h --- a/sys/net80211/ieee80211_ioctl.h +++ b/sys/net80211/ieee80211_ioctl.h @@ -715,6 +715,10 @@ #define IEEE80211_IOC_LDPC 114 /* LDPC Tx/RX (on, off) */ #define IEEE80211_IOC_UAPSD 115 /* UAPSD (on, off) */ #define IEEE80211_IOC_UAPSD_INFO 116 /* UAPSD (SP, per-AC enable) */ +#define IEEE80211_IOC_MFP 117 /* MFP (off, optional, required) */ +#define IEEE80211_MFP_DISABLED 0 +#define IEEE80211_MFP_OPTIONAL 1 +#define IEEE80211_MFP_REQUIRED 2 /* VHT */ #define IEEE80211_IOC_VHTCONF 130 /* VHT config (off, on; widths) */ diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -1166,6 +1166,19 @@ if (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD) ireq->i_val = 1; break; + case IEEE80211_IOC_MFP: + switch (vap->iv_mfp_cfg) { + case IEEE80211_MFP_PROTMODE_DISABLED: + ireq->i_val = IEEE80211_MFP_DISABLED; + break; + case IEEE80211_MFP_PROTMODE_OPTIONAL: + ireq->i_val = IEEE80211_MFP_OPTIONAL; + break; + case IEEE80211_MFP_PROTMODE_REQUIRED: + ireq->i_val = IEEE80211_MFP_REQUIRED; + break; + } + break; case IEEE80211_IOC_VHTCONF: ireq->i_val = vap->iv_vht_flags & IEEE80211_FVHT_MASK; break; @@ -3509,6 +3522,24 @@ else return EINVAL; break; + case IEEE80211_IOC_MFP: + if ((vap->iv_ic->ic_caps & IEEE80211_C_MFP) == 0) + return EOPNOTSUPP; + if_printf(vap->iv_ifp, "%s: MFP: set %d\n", __func__, ireq->i_val); + switch (ireq->i_val) { + case IEEE80211_MFP_DISABLED: + vap->iv_mfp_cfg = IEEE80211_MFP_PROTMODE_DISABLED; + break; + case IEEE80211_MFP_OPTIONAL: + vap->iv_mfp_cfg = IEEE80211_MFP_PROTMODE_OPTIONAL; + break; + case IEEE80211_MFP_REQUIRED: + vap->iv_mfp_cfg = IEEE80211_MFP_PROTMODE_REQUIRED; + break; + default: + return EINVAL; + } + break; /* VHT */ case IEEE80211_IOC_VHTCONF: diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -611,6 +611,9 @@ /* per-vap U-APSD state */ uint8_t iv_uapsdinfo; /* sta mode QoS Info flags */ + /* per-VAP MFP configuration */ + enum ieee80211_mfp_mode iv_mfp_cfg; + /* Optional transmit/receive histogram statistics */ struct ieee80211_rx_histogram *rx_histogram; struct ieee80211_tx_histogram *tx_histogram;