2 * Copyright (c) 2007 Michael Taylor, Apprion
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * $Id: ieee80211_linux.c 2829 2007-11-05 20:43:50Z mtaylor $
35 * IEEE 802.11 support (Linux-specific code)
37 #ifndef AUTOCONF_INCLUDED
38 #include <linux/config.h>
40 #include <linux/version.h>
41 #include <linux/module.h>
42 #include <linux/kmod.h>
43 #include <linux/init.h>
44 #include <linux/skbuff.h>
45 #include <linux/sysctl.h>
46 #include <linux/netdevice.h>
47 #include <linux/etherdevice.h>
48 #include <linux/if_vlan.h>
49 #include <linux/vmalloc.h>
50 #include <linux/proc_fs.h>
52 #include <net/iw_handler.h>
53 #include <linux/wireless.h>
54 #include <linux/if_arp.h> /* XXX for ARPHRD_* */
56 #include <asm/uaccess.h>
59 #include "if_ethersubr.h"
61 #include <net80211/ieee80211_var.h>
62 #include <net80211/ieee80211_monitor.h>
64 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
65 #include <linux/device.h>
71 #undef dev_kfree_skb_any
72 #undef dev_kfree_skb_irq
80 #undef skb_copy_expand
82 #undef skb_realloc_headroom
83 #undef skb_share_check
85 #undef vlan_hwaccel_rx
87 atomic_t skb_total_counter
= ATOMIC_INIT(0);
88 EXPORT_SYMBOL(skb_total_counter
);
90 #ifdef IEEE80211_DEBUG_REFCNT
91 atomic_t skb_refs_counter
= ATOMIC_INIT(0);
92 EXPORT_SYMBOL(skb_refs_counter
);
95 /*******************************************************************************
97 ******************************************************************************/
99 static void skb_print_message(
101 const struct sk_buff
*skb
,
102 const char *func
, int line
,
107 char skb_count
[32] = { '\0' };
108 char expanded_message
[1024] = { '\0' };
110 #ifdef IEEE80211_DEBUG_REFCNT
113 "[#SKB=%05d #REF=%05d] ",
114 atomic_read(&skb_total_counter
),
115 atomic_read(&skb_refs_counter
));
120 atomic_read(&skb_total_counter
));
124 va_start(args
, message
);
125 vsnprintf(expanded_message
, sizeof(expanded_message
), message
, args
);
126 printk(KERN_DEBUG
"%s: %s%s:%d %s\n",
127 ((skb
!= NULL
) ? DEV_NAME(skb
->dev
) : "none"),
132 #ifdef IEEE80211_DEBUG_REFCNT
137 #ifdef IEEE80211_DEBUG_REFCNT
140 print_skb_refchange_message(
141 const struct sk_buff
*skb
, int users_adjustment
,
142 const char *func
, int line
);
144 print_skb_trackchange_message(
145 const struct sk_buff
*skb
, int users_adjustment
,
146 const char *func
, int line
,
149 /* Called automatically when an SKB reaches zero users,
150 * reporting any leaked node references. */
151 #ifdef IEEE80211_DEBUG_REFCNT_SKBDEST
152 static void skb_destructor(struct sk_buff
*skb
);
154 static void get_skb_description(char *dst
, int dst_size
, const char *label
,
155 const struct sk_buff
*skb
, int users_adjustment
);
157 static struct sk_buff
*
158 clean_clone_or_copy(struct sk_buff
*skb
);
160 static struct sk_buff
*
161 track_skb(struct sk_buff
*skb
, int users_adjustment
,
162 const char *func
, int line
);
164 static struct sk_buff
*
165 untrack_skb(struct sk_buff
*skb
, int users_adjustment
,
166 const char *func
, int line
);
168 #define UNREF_USE_KFREE_SKB 0
169 #define UNREF_USE_DEV_KFREE_SKB_ANY 1
170 #define UNREF_USE_DEV_KFREE_SKB 2
171 #define UNREF_USE_DEV_KFREE_SKB_IRQ 3
173 /* Assumes SKB is not yet freed at the time of the call and shows the new users
174 * count as (users - 1). */
175 static void unref_skb(struct sk_buff
*skb
, int type
,
176 const char *func
, int line
);
178 /* Assumes SKB reference counter has already been updated and reports count as
179 * atomic_read(&skb->users). */
180 static struct sk_buff
*
181 ref_skb(struct sk_buff
*skb
,
182 const char *func
, int line
);
185 #ifdef IEEE80211_DEBUG_REFCNT_SKBDEST
186 /* Destructor for reporting node reference leaks */
187 static void skb_destructor(struct sk_buff
*skb
) {
188 /* Report any node reference leaks - caused by kernel net device queue
189 * dropping buffer, rather than passing it to the driver. */
190 if (SKB_NI(skb
) != NULL
) {
191 printk(KERN_ERR
"%s:%d - ERROR: non-NULL node pointer in %p, %p<" MAC_FMT
">! "
194 skb
, SKB_NI(skb
), MAC_ADDR(SKB_NI(skb
)->ni_macaddr
));
197 if (SKB_CB(skb
)->next_destructor
!= NULL
) {
198 SKB_CB(skb
)->next_destructor(skb
);
201 EXPORT_SYMBOL(skb_destructor
);
202 #endif /* #ifdef IEEE80211_DEBUG_REFCNT_SKBDEST */
204 static void get_skb_description(char *dst
, int dst_size
, const char *label
, const struct sk_buff
*skb
, int users_adjustment
) {
207 int adj_users
= atomic_read(&skb
->users
) + users_adjustment
;
208 if (SKB_NI(skb
) != NULL
) {
209 snprintf(dst
, dst_size
,
210 " [%s%s%p,users=%d,node=%p<" MAC_FMT
">,aid=%d%s%s]",
212 (label
!= NULL
? ": " : ""),
216 MAC_ADDR(SKB_NI(skb
)->ni_macaddr
),
217 SKB_NI(skb
)->ni_associd
,
218 ((adj_users
< 0) ? " ** CORRUPTED **" : ""),
219 ((adj_users
== 0) ? " ** RELEASED **" : "")
223 snprintf(dst
, dst_size
,
224 " [%s%s%p,users=%d,node=NULL,aid=N/A%s%s]",
226 (label
!= NULL
? ": " : ""),
229 ((adj_users
< 0) ? " ** CORRUPTED **" : ""),
230 ((adj_users
== 0) ? " ** RELEASED **" : "")
233 dst
[dst_size
-1] = '\0';
237 static void print_skb_refchange_message(
238 const struct sk_buff
*skb
, int users_adjustment
,
239 const char *func
, int line
)
241 char skb_desc
[128] = { '\0' };
242 if (0 == (ath_debug_global
& GLOBAL_DEBUG_SKB_REF
))
244 get_skb_description(skb_desc
, sizeof(skb_desc
),
245 "skb", skb
, users_adjustment
);
246 skb_print_message(0 /* no global count */, skb
,
251 static void print_skb_trackchange_message(
252 const struct sk_buff
*skb
, int users_adjustment
,
253 const char *func
, int line
,
256 char skb_desc
[128] = { '\0' };
257 if (0 == (ath_debug_global
& GLOBAL_DEBUG_SKB
))
259 get_skb_description(skb_desc
, sizeof(skb_desc
),
260 "skb", skb
, users_adjustment
);
261 skb_print_message(1 /* show global count */, skb
,
263 "%s%s", skb_desc
, message
);
266 static struct sk_buff
*
267 clean_clone_or_copy(struct sk_buff
*skb
) {
269 M_FLAG_CLR(skb
, M_SKB_TRACKED
);
273 static struct sk_buff
*
274 track_skb(struct sk_buff
*skb
, int users_adjustment
,
275 const char *func
, int line
)
278 skb_print_message(0 /* show_counter */,
280 "ERROR: NULL skb received. Skipping.");
283 if (M_FLAG_GET(skb
, M_SKB_TRACKED
)) {
284 skb_print_message(0 /* show_counter */,
286 "ERROR: Already tracked skb received. Skipping.");
290 if (skb_shared(skb
)) {
291 skb_print_message(0 /* show_counter */,
293 "ERROR: Shared skb received. References leaked??");
296 atomic_inc(&skb_total_counter
);
297 atomic_inc(&skb_refs_counter
);
298 M_FLAG_SET(skb
, M_SKB_TRACKED
);
299 print_skb_trackchange_message(skb
, users_adjustment
,
301 " is now ** TRACKED **");
302 #ifdef IEEE80211_DEBUG_REFCNT_SKBDEST
303 /* Install our debug destructor, chaining to the original... */
304 if (skb
->destructor
!= skb_destructor
) {
305 SKB_CB(skb
)->next_destructor
= skb
->destructor
;
306 skb
->destructor
= skb_destructor
;
308 #endif /* #ifdef IEEE80211_DEBUG_REFCNT_SKBDEST */
312 static struct sk_buff
*
313 untrack_skb(struct sk_buff
*skb
, int users_adjustment
,
314 const char *func
, int line
)
317 skb_print_message(0 /* show_counter */,
319 "ERROR: NULL skb received. No changes made.");
322 if (!M_FLAG_GET(skb
, M_SKB_TRACKED
)) {
323 skb_print_message(0 /* show_counter */,
325 "ERROR: Untracked skb received. No changes made.");
328 if (skb_shared(skb
)) {
329 skb_print_message(0 /* show_counter */,
331 "ERROR: Shared skb received. References leaked??");
333 atomic_dec(&skb_total_counter
);
334 atomic_dec(&skb_refs_counter
);
335 M_FLAG_CLR(skb
, M_SKB_TRACKED
);
336 #ifdef IEEE80211_DEBUG_REFCNT_SKBDEST
337 /* Uninstall our debug destructor, restoring any original... */
338 if (skb
->destructor
== skb_destructor
) {
339 skb
->destructor
= SKB_CB(skb
)->next_destructor
;
340 SKB_CB(skb
)->next_destructor
= NULL
;
342 #endif /* #ifdef IEEE80211_DEBUG_REFCNT_SKBDEST */
343 print_skb_trackchange_message(skb
, users_adjustment
,
345 " is now ** UNTRACKED **");
349 #define UNREF_USE_KFREE_SKB 0
350 #define UNREF_USE_DEV_KFREE_SKB_ANY 1
351 #define UNREF_USE_DEV_KFREE_SKB 2
352 #define UNREF_USE_DEV_KFREE_SKB_IRQ 3
354 /* Assumes SKB is not yet freed at the time of the call and shows the new users
355 * count as (users - 1). */
357 unref_skb(struct sk_buff
*skb
, int type
,
358 const char *func
, int line
)
361 skb_print_message(0 /* show_counter */,
363 "ERROR: NULL skb received.");
367 if (!M_FLAG_GET(skb
, M_SKB_TRACKED
)) {
368 skb_print_message(0 /* show_counter */,
370 "ERROR: Untracked skb received. Probable duplicate free error!");
374 /* If free is unacceptable for current user count, report the error. */
375 if (atomic_read(&skb
->users
) < 1) {
376 skb_print_message(0 /* show_counter */,
378 "ERROR: free an skb with %d users",
379 atomic_read(&skb
->users
));
384 if (skb_shared(skb
)) {
385 atomic_dec(&skb_refs_counter
);
386 print_skb_refchange_message(skb
, -1, func2
, line2
);
389 if (SKB_NI(skb
) != NULL
) {
390 printk(KERN_ERR
"%s:%d - ERROR: non-NULL node pointer in %p, %p<" MAC_FMT
">! "
391 "Driver Leak Detected!\n",
393 skb
, SKB_NI(skb
), MAC_ADDR(SKB_NI(skb
)->ni_macaddr
));
395 /* Allow the leak and let programmer fix it, but do not
396 * report it again in the destructor. */
399 untrack_skb(skb
, -1, func
, line
);
402 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
403 if ((in_irq() || irqs_disabled()) &&
404 (type
== UNREF_USE_KFREE_SKB
||
405 type
== UNREF_USE_DEV_KFREE_SKB
)) {
406 skb_print_message(0 /* show_counter */,
408 "ERROR: free an skb in interrupt context using a non-"
409 "safe form of skb free function.");
410 type
= UNREF_USE_DEV_KFREE_SKB_ANY
;
416 case UNREF_USE_DEV_KFREE_SKB_ANY
:
417 dev_kfree_skb_any(skb
);
419 case UNREF_USE_DEV_KFREE_SKB_IRQ
:
420 dev_kfree_skb_irq(skb
);
422 case UNREF_USE_DEV_KFREE_SKB
:
423 /* NOTE: dev_kfree_skb is a macro pointing to kfree_skb, so
425 case UNREF_USE_KFREE_SKB
:
433 /* Assumes SKB reference counter has already been updated and reports count as
434 * atomic_read(&skb->users). */
435 static struct sk_buff
*
436 ref_skb(struct sk_buff
*skb
,
437 const char *func
, int line
)
440 skb_print_message(0 /* show_counter */,
442 "ERROR: NULL skb received. No changes made.");
446 if (!M_FLAG_GET(skb
, M_SKB_TRACKED
)) {
447 skb_print_message(0 /* show_counter */,
449 "ERROR: Untracked skb received. Probable use after free! "
454 print_skb_refchange_message(skb
, 0, func
, line
);
458 #endif /* #ifdef IEEE80211_DEBUG_REFCNT */
460 /*******************************************************************************
462 ******************************************************************************/
464 /* ieee80211_dev_kfree_skb will release one reference from SKB.
465 * If SKB refcount is going to zero:
466 * - Free the node reference and set it to null.
467 * - Break the linked list, clearing next skb's prev pointer if possible. */
468 void ieee80211_dev_kfree_skb(struct sk_buff
**pskb
)
472 /* Do not fail on null, as we are going to use this in cleanup code. */
473 if (!pskb
|| !(skb
= *pskb
))
476 /* Release the SKB references, for fragments of chain that are
477 * unshared... starting at skb passed in. */
478 if (skb
->prev
== NULL
) {
479 if (skb
->next
!= NULL
)
480 skb
->next
->prev
= NULL
;
484 if (SKB_NI(skb
) != NULL
)
485 ieee80211_unref_node(&SKB_NI(skb
));
487 #ifdef IEEE80211_DEBUG_REFCNT
488 unref_skb(skb
, UNREF_USE_DEV_KFREE_SKB_ANY
,
491 dev_kfree_skb_any(skb
);
497 /* ieee80211_dev_kfree_skb_list will invoke ieee80211_dev_kfree_skb on each node in
498 * a list of skbs, starting with the first. */
500 ieee80211_dev_kfree_skb_list(struct sk_buff
**pskb
)
502 struct sk_buff
*skb
, *tskb
;
504 /* Do not fail on null, as we are going to use this in cleanup code */
505 if (!pskb
|| !(skb
= *pskb
))
511 ieee80211_dev_kfree_skb(&skb
);
519 ieee80211_dev_alloc_skb(int size
)
521 struct sk_buff
*skb
= dev_alloc_skb(size
);
524 0 /* show_counter */,
527 "sk_buff allocation of size %u failed",
532 #ifdef IEEE80211_DEBUG_REFCNT
533 return track_skb(skb
, 0, __func__
, __LINE__
);
540 ieee80211_skb_track(struct sk_buff
*skb
) {
541 #ifdef IEEE80211_DEBUG_REFCNT
542 track_skb(skb
, 0 /* users_adjustment */,
545 /* Just a dumb counter, in no-debug builds */
546 atomic_inc(&skb_total_counter
);
547 #endif /* #ifdef IEEE80211_DEBUG_REFCNT */
551 ieee80211_skb_untrack(struct sk_buff
*skb
) {
552 /* Just a dumb counter, in no-debug builds */
553 atomic_dec(&skb_total_counter
);
556 #ifdef IEEE80211_DEBUG_REFCNT
558 ieee80211_skb_counter(void) {
559 return atomic_read(&skb_total_counter
);
563 ieee80211_skb_references(void) {
564 return atomic_read(&skb_refs_counter
);
566 #endif /* #ifdef IEEE80211_DEBUG_REFCNT */
568 /*******************************************************************************
569 * skbuff leak/refcount debugging Replacement Functions
570 * PUT last in order to avoid conflicts with use of original functions in
571 * inline functions above this point.
572 ******************************************************************************/
574 #ifdef IEEE80211_DEBUG_REFCNT
576 int vlan_hwaccel_rx_debug(struct sk_buff
*skb
,
577 struct vlan_group
*grp
, unsigned short vlan_tag
,
578 const char *func
, int line
) {
579 return vlan_hwaccel_rx(
580 untrack_skb(skb
, 0, __func__
, __LINE__
),
584 int netif_rx_debug(struct sk_buff
*skb
, const char *func
, int line
) {
585 return netif_rx(untrack_skb(skb
, 0, __func__
, __LINE__
));
588 struct sk_buff
*alloc_skb_debug(unsigned int length
, gfp_t gfp_mask
,
589 const char *func
, int line
) {
590 return track_skb(alloc_skb(length
, gfp_mask
),
591 0 /* users_adjustment */,
595 struct sk_buff
*dev_alloc_skb_debug(unsigned int length
,
596 const char *func
, int line
)
598 return track_skb(dev_alloc_skb(length
),
599 0 /* users_adjustment */,
605 struct sk_buff
*skb_clone_debug(struct sk_buff
*skb
, gfp_t pri
,
606 const char *func
, int line
)
609 clean_clone_or_copy(skb_clone(skb
, pri
)),
610 0 /* users_adjustment */,
614 struct sk_buff
*skb_copy_debug(struct sk_buff
*skb
, gfp_t pri
,
615 const char *func
, int line
)
618 clean_clone_or_copy(skb_copy(skb
, pri
)), 0 /* users_adjustment */,
622 struct sk_buff
*skb_get_debug(struct sk_buff
*skb
,
623 const char *func
, int line
)
625 return ref_skb(skb_get(skb
),
629 struct sk_buff
*skb_realloc_headroom_debug(struct sk_buff
*skb
, unsigned int headroom
,
630 const char *func
, int line
)
632 /* skb_realloc_headroom ALWAYS returns a copy or a clone, refcount of
633 * new one is always zero and refcount of original is not touched. */
636 skb_realloc_headroom(skb
, headroom
)),
637 0 /* users_adjustment */,
641 struct sk_buff
*pskb_copy_debug(struct sk_buff
*skb
, gfp_t pri
,
642 const char *func
, int line
)
645 clean_clone_or_copy(pskb_copy(skb
, pri
)),
646 0 /* users_adjustment */,
650 int dev_queue_xmit_debug(struct sk_buff
*skb
,
651 const char *func
, int line
)
653 return dev_queue_xmit(untrack_skb(skb
, 0, __func__
, __LINE__
));
656 struct sk_buff
*skb_share_check_debug(struct sk_buff
*skb
, gfp_t pri
,
657 const char *func
, int line
)
659 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
660 might_sleep_if(pri
& __GFP_WAIT
);
662 if (skb_shared(skb
)) {
663 struct sk_buff
*nskb
= track_skb(
664 clean_clone_or_copy(skb_clone(skb
, pri
)),
667 unref_skb(skb
, UNREF_USE_DEV_KFREE_SKB_ANY
,
674 void kfree_skb_fast_debug(struct sk_buff
*skb
,
675 const char *func
, int line
)
678 unref_skb(skb
, UNREF_USE_DEV_KFREE_SKB_ANY
, func
, line
, __func__
, __LINE__
);
681 struct sk_buff
*skb_unshare_debug(struct sk_buff
*skb
, gfp_t pri
,
682 const char *func
, int line
)
684 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
685 might_sleep_if(pri
& __GFP_WAIT
);
687 if (skb_cloned(skb
)) {
688 struct sk_buff
*nskb
= track_skb(
689 clean_clone_or_copy(skb_copy(skb
, pri
)), 0,
691 unref_skb(skb
, UNREF_USE_DEV_KFREE_SKB_ANY
,
698 struct sk_buff
*skb_copy_expand_debug(const struct sk_buff
*skb
, int newheadroom
,
699 int newtailroom
, gfp_t gfp_mask
,
700 const char *func
, int line
)
704 skb_copy_expand(skb
, newheadroom
, newtailroom
, gfp_mask
)),
705 0 /* users_adjustment */,
709 EXPORT_SYMBOL(vlan_hwaccel_rx_debug
);
710 EXPORT_SYMBOL(netif_rx_debug
);
711 EXPORT_SYMBOL(alloc_skb_debug
);
712 EXPORT_SYMBOL(dev_alloc_skb_debug
);
713 EXPORT_SYMBOL(skb_clone_debug
);
714 EXPORT_SYMBOL(skb_copy_debug
);
715 EXPORT_SYMBOL(skb_get_debug
);
716 EXPORT_SYMBOL(skb_realloc_headroom_debug
);
717 EXPORT_SYMBOL(pskb_copy_debug
);
718 EXPORT_SYMBOL(dev_queue_xmit_debug
);
719 EXPORT_SYMBOL(skb_share_check_debug
);
720 EXPORT_SYMBOL(kfree_skb_fast_debug
);
721 EXPORT_SYMBOL(skb_unshare_debug
);
722 EXPORT_SYMBOL(skb_copy_expand_debug
);
724 EXPORT_SYMBOL(ieee80211_skb_counter
);
725 EXPORT_SYMBOL(ieee80211_skb_references
);
726 #endif /* #ifdef IEEE80211_DEBUG_REFCNT */
728 EXPORT_SYMBOL(ieee80211_dev_alloc_skb
);
729 EXPORT_SYMBOL(ieee80211_skb_untrack
);
730 EXPORT_SYMBOL(ieee80211_dev_kfree_skb_list
);
731 EXPORT_SYMBOL(ieee80211_dev_kfree_skb
);
732 EXPORT_SYMBOL(ieee80211_skb_track
);