|
@@ -1035,103 +1035,6 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
|
|
|
|
|
|
/* actual transmit path */
|
|
|
|
|
|
-/*
|
|
|
- * deal with packet injection down monitor interface
|
|
|
- * with Radiotap Header -- only called for monitor mode interface
|
|
|
- */
|
|
|
-static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
|
|
- struct sk_buff *skb)
|
|
|
-{
|
|
|
- /*
|
|
|
- * this is the moment to interpret and discard the radiotap header that
|
|
|
- * must be at the start of the packet injected in Monitor mode
|
|
|
- *
|
|
|
- * Need to take some care with endian-ness since radiotap
|
|
|
- * args are little-endian
|
|
|
- */
|
|
|
-
|
|
|
- struct ieee80211_radiotap_iterator iterator;
|
|
|
- struct ieee80211_radiotap_header *rthdr =
|
|
|
- (struct ieee80211_radiotap_header *) skb->data;
|
|
|
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
|
- int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
|
|
|
- NULL);
|
|
|
- u16 txflags;
|
|
|
-
|
|
|
- info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
|
|
- IEEE80211_TX_CTL_DONTFRAG;
|
|
|
-
|
|
|
- /*
|
|
|
- * for every radiotap entry that is present
|
|
|
- * (ieee80211_radiotap_iterator_next returns -ENOENT when no more
|
|
|
- * entries present, or -EINVAL on error)
|
|
|
- */
|
|
|
-
|
|
|
- while (!ret) {
|
|
|
- ret = ieee80211_radiotap_iterator_next(&iterator);
|
|
|
-
|
|
|
- if (ret)
|
|
|
- continue;
|
|
|
-
|
|
|
- /* see if this argument is something we can use */
|
|
|
- switch (iterator.this_arg_index) {
|
|
|
- /*
|
|
|
- * You must take care when dereferencing iterator.this_arg
|
|
|
- * for multibyte types... the pointer is not aligned. Use
|
|
|
- * get_unaligned((type *)iterator.this_arg) to dereference
|
|
|
- * iterator.this_arg for type "type" safely on all arches.
|
|
|
- */
|
|
|
- case IEEE80211_RADIOTAP_FLAGS:
|
|
|
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
|
|
|
- /*
|
|
|
- * this indicates that the skb we have been
|
|
|
- * handed has the 32-bit FCS CRC at the end...
|
|
|
- * we should react to that by snipping it off
|
|
|
- * because it will be recomputed and added
|
|
|
- * on transmission
|
|
|
- */
|
|
|
- if (skb->len < (iterator._max_length + FCS_LEN))
|
|
|
- return false;
|
|
|
-
|
|
|
- skb_trim(skb, skb->len - FCS_LEN);
|
|
|
- }
|
|
|
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
|
|
|
- info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
|
|
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
|
|
|
- info->flags &= ~IEEE80211_TX_CTL_DONTFRAG;
|
|
|
- break;
|
|
|
-
|
|
|
- case IEEE80211_RADIOTAP_TX_FLAGS:
|
|
|
- txflags = le16_to_cpu(get_unaligned((__le16*)
|
|
|
- iterator.this_arg));
|
|
|
- if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK)
|
|
|
- info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
|
|
- break;
|
|
|
-
|
|
|
- /*
|
|
|
- * Please update the file
|
|
|
- * Documentation/networking/mac80211-injection.txt
|
|
|
- * when parsing new fields here.
|
|
|
- */
|
|
|
-
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
|
|
|
- return false;
|
|
|
-
|
|
|
- /*
|
|
|
- * remove the radiotap header
|
|
|
- * iterator->_max_length was sanity-checked against
|
|
|
- * skb->len by iterator init
|
|
|
- */
|
|
|
- skb_pull(skb, iterator._max_length);
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
|
|
|
struct sk_buff *skb,
|
|
|
struct ieee80211_tx_info *info,
|
|
@@ -1205,19 +1108,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
|
|
|
tx->sdata = sdata;
|
|
|
tx->channel = local->hw.conf.channel;
|
|
|
|
|
|
- /* process and remove the injection radiotap header */
|
|
|
- if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) {
|
|
|
- if (!__ieee80211_parse_tx_radiotap(tx, skb))
|
|
|
- return TX_DROP;
|
|
|
-
|
|
|
- /*
|
|
|
- * __ieee80211_parse_tx_radiotap has now removed
|
|
|
- * the radiotap header that was present and pre-filled
|
|
|
- * 'tx' with tx control information.
|
|
|
- */
|
|
|
- info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP;
|
|
|
- }
|
|
|
-
|
|
|
/*
|
|
|
* If this flag is set to true anywhere, and we get here,
|
|
|
* we are doing the needed processing, so remove the flag
|
|
@@ -1559,6 +1449,89 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
|
|
|
rcu_read_unlock();
|
|
|
}
|
|
|
|
|
|
+static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
|
|
|
+{
|
|
|
+ struct ieee80211_radiotap_iterator iterator;
|
|
|
+ struct ieee80211_radiotap_header *rthdr =
|
|
|
+ (struct ieee80211_radiotap_header *) skb->data;
|
|
|
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
|
+ int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
|
|
|
+ NULL);
|
|
|
+ u16 txflags;
|
|
|
+
|
|
|
+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
|
|
+ IEEE80211_TX_CTL_DONTFRAG;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * for every radiotap entry that is present
|
|
|
+ * (ieee80211_radiotap_iterator_next returns -ENOENT when no more
|
|
|
+ * entries present, or -EINVAL on error)
|
|
|
+ */
|
|
|
+
|
|
|
+ while (!ret) {
|
|
|
+ ret = ieee80211_radiotap_iterator_next(&iterator);
|
|
|
+
|
|
|
+ if (ret)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* see if this argument is something we can use */
|
|
|
+ switch (iterator.this_arg_index) {
|
|
|
+ /*
|
|
|
+ * You must take care when dereferencing iterator.this_arg
|
|
|
+ * for multibyte types... the pointer is not aligned. Use
|
|
|
+ * get_unaligned((type *)iterator.this_arg) to dereference
|
|
|
+ * iterator.this_arg for type "type" safely on all arches.
|
|
|
+ */
|
|
|
+ case IEEE80211_RADIOTAP_FLAGS:
|
|
|
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
|
|
|
+ /*
|
|
|
+ * this indicates that the skb we have been
|
|
|
+ * handed has the 32-bit FCS CRC at the end...
|
|
|
+ * we should react to that by snipping it off
|
|
|
+ * because it will be recomputed and added
|
|
|
+ * on transmission
|
|
|
+ */
|
|
|
+ if (skb->len < (iterator._max_length + FCS_LEN))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ skb_trim(skb, skb->len - FCS_LEN);
|
|
|
+ }
|
|
|
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
|
|
|
+ info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
|
|
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
|
|
|
+ info->flags &= ~IEEE80211_TX_CTL_DONTFRAG;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case IEEE80211_RADIOTAP_TX_FLAGS:
|
|
|
+ txflags = get_unaligned_le16(iterator.this_arg);
|
|
|
+ if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK)
|
|
|
+ info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
|
|
+ break;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Please update the file
|
|
|
+ * Documentation/networking/mac80211-injection.txt
|
|
|
+ * when parsing new fields here.
|
|
|
+ */
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
|
|
|
+ return false;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * remove the radiotap header
|
|
|
+ * iterator->_max_length was sanity-checked against
|
|
|
+ * skb->len by iterator init
|
|
|
+ */
|
|
|
+ skb_pull(skb, iterator._max_length);
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
|
|
struct net_device *dev)
|
|
|
{
|
|
@@ -1646,8 +1619,11 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
|
|
memset(info, 0, sizeof(*info));
|
|
|
|
|
|
info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
|
|
- IEEE80211_TX_CTL_INJECTED |
|
|
|
- IEEE80211_TX_INTFL_HAS_RADIOTAP;
|
|
|
+ IEEE80211_TX_CTL_INJECTED;
|
|
|
+
|
|
|
+ /* process and remove the injection radiotap header */
|
|
|
+ if (!ieee80211_parse_tx_radiotap(skb))
|
|
|
+ goto fail;
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
|
@@ -1674,7 +1650,6 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /* pass the radiotap header up to xmit */
|
|
|
ieee80211_xmit(sdata, skb);
|
|
|
rcu_read_unlock();
|
|
|
|