diff options
author | Andy Green <andy@warmcat.com> | 2007-07-10 13:32:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2007-07-12 16:07:24 -0400 |
commit | e4c967c6d88ca94365dd8e2a7bbd22eedb8d7ae7 (patch) | |
tree | ae6e1d6335018c2540b5fd58c679e4bdd5c05dfd /net | |
parent | 179f831bc33104d14deb54a52b7a8b43433f8ccc (diff) |
[PATCH] mac80211: Monitor mode radiotap-based packet injection
Signed-off-by: Andy Green <andy@warmcat.com>
Signed-off-by: Jiri Benc <jbenc@suse.cz>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ieee80211.c | 234 |
1 files changed, 224 insertions, 10 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 4e84f24fd439..8b57eaa2a271 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/compiler.h> | 24 | #include <linux/compiler.h> |
25 | #include <linux/bitmap.h> | 25 | #include <linux/bitmap.h> |
26 | #include <net/cfg80211.h> | 26 | #include <net/cfg80211.h> |
27 | #include <asm/unaligned.h> | ||
27 | 28 | ||
28 | #include "ieee80211_common.h" | 29 | #include "ieee80211_common.h" |
29 | #include "ieee80211_i.h" | 30 | #include "ieee80211_i.h" |
@@ -1118,7 +1119,138 @@ ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) | |||
1118 | } | 1119 | } |
1119 | 1120 | ||
1120 | 1121 | ||
1121 | static void inline | 1122 | /* |
1123 | * deal with packet injection down monitor interface | ||
1124 | * with Radiotap Header -- only called for monitor mode interface | ||
1125 | */ | ||
1126 | |||
1127 | static ieee80211_txrx_result | ||
1128 | __ieee80211_parse_tx_radiotap( | ||
1129 | struct ieee80211_txrx_data *tx, | ||
1130 | struct sk_buff *skb, struct ieee80211_tx_control *control) | ||
1131 | { | ||
1132 | /* | ||
1133 | * this is the moment to interpret and discard the radiotap header that | ||
1134 | * must be at the start of the packet injected in Monitor mode | ||
1135 | * | ||
1136 | * Need to take some care with endian-ness since radiotap | ||
1137 | * args are little-endian | ||
1138 | */ | ||
1139 | |||
1140 | struct ieee80211_radiotap_iterator iterator; | ||
1141 | struct ieee80211_radiotap_header *rthdr = | ||
1142 | (struct ieee80211_radiotap_header *) skb->data; | ||
1143 | struct ieee80211_hw_mode *mode = tx->local->hw.conf.mode; | ||
1144 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); | ||
1145 | |||
1146 | /* | ||
1147 | * default control situation for all injected packets | ||
1148 | * FIXME: this does not suit all usage cases, expand to allow control | ||
1149 | */ | ||
1150 | |||
1151 | control->retry_limit = 1; /* no retry */ | ||
1152 | control->key_idx = -1; /* no encryption key */ | ||
1153 | control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS | | ||
1154 | IEEE80211_TXCTL_USE_CTS_PROTECT); | ||
1155 | control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT | | ||
1156 | IEEE80211_TXCTL_NO_ACK; | ||
1157 | control->antenna_sel_tx = 0; /* default to default antenna */ | ||
1158 | |||
1159 | /* | ||
1160 | * for every radiotap entry that is present | ||
1161 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more | ||
1162 | * entries present, or -EINVAL on error) | ||
1163 | */ | ||
1164 | |||
1165 | while (!ret) { | ||
1166 | int i, target_rate; | ||
1167 | |||
1168 | ret = ieee80211_radiotap_iterator_next(&iterator); | ||
1169 | |||
1170 | if (ret) | ||
1171 | continue; | ||
1172 | |||
1173 | /* see if this argument is something we can use */ | ||
1174 | switch (iterator.this_arg_index) { | ||
1175 | /* | ||
1176 | * You must take care when dereferencing iterator.this_arg | ||
1177 | * for multibyte types... the pointer is not aligned. Use | ||
1178 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
1179 | * iterator.this_arg for type "type" safely on all arches. | ||
1180 | */ | ||
1181 | case IEEE80211_RADIOTAP_RATE: | ||
1182 | /* | ||
1183 | * radiotap rate u8 is in 500kbps units eg, 0x02=1Mbps | ||
1184 | * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps | ||
1185 | */ | ||
1186 | target_rate = (*iterator.this_arg) * 5; | ||
1187 | for (i = 0; i < mode->num_rates; i++) { | ||
1188 | struct ieee80211_rate *r = &mode->rates[i]; | ||
1189 | |||
1190 | if (r->rate > target_rate) | ||
1191 | continue; | ||
1192 | |||
1193 | control->rate = r; | ||
1194 | |||
1195 | if (r->flags & IEEE80211_RATE_PREAMBLE2) | ||
1196 | control->tx_rate = r->val2; | ||
1197 | else | ||
1198 | control->tx_rate = r->val; | ||
1199 | |||
1200 | /* end on exact match */ | ||
1201 | if (r->rate == target_rate) | ||
1202 | i = mode->num_rates; | ||
1203 | } | ||
1204 | break; | ||
1205 | |||
1206 | case IEEE80211_RADIOTAP_ANTENNA: | ||
1207 | /* | ||
1208 | * radiotap uses 0 for 1st ant, mac80211 is 1 for | ||
1209 | * 1st ant | ||
1210 | */ | ||
1211 | control->antenna_sel_tx = (*iterator.this_arg) + 1; | ||
1212 | break; | ||
1213 | |||
1214 | case IEEE80211_RADIOTAP_DBM_TX_POWER: | ||
1215 | control->power_level = *iterator.this_arg; | ||
1216 | break; | ||
1217 | |||
1218 | case IEEE80211_RADIOTAP_FLAGS: | ||
1219 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { | ||
1220 | /* | ||
1221 | * this indicates that the skb we have been | ||
1222 | * handed has the 32-bit FCS CRC at the end... | ||
1223 | * we should react to that by snipping it off | ||
1224 | * because it will be recomputed and added | ||
1225 | * on transmission | ||
1226 | */ | ||
1227 | if (skb->len < (iterator.max_length + FCS_LEN)) | ||
1228 | return TXRX_DROP; | ||
1229 | |||
1230 | skb_trim(skb, skb->len - FCS_LEN); | ||
1231 | } | ||
1232 | break; | ||
1233 | |||
1234 | default: | ||
1235 | break; | ||
1236 | } | ||
1237 | } | ||
1238 | |||
1239 | if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ | ||
1240 | return TXRX_DROP; | ||
1241 | |||
1242 | /* | ||
1243 | * remove the radiotap header | ||
1244 | * iterator->max_length was sanity-checked against | ||
1245 | * skb->len by iterator init | ||
1246 | */ | ||
1247 | skb_pull(skb, iterator.max_length); | ||
1248 | |||
1249 | return TXRX_CONTINUE; | ||
1250 | } | ||
1251 | |||
1252 | |||
1253 | static ieee80211_txrx_result inline | ||
1122 | __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | 1254 | __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, |
1123 | struct sk_buff *skb, | 1255 | struct sk_buff *skb, |
1124 | struct net_device *dev, | 1256 | struct net_device *dev, |
@@ -1126,6 +1258,9 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
1126 | { | 1258 | { |
1127 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1259 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1128 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1260 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1261 | struct ieee80211_sub_if_data *sdata; | ||
1262 | ieee80211_txrx_result res = TXRX_CONTINUE; | ||
1263 | |||
1129 | int hdrlen; | 1264 | int hdrlen; |
1130 | 1265 | ||
1131 | memset(tx, 0, sizeof(*tx)); | 1266 | memset(tx, 0, sizeof(*tx)); |
@@ -1135,7 +1270,32 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
1135 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1270 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1136 | tx->sta = sta_info_get(local, hdr->addr1); | 1271 | tx->sta = sta_info_get(local, hdr->addr1); |
1137 | tx->fc = le16_to_cpu(hdr->frame_control); | 1272 | tx->fc = le16_to_cpu(hdr->frame_control); |
1273 | |||
1274 | /* | ||
1275 | * set defaults for things that can be set by | ||
1276 | * injected radiotap headers | ||
1277 | */ | ||
1138 | control->power_level = local->hw.conf.power_level; | 1278 | control->power_level = local->hw.conf.power_level; |
1279 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | ||
1280 | if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta) | ||
1281 | control->antenna_sel_tx = tx->sta->antenna_sel_tx; | ||
1282 | |||
1283 | /* process and remove the injection radiotap header */ | ||
1284 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1285 | if (unlikely(sdata->type == IEEE80211_IF_TYPE_MNTR)) { | ||
1286 | if (__ieee80211_parse_tx_radiotap(tx, skb, control) == | ||
1287 | TXRX_DROP) { | ||
1288 | return TXRX_DROP; | ||
1289 | } | ||
1290 | /* | ||
1291 | * we removed the radiotap header after this point, | ||
1292 | * we filled control with what we could use | ||
1293 | * set to the actual ieee header now | ||
1294 | */ | ||
1295 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1296 | res = TXRX_QUEUED; /* indication it was monitor packet */ | ||
1297 | } | ||
1298 | |||
1139 | tx->u.tx.control = control; | 1299 | tx->u.tx.control = control; |
1140 | tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1); | 1300 | tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1); |
1141 | if (is_multicast_ether_addr(hdr->addr1)) | 1301 | if (is_multicast_ether_addr(hdr->addr1)) |
@@ -1152,9 +1312,6 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
1152 | control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK; | 1312 | control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK; |
1153 | tx->sta->clear_dst_mask = 0; | 1313 | tx->sta->clear_dst_mask = 0; |
1154 | } | 1314 | } |
1155 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | ||
1156 | if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta) | ||
1157 | control->antenna_sel_tx = tx->sta->antenna_sel_tx; | ||
1158 | hdrlen = ieee80211_get_hdrlen(tx->fc); | 1315 | hdrlen = ieee80211_get_hdrlen(tx->fc); |
1159 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { | 1316 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { |
1160 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; | 1317 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; |
@@ -1162,6 +1319,7 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, | |||
1162 | } | 1319 | } |
1163 | control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT; | 1320 | control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT; |
1164 | 1321 | ||
1322 | return res; | ||
1165 | } | 1323 | } |
1166 | 1324 | ||
1167 | static int inline is_ieee80211_device(struct net_device *dev, | 1325 | static int inline is_ieee80211_device(struct net_device *dev, |
@@ -1274,7 +1432,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1274 | struct sta_info *sta; | 1432 | struct sta_info *sta; |
1275 | ieee80211_tx_handler *handler; | 1433 | ieee80211_tx_handler *handler; |
1276 | struct ieee80211_txrx_data tx; | 1434 | struct ieee80211_txrx_data tx; |
1277 | ieee80211_txrx_result res = TXRX_DROP; | 1435 | ieee80211_txrx_result res = TXRX_DROP, res_prepare; |
1278 | int ret, i; | 1436 | int ret, i; |
1279 | 1437 | ||
1280 | WARN_ON(__ieee80211_queue_pending(local, control->queue)); | 1438 | WARN_ON(__ieee80211_queue_pending(local, control->queue)); |
@@ -1284,15 +1442,26 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1284 | return 0; | 1442 | return 0; |
1285 | } | 1443 | } |
1286 | 1444 | ||
1287 | __ieee80211_tx_prepare(&tx, skb, dev, control); | 1445 | res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control); |
1446 | |||
1447 | if (res_prepare == TXRX_DROP) { | ||
1448 | dev_kfree_skb(skb); | ||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1288 | sta = tx.sta; | 1452 | sta = tx.sta; |
1289 | tx.u.tx.mgmt_interface = mgmt; | 1453 | tx.u.tx.mgmt_interface = mgmt; |
1290 | tx.u.tx.mode = local->hw.conf.mode; | 1454 | tx.u.tx.mode = local->hw.conf.mode; |
1291 | 1455 | ||
1292 | for (handler = local->tx_handlers; *handler != NULL; handler++) { | 1456 | if (res_prepare == TXRX_QUEUED) { /* if it was an injected packet */ |
1293 | res = (*handler)(&tx); | 1457 | res = TXRX_CONTINUE; |
1294 | if (res != TXRX_CONTINUE) | 1458 | } else { |
1295 | break; | 1459 | for (handler = local->tx_handlers; *handler != NULL; |
1460 | handler++) { | ||
1461 | res = (*handler)(&tx); | ||
1462 | if (res != TXRX_CONTINUE) | ||
1463 | break; | ||
1464 | } | ||
1296 | } | 1465 | } |
1297 | 1466 | ||
1298 | skb = tx.skb; /* handlers are allowed to change skb */ | 1467 | skb = tx.skb; /* handlers are allowed to change skb */ |
@@ -1531,6 +1700,51 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1531 | goto fail; | 1700 | goto fail; |
1532 | } | 1701 | } |
1533 | 1702 | ||
1703 | if (unlikely(sdata->type == IEEE80211_IF_TYPE_MNTR)) { | ||
1704 | struct ieee80211_radiotap_header *prthdr = | ||
1705 | (struct ieee80211_radiotap_header *)skb->data; | ||
1706 | u16 len; | ||
1707 | |||
1708 | /* | ||
1709 | * there must be a radiotap header at the | ||
1710 | * start in this case | ||
1711 | */ | ||
1712 | if (unlikely(prthdr->it_version)) { | ||
1713 | /* only version 0 is supported */ | ||
1714 | ret = 0; | ||
1715 | goto fail; | ||
1716 | } | ||
1717 | |||
1718 | skb->dev = local->mdev; | ||
1719 | |||
1720 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | ||
1721 | memset(pkt_data, 0, sizeof(*pkt_data)); | ||
1722 | pkt_data->ifindex = sdata->dev->ifindex; | ||
1723 | pkt_data->mgmt_iface = 0; | ||
1724 | pkt_data->do_not_encrypt = 1; | ||
1725 | |||
1726 | /* above needed because we set skb device to master */ | ||
1727 | |||
1728 | /* | ||
1729 | * fix up the pointers accounting for the radiotap | ||
1730 | * header still being in there. We are being given | ||
1731 | * a precooked IEEE80211 header so no need for | ||
1732 | * normal processing | ||
1733 | */ | ||
1734 | len = le16_to_cpu(get_unaligned(&prthdr->it_len)); | ||
1735 | skb_set_mac_header(skb, len); | ||
1736 | skb_set_network_header(skb, len + sizeof(hdr)); | ||
1737 | skb_set_transport_header(skb, len + sizeof(hdr)); | ||
1738 | |||
1739 | /* | ||
1740 | * pass the radiotap header up to | ||
1741 | * the next stage intact | ||
1742 | */ | ||
1743 | dev_queue_xmit(skb); | ||
1744 | |||
1745 | return 0; | ||
1746 | } | ||
1747 | |||
1534 | nh_pos = skb_network_header(skb) - skb->data; | 1748 | nh_pos = skb_network_header(skb) - skb->data; |
1535 | h_pos = skb_transport_header(skb) - skb->data; | 1749 | h_pos = skb_transport_header(skb) - skb->data; |
1536 | 1750 | ||