1 void hostap_dump_tx_80211(const char *name
, struct sk_buff
*skb
)
3 struct hostap_ieee80211_hdr
*hdr
;
6 hdr
= (struct hostap_ieee80211_hdr
*) skb
->data
;
8 printk(KERN_DEBUG
"%s: TX len=%d jiffies=%ld\n",
9 name
, skb
->len
, jiffies
);
14 fc
= le16_to_cpu(hdr
->frame_control
);
15 printk(KERN_DEBUG
" FC=0x%04x (type=%d:%d)%s%s",
16 fc
, WLAN_FC_GET_TYPE(fc
), WLAN_FC_GET_STYPE(fc
),
17 fc
& WLAN_FC_TODS
? " [ToDS]" : "",
18 fc
& WLAN_FC_FROMDS
? " [FromDS]" : "");
20 if (skb
->len
< IEEE80211_DATA_HDR3_LEN
) {
25 printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr
->duration_id
),
26 le16_to_cpu(hdr
->seq_ctrl
));
28 printk(KERN_DEBUG
" A1=" MACSTR
" A2=" MACSTR
" A3=" MACSTR
,
29 MAC2STR(hdr
->addr1
), MAC2STR(hdr
->addr2
), MAC2STR(hdr
->addr3
));
31 printk(" A4=" MACSTR
, MAC2STR(hdr
->addr4
));
36 /* hard_start_xmit function for data interfaces (wlan#, wlan#wds#, wlan#sta)
37 * Convert Ethernet header into a suitable IEEE 802.11 header depending on
38 * device configuration. */
39 int hostap_data_start_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
41 struct hostap_interface
*iface
;
43 int need_headroom
, need_tailroom
= 0;
44 struct hostap_ieee80211_hdr hdr
;
45 u16 fc
, ethertype
= 0;
47 WDS_NO
= 0, WDS_OWN_FRAME
, WDS_COMPLIANT_FRAME
50 int hdr_len
, encaps_len
, skip_header_bytes
;
52 struct hostap_skb_tx_data
*meta
;
54 iface
= netdev_priv(dev
);
57 if (skb
->len
< ETH_HLEN
) {
58 printk(KERN_DEBUG
"%s: hostap_data_start_xmit: short skb "
59 "(len=%d)\n", dev
->name
, skb
->len
);
64 if (local
->ddev
!= dev
) {
65 use_wds
= (local
->iw_mode
== IW_MODE_MASTER
&&
66 !(local
->wds_type
& HOSTAP_WDS_STANDARD_FRAME
)) ?
67 WDS_OWN_FRAME
: WDS_COMPLIANT_FRAME
;
68 if (dev
== local
->stadev
) {
71 } else if (dev
== local
->apdev
) {
72 printk(KERN_DEBUG
"%s: prism2_tx: trying to use "
73 "AP device with Ethernet net dev\n", dev
->name
);
78 if (local
->iw_mode
== IW_MODE_REPEAT
) {
79 printk(KERN_DEBUG
"%s: prism2_tx: trying to use "
80 "non-WDS link in Repeater mode\n", dev
->name
);
83 } else if (local
->iw_mode
== IW_MODE_INFRA
&&
84 (local
->wds_type
& HOSTAP_WDS_AP_CLIENT
) &&
85 memcmp(skb
->data
+ ETH_ALEN
, dev
->dev_addr
,
87 /* AP client mode: send frames with foreign src addr
88 * using 4-addr WDS frames */
89 use_wds
= WDS_COMPLIANT_FRAME
;
93 /* Incoming skb->data: dst_addr[6], src_addr[6], proto[2], payload
95 * Prism2 TX frame with 802.11 header:
96 * txdesc (address order depending on used mode; includes dst_addr and
97 * src_addr), possible encapsulation (RFC1042/Bridge-Tunnel;
98 * proto[2], payload {, possible addr4[6]} */
100 ethertype
= (skb
->data
[12] << 8) | skb
->data
[13];
102 memset(&hdr
, 0, sizeof(hdr
));
104 /* Length of data after IEEE 802.11 header */
107 skip_header_bytes
= ETH_HLEN
;
108 if (ethertype
== ETH_P_AARP
|| ethertype
== ETH_P_IPX
) {
109 encaps_data
= bridge_tunnel_header
;
110 encaps_len
= sizeof(bridge_tunnel_header
);
111 skip_header_bytes
-= 2;
112 } else if (ethertype
>= 0x600) {
113 encaps_data
= rfc1042_header
;
114 encaps_len
= sizeof(rfc1042_header
);
115 skip_header_bytes
-= 2;
118 fc
= (WLAN_FC_TYPE_DATA
<< 2) | (WLAN_FC_STYPE_DATA
<< 4);
119 hdr_len
= IEEE80211_DATA_HDR3_LEN
;
121 if (use_wds
!= WDS_NO
) {
122 /* Note! Prism2 station firmware has problems with sending real
123 * 802.11 frames with four addresses; until these problems can
124 * be fixed or worked around, 4-addr frames needed for WDS are
125 * using incompatible format: FromDS flag is not set and the
126 * fourth address is added after the frame payload; it is
127 * assumed, that the receiving station knows how to handle this
130 if (use_wds
== WDS_COMPLIANT_FRAME
) {
131 fc
|= WLAN_FC_FROMDS
| WLAN_FC_TODS
;
132 /* From&To DS: Addr1 = RA, Addr2 = TA, Addr3 = DA,
134 memcpy(&hdr
.addr4
, skb
->data
+ ETH_ALEN
, ETH_ALEN
);
137 /* bogus 4-addr format to workaround Prism2 station
140 /* From DS: Addr1 = DA (used as RA),
141 * Addr2 = BSSID (used as TA), Addr3 = SA (used as DA),
144 /* SA from skb->data + ETH_ALEN will be added after
145 * frame payload; use hdr.addr4 as a temporary buffer
147 memcpy(&hdr
.addr4
, skb
->data
+ ETH_ALEN
, ETH_ALEN
);
148 need_tailroom
+= ETH_ALEN
;
151 /* send broadcast and multicast frames to broadcast RA, if
152 * configured; otherwise, use unicast RA of the WDS link */
153 if ((local
->wds_type
& HOSTAP_WDS_BROADCAST_RA
) &&
155 memset(&hdr
.addr1
, 0xff, ETH_ALEN
);
156 else if (iface
->type
== HOSTAP_INTERFACE_WDS
)
157 memcpy(&hdr
.addr1
, iface
->u
.wds
.remote_addr
,
160 memcpy(&hdr
.addr1
, local
->bssid
, ETH_ALEN
);
161 memcpy(&hdr
.addr2
, dev
->dev_addr
, ETH_ALEN
);
162 memcpy(&hdr
.addr3
, skb
->data
, ETH_ALEN
);
163 } else if (local
->iw_mode
== IW_MODE_MASTER
&& !to_assoc_ap
) {
164 fc
|= WLAN_FC_FROMDS
;
165 /* From DS: Addr1 = DA, Addr2 = BSSID, Addr3 = SA */
166 memcpy(&hdr
.addr1
, skb
->data
, ETH_ALEN
);
167 memcpy(&hdr
.addr2
, dev
->dev_addr
, ETH_ALEN
);
168 memcpy(&hdr
.addr3
, skb
->data
+ ETH_ALEN
, ETH_ALEN
);
169 } else if (local
->iw_mode
== IW_MODE_INFRA
|| to_assoc_ap
) {
171 /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
172 memcpy(&hdr
.addr1
, to_assoc_ap
?
173 local
->assoc_ap_addr
: local
->bssid
, ETH_ALEN
);
174 memcpy(&hdr
.addr2
, skb
->data
+ ETH_ALEN
, ETH_ALEN
);
175 memcpy(&hdr
.addr3
, skb
->data
, ETH_ALEN
);
176 } else if (local
->iw_mode
== IW_MODE_ADHOC
) {
177 /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
178 memcpy(&hdr
.addr1
, skb
->data
, ETH_ALEN
);
179 memcpy(&hdr
.addr2
, skb
->data
+ ETH_ALEN
, ETH_ALEN
);
180 memcpy(&hdr
.addr3
, local
->bssid
, ETH_ALEN
);
183 hdr
.frame_control
= cpu_to_le16(fc
);
185 skb_pull(skb
, skip_header_bytes
);
186 need_headroom
= local
->func
->need_tx_headroom
+ hdr_len
+ encaps_len
;
187 if (skb_tailroom(skb
) < need_tailroom
) {
188 skb
= skb_unshare(skb
, GFP_ATOMIC
);
190 iface
->stats
.tx_dropped
++;
193 if (pskb_expand_head(skb
, need_headroom
, need_tailroom
,
196 iface
->stats
.tx_dropped
++;
199 } else if (skb_headroom(skb
) < need_headroom
) {
200 struct sk_buff
*tmp
= skb
;
201 skb
= skb_realloc_headroom(skb
, need_headroom
);
204 iface
->stats
.tx_dropped
++;
208 skb
= skb_unshare(skb
, GFP_ATOMIC
);
210 iface
->stats
.tx_dropped
++;
216 memcpy(skb_push(skb
, encaps_len
), encaps_data
, encaps_len
);
217 memcpy(skb_push(skb
, hdr_len
), &hdr
, hdr_len
);
218 if (use_wds
== WDS_OWN_FRAME
) {
219 memcpy(skb_put(skb
, ETH_ALEN
), &hdr
.addr4
, ETH_ALEN
);
222 iface
->stats
.tx_packets
++;
223 iface
->stats
.tx_bytes
+= skb
->len
;
225 skb
->mac
.raw
= skb
->data
;
226 meta
= (struct hostap_skb_tx_data
*) skb
->cb
;
227 memset(meta
, 0, sizeof(*meta
));
228 meta
->magic
= HOSTAP_SKB_TX_DATA_MAGIC
;
230 meta
->ethertype
= ethertype
;
233 /* Send IEEE 802.11 encapsulated frame using the master radio device */
234 skb
->dev
= local
->dev
;
240 /* hard_start_xmit function for hostapd wlan#ap interfaces */
241 int hostap_mgmt_start_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
243 struct hostap_interface
*iface
;
245 struct hostap_skb_tx_data
*meta
;
246 struct hostap_ieee80211_hdr
*hdr
;
249 iface
= netdev_priv(dev
);
250 local
= iface
->local
;
253 printk(KERN_DEBUG
"%s: hostap_mgmt_start_xmit: short skb "
254 "(len=%d)\n", dev
->name
, skb
->len
);
259 iface
->stats
.tx_packets
++;
260 iface
->stats
.tx_bytes
+= skb
->len
;
262 meta
= (struct hostap_skb_tx_data
*) skb
->cb
;
263 memset(meta
, 0, sizeof(*meta
));
264 meta
->magic
= HOSTAP_SKB_TX_DATA_MAGIC
;
267 if (skb
->len
>= IEEE80211_DATA_HDR3_LEN
+ sizeof(rfc1042_header
) + 2) {
268 hdr
= (struct hostap_ieee80211_hdr
*) skb
->data
;
269 fc
= le16_to_cpu(hdr
->frame_control
);
270 if (WLAN_FC_GET_TYPE(fc
) == WLAN_FC_TYPE_DATA
&&
271 WLAN_FC_GET_STYPE(fc
) == WLAN_FC_STYPE_DATA
) {
272 u8
*pos
= &skb
->data
[IEEE80211_DATA_HDR3_LEN
+
273 sizeof(rfc1042_header
)];
274 meta
->ethertype
= (pos
[0] << 8) | pos
[1];
278 /* Send IEEE 802.11 encapsulated frame using the master radio device */
279 skb
->dev
= local
->dev
;
285 /* Called only from software IRQ */
286 struct sk_buff
* hostap_tx_encrypt(struct sk_buff
*skb
,
287 struct prism2_crypt_data
*crypt
)
289 struct hostap_interface
*iface
;
291 struct hostap_ieee80211_hdr
*hdr
;
295 iface
= netdev_priv(skb
->dev
);
296 local
= iface
->local
;
298 if (skb
->len
< IEEE80211_DATA_HDR3_LEN
) {
303 if (local
->tkip_countermeasures
&&
304 crypt
&& crypt
->ops
&& strcmp(crypt
->ops
->name
, "TKIP") == 0) {
305 hdr
= (struct hostap_ieee80211_hdr
*) skb
->data
;
306 if (net_ratelimit()) {
307 printk(KERN_DEBUG
"%s: TKIP countermeasures: dropped "
308 "TX packet to " MACSTR
"\n",
309 local
->dev
->name
, MAC2STR(hdr
->addr1
));
315 skb
= skb_unshare(skb
, GFP_ATOMIC
);
319 if ((skb_headroom(skb
) < crypt
->ops
->extra_prefix_len
||
320 skb_tailroom(skb
) < crypt
->ops
->extra_postfix_len
) &&
321 pskb_expand_head(skb
, crypt
->ops
->extra_prefix_len
,
322 crypt
->ops
->extra_postfix_len
, GFP_ATOMIC
)) {
327 hdr
= (struct hostap_ieee80211_hdr
*) skb
->data
;
328 fc
= le16_to_cpu(hdr
->frame_control
);
329 hdr_len
= hostap_80211_get_hdrlen(fc
);
331 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
332 * call both MSDU and MPDU encryption functions from here. */
333 atomic_inc(&crypt
->refcnt
);
335 if (crypt
->ops
->encrypt_msdu
)
336 res
= crypt
->ops
->encrypt_msdu(skb
, hdr_len
, crypt
->priv
);
337 if (res
== 0 && crypt
->ops
->encrypt_mpdu
)
338 res
= crypt
->ops
->encrypt_mpdu(skb
, hdr_len
, crypt
->priv
);
339 atomic_dec(&crypt
->refcnt
);
349 /* hard_start_xmit function for master radio interface wifi#.
350 * AP processing (TX rate control, power save buffering, etc.).
351 * Use hardware TX function to send the frame. */
352 int hostap_master_start_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
354 struct hostap_interface
*iface
;
358 struct hostap_tx_data tx
;
360 struct hostap_skb_tx_data
*meta
;
362 struct hostap_ieee80211_hdr
*hdr
;
364 iface
= netdev_priv(dev
);
365 local
= iface
->local
;
370 meta
= (struct hostap_skb_tx_data
*) skb
->cb
;
371 if (meta
->magic
!= HOSTAP_SKB_TX_DATA_MAGIC
) {
372 printk(KERN_DEBUG
"%s: invalid skb->cb magic (0x%08x, "
373 "expected 0x%08x)\n",
374 dev
->name
, meta
->magic
, HOSTAP_SKB_TX_DATA_MAGIC
);
376 iface
->stats
.tx_dropped
++;
380 if (local
->host_encrypt
) {
381 /* Set crypt to default algorithm and key; will be replaced in
382 * AP code if STA has own alg/key */
383 tx
.crypt
= local
->crypt
[local
->tx_keyidx
];
391 printk(KERN_DEBUG
"%s: hostap_master_start_xmit: short skb "
392 "(len=%d)\n", dev
->name
, skb
->len
);
394 iface
->stats
.tx_dropped
++;
399 * Wi-Fi 802.11b test plan suggests that AP should ignore power save
400 * bit in authentication and (re)association frames and assume tha
401 * STA remains awake for the response. */
402 tx_ret
= hostap_handle_sta_tx(local
, &tx
);
404 meta
= (struct hostap_skb_tx_data
*) skb
->cb
;
405 hdr
= (struct hostap_ieee80211_hdr
*) skb
->data
;
406 fc
= le16_to_cpu(hdr
->frame_control
);
410 case AP_TX_CONTINUE_NOT_AUTHORIZED
:
411 if (local
->ieee_802_1x
&&
412 WLAN_FC_GET_TYPE(fc
) == WLAN_FC_TYPE_DATA
&&
413 meta
->ethertype
!= ETH_P_PAE
&& !meta
->wds
) {
414 printk(KERN_DEBUG
"%s: dropped frame to unauthorized "
415 "port (IEEE 802.1X): ethertype=0x%04x\n",
416 dev
->name
, meta
->ethertype
);
417 hostap_dump_tx_80211(dev
->name
, skb
);
419 ret
= 0; /* drop packet */
420 iface
->stats
.tx_dropped
++;
425 ret
= 0; /* drop packet */
426 iface
->stats
.tx_dropped
++;
431 /* do not free skb here, it will be freed when the
432 * buffered frame is sent/timed out */
437 /* Request TX callback if protocol version is 2 in 802.11 header;
438 * this version 2 is a special case used between hostapd and kernel
440 if (((fc
& WLAN_FC_PVER
) == BIT(1)) &&
441 local
->ap
&& local
->ap
->tx_callback_idx
&& meta
->tx_cb_idx
== 0) {
442 meta
->tx_cb_idx
= local
->ap
->tx_callback_idx
;
444 /* remove special version from the frame header */
446 hdr
->frame_control
= cpu_to_le16(fc
);
449 if (WLAN_FC_GET_TYPE(fc
) != WLAN_FC_TYPE_DATA
) {
454 if (local
->ieee_802_1x
&& meta
->ethertype
== ETH_P_PAE
&& tx
.crypt
&&
455 !(fc
& WLAN_FC_ISWEP
)) {
457 PDEBUG(DEBUG_EXTRA2
, "%s: TX: IEEE 802.1X - passing "
458 "unencrypted EAPOL frame\n", dev
->name
);
459 tx
.crypt
= NULL
; /* no encryption for IEEE 802.1X frames */
462 if (tx
.crypt
&& (!tx
.crypt
->ops
|| !tx
.crypt
->ops
->encrypt_mpdu
))
464 else if ((tx
.crypt
|| local
->crypt
[local
->tx_keyidx
]) && !no_encrypt
) {
465 /* Add ISWEP flag both for firmware and host based encryption
468 hdr
->frame_control
= cpu_to_le16(fc
);
469 } else if (local
->drop_unencrypted
&&
470 WLAN_FC_GET_TYPE(fc
) == WLAN_FC_TYPE_DATA
&&
471 meta
->ethertype
!= ETH_P_PAE
) {
472 if (net_ratelimit()) {
473 printk(KERN_DEBUG
"%s: dropped unencrypted TX data "
474 "frame (drop_unencrypted=1)\n", dev
->name
);
476 iface
->stats
.tx_dropped
++;
482 skb
= hostap_tx_encrypt(skb
, tx
.crypt
);
484 printk(KERN_DEBUG
"%s: TX - encryption failed\n",
489 meta
= (struct hostap_skb_tx_data
*) skb
->cb
;
490 if (meta
->magic
!= HOSTAP_SKB_TX_DATA_MAGIC
) {
491 printk(KERN_DEBUG
"%s: invalid skb->cb magic (0x%08x, "
492 "expected 0x%08x) after hostap_tx_encrypt\n",
493 dev
->name
, meta
->magic
,
494 HOSTAP_SKB_TX_DATA_MAGIC
);
496 iface
->stats
.tx_dropped
++;
501 if (local
->func
->tx
== NULL
|| local
->func
->tx(skb
, dev
)) {
503 iface
->stats
.tx_dropped
++;
506 iface
->stats
.tx_packets
++;
507 iface
->stats
.tx_bytes
+= skb
->len
;
515 hostap_handle_sta_release(tx
.sta_ptr
);
520 EXPORT_SYMBOL(hostap_dump_tx_80211
);
521 EXPORT_SYMBOL(hostap_tx_encrypt
);
522 EXPORT_SYMBOL(hostap_master_start_xmit
);