| 1 | --- a/net80211/ieee80211.c |
| 2 | +++ b/net80211/ieee80211.c |
| 3 | @@ -333,7 +333,9 @@ ieee80211_ifattach(struct ieee80211com * |
| 4 | IEEE80211_MS_TO_TU(IEEE80211_BMISSTHRESH_DEFAULT_MS), |
| 5 | ic->ic_lintval), ic->ic_lintval); |
| 6 | } |
| 7 | - |
| 8 | + ic->ic_protmode_timeout = IEEE80211_PROTMODE_TIMEOUT; |
| 9 | + ic->ic_protmode_rssi = IEEE80211_PROTMODE_RSSITHR; |
| 10 | + |
| 11 | IEEE80211_LOCK_INIT(ic, "ieee80211com"); |
| 12 | IEEE80211_VAPS_LOCK_INIT(ic, "ieee80211com_vaps"); |
| 13 | TAILQ_INIT(&ic->ic_vaps); |
| 14 | --- a/net80211/ieee80211_input.c |
| 15 | +++ b/net80211/ieee80211_input.c |
| 16 | @@ -3411,14 +3411,18 @@ ieee80211_recv_mgmt(struct ieee80211vap |
| 17 | IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) { |
| 18 | |
| 19 | /* Assume no ERP IE == 11b AP */ |
| 20 | - if ((!has_erp || (has_erp && (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) && |
| 21 | - !(ic->ic_flags & IEEE80211_F_USEPROT)) { |
| 22 | + if ((!has_erp || (has_erp && |
| 23 | + (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) && |
| 24 | + (rssi > ic->ic_protmode_rssi)) { |
| 25 | struct ieee80211vap *tmpvap; |
| 26 | |
| 27 | - ic->ic_flags |= IEEE80211_F_USEPROT; |
| 28 | - TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) { |
| 29 | - tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE; |
| 30 | + if (!(ic->ic_flags & IEEE80211_F_USEPROT)) { |
| 31 | + ic->ic_flags |= IEEE80211_F_USEPROT; |
| 32 | + TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) { |
| 33 | + tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE; |
| 34 | + } |
| 35 | } |
| 36 | + ic->ic_protmode_lasttrig = jiffies; |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | --- a/net80211/ieee80211_ioctl.h |
| 41 | +++ b/net80211/ieee80211_ioctl.h |
| 42 | @@ -643,6 +643,8 @@ enum { |
| 43 | IEEE80211_PARAM_BEACON_MISS_THRESH_MS = 74, /* Beacon miss threshold (in ms) */ |
| 44 | IEEE80211_PARAM_MAXRATE = 75, /* Maximum rate (by table index) */ |
| 45 | IEEE80211_PARAM_MINRATE = 76, /* Minimum rate (by table index) */ |
| 46 | + IEEE80211_PARAM_PROTMODE_RSSI = 77, /* RSSI Threshold for enabling protection mode */ |
| 47 | + IEEE80211_PARAM_PROTMODE_TIMEOUT = 78, /* Timeout for expiring protection mode */ |
| 48 | }; |
| 49 | |
| 50 | #define SIOCG80211STATS (SIOCDEVPRIVATE+2) |
| 51 | --- a/net80211/ieee80211_var.h |
| 52 | +++ b/net80211/ieee80211_var.h |
| 53 | @@ -128,6 +128,9 @@ |
| 54 | |
| 55 | #define IEEE80211_APPIE_MAX 1024 |
| 56 | |
| 57 | +#define IEEE80211_PROTMODE_RSSITHR 15 /* default rssi threshold for protection mode trigger */ |
| 58 | +#define IEEE80211_PROTMODE_TIMEOUT 30 /* timeout for keeping protection mode alive */ |
| 59 | + |
| 60 | #define IEEE80211_PWRCONSTRAINT_VAL(ic) \ |
| 61 | (((ic)->ic_bsschan->ic_maxregpower > (ic)->ic_curchanmaxpwr) ? \ |
| 62 | (ic)->ic_bsschan->ic_maxregpower - (ic)->ic_curchanmaxpwr : 0) |
| 63 | @@ -324,6 +327,9 @@ struct ieee80211com { |
| 64 | u_int16_t ic_newtxpowlimit; /* tx power limit to change to (in 0.5 dBm) */ |
| 65 | u_int16_t ic_uapsdmaxtriggers; /* max triggers that could arrive */ |
| 66 | u_int8_t ic_coverageclass; /* coverage class */ |
| 67 | + u_int8_t ic_protmode_rssi; /* rssi threshold for protection mode */ |
| 68 | + u_int64_t ic_protmode_lasttrig; /* last trigger for protection mode */ |
| 69 | + u_int16_t ic_protmode_timeout; /* protection mode timeout */ |
| 70 | |
| 71 | /* Channel state: |
| 72 | * |
| 73 | --- a/net80211/ieee80211_wireless.c |
| 74 | +++ b/net80211/ieee80211_wireless.c |
| 75 | @@ -2312,6 +2312,12 @@ ieee80211_ioctl_setparam(struct net_devi |
| 76 | IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) |
| 77 | retv = ENETRESET; |
| 78 | break; |
| 79 | + case IEEE80211_PARAM_PROTMODE_TIMEOUT: |
| 80 | + ic->ic_protmode_timeout = value; |
| 81 | + break; |
| 82 | + case IEEE80211_PARAM_PROTMODE_RSSI: |
| 83 | + ic->ic_protmode_rssi = value; |
| 84 | + break; |
| 85 | case IEEE80211_PARAM_MCASTCIPHER: |
| 86 | if ((vap->iv_caps & cipher2cap(value)) == 0 && |
| 87 | !ieee80211_crypto_available(vap, value)) |
| 88 | @@ -2955,6 +2961,12 @@ ieee80211_ioctl_getparam(struct net_devi |
| 89 | case IEEE80211_PARAM_PROTMODE: |
| 90 | param[0] = ic->ic_protmode; |
| 91 | break; |
| 92 | + case IEEE80211_PARAM_PROTMODE_TIMEOUT: |
| 93 | + param[0] = ic->ic_protmode_timeout; |
| 94 | + break; |
| 95 | + case IEEE80211_PARAM_PROTMODE_RSSI: |
| 96 | + param[0] = ic->ic_protmode_rssi; |
| 97 | + break; |
| 98 | case IEEE80211_PARAM_MCASTCIPHER: |
| 99 | param[0] = rsn->rsn_mcastcipher; |
| 100 | break; |
| 101 | @@ -5346,6 +5358,14 @@ static const struct iw_priv_args ieee802 |
| 102 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "protmode" }, |
| 103 | { IEEE80211_PARAM_PROTMODE, |
| 104 | 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_protmode" }, |
| 105 | + { IEEE80211_PARAM_PROTMODE_RSSI, |
| 106 | + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "protrssi" }, |
| 107 | + { IEEE80211_PARAM_PROTMODE_RSSI, |
| 108 | + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_protrssi" }, |
| 109 | + { IEEE80211_PARAM_PROTMODE_TIMEOUT, |
| 110 | + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "prottime" }, |
| 111 | + { IEEE80211_PARAM_PROTMODE_TIMEOUT, |
| 112 | + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_prottime" }, |
| 113 | { IEEE80211_PARAM_MCASTCIPHER, |
| 114 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mcastcipher" }, |
| 115 | { IEEE80211_PARAM_MCASTCIPHER, |
| 116 | --- a/net80211/ieee80211_node.c |
| 117 | +++ b/net80211/ieee80211_node.c |
| 118 | @@ -1877,6 +1877,17 @@ ieee80211_node_timeout(unsigned long arg |
| 119 | |
| 120 | ieee80211_scan_timeout(ic); |
| 121 | ieee80211_timeout_stations(&ic->ic_sta); |
| 122 | + if ((ic->ic_flags & IEEE80211_F_USEPROT) && |
| 123 | + (ic->ic_protmode_lasttrig + ic->ic_protmode_timeout * HZ < |
| 124 | + jiffies)) { |
| 125 | + struct ieee80211vap *tmpvap; |
| 126 | + |
| 127 | + /* expire protection mode */ |
| 128 | + ic->ic_flags &= ~IEEE80211_F_USEPROT; |
| 129 | + TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) { |
| 130 | + tmpvap->iv_flags_ext |= IEEE80211_FEXT_ERPUPDATE; |
| 131 | + } |
| 132 | + } |
| 133 | |
| 134 | ic->ic_inact.expires = jiffies + IEEE80211_INACT_WAIT * HZ; |
| 135 | add_timer(&ic->ic_inact); |
| 136 | |