aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-09-12 16:52:47 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-15 16:48:25 -0400
commit25d834e16294c8dfd923dae6bdb8a055391a99a5 (patch)
treeb9d756464d89949651e5acd1df97846af3028df0 /net/mac80211
parent9c31fd635ddfae6eb61712491770befa2ce1fdde (diff)
mac80211: fix virtual interfaces vs. injection
Currently, virtual interface pointers passed to drivers might be from monitor interfaces and as such completely uninitialised because we do not tell the driver about monitor interfaces when those are created. Instead of passing them, we should therefore indicate to the driver that there is no information; do that by passing a NULL value and adjust drivers to cope with it. As a result, some mac80211 API functions also need to cope with a NULL vif pointer so drivers can still call them unconditionally. Also, when injecting frames we really don't want to pass NULL all the time, if we know we are the source address of a frame and have a local interface for that address, we can to use that interface. This also helps with processing the frame correctly for that interface which will help the 802.11w implementation. It's not entirely correct for VLANs or WDS interfaces because there the MAC address isn't unique, but it's already a lot better than what we do now. Finally, when injecting without a matching local interface, don't assign sequence numbers at all. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/tx.c64
-rw-r--r--net/mac80211/util.c37
2 files changed, 85 insertions, 16 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 698c8233e6b3..c12f361d7185 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -624,7 +624,14 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
624 u8 *qc; 624 u8 *qc;
625 int tid; 625 int tid;
626 626
627 /* only for injected frames */ 627 /*
628 * Packet injection may want to control the sequence
629 * number, if we have no matching interface then we
630 * neither assign one ourselves nor ask the driver to.
631 */
632 if (unlikely(!info->control.vif))
633 return TX_CONTINUE;
634
628 if (unlikely(ieee80211_is_ctl(hdr->frame_control))) 635 if (unlikely(ieee80211_is_ctl(hdr->frame_control)))
629 return TX_CONTINUE; 636 return TX_CONTINUE;
630 637
@@ -849,7 +856,6 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
849 sband = tx->local->hw.wiphy->bands[tx->channel->band]; 856 sband = tx->local->hw.wiphy->bands[tx->channel->band];
850 857
851 skb->do_not_encrypt = 1; 858 skb->do_not_encrypt = 1;
852 info->flags |= IEEE80211_TX_CTL_INJECTED;
853 tx->flags &= ~IEEE80211_TX_FRAGMENTED; 859 tx->flags &= ~IEEE80211_TX_FRAGMENTED;
854 860
855 /* 861 /*
@@ -981,7 +987,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
981 987
982 /* process and remove the injection radiotap header */ 988 /* process and remove the injection radiotap header */
983 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 989 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
984 if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { 990 if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) {
985 if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP) 991 if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP)
986 return TX_DROP; 992 return TX_DROP;
987 993
@@ -1300,6 +1306,11 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
1300 struct ieee80211_sub_if_data *osdata; 1306 struct ieee80211_sub_if_data *osdata;
1301 int headroom; 1307 int headroom;
1302 bool may_encrypt; 1308 bool may_encrypt;
1309 enum {
1310 NOT_MONITOR,
1311 FOUND_SDATA,
1312 UNKNOWN_ADDRESS,
1313 } monitor_iface = NOT_MONITOR;
1303 int ret; 1314 int ret;
1304 1315
1305 if (skb->iif) 1316 if (skb->iif)
@@ -1335,6 +1346,50 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
1335 IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, 1346 IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh,
1336 fwded_frames); 1347 fwded_frames);
1337 } 1348 }
1349 } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) {
1350 struct ieee80211_sub_if_data *sdata;
1351 struct ieee80211_local *local = osdata->local;
1352 struct ieee80211_hdr *hdr;
1353 int hdrlen;
1354 u16 len_rthdr;
1355
1356 info->flags |= IEEE80211_TX_CTL_INJECTED;
1357 monitor_iface = UNKNOWN_ADDRESS;
1358
1359 len_rthdr = ieee80211_get_radiotap_len(skb->data);
1360 hdr = (struct ieee80211_hdr *)skb->data + len_rthdr;
1361 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1362
1363 /* check the header is complete in the frame */
1364 if (likely(skb->len >= len_rthdr + hdrlen)) {
1365 /*
1366 * We process outgoing injected frames that have a
1367 * local address we handle as though they are our
1368 * own frames.
1369 * This code here isn't entirely correct, the local
1370 * MAC address is not necessarily enough to find
1371 * the interface to use; for that proper VLAN/WDS
1372 * support we will need a different mechanism.
1373 */
1374
1375 rcu_read_lock();
1376 list_for_each_entry_rcu(sdata, &local->interfaces,
1377 list) {
1378 if (!netif_running(sdata->dev))
1379 continue;
1380 if (compare_ether_addr(sdata->dev->dev_addr,
1381 hdr->addr2)) {
1382 dev_hold(sdata->dev);
1383 dev_put(odev);
1384 osdata = sdata;
1385 odev = osdata->dev;
1386 skb->iif = sdata->dev->ifindex;
1387 monitor_iface = FOUND_SDATA;
1388 break;
1389 }
1390 }
1391 rcu_read_unlock();
1392 }
1338 } 1393 }
1339 1394
1340 may_encrypt = !skb->do_not_encrypt; 1395 may_encrypt = !skb->do_not_encrypt;
@@ -1355,7 +1410,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
1355 osdata = container_of(osdata->bss, 1410 osdata = container_of(osdata->bss,
1356 struct ieee80211_sub_if_data, 1411 struct ieee80211_sub_if_data,
1357 u.ap); 1412 u.ap);
1358 info->control.vif = &osdata->vif; 1413 if (likely(monitor_iface != UNKNOWN_ADDRESS))
1414 info->control.vif = &osdata->vif;
1359 ret = ieee80211_tx(odev, skb); 1415 ret = ieee80211_tx(odev, skb);
1360 dev_put(odev); 1416 dev_put(odev);
1361 1417
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 6eb222369bcb..f32561ec224c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -231,16 +231,21 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
231 struct ieee80211_rate *rate) 231 struct ieee80211_rate *rate)
232{ 232{
233 struct ieee80211_local *local = hw_to_local(hw); 233 struct ieee80211_local *local = hw_to_local(hw);
234 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 234 struct ieee80211_sub_if_data *sdata;
235 u16 dur; 235 u16 dur;
236 int erp; 236 int erp;
237 bool short_preamble = false;
237 238
238 erp = 0; 239 erp = 0;
239 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 240 if (vif) {
240 erp = rate->flags & IEEE80211_RATE_ERP_G; 241 sdata = vif_to_sdata(vif);
242 short_preamble = sdata->bss_conf.use_short_preamble;
243 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
244 erp = rate->flags & IEEE80211_RATE_ERP_G;
245 }
241 246
242 dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, 247 dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp,
243 sdata->bss_conf.use_short_preamble); 248 short_preamble);
244 249
245 return cpu_to_le16(dur); 250 return cpu_to_le16(dur);
246} 251}
@@ -252,7 +257,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
252{ 257{
253 struct ieee80211_local *local = hw_to_local(hw); 258 struct ieee80211_local *local = hw_to_local(hw);
254 struct ieee80211_rate *rate; 259 struct ieee80211_rate *rate;
255 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 260 struct ieee80211_sub_if_data *sdata;
256 bool short_preamble; 261 bool short_preamble;
257 int erp; 262 int erp;
258 u16 dur; 263 u16 dur;
@@ -260,13 +265,17 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
260 265
261 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 266 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
262 267
263 short_preamble = sdata->bss_conf.use_short_preamble; 268 short_preamble = false;
264 269
265 rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; 270 rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
266 271
267 erp = 0; 272 erp = 0;
268 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 273 if (vif) {
269 erp = rate->flags & IEEE80211_RATE_ERP_G; 274 sdata = vif_to_sdata(vif);
275 short_preamble = sdata->bss_conf.use_short_preamble;
276 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
277 erp = rate->flags & IEEE80211_RATE_ERP_G;
278 }
270 279
271 /* CTS duration */ 280 /* CTS duration */
272 dur = ieee80211_frame_duration(local, 10, rate->bitrate, 281 dur = ieee80211_frame_duration(local, 10, rate->bitrate,
@@ -289,7 +298,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
289{ 298{
290 struct ieee80211_local *local = hw_to_local(hw); 299 struct ieee80211_local *local = hw_to_local(hw);
291 struct ieee80211_rate *rate; 300 struct ieee80211_rate *rate;
292 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 301 struct ieee80211_sub_if_data *sdata;
293 bool short_preamble; 302 bool short_preamble;
294 int erp; 303 int erp;
295 u16 dur; 304 u16 dur;
@@ -297,12 +306,16 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
297 306
298 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 307 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
299 308
300 short_preamble = sdata->bss_conf.use_short_preamble; 309 short_preamble = false;
301 310
302 rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; 311 rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
303 erp = 0; 312 erp = 0;
304 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) 313 if (vif) {
305 erp = rate->flags & IEEE80211_RATE_ERP_G; 314 sdata = vif_to_sdata(vif);
315 short_preamble = sdata->bss_conf.use_short_preamble;
316 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
317 erp = rate->flags & IEEE80211_RATE_ERP_G;
318 }
306 319
307 /* Data frame duration */ 320 /* Data frame duration */
308 dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, 321 dur = ieee80211_frame_duration(local, frame_len, rate->bitrate,