summaryrefslogtreecommitdiffstats
path: root/package/madwifi/patches/305-pureg_fix.patch
blob: ba7e62ed8fd80b5d170220ebdc396c3ea44d9fea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -4157,7 +4157,9 @@
 		rfilt |= HAL_RX_FILTER_PROM;
 	if (ic->ic_opmode == IEEE80211_M_STA ||
 	    sc->sc_opmode == HAL_M_IBSS ||	/* NB: AHDEMO too */
-	    (sc->sc_nostabeacons) || sc->sc_scanning)
+	    (sc->sc_nostabeacons) || sc->sc_scanning ||
+		((ic->ic_opmode == IEEE80211_M_HOSTAP) &&
+		 (ic->ic_protmode != IEEE80211_PROT_NONE)))
 		rfilt |= HAL_RX_FILTER_BEACON;
 	if (sc->sc_nmonvaps > 0)
 		rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON |
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -346,11 +346,12 @@
 				bssid = wh->i_addr3;
 			}
 			/*
-			 * Validate the bssid.
+			 * Validate the bssid. Let beacons get through though for 11g protection mode.
 			 */
-#ifdef ATH_SUPERG_XR
 			if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bssid) &&
-			    !IEEE80211_ADDR_EQ(bssid, dev->broadcast)) {
+			    !IEEE80211_ADDR_EQ(bssid, dev->broadcast) &&
+				(subtype != IEEE80211_FC0_SUBTYPE_BEACON)) {
+#ifdef ATH_SUPERG_XR
 				/*
 				 * allow MGT frames to vap->iv_xrvap.
 				 * this will allow roaming between  XR and normal vaps
@@ -366,18 +367,14 @@
 					vap->iv_stats.is_rx_wrongbss++;
 					goto out;
 				}
-			}
 #else
-			if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bssid) &&
-			    !IEEE80211_ADDR_EQ(bssid, dev->broadcast)) {
 				/* not interested in */
 				IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
 					bssid, NULL, "%s", "not to bss");
 				vap->iv_stats.is_rx_wrongbss++;
 				goto out;
-			}
-
 #endif
+			}
 			break;
 		case IEEE80211_M_WDS:
 			if (skb->len < sizeof(struct ieee80211_frame_addr4)) {
@@ -3066,7 +3063,7 @@
 	u_int8_t *frm, *efrm;
 	u_int8_t *ssid, *rates, *xrates, *suppchan, *wpa, *rsn, *wme, *ath;
 	u_int8_t rate;
-	int reassoc, resp, allocbs = 0;
+	int reassoc, resp, allocbs = 0, has_erp = 0;
 	u_int8_t qosinfo;
 
 	if (ni_or_null == NULL)
@@ -3096,11 +3093,15 @@
 		 *    o station mode when associated (to collect state
 		 *      updates such as 802.11g slot time), or
 		 *    o adhoc mode (to discover neighbors)
+		 *    o ap mode in protection mode (beacons only)
 		 * Frames otherwise received are discarded.
 		 */
 		if (!((ic->ic_flags & IEEE80211_F_SCAN) ||
 		    (vap->iv_opmode == IEEE80211_M_STA && ni->ni_associd) ||
-		    vap->iv_opmode == IEEE80211_M_IBSS)) {
+		    (vap->iv_opmode == IEEE80211_M_IBSS) ||
+			((subtype == IEEE80211_FC0_SUBTYPE_BEACON) &&
+			 (vap->iv_opmode == IEEE80211_M_HOSTAP) &&
+			 (ic->ic_protmode != IEEE80211_PROT_NONE)))) {
 			vap->iv_stats.is_rx_mgtdiscard++;
 			return;
 		}
@@ -3184,6 +3185,7 @@
 					break;
 				}
 				scan.erp = frm[2];
+				has_erp = 1;
 				break;
 			case IEEE80211_ELEMID_RSN:
 				scan.rsn = frm;
@@ -3421,6 +3423,20 @@
 				ieee80211_bg_scan(vap);
 			return;
 		}
+
+		/* Update AP protection mode when in 11G mode */
+		if ((vap->iv_opmode == IEEE80211_M_HOSTAP) &&
+			IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
+
+			/* Assume no ERP IE == 11b AP */
+			if ((!has_erp || (has_erp && (scan.erp & IEEE80211_ERP_NON_ERP_PRESENT))) &&
+				!(ic->ic_flags & IEEE80211_F_USEPROT)) {
+
+				ic->ic_flags |= IEEE80211_F_USEPROT;
+				ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;
+			}
+		}
+
 		/*
 		 * If scanning, just pass information to the scan module.
 		 */
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -383,10 +383,16 @@
 	/* Update country ie information */
 	ieee80211_build_countryie(ic);
 
-	if (IEEE80211_IS_CHAN_HALF(chan))
+	if (IEEE80211_IS_CHAN_HALF(chan)) {
 		ni->ni_rates = ic->ic_sup_half_rates;
-	else if (IEEE80211_IS_CHAN_QUARTER(chan))
+	} else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
 		ni->ni_rates = ic->ic_sup_quarter_rates;
+	}
+
+	if ((vap->iv_flags & IEEE80211_F_PUREG) &&
+		IEEE80211_IS_CHAN_ANYG(chan)) {
+		ieee80211_setpuregbasicrates(&ni->ni_rates);
+	}
 
 	(void) ieee80211_sta_join1(PASS_NODE(ni));
 }
--- a/net80211/ieee80211_proto.c
+++ b/net80211/ieee80211_proto.c
@@ -595,6 +595,28 @@
 	{ 4, { 2, 4, 11, 22 } },	/* IEEE80211_MODE_TURBO_G (mixed b/g) */
 };
 
+static const struct ieee80211_rateset basicpureg[] = {
+    { 7, {2, 4, 11, 22, 12, 24, 48 } },
+};
+
+/*
+ * Mark basic rates for the 11g rate table based on the pureg setting
+ */
+void
+ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs)
+{
+	int i, j;
+
+	for (i = 0; i < rs->rs_nrates; i++) {
+		rs->rs_rates[i] &= IEEE80211_RATE_VAL;
+		for (j = 0; j < basicpureg[0].rs_nrates; j++)
+			if (basicpureg[0].rs_rates[j] == rs->rs_rates[i]) {
+				rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
+				break;
+			}
+	}
+}
+
 /*
  * Mark the basic rates for the 11g rate table based on the
  * specified mode.  For 11b compatibility we mark only 11b
--- a/net80211/ieee80211_var.h
+++ b/net80211/ieee80211_var.h
@@ -708,6 +708,7 @@
 void ieee80211_build_sc_ie(struct ieee80211com *);
 void ieee80211_dfs_action(struct ieee80211com *);
 void ieee80211_expire_channel_excl_restrictions(struct ieee80211com *);
+void ieee80211_setpuregbasicrates(struct ieee80211_rateset *rs);
 
 /*
  * Iterate through ic_channels to enumerate all distinct ic_ieee channel numbers.