aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/Makefile2
-rw-r--r--net/core/dev.c56
-rw-r--r--net/core/dst.c3
-rw-r--r--net/core/neighbour.c14
-rw-r--r--net/core/netevent.c69
-rw-r--r--net/core/pktgen.c4
-rw-r--r--net/core/rtnetlink.c15
-rw-r--r--net/core/skbuff.c47
-rw-r--r--net/core/utils.c7
-rw-r--r--net/core/wireless.c24
10 files changed, 177 insertions, 64 deletions
diff --git a/net/core/Makefile b/net/core/Makefile
index e9bd2467d5a9..2645ba428d48 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -7,7 +7,7 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
7 7
8obj-$(CONFIG_SYSCTL) += sysctl_net_core.o 8obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
9 9
10obj-y += dev.o ethtool.o dev_mcast.o dst.o \ 10obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \
11 neighbour.o rtnetlink.o utils.o link_watch.o filter.o 11 neighbour.o rtnetlink.o utils.o link_watch.o filter.o
12 12
13obj-$(CONFIG_XFRM) += flow.o 13obj-$(CONFIG_XFRM) += flow.o
diff --git a/net/core/dev.c b/net/core/dev.c
index 4d2b5167d7f5..d4a1ec3bded5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -116,6 +116,7 @@
116#include <linux/audit.h> 116#include <linux/audit.h>
117#include <linux/dmaengine.h> 117#include <linux/dmaengine.h>
118#include <linux/err.h> 118#include <linux/err.h>
119#include <linux/ctype.h>
119 120
120/* 121/*
121 * The list of packet types we will receive (as opposed to discard) 122 * The list of packet types we will receive (as opposed to discard)
@@ -632,14 +633,22 @@ struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mas
632 * @name: name string 633 * @name: name string
633 * 634 *
634 * Network device names need to be valid file names to 635 * Network device names need to be valid file names to
635 * to allow sysfs to work 636 * to allow sysfs to work. We also disallow any kind of
637 * whitespace.
636 */ 638 */
637int dev_valid_name(const char *name) 639int dev_valid_name(const char *name)
638{ 640{
639 return !(*name == '\0' 641 if (*name == '\0')
640 || !strcmp(name, ".") 642 return 0;
641 || !strcmp(name, "..") 643 if (!strcmp(name, ".") || !strcmp(name, ".."))
642 || strchr(name, '/')); 644 return 0;
645
646 while (*name) {
647 if (*name == '/' || isspace(*name))
648 return 0;
649 name++;
650 }
651 return 1;
643} 652}
644 653
645/** 654/**
@@ -1166,11 +1175,6 @@ int skb_checksum_help(struct sk_buff *skb, int inward)
1166 goto out_set_summed; 1175 goto out_set_summed;
1167 1176
1168 if (unlikely(skb_shinfo(skb)->gso_size)) { 1177 if (unlikely(skb_shinfo(skb)->gso_size)) {
1169 static int warned;
1170
1171 WARN_ON(!warned);
1172 warned = 1;
1173
1174 /* Let GSO fix up the checksum. */ 1178 /* Let GSO fix up the checksum. */
1175 goto out_set_summed; 1179 goto out_set_summed;
1176 } 1180 }
@@ -1220,11 +1224,6 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
1220 __skb_pull(skb, skb->mac_len); 1224 __skb_pull(skb, skb->mac_len);
1221 1225
1222 if (unlikely(skb->ip_summed != CHECKSUM_HW)) { 1226 if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
1223 static int warned;
1224
1225 WARN_ON(!warned);
1226 warned = 1;
1227
1228 if (skb_header_cloned(skb) && 1227 if (skb_header_cloned(skb) &&
1229 (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) 1228 (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
1230 return ERR_PTR(err); 1229 return ERR_PTR(err);
@@ -1629,26 +1628,10 @@ static inline struct net_device *skb_bond(struct sk_buff *skb)
1629 struct net_device *dev = skb->dev; 1628 struct net_device *dev = skb->dev;
1630 1629
1631 if (dev->master) { 1630 if (dev->master) {
1632 /* 1631 if (skb_bond_should_drop(skb)) {
1633 * On bonding slaves other than the currently active
1634 * slave, suppress duplicates except for 802.3ad
1635 * ETH_P_SLOW and alb non-mcast/bcast.
1636 */
1637 if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
1638 if (dev->master->priv_flags & IFF_MASTER_ALB) {
1639 if (skb->pkt_type != PACKET_BROADCAST &&
1640 skb->pkt_type != PACKET_MULTICAST)
1641 goto keep;
1642 }
1643
1644 if (dev->master->priv_flags & IFF_MASTER_8023AD &&
1645 skb->protocol == __constant_htons(ETH_P_SLOW))
1646 goto keep;
1647
1648 kfree_skb(skb); 1632 kfree_skb(skb);
1649 return NULL; 1633 return NULL;
1650 } 1634 }
1651keep:
1652 skb->dev = dev->master; 1635 skb->dev = dev->master;
1653 } 1636 }
1654 1637
@@ -3429,12 +3412,9 @@ static void net_dma_rebalance(void)
3429 unsigned int cpu, i, n; 3412 unsigned int cpu, i, n;
3430 struct dma_chan *chan; 3413 struct dma_chan *chan;
3431 3414
3432 lock_cpu_hotplug();
3433
3434 if (net_dma_count == 0) { 3415 if (net_dma_count == 0) {
3435 for_each_online_cpu(cpu) 3416 for_each_online_cpu(cpu)
3436 rcu_assign_pointer(per_cpu(softnet_data.net_dma, cpu), NULL); 3417 rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL);
3437 unlock_cpu_hotplug();
3438 return; 3418 return;
3439 } 3419 }
3440 3420
@@ -3447,15 +3427,13 @@ static void net_dma_rebalance(void)
3447 + (i < (num_online_cpus() % net_dma_count) ? 1 : 0)); 3427 + (i < (num_online_cpus() % net_dma_count) ? 1 : 0));
3448 3428
3449 while(n) { 3429 while(n) {
3450 per_cpu(softnet_data.net_dma, cpu) = chan; 3430 per_cpu(softnet_data, cpu).net_dma = chan;
3451 cpu = next_cpu(cpu, cpu_online_map); 3431 cpu = next_cpu(cpu, cpu_online_map);
3452 n--; 3432 n--;
3453 } 3433 }
3454 i++; 3434 i++;
3455 } 3435 }
3456 rcu_read_unlock(); 3436 rcu_read_unlock();
3457
3458 unlock_cpu_hotplug();
3459} 3437}
3460 3438
3461/** 3439/**
diff --git a/net/core/dst.c b/net/core/dst.c
index 470c05bc4cb2..1a5e49da0e77 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -95,12 +95,11 @@ static void dst_run_gc(unsigned long dummy)
95 dst_gc_timer_inc = DST_GC_INC; 95 dst_gc_timer_inc = DST_GC_INC;
96 dst_gc_timer_expires = DST_GC_MIN; 96 dst_gc_timer_expires = DST_GC_MIN;
97 } 97 }
98 dst_gc_timer.expires = jiffies + dst_gc_timer_expires;
99#if RT_CACHE_DEBUG >= 2 98#if RT_CACHE_DEBUG >= 2
100 printk("dst_total: %d/%d %ld\n", 99 printk("dst_total: %d/%d %ld\n",
101 atomic_read(&dst_total), delayed, dst_gc_timer_expires); 100 atomic_read(&dst_total), delayed, dst_gc_timer_expires);
102#endif 101#endif
103 add_timer(&dst_gc_timer); 102 mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires);
104 103
105out: 104out:
106 spin_unlock(&dst_lock); 105 spin_unlock(&dst_lock);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 7ad681f5e712..5130d2efdbbe 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -29,6 +29,7 @@
29#include <net/neighbour.h> 29#include <net/neighbour.h>
30#include <net/dst.h> 30#include <net/dst.h>
31#include <net/sock.h> 31#include <net/sock.h>
32#include <net/netevent.h>
32#include <linux/rtnetlink.h> 33#include <linux/rtnetlink.h>
33#include <linux/random.h> 34#include <linux/random.h>
34#include <linux/string.h> 35#include <linux/string.h>
@@ -754,6 +755,7 @@ static void neigh_timer_handler(unsigned long arg)
754 neigh->nud_state = NUD_STALE; 755 neigh->nud_state = NUD_STALE;
755 neigh->updated = jiffies; 756 neigh->updated = jiffies;
756 neigh_suspect(neigh); 757 neigh_suspect(neigh);
758 notify = 1;
757 } 759 }
758 } else if (state & NUD_DELAY) { 760 } else if (state & NUD_DELAY) {
759 if (time_before_eq(now, 761 if (time_before_eq(now,
@@ -762,6 +764,7 @@ static void neigh_timer_handler(unsigned long arg)
762 neigh->nud_state = NUD_REACHABLE; 764 neigh->nud_state = NUD_REACHABLE;
763 neigh->updated = jiffies; 765 neigh->updated = jiffies;
764 neigh_connect(neigh); 766 neigh_connect(neigh);
767 notify = 1;
765 next = neigh->confirmed + neigh->parms->reachable_time; 768 next = neigh->confirmed + neigh->parms->reachable_time;
766 } else { 769 } else {
767 NEIGH_PRINTK2("neigh %p is probed.\n", neigh); 770 NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
@@ -819,6 +822,8 @@ static void neigh_timer_handler(unsigned long arg)
819out: 822out:
820 write_unlock(&neigh->lock); 823 write_unlock(&neigh->lock);
821 } 824 }
825 if (notify)
826 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
822 827
823#ifdef CONFIG_ARPD 828#ifdef CONFIG_ARPD
824 if (notify && neigh->parms->app_probes) 829 if (notify && neigh->parms->app_probes)
@@ -926,9 +931,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
926{ 931{
927 u8 old; 932 u8 old;
928 int err; 933 int err;
929#ifdef CONFIG_ARPD
930 int notify = 0; 934 int notify = 0;
931#endif
932 struct net_device *dev; 935 struct net_device *dev;
933 int update_isrouter = 0; 936 int update_isrouter = 0;
934 937
@@ -948,9 +951,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
948 neigh_suspect(neigh); 951 neigh_suspect(neigh);
949 neigh->nud_state = new; 952 neigh->nud_state = new;
950 err = 0; 953 err = 0;
951#ifdef CONFIG_ARPD
952 notify = old & NUD_VALID; 954 notify = old & NUD_VALID;
953#endif
954 goto out; 955 goto out;
955 } 956 }
956 957
@@ -1022,9 +1023,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1022 if (!(new & NUD_CONNECTED)) 1023 if (!(new & NUD_CONNECTED))
1023 neigh->confirmed = jiffies - 1024 neigh->confirmed = jiffies -
1024 (neigh->parms->base_reachable_time << 1); 1025 (neigh->parms->base_reachable_time << 1);
1025#ifdef CONFIG_ARPD
1026 notify = 1; 1026 notify = 1;
1027#endif
1028 } 1027 }
1029 if (new == old) 1028 if (new == old)
1030 goto out; 1029 goto out;
@@ -1056,6 +1055,9 @@ out:
1056 (neigh->flags & ~NTF_ROUTER); 1055 (neigh->flags & ~NTF_ROUTER);
1057 } 1056 }
1058 write_unlock_bh(&neigh->lock); 1057 write_unlock_bh(&neigh->lock);
1058
1059 if (notify)
1060 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
1059#ifdef CONFIG_ARPD 1061#ifdef CONFIG_ARPD
1060 if (notify && neigh->parms->app_probes) 1062 if (notify && neigh->parms->app_probes)
1061 neigh_app_notify(neigh); 1063 neigh_app_notify(neigh);
diff --git a/net/core/netevent.c b/net/core/netevent.c
new file mode 100644
index 000000000000..35d02c38554e
--- /dev/null
+++ b/net/core/netevent.c
@@ -0,0 +1,69 @@
1/*
2 * Network event notifiers
3 *
4 * Authors:
5 * Tom Tucker <tom@opengridcomputing.com>
6 * Steve Wise <swise@opengridcomputing.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 *
13 * Fixes:
14 */
15
16#include <linux/rtnetlink.h>
17#include <linux/notifier.h>
18
19static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain);
20
21/**
22 * register_netevent_notifier - register a netevent notifier block
23 * @nb: notifier
24 *
25 * Register a notifier to be called when a netevent occurs.
26 * The notifier passed is linked into the kernel structures and must
27 * not be reused until it has been unregistered. A negative errno code
28 * is returned on a failure.
29 */
30int register_netevent_notifier(struct notifier_block *nb)
31{
32 int err;
33
34 err = atomic_notifier_chain_register(&netevent_notif_chain, nb);
35 return err;
36}
37
38/**
39 * netevent_unregister_notifier - unregister a netevent notifier block
40 * @nb: notifier
41 *
42 * Unregister a notifier previously registered by
43 * register_neigh_notifier(). The notifier is unlinked into the
44 * kernel structures and may then be reused. A negative errno code
45 * is returned on a failure.
46 */
47
48int unregister_netevent_notifier(struct notifier_block *nb)
49{
50 return atomic_notifier_chain_unregister(&netevent_notif_chain, nb);
51}
52
53/**
54 * call_netevent_notifiers - call all netevent notifier blocks
55 * @val: value passed unmodified to notifier function
56 * @v: pointer passed unmodified to notifier function
57 *
58 * Call all neighbour notifier blocks. Parameters and return value
59 * are as for notifier_call_chain().
60 */
61
62int call_netevent_notifiers(unsigned long val, void *v)
63{
64 return atomic_notifier_call_chain(&netevent_notif_chain, val, v);
65}
66
67EXPORT_SYMBOL_GPL(register_netevent_notifier);
68EXPORT_SYMBOL_GPL(unregister_netevent_notifier);
69EXPORT_SYMBOL_GPL(call_netevent_notifiers);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 67ed14ddabd2..6a7320b39ed0 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2149,6 +2149,8 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
2149 skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32); 2149 skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
2150 skb->dev = odev; 2150 skb->dev = odev;
2151 skb->pkt_type = PACKET_HOST; 2151 skb->pkt_type = PACKET_HOST;
2152 skb->nh.iph = iph;
2153 skb->h.uh = udph;
2152 2154
2153 if (pkt_dev->nfrags <= 0) 2155 if (pkt_dev->nfrags <= 0)
2154 pgh = (struct pktgen_hdr *)skb_put(skb, datalen); 2156 pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
@@ -2460,6 +2462,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2460 skb->protocol = protocol; 2462 skb->protocol = protocol;
2461 skb->dev = odev; 2463 skb->dev = odev;
2462 skb->pkt_type = PACKET_HOST; 2464 skb->pkt_type = PACKET_HOST;
2465 skb->nh.ipv6h = iph;
2466 skb->h.uh = udph;
2463 2467
2464 if (pkt_dev->nfrags <= 0) 2468 if (pkt_dev->nfrags <= 0)
2465 pgh = (struct pktgen_hdr *)skb_put(skb, datalen); 2469 pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 20e5bb73f147..30cc1ba6ed5c 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -394,6 +394,9 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
394 } 394 }
395 395
396 if (ida[IFLA_ADDRESS - 1]) { 396 if (ida[IFLA_ADDRESS - 1]) {
397 struct sockaddr *sa;
398 int len;
399
397 if (!dev->set_mac_address) { 400 if (!dev->set_mac_address) {
398 err = -EOPNOTSUPP; 401 err = -EOPNOTSUPP;
399 goto out; 402 goto out;
@@ -405,7 +408,17 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
405 if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) 408 if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len))
406 goto out; 409 goto out;
407 410
408 err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1])); 411 len = sizeof(sa_family_t) + dev->addr_len;
412 sa = kmalloc(len, GFP_KERNEL);
413 if (!sa) {
414 err = -ENOMEM;
415 goto out;
416 }
417 sa->sa_family = dev->type;
418 memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]),
419 dev->addr_len);
420 err = dev->set_mac_address(dev, sa);
421 kfree(sa);
409 if (err) 422 if (err)
410 goto out; 423 goto out;
411 send_addr_notify = 1; 424 send_addr_notify = 1;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 476aa3978504..c54f3664bce5 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -71,13 +71,6 @@ static kmem_cache_t *skbuff_head_cache __read_mostly;
71static kmem_cache_t *skbuff_fclone_cache __read_mostly; 71static kmem_cache_t *skbuff_fclone_cache __read_mostly;
72 72
73/* 73/*
74 * lockdep: lock class key used by skb_queue_head_init():
75 */
76struct lock_class_key skb_queue_lock_key;
77
78EXPORT_SYMBOL(skb_queue_lock_key);
79
80/*
81 * Keep out-of-line to prevent kernel bloat. 74 * Keep out-of-line to prevent kernel bloat.
82 * __builtin_return_address is not used because it is not always 75 * __builtin_return_address is not used because it is not always
83 * reliable. 76 * reliable.
@@ -256,6 +249,31 @@ nodata:
256 goto out; 249 goto out;
257} 250}
258 251
252/**
253 * __netdev_alloc_skb - allocate an skbuff for rx on a specific device
254 * @dev: network device to receive on
255 * @length: length to allocate
256 * @gfp_mask: get_free_pages mask, passed to alloc_skb
257 *
258 * Allocate a new &sk_buff and assign it a usage count of one. The
259 * buffer has unspecified headroom built in. Users should allocate
260 * the headroom they think they need without accounting for the
261 * built in space. The built in space is used for optimisations.
262 *
263 * %NULL is returned if there is no free memory.
264 */
265struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
266 unsigned int length, gfp_t gfp_mask)
267{
268 struct sk_buff *skb;
269
270 skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
271 if (likely(skb)) {
272 skb_reserve(skb, NET_SKB_PAD);
273 skb->dev = dev;
274 }
275 return skb;
276}
259 277
260static void skb_drop_list(struct sk_buff **listp) 278static void skb_drop_list(struct sk_buff **listp)
261{ 279{
@@ -846,7 +864,11 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
846 unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))) 864 unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))))
847 return err; 865 return err;
848 866
849 for (i = 0; i < nfrags; i++) { 867 i = 0;
868 if (offset >= len)
869 goto drop_pages;
870
871 for (; i < nfrags; i++) {
850 int end = offset + skb_shinfo(skb)->frags[i].size; 872 int end = offset + skb_shinfo(skb)->frags[i].size;
851 873
852 if (end < len) { 874 if (end < len) {
@@ -854,9 +876,9 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
854 continue; 876 continue;
855 } 877 }
856 878
857 if (len > offset) 879 skb_shinfo(skb)->frags[i++].size = len - offset;
858 skb_shinfo(skb)->frags[i++].size = len - offset;
859 880
881drop_pages:
860 skb_shinfo(skb)->nr_frags = i; 882 skb_shinfo(skb)->nr_frags = i;
861 883
862 for (; i < nfrags; i++) 884 for (; i < nfrags; i++)
@@ -864,7 +886,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
864 886
865 if (skb_shinfo(skb)->frag_list) 887 if (skb_shinfo(skb)->frag_list)
866 skb_drop_fraglist(skb); 888 skb_drop_fraglist(skb);
867 break; 889 goto done;
868 } 890 }
869 891
870 for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp); 892 for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp);
@@ -879,6 +901,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
879 return -ENOMEM; 901 return -ENOMEM;
880 902
881 nfrag->next = frag->next; 903 nfrag->next = frag->next;
904 kfree_skb(frag);
882 frag = nfrag; 905 frag = nfrag;
883 *fragp = frag; 906 *fragp = frag;
884 } 907 }
@@ -897,6 +920,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
897 break; 920 break;
898 } 921 }
899 922
923done:
900 if (len > skb_headlen(skb)) { 924 if (len > skb_headlen(skb)) {
901 skb->data_len -= skb->len - len; 925 skb->data_len -= skb->len - len;
902 skb->len = len; 926 skb->len = len;
@@ -2042,6 +2066,7 @@ EXPORT_SYMBOL(__kfree_skb);
2042EXPORT_SYMBOL(kfree_skb); 2066EXPORT_SYMBOL(kfree_skb);
2043EXPORT_SYMBOL(__pskb_pull_tail); 2067EXPORT_SYMBOL(__pskb_pull_tail);
2044EXPORT_SYMBOL(__alloc_skb); 2068EXPORT_SYMBOL(__alloc_skb);
2069EXPORT_SYMBOL(__netdev_alloc_skb);
2045EXPORT_SYMBOL(pskb_copy); 2070EXPORT_SYMBOL(pskb_copy);
2046EXPORT_SYMBOL(pskb_expand_head); 2071EXPORT_SYMBOL(pskb_expand_head);
2047EXPORT_SYMBOL(skb_checksum); 2072EXPORT_SYMBOL(skb_checksum);
diff --git a/net/core/utils.c b/net/core/utils.c
index 4f96f389243d..e31c90e05594 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -130,12 +130,13 @@ void __init net_random_init(void)
130static int net_random_reseed(void) 130static int net_random_reseed(void)
131{ 131{
132 int i; 132 int i;
133 unsigned long seed[NR_CPUS]; 133 unsigned long seed;
134 134
135 get_random_bytes(seed, sizeof(seed));
136 for_each_possible_cpu(i) { 135 for_each_possible_cpu(i) {
137 struct nrnd_state *state = &per_cpu(net_rand_state,i); 136 struct nrnd_state *state = &per_cpu(net_rand_state,i);
138 __net_srandom(state, seed[i]); 137
138 get_random_bytes(&seed, sizeof(seed));
139 __net_srandom(state, seed);
139 } 140 }
140 return 0; 141 return 0;
141} 142}
diff --git a/net/core/wireless.c b/net/core/wireless.c
index d2bc72d318f7..de0bde4b51dd 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -82,6 +82,7 @@
82#include <linux/init.h> /* for __init */ 82#include <linux/init.h> /* for __init */
83#include <linux/if_arp.h> /* ARPHRD_ETHER */ 83#include <linux/if_arp.h> /* ARPHRD_ETHER */
84#include <linux/etherdevice.h> /* compare_ether_addr */ 84#include <linux/etherdevice.h> /* compare_ether_addr */
85#include <linux/interrupt.h>
85 86
86#include <linux/wireless.h> /* Pretty obvious */ 87#include <linux/wireless.h> /* Pretty obvious */
87#include <net/iw_handler.h> /* New driver API */ 88#include <net/iw_handler.h> /* New driver API */
@@ -1842,6 +1843,18 @@ int wireless_rtnetlink_set(struct net_device * dev,
1842 */ 1843 */
1843 1844
1844#ifdef WE_EVENT_RTNETLINK 1845#ifdef WE_EVENT_RTNETLINK
1846static struct sk_buff_head wireless_nlevent_queue;
1847
1848static void wireless_nlevent_process(unsigned long data)
1849{
1850 struct sk_buff *skb;
1851
1852 while ((skb = skb_dequeue(&wireless_nlevent_queue)))
1853 netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
1854}
1855
1856static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0);
1857
1845/* ---------------------------------------------------------------- */ 1858/* ---------------------------------------------------------------- */
1846/* 1859/*
1847 * Fill a rtnetlink message with our event data. 1860 * Fill a rtnetlink message with our event data.
@@ -1904,8 +1917,17 @@ static inline void rtmsg_iwinfo(struct net_device * dev,
1904 return; 1917 return;
1905 } 1918 }
1906 NETLINK_CB(skb).dst_group = RTNLGRP_LINK; 1919 NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
1907 netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); 1920 skb_queue_tail(&wireless_nlevent_queue, skb);
1921 tasklet_schedule(&wireless_nlevent_tasklet);
1922}
1923
1924static int __init wireless_nlevent_init(void)
1925{
1926 skb_queue_head_init(&wireless_nlevent_queue);
1927 return 0;
1908} 1928}
1929
1930subsys_initcall(wireless_nlevent_init);
1909#endif /* WE_EVENT_RTNETLINK */ 1931#endif /* WE_EVENT_RTNETLINK */
1910 1932
1911/* ---------------------------------------------------------------- */ 1933/* ---------------------------------------------------------------- */