Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.26-rc7 549 lines 16 kB view raw
1#include "hostap_80211.h" 2#include "hostap_common.h" 3#include "hostap_wlan.h" 4#include "hostap.h" 5#include "hostap_ap.h" 6 7/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ 8/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ 9static unsigned char rfc1042_header[] = 10{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; 11/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ 12static unsigned char bridge_tunnel_header[] = 13{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; 14/* No encapsulation header if EtherType < 0x600 (=length) */ 15 16void hostap_dump_tx_80211(const char *name, struct sk_buff *skb) 17{ 18 struct ieee80211_hdr_4addr *hdr; 19 u16 fc; 20 DECLARE_MAC_BUF(mac); 21 22 hdr = (struct ieee80211_hdr_4addr *) skb->data; 23 24 printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n", 25 name, skb->len, jiffies); 26 27 if (skb->len < 2) 28 return; 29 30 fc = le16_to_cpu(hdr->frame_ctl); 31 printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s", 32 fc, WLAN_FC_GET_TYPE(fc) >> 2, WLAN_FC_GET_STYPE(fc) >> 4, 33 fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "", 34 fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : ""); 35 36 if (skb->len < IEEE80211_DATA_HDR3_LEN) { 37 printk("\n"); 38 return; 39 } 40 41 printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id), 42 le16_to_cpu(hdr->seq_ctl)); 43 44 printk(KERN_DEBUG " A1=%s", print_mac(mac, hdr->addr1)); 45 printk(" A2=%s", print_mac(mac, hdr->addr2)); 46 printk(" A3=%s", print_mac(mac, hdr->addr3)); 47 if (skb->len >= 30) 48 printk(" A4=%s", print_mac(mac, hdr->addr4)); 49 printk("\n"); 50} 51 52 53/* hard_start_xmit function for data interfaces (wlan#, wlan#wds#, wlan#sta) 54 * Convert Ethernet header into a suitable IEEE 802.11 header depending on 55 * device configuration. */ 56int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev) 57{ 58 struct hostap_interface *iface; 59 local_info_t *local; 60 int need_headroom, need_tailroom = 0; 61 struct ieee80211_hdr_4addr hdr; 62 u16 fc, ethertype = 0; 63 enum { 64 WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME 65 } use_wds = WDS_NO; 66 u8 *encaps_data; 67 int hdr_len, encaps_len, skip_header_bytes; 68 int to_assoc_ap = 0; 69 struct hostap_skb_tx_data *meta; 70 71 iface = netdev_priv(dev); 72 local = iface->local; 73 74 if (skb->len < ETH_HLEN) { 75 printk(KERN_DEBUG "%s: hostap_data_start_xmit: short skb " 76 "(len=%d)\n", dev->name, skb->len); 77 kfree_skb(skb); 78 return 0; 79 } 80 81 if (local->ddev != dev) { 82 use_wds = (local->iw_mode == IW_MODE_MASTER && 83 !(local->wds_type & HOSTAP_WDS_STANDARD_FRAME)) ? 84 WDS_OWN_FRAME : WDS_COMPLIANT_FRAME; 85 if (dev == local->stadev) { 86 to_assoc_ap = 1; 87 use_wds = WDS_NO; 88 } else if (dev == local->apdev) { 89 printk(KERN_DEBUG "%s: prism2_tx: trying to use " 90 "AP device with Ethernet net dev\n", dev->name); 91 kfree_skb(skb); 92 return 0; 93 } 94 } else { 95 if (local->iw_mode == IW_MODE_REPEAT) { 96 printk(KERN_DEBUG "%s: prism2_tx: trying to use " 97 "non-WDS link in Repeater mode\n", dev->name); 98 kfree_skb(skb); 99 return 0; 100 } else if (local->iw_mode == IW_MODE_INFRA && 101 (local->wds_type & HOSTAP_WDS_AP_CLIENT) && 102 memcmp(skb->data + ETH_ALEN, dev->dev_addr, 103 ETH_ALEN) != 0) { 104 /* AP client mode: send frames with foreign src addr 105 * using 4-addr WDS frames */ 106 use_wds = WDS_COMPLIANT_FRAME; 107 } 108 } 109 110 /* Incoming skb->data: dst_addr[6], src_addr[6], proto[2], payload 111 * ==> 112 * Prism2 TX frame with 802.11 header: 113 * txdesc (address order depending on used mode; includes dst_addr and 114 * src_addr), possible encapsulation (RFC1042/Bridge-Tunnel; 115 * proto[2], payload {, possible addr4[6]} */ 116 117 ethertype = (skb->data[12] << 8) | skb->data[13]; 118 119 memset(&hdr, 0, sizeof(hdr)); 120 121 /* Length of data after IEEE 802.11 header */ 122 encaps_data = NULL; 123 encaps_len = 0; 124 skip_header_bytes = ETH_HLEN; 125 if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) { 126 encaps_data = bridge_tunnel_header; 127 encaps_len = sizeof(bridge_tunnel_header); 128 skip_header_bytes -= 2; 129 } else if (ethertype >= 0x600) { 130 encaps_data = rfc1042_header; 131 encaps_len = sizeof(rfc1042_header); 132 skip_header_bytes -= 2; 133 } 134 135 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; 136 hdr_len = IEEE80211_DATA_HDR3_LEN; 137 138 if (use_wds != WDS_NO) { 139 /* Note! Prism2 station firmware has problems with sending real 140 * 802.11 frames with four addresses; until these problems can 141 * be fixed or worked around, 4-addr frames needed for WDS are 142 * using incompatible format: FromDS flag is not set and the 143 * fourth address is added after the frame payload; it is 144 * assumed, that the receiving station knows how to handle this 145 * frame format */ 146 147 if (use_wds == WDS_COMPLIANT_FRAME) { 148 fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS; 149 /* From&To DS: Addr1 = RA, Addr2 = TA, Addr3 = DA, 150 * Addr4 = SA */ 151 skb_copy_from_linear_data_offset(skb, ETH_ALEN, 152 &hdr.addr4, ETH_ALEN); 153 hdr_len += ETH_ALEN; 154 } else { 155 /* bogus 4-addr format to workaround Prism2 station 156 * f/w bug */ 157 fc |= IEEE80211_FCTL_TODS; 158 /* From DS: Addr1 = DA (used as RA), 159 * Addr2 = BSSID (used as TA), Addr3 = SA (used as DA), 160 */ 161 162 /* SA from skb->data + ETH_ALEN will be added after 163 * frame payload; use hdr.addr4 as a temporary buffer 164 */ 165 skb_copy_from_linear_data_offset(skb, ETH_ALEN, 166 &hdr.addr4, ETH_ALEN); 167 need_tailroom += ETH_ALEN; 168 } 169 170 /* send broadcast and multicast frames to broadcast RA, if 171 * configured; otherwise, use unicast RA of the WDS link */ 172 if ((local->wds_type & HOSTAP_WDS_BROADCAST_RA) && 173 skb->data[0] & 0x01) 174 memset(&hdr.addr1, 0xff, ETH_ALEN); 175 else if (iface->type == HOSTAP_INTERFACE_WDS) 176 memcpy(&hdr.addr1, iface->u.wds.remote_addr, 177 ETH_ALEN); 178 else 179 memcpy(&hdr.addr1, local->bssid, ETH_ALEN); 180 memcpy(&hdr.addr2, dev->dev_addr, ETH_ALEN); 181 skb_copy_from_linear_data(skb, &hdr.addr3, ETH_ALEN); 182 } else if (local->iw_mode == IW_MODE_MASTER && !to_assoc_ap) { 183 fc |= IEEE80211_FCTL_FROMDS; 184 /* From DS: Addr1 = DA, Addr2 = BSSID, Addr3 = SA */ 185 skb_copy_from_linear_data(skb, &hdr.addr1, ETH_ALEN); 186 memcpy(&hdr.addr2, dev->dev_addr, ETH_ALEN); 187 skb_copy_from_linear_data_offset(skb, ETH_ALEN, &hdr.addr3, 188 ETH_ALEN); 189 } else if (local->iw_mode == IW_MODE_INFRA || to_assoc_ap) { 190 fc |= IEEE80211_FCTL_TODS; 191 /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ 192 memcpy(&hdr.addr1, to_assoc_ap ? 193 local->assoc_ap_addr : local->bssid, ETH_ALEN); 194 skb_copy_from_linear_data_offset(skb, ETH_ALEN, &hdr.addr2, 195 ETH_ALEN); 196 skb_copy_from_linear_data(skb, &hdr.addr3, ETH_ALEN); 197 } else if (local->iw_mode == IW_MODE_ADHOC) { 198 /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ 199 skb_copy_from_linear_data(skb, &hdr.addr1, ETH_ALEN); 200 skb_copy_from_linear_data_offset(skb, ETH_ALEN, &hdr.addr2, 201 ETH_ALEN); 202 memcpy(&hdr.addr3, local->bssid, ETH_ALEN); 203 } 204 205 hdr.frame_ctl = cpu_to_le16(fc); 206 207 skb_pull(skb, skip_header_bytes); 208 need_headroom = local->func->need_tx_headroom + hdr_len + encaps_len; 209 if (skb_tailroom(skb) < need_tailroom) { 210 skb = skb_unshare(skb, GFP_ATOMIC); 211 if (skb == NULL) { 212 iface->stats.tx_dropped++; 213 return 0; 214 } 215 if (pskb_expand_head(skb, need_headroom, need_tailroom, 216 GFP_ATOMIC)) { 217 kfree_skb(skb); 218 iface->stats.tx_dropped++; 219 return 0; 220 } 221 } else if (skb_headroom(skb) < need_headroom) { 222 struct sk_buff *tmp = skb; 223 skb = skb_realloc_headroom(skb, need_headroom); 224 kfree_skb(tmp); 225 if (skb == NULL) { 226 iface->stats.tx_dropped++; 227 return 0; 228 } 229 } else { 230 skb = skb_unshare(skb, GFP_ATOMIC); 231 if (skb == NULL) { 232 iface->stats.tx_dropped++; 233 return 0; 234 } 235 } 236 237 if (encaps_data) 238 memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len); 239 memcpy(skb_push(skb, hdr_len), &hdr, hdr_len); 240 if (use_wds == WDS_OWN_FRAME) { 241 memcpy(skb_put(skb, ETH_ALEN), &hdr.addr4, ETH_ALEN); 242 } 243 244 iface->stats.tx_packets++; 245 iface->stats.tx_bytes += skb->len; 246 247 skb_reset_mac_header(skb); 248 meta = (struct hostap_skb_tx_data *) skb->cb; 249 memset(meta, 0, sizeof(*meta)); 250 meta->magic = HOSTAP_SKB_TX_DATA_MAGIC; 251 if (use_wds) 252 meta->flags |= HOSTAP_TX_FLAGS_WDS; 253 meta->ethertype = ethertype; 254 meta->iface = iface; 255 256 /* Send IEEE 802.11 encapsulated frame using the master radio device */ 257 skb->dev = local->dev; 258 dev_queue_xmit(skb); 259 return 0; 260} 261 262 263/* hard_start_xmit function for hostapd wlan#ap interfaces */ 264int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev) 265{ 266 struct hostap_interface *iface; 267 local_info_t *local; 268 struct hostap_skb_tx_data *meta; 269 struct ieee80211_hdr_4addr *hdr; 270 u16 fc; 271 272 iface = netdev_priv(dev); 273 local = iface->local; 274 275 if (skb->len < 10) { 276 printk(KERN_DEBUG "%s: hostap_mgmt_start_xmit: short skb " 277 "(len=%d)\n", dev->name, skb->len); 278 kfree_skb(skb); 279 return 0; 280 } 281 282 iface->stats.tx_packets++; 283 iface->stats.tx_bytes += skb->len; 284 285 meta = (struct hostap_skb_tx_data *) skb->cb; 286 memset(meta, 0, sizeof(*meta)); 287 meta->magic = HOSTAP_SKB_TX_DATA_MAGIC; 288 meta->iface = iface; 289 290 if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) { 291 hdr = (struct ieee80211_hdr_4addr *) skb->data; 292 fc = le16_to_cpu(hdr->frame_ctl); 293 if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA && 294 WLAN_FC_GET_STYPE(fc) == IEEE80211_STYPE_DATA) { 295 u8 *pos = &skb->data[IEEE80211_DATA_HDR3_LEN + 296 sizeof(rfc1042_header)]; 297 meta->ethertype = (pos[0] << 8) | pos[1]; 298 } 299 } 300 301 /* Send IEEE 802.11 encapsulated frame using the master radio device */ 302 skb->dev = local->dev; 303 dev_queue_xmit(skb); 304 return 0; 305} 306 307 308/* Called only from software IRQ */ 309static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, 310 struct ieee80211_crypt_data *crypt) 311{ 312 struct hostap_interface *iface; 313 local_info_t *local; 314 struct ieee80211_hdr_4addr *hdr; 315 u16 fc; 316 int prefix_len, postfix_len, hdr_len, res; 317 318 iface = netdev_priv(skb->dev); 319 local = iface->local; 320 321 if (skb->len < IEEE80211_DATA_HDR3_LEN) { 322 kfree_skb(skb); 323 return NULL; 324 } 325 326 if (local->tkip_countermeasures && 327 strcmp(crypt->ops->name, "TKIP") == 0) { 328 hdr = (struct ieee80211_hdr_4addr *) skb->data; 329 if (net_ratelimit()) { 330 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " 331 "TX packet to " MAC_FMT "\n", 332 local->dev->name, 333 hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], 334 hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]); 335 } 336 kfree_skb(skb); 337 return NULL; 338 } 339 340 skb = skb_unshare(skb, GFP_ATOMIC); 341 if (skb == NULL) 342 return NULL; 343 344 prefix_len = crypt->ops->extra_mpdu_prefix_len + 345 crypt->ops->extra_msdu_prefix_len; 346 postfix_len = crypt->ops->extra_mpdu_postfix_len + 347 crypt->ops->extra_msdu_postfix_len; 348 if ((skb_headroom(skb) < prefix_len || 349 skb_tailroom(skb) < postfix_len) && 350 pskb_expand_head(skb, prefix_len, postfix_len, GFP_ATOMIC)) { 351 kfree_skb(skb); 352 return NULL; 353 } 354 355 hdr = (struct ieee80211_hdr_4addr *) skb->data; 356 fc = le16_to_cpu(hdr->frame_ctl); 357 hdr_len = hostap_80211_get_hdrlen(fc); 358 359 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so 360 * call both MSDU and MPDU encryption functions from here. */ 361 atomic_inc(&crypt->refcnt); 362 res = 0; 363 if (crypt->ops->encrypt_msdu) 364 res = crypt->ops->encrypt_msdu(skb, hdr_len, crypt->priv); 365 if (res == 0 && crypt->ops->encrypt_mpdu) 366 res = crypt->ops->encrypt_mpdu(skb, hdr_len, crypt->priv); 367 atomic_dec(&crypt->refcnt); 368 if (res < 0) { 369 kfree_skb(skb); 370 return NULL; 371 } 372 373 return skb; 374} 375 376 377/* hard_start_xmit function for master radio interface wifi#. 378 * AP processing (TX rate control, power save buffering, etc.). 379 * Use hardware TX function to send the frame. */ 380int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev) 381{ 382 struct hostap_interface *iface; 383 local_info_t *local; 384 int ret = 1; 385 u16 fc; 386 struct hostap_tx_data tx; 387 ap_tx_ret tx_ret; 388 struct hostap_skb_tx_data *meta; 389 int no_encrypt = 0; 390 struct ieee80211_hdr_4addr *hdr; 391 392 iface = netdev_priv(dev); 393 local = iface->local; 394 395 tx.skb = skb; 396 tx.sta_ptr = NULL; 397 398 meta = (struct hostap_skb_tx_data *) skb->cb; 399 if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) { 400 printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, " 401 "expected 0x%08x)\n", 402 dev->name, meta->magic, HOSTAP_SKB_TX_DATA_MAGIC); 403 ret = 0; 404 iface->stats.tx_dropped++; 405 goto fail; 406 } 407 408 if (local->host_encrypt) { 409 /* Set crypt to default algorithm and key; will be replaced in 410 * AP code if STA has own alg/key */ 411 tx.crypt = local->crypt[local->tx_keyidx]; 412 tx.host_encrypt = 1; 413 } else { 414 tx.crypt = NULL; 415 tx.host_encrypt = 0; 416 } 417 418 if (skb->len < 24) { 419 printk(KERN_DEBUG "%s: hostap_master_start_xmit: short skb " 420 "(len=%d)\n", dev->name, skb->len); 421 ret = 0; 422 iface->stats.tx_dropped++; 423 goto fail; 424 } 425 426 /* FIX (?): 427 * Wi-Fi 802.11b test plan suggests that AP should ignore power save 428 * bit in authentication and (re)association frames and assume tha 429 * STA remains awake for the response. */ 430 tx_ret = hostap_handle_sta_tx(local, &tx); 431 skb = tx.skb; 432 meta = (struct hostap_skb_tx_data *) skb->cb; 433 hdr = (struct ieee80211_hdr_4addr *) skb->data; 434 fc = le16_to_cpu(hdr->frame_ctl); 435 switch (tx_ret) { 436 case AP_TX_CONTINUE: 437 break; 438 case AP_TX_CONTINUE_NOT_AUTHORIZED: 439 if (local->ieee_802_1x && 440 WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA && 441 meta->ethertype != ETH_P_PAE && 442 !(meta->flags & HOSTAP_TX_FLAGS_WDS)) { 443 printk(KERN_DEBUG "%s: dropped frame to unauthorized " 444 "port (IEEE 802.1X): ethertype=0x%04x\n", 445 dev->name, meta->ethertype); 446 hostap_dump_tx_80211(dev->name, skb); 447 448 ret = 0; /* drop packet */ 449 iface->stats.tx_dropped++; 450 goto fail; 451 } 452 break; 453 case AP_TX_DROP: 454 ret = 0; /* drop packet */ 455 iface->stats.tx_dropped++; 456 goto fail; 457 case AP_TX_RETRY: 458 goto fail; 459 case AP_TX_BUFFERED: 460 /* do not free skb here, it will be freed when the 461 * buffered frame is sent/timed out */ 462 ret = 0; 463 goto tx_exit; 464 } 465 466 /* Request TX callback if protocol version is 2 in 802.11 header; 467 * this version 2 is a special case used between hostapd and kernel 468 * driver */ 469 if (((fc & IEEE80211_FCTL_VERS) == BIT(1)) && 470 local->ap && local->ap->tx_callback_idx && meta->tx_cb_idx == 0) { 471 meta->tx_cb_idx = local->ap->tx_callback_idx; 472 473 /* remove special version from the frame header */ 474 fc &= ~IEEE80211_FCTL_VERS; 475 hdr->frame_ctl = cpu_to_le16(fc); 476 } 477 478 if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_DATA) { 479 no_encrypt = 1; 480 tx.crypt = NULL; 481 } 482 483 if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt && 484 !(fc & IEEE80211_FCTL_PROTECTED)) { 485 no_encrypt = 1; 486 PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing " 487 "unencrypted EAPOL frame\n", dev->name); 488 tx.crypt = NULL; /* no encryption for IEEE 802.1X frames */ 489 } 490 491 if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu)) 492 tx.crypt = NULL; 493 else if ((tx.crypt || local->crypt[local->tx_keyidx]) && !no_encrypt) { 494 /* Add ISWEP flag both for firmware and host based encryption 495 */ 496 fc |= IEEE80211_FCTL_PROTECTED; 497 hdr->frame_ctl = cpu_to_le16(fc); 498 } else if (local->drop_unencrypted && 499 WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA && 500 meta->ethertype != ETH_P_PAE) { 501 if (net_ratelimit()) { 502 printk(KERN_DEBUG "%s: dropped unencrypted TX data " 503 "frame (drop_unencrypted=1)\n", dev->name); 504 } 505 iface->stats.tx_dropped++; 506 ret = 0; 507 goto fail; 508 } 509 510 if (tx.crypt) { 511 skb = hostap_tx_encrypt(skb, tx.crypt); 512 if (skb == NULL) { 513 printk(KERN_DEBUG "%s: TX - encryption failed\n", 514 dev->name); 515 ret = 0; 516 goto fail; 517 } 518 meta = (struct hostap_skb_tx_data *) skb->cb; 519 if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) { 520 printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, " 521 "expected 0x%08x) after hostap_tx_encrypt\n", 522 dev->name, meta->magic, 523 HOSTAP_SKB_TX_DATA_MAGIC); 524 ret = 0; 525 iface->stats.tx_dropped++; 526 goto fail; 527 } 528 } 529 530 if (local->func->tx == NULL || local->func->tx(skb, dev)) { 531 ret = 0; 532 iface->stats.tx_dropped++; 533 } else { 534 ret = 0; 535 iface->stats.tx_packets++; 536 iface->stats.tx_bytes += skb->len; 537 } 538 539 fail: 540 if (!ret && skb) 541 dev_kfree_skb(skb); 542 tx_exit: 543 if (tx.sta_ptr) 544 hostap_handle_sta_release(tx.sta_ptr); 545 return ret; 546} 547 548 549EXPORT_SYMBOL(hostap_master_start_xmit);