diff options
Diffstat (limited to 'net')
34 files changed, 273 insertions, 128 deletions
diff --git a/net/atm/proc.c b/net/atm/proc.c index 3f95b0886a6a..91fe5f53ff11 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c | |||
@@ -507,7 +507,7 @@ err_out: | |||
507 | goto out; | 507 | goto out; |
508 | } | 508 | } |
509 | 509 | ||
510 | void __exit atm_proc_exit(void) | 510 | void atm_proc_exit(void) |
511 | { | 511 | { |
512 | atm_proc_dirs_remove(); | 512 | atm_proc_dirs_remove(); |
513 | } | 513 | } |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index f55ef682ef84..b1211d5342f6 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -386,12 +386,17 @@ void br_features_recompute(struct net_bridge *br) | |||
386 | checksum = 0; | 386 | checksum = 0; |
387 | 387 | ||
388 | if (feature & NETIF_F_GSO) | 388 | if (feature & NETIF_F_GSO) |
389 | feature |= NETIF_F_TSO; | 389 | feature |= NETIF_F_GSO_SOFTWARE; |
390 | feature |= NETIF_F_GSO; | 390 | feature |= NETIF_F_GSO; |
391 | 391 | ||
392 | features &= feature; | 392 | features &= feature; |
393 | } | 393 | } |
394 | 394 | ||
395 | if (!(checksum & NETIF_F_ALL_CSUM)) | ||
396 | features &= ~NETIF_F_SG; | ||
397 | if (!(features & NETIF_F_SG)) | ||
398 | features &= ~NETIF_F_GSO_MASK; | ||
399 | |||
395 | br->dev->features = features | checksum | NETIF_F_LLTX | | 400 | br->dev->features = features | checksum | NETIF_F_LLTX | |
396 | NETIF_F_GSO_ROBUST; | 401 | NETIF_F_GSO_ROBUST; |
397 | } | 402 | } |
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 02693a230dc1..9f950db3b76f 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c | |||
@@ -74,6 +74,9 @@ static void ulog_send(unsigned int nlgroup) | |||
74 | if (timer_pending(&ub->timer)) | 74 | if (timer_pending(&ub->timer)) |
75 | del_timer(&ub->timer); | 75 | del_timer(&ub->timer); |
76 | 76 | ||
77 | if (!ub->skb) | ||
78 | return; | ||
79 | |||
77 | /* last nlmsg needs NLMSG_DONE */ | 80 | /* last nlmsg needs NLMSG_DONE */ |
78 | if (ub->qlen > 1) | 81 | if (ub->qlen > 1) |
79 | ub->lastnlh->nlmsg_type = NLMSG_DONE; | 82 | ub->lastnlh->nlmsg_type = NLMSG_DONE; |
diff --git a/net/core/dev.c b/net/core/dev.c index d95e2626d944..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 | */ |
637 | int dev_valid_name(const char *name) | 639 | int 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 | /** |
@@ -1619,26 +1628,10 @@ static inline struct net_device *skb_bond(struct sk_buff *skb) | |||
1619 | struct net_device *dev = skb->dev; | 1628 | struct net_device *dev = skb->dev; |
1620 | 1629 | ||
1621 | if (dev->master) { | 1630 | if (dev->master) { |
1622 | /* | 1631 | if (skb_bond_should_drop(skb)) { |
1623 | * On bonding slaves other than the currently active | ||
1624 | * slave, suppress duplicates except for 802.3ad | ||
1625 | * ETH_P_SLOW and alb non-mcast/bcast. | ||
1626 | */ | ||
1627 | if (dev->priv_flags & IFF_SLAVE_INACTIVE) { | ||
1628 | if (dev->master->priv_flags & IFF_MASTER_ALB) { | ||
1629 | if (skb->pkt_type != PACKET_BROADCAST && | ||
1630 | skb->pkt_type != PACKET_MULTICAST) | ||
1631 | goto keep; | ||
1632 | } | ||
1633 | |||
1634 | if (dev->master->priv_flags & IFF_MASTER_8023AD && | ||
1635 | skb->protocol == __constant_htons(ETH_P_SLOW)) | ||
1636 | goto keep; | ||
1637 | |||
1638 | kfree_skb(skb); | 1632 | kfree_skb(skb); |
1639 | return NULL; | 1633 | return NULL; |
1640 | } | 1634 | } |
1641 | keep: | ||
1642 | skb->dev = dev->master; | 1635 | skb->dev = dev->master; |
1643 | } | 1636 | } |
1644 | 1637 | ||
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 | ||
105 | out: | 104 | out: |
106 | spin_unlock(&dst_lock); | 105 | spin_unlock(&dst_lock); |
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 022d8894c11d..c54f3664bce5 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -268,8 +268,10 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, | |||
268 | struct sk_buff *skb; | 268 | struct sk_buff *skb; |
269 | 269 | ||
270 | skb = alloc_skb(length + NET_SKB_PAD, gfp_mask); | 270 | skb = alloc_skb(length + NET_SKB_PAD, gfp_mask); |
271 | if (likely(skb)) | 271 | if (likely(skb)) { |
272 | skb_reserve(skb, NET_SKB_PAD); | 272 | skb_reserve(skb, NET_SKB_PAD); |
273 | skb->dev = dev; | ||
274 | } | ||
273 | return skb; | 275 | return skb; |
274 | } | 276 | } |
275 | 277 | ||
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) | |||
130 | static int net_random_reseed(void) | 130 | static 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 |
1846 | static struct sk_buff_head wireless_nlevent_queue; | ||
1847 | |||
1848 | static 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 | |||
1856 | static 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 | |||
1924 | static int __init wireless_nlevent_init(void) | ||
1925 | { | ||
1926 | skb_queue_head_init(&wireless_nlevent_queue); | ||
1927 | return 0; | ||
1908 | } | 1928 | } |
1929 | |||
1930 | subsys_initcall(wireless_nlevent_init); | ||
1909 | #endif /* WE_EVENT_RTNETLINK */ | 1931 | #endif /* WE_EVENT_RTNETLINK */ |
1910 | 1932 | ||
1911 | /* ---------------------------------------------------------------- */ | 1933 | /* ---------------------------------------------------------------- */ |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 9be53a8e72c3..51738000f3dc 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -159,7 +159,7 @@ void free_fib_info(struct fib_info *fi) | |||
159 | 159 | ||
160 | void fib_release_info(struct fib_info *fi) | 160 | void fib_release_info(struct fib_info *fi) |
161 | { | 161 | { |
162 | write_lock(&fib_info_lock); | 162 | write_lock_bh(&fib_info_lock); |
163 | if (fi && --fi->fib_treeref == 0) { | 163 | if (fi && --fi->fib_treeref == 0) { |
164 | hlist_del(&fi->fib_hash); | 164 | hlist_del(&fi->fib_hash); |
165 | if (fi->fib_prefsrc) | 165 | if (fi->fib_prefsrc) |
@@ -172,7 +172,7 @@ void fib_release_info(struct fib_info *fi) | |||
172 | fi->fib_dead = 1; | 172 | fi->fib_dead = 1; |
173 | fib_info_put(fi); | 173 | fib_info_put(fi); |
174 | } | 174 | } |
175 | write_unlock(&fib_info_lock); | 175 | write_unlock_bh(&fib_info_lock); |
176 | } | 176 | } |
177 | 177 | ||
178 | static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi) | 178 | static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi) |
@@ -598,7 +598,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash, | |||
598 | unsigned int old_size = fib_hash_size; | 598 | unsigned int old_size = fib_hash_size; |
599 | unsigned int i, bytes; | 599 | unsigned int i, bytes; |
600 | 600 | ||
601 | write_lock(&fib_info_lock); | 601 | write_lock_bh(&fib_info_lock); |
602 | old_info_hash = fib_info_hash; | 602 | old_info_hash = fib_info_hash; |
603 | old_laddrhash = fib_info_laddrhash; | 603 | old_laddrhash = fib_info_laddrhash; |
604 | fib_hash_size = new_size; | 604 | fib_hash_size = new_size; |
@@ -639,7 +639,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash, | |||
639 | } | 639 | } |
640 | fib_info_laddrhash = new_laddrhash; | 640 | fib_info_laddrhash = new_laddrhash; |
641 | 641 | ||
642 | write_unlock(&fib_info_lock); | 642 | write_unlock_bh(&fib_info_lock); |
643 | 643 | ||
644 | bytes = old_size * sizeof(struct hlist_head *); | 644 | bytes = old_size * sizeof(struct hlist_head *); |
645 | fib_hash_free(old_info_hash, bytes); | 645 | fib_hash_free(old_info_hash, bytes); |
@@ -820,7 +820,7 @@ link_it: | |||
820 | 820 | ||
821 | fi->fib_treeref++; | 821 | fi->fib_treeref++; |
822 | atomic_inc(&fi->fib_clntref); | 822 | atomic_inc(&fi->fib_clntref); |
823 | write_lock(&fib_info_lock); | 823 | write_lock_bh(&fib_info_lock); |
824 | hlist_add_head(&fi->fib_hash, | 824 | hlist_add_head(&fi->fib_hash, |
825 | &fib_info_hash[fib_info_hashfn(fi)]); | 825 | &fib_info_hash[fib_info_hashfn(fi)]); |
826 | if (fi->fib_prefsrc) { | 826 | if (fi->fib_prefsrc) { |
@@ -839,7 +839,7 @@ link_it: | |||
839 | head = &fib_info_devhash[hash]; | 839 | head = &fib_info_devhash[hash]; |
840 | hlist_add_head(&nh->nh_hash, head); | 840 | hlist_add_head(&nh->nh_hash, head); |
841 | } endfor_nexthops(fi) | 841 | } endfor_nexthops(fi) |
842 | write_unlock(&fib_info_lock); | 842 | write_unlock_bh(&fib_info_lock); |
843 | return fi; | 843 | return fi; |
844 | 844 | ||
845 | err_inval: | 845 | err_inval: |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 9f4b752f5a33..8e8117c19e4d 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -1793,29 +1793,35 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) | |||
1793 | struct in_device *in_dev; | 1793 | struct in_device *in_dev; |
1794 | u32 group = imr->imr_multiaddr.s_addr; | 1794 | u32 group = imr->imr_multiaddr.s_addr; |
1795 | u32 ifindex; | 1795 | u32 ifindex; |
1796 | int ret = -EADDRNOTAVAIL; | ||
1796 | 1797 | ||
1797 | rtnl_lock(); | 1798 | rtnl_lock(); |
1798 | in_dev = ip_mc_find_dev(imr); | 1799 | in_dev = ip_mc_find_dev(imr); |
1799 | if (!in_dev) { | ||
1800 | rtnl_unlock(); | ||
1801 | return -ENODEV; | ||
1802 | } | ||
1803 | ifindex = imr->imr_ifindex; | 1800 | ifindex = imr->imr_ifindex; |
1804 | for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) { | 1801 | for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) { |
1805 | if (iml->multi.imr_multiaddr.s_addr == group && | 1802 | if (iml->multi.imr_multiaddr.s_addr != group) |
1806 | iml->multi.imr_ifindex == ifindex) { | 1803 | continue; |
1807 | (void) ip_mc_leave_src(sk, iml, in_dev); | 1804 | if (ifindex) { |
1805 | if (iml->multi.imr_ifindex != ifindex) | ||
1806 | continue; | ||
1807 | } else if (imr->imr_address.s_addr && imr->imr_address.s_addr != | ||
1808 | iml->multi.imr_address.s_addr) | ||
1809 | continue; | ||
1810 | |||
1811 | (void) ip_mc_leave_src(sk, iml, in_dev); | ||
1808 | 1812 | ||
1809 | *imlp = iml->next; | 1813 | *imlp = iml->next; |
1810 | 1814 | ||
1815 | if (in_dev) | ||
1811 | ip_mc_dec_group(in_dev, group); | 1816 | ip_mc_dec_group(in_dev, group); |
1812 | rtnl_unlock(); | 1817 | rtnl_unlock(); |
1813 | sock_kfree_s(sk, iml, sizeof(*iml)); | 1818 | sock_kfree_s(sk, iml, sizeof(*iml)); |
1814 | return 0; | 1819 | return 0; |
1815 | } | ||
1816 | } | 1820 | } |
1821 | if (!in_dev) | ||
1822 | ret = -ENODEV; | ||
1817 | rtnl_unlock(); | 1823 | rtnl_unlock(); |
1818 | return -EADDRNOTAVAIL; | 1824 | return ret; |
1819 | } | 1825 | } |
1820 | 1826 | ||
1821 | int ip_mc_source(int add, int omode, struct sock *sk, struct | 1827 | int ip_mc_source(int add, int omode, struct sock *sk, struct |
@@ -2199,13 +2205,13 @@ void ip_mc_drop_socket(struct sock *sk) | |||
2199 | struct in_device *in_dev; | 2205 | struct in_device *in_dev; |
2200 | inet->mc_list = iml->next; | 2206 | inet->mc_list = iml->next; |
2201 | 2207 | ||
2202 | if ((in_dev = inetdev_by_index(iml->multi.imr_ifindex)) != NULL) { | 2208 | in_dev = inetdev_by_index(iml->multi.imr_ifindex); |
2203 | (void) ip_mc_leave_src(sk, iml, in_dev); | 2209 | (void) ip_mc_leave_src(sk, iml, in_dev); |
2210 | if (in_dev != NULL) { | ||
2204 | ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr); | 2211 | ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr); |
2205 | in_dev_put(in_dev); | 2212 | in_dev_put(in_dev); |
2206 | } | 2213 | } |
2207 | sock_kfree_s(sk, iml, sizeof(*iml)); | 2214 | sock_kfree_s(sk, iml, sizeof(*iml)); |
2208 | |||
2209 | } | 2215 | } |
2210 | rtnl_unlock(); | 2216 | rtnl_unlock(); |
2211 | } | 2217 | } |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 9bf307a29783..4c20f5546893 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -947,7 +947,7 @@ alloc_new_skb: | |||
947 | skb_prev->csum = csum_sub(skb_prev->csum, | 947 | skb_prev->csum = csum_sub(skb_prev->csum, |
948 | skb->csum); | 948 | skb->csum); |
949 | data += fraggap; | 949 | data += fraggap; |
950 | skb_trim(skb_prev, maxfraglen); | 950 | pskb_trim_unique(skb_prev, maxfraglen); |
951 | } | 951 | } |
952 | 952 | ||
953 | copy = datalen - transhdrlen - fraggap; | 953 | copy = datalen - transhdrlen - fraggap; |
@@ -1142,7 +1142,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1142 | data, fraggap, 0); | 1142 | data, fraggap, 0); |
1143 | skb_prev->csum = csum_sub(skb_prev->csum, | 1143 | skb_prev->csum = csum_sub(skb_prev->csum, |
1144 | skb->csum); | 1144 | skb->csum); |
1145 | skb_trim(skb_prev, maxfraglen); | 1145 | pskb_trim_unique(skb_prev, maxfraglen); |
1146 | } | 1146 | } |
1147 | 1147 | ||
1148 | /* | 1148 | /* |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 80c73ca90116..df4854cf598b 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -1170,21 +1170,34 @@ static int __init arp_tables_init(void) | |||
1170 | { | 1170 | { |
1171 | int ret; | 1171 | int ret; |
1172 | 1172 | ||
1173 | xt_proto_init(NF_ARP); | 1173 | ret = xt_proto_init(NF_ARP); |
1174 | if (ret < 0) | ||
1175 | goto err1; | ||
1174 | 1176 | ||
1175 | /* Noone else will be downing sem now, so we won't sleep */ | 1177 | /* Noone else will be downing sem now, so we won't sleep */ |
1176 | xt_register_target(&arpt_standard_target); | 1178 | ret = xt_register_target(&arpt_standard_target); |
1177 | xt_register_target(&arpt_error_target); | 1179 | if (ret < 0) |
1180 | goto err2; | ||
1181 | ret = xt_register_target(&arpt_error_target); | ||
1182 | if (ret < 0) | ||
1183 | goto err3; | ||
1178 | 1184 | ||
1179 | /* Register setsockopt */ | 1185 | /* Register setsockopt */ |
1180 | ret = nf_register_sockopt(&arpt_sockopts); | 1186 | ret = nf_register_sockopt(&arpt_sockopts); |
1181 | if (ret < 0) { | 1187 | if (ret < 0) |
1182 | duprintf("Unable to register sockopts.\n"); | 1188 | goto err4; |
1183 | return ret; | ||
1184 | } | ||
1185 | 1189 | ||
1186 | printk("arp_tables: (C) 2002 David S. Miller\n"); | 1190 | printk("arp_tables: (C) 2002 David S. Miller\n"); |
1187 | return 0; | 1191 | return 0; |
1192 | |||
1193 | err4: | ||
1194 | xt_unregister_target(&arpt_error_target); | ||
1195 | err3: | ||
1196 | xt_unregister_target(&arpt_standard_target); | ||
1197 | err2: | ||
1198 | xt_proto_fini(NF_ARP); | ||
1199 | err1: | ||
1200 | return ret; | ||
1188 | } | 1201 | } |
1189 | 1202 | ||
1190 | static void __exit arp_tables_fini(void) | 1203 | static void __exit arp_tables_fini(void) |
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 33891bb1fde4..0d4cc92391fa 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c | |||
@@ -415,21 +415,18 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
415 | cb->args[0], *id); | 415 | cb->args[0], *id); |
416 | 416 | ||
417 | read_lock_bh(&ip_conntrack_lock); | 417 | read_lock_bh(&ip_conntrack_lock); |
418 | last = (struct ip_conntrack *)cb->args[1]; | ||
418 | for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) { | 419 | for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) { |
419 | restart: | 420 | restart: |
420 | last = (struct ip_conntrack *)cb->args[1]; | ||
421 | list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) { | 421 | list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) { |
422 | h = (struct ip_conntrack_tuple_hash *) i; | 422 | h = (struct ip_conntrack_tuple_hash *) i; |
423 | if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) | 423 | if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) |
424 | continue; | 424 | continue; |
425 | ct = tuplehash_to_ctrack(h); | 425 | ct = tuplehash_to_ctrack(h); |
426 | if (last != NULL) { | 426 | if (cb->args[1]) { |
427 | if (ct == last) { | 427 | if (ct != last) |
428 | ip_conntrack_put(last); | ||
429 | cb->args[1] = 0; | ||
430 | last = NULL; | ||
431 | } else | ||
432 | continue; | 428 | continue; |
429 | cb->args[1] = 0; | ||
433 | } | 430 | } |
434 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, | 431 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, |
435 | cb->nlh->nlmsg_seq, | 432 | cb->nlh->nlmsg_seq, |
@@ -440,17 +437,17 @@ restart: | |||
440 | goto out; | 437 | goto out; |
441 | } | 438 | } |
442 | } | 439 | } |
443 | if (last != NULL) { | 440 | if (cb->args[1]) { |
444 | ip_conntrack_put(last); | ||
445 | cb->args[1] = 0; | 441 | cb->args[1] = 0; |
446 | goto restart; | 442 | goto restart; |
447 | } | 443 | } |
448 | } | 444 | } |
449 | out: | 445 | out: |
450 | read_unlock_bh(&ip_conntrack_lock); | 446 | read_unlock_bh(&ip_conntrack_lock); |
447 | if (last) | ||
448 | ip_conntrack_put(last); | ||
451 | 449 | ||
452 | DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); | 450 | DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); |
453 | |||
454 | return skb->len; | 451 | return skb->len; |
455 | } | 452 | } |
456 | 453 | ||
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index fc5bdd5eb7d3..048514f15f2f 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -230,7 +230,7 @@ ipt_do_table(struct sk_buff **pskb, | |||
230 | const char *indev, *outdev; | 230 | const char *indev, *outdev; |
231 | void *table_base; | 231 | void *table_base; |
232 | struct ipt_entry *e, *back; | 232 | struct ipt_entry *e, *back; |
233 | struct xt_table_info *private = table->private; | 233 | struct xt_table_info *private; |
234 | 234 | ||
235 | /* Initialization */ | 235 | /* Initialization */ |
236 | ip = (*pskb)->nh.iph; | 236 | ip = (*pskb)->nh.iph; |
@@ -247,6 +247,7 @@ ipt_do_table(struct sk_buff **pskb, | |||
247 | 247 | ||
248 | read_lock_bh(&table->lock); | 248 | read_lock_bh(&table->lock); |
249 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 249 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
250 | private = table->private; | ||
250 | table_base = (void *)private->entries[smp_processor_id()]; | 251 | table_base = (void *)private->entries[smp_processor_id()]; |
251 | e = get_entry(table_base, private->hook_entry[hook]); | 252 | e = get_entry(table_base, private->hook_entry[hook]); |
252 | 253 | ||
@@ -2239,22 +2240,39 @@ static int __init ip_tables_init(void) | |||
2239 | { | 2240 | { |
2240 | int ret; | 2241 | int ret; |
2241 | 2242 | ||
2242 | xt_proto_init(AF_INET); | 2243 | ret = xt_proto_init(AF_INET); |
2244 | if (ret < 0) | ||
2245 | goto err1; | ||
2243 | 2246 | ||
2244 | /* Noone else will be downing sem now, so we won't sleep */ | 2247 | /* Noone else will be downing sem now, so we won't sleep */ |
2245 | xt_register_target(&ipt_standard_target); | 2248 | ret = xt_register_target(&ipt_standard_target); |
2246 | xt_register_target(&ipt_error_target); | 2249 | if (ret < 0) |
2247 | xt_register_match(&icmp_matchstruct); | 2250 | goto err2; |
2251 | ret = xt_register_target(&ipt_error_target); | ||
2252 | if (ret < 0) | ||
2253 | goto err3; | ||
2254 | ret = xt_register_match(&icmp_matchstruct); | ||
2255 | if (ret < 0) | ||
2256 | goto err4; | ||
2248 | 2257 | ||
2249 | /* Register setsockopt */ | 2258 | /* Register setsockopt */ |
2250 | ret = nf_register_sockopt(&ipt_sockopts); | 2259 | ret = nf_register_sockopt(&ipt_sockopts); |
2251 | if (ret < 0) { | 2260 | if (ret < 0) |
2252 | duprintf("Unable to register sockopts.\n"); | 2261 | goto err5; |
2253 | return ret; | ||
2254 | } | ||
2255 | 2262 | ||
2256 | printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n"); | 2263 | printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n"); |
2257 | return 0; | 2264 | return 0; |
2265 | |||
2266 | err5: | ||
2267 | xt_unregister_match(&icmp_matchstruct); | ||
2268 | err4: | ||
2269 | xt_unregister_target(&ipt_error_target); | ||
2270 | err3: | ||
2271 | xt_unregister_target(&ipt_standard_target); | ||
2272 | err2: | ||
2273 | xt_proto_fini(AF_INET); | ||
2274 | err1: | ||
2275 | return ret; | ||
2258 | } | 2276 | } |
2259 | 2277 | ||
2260 | static void __exit ip_tables_fini(void) | 2278 | static void __exit ip_tables_fini(void) |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index d7dd7fe7051c..d46fd677fa11 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -115,6 +115,11 @@ static void ulog_send(unsigned int nlgroupnum) | |||
115 | del_timer(&ub->timer); | 115 | del_timer(&ub->timer); |
116 | } | 116 | } |
117 | 117 | ||
118 | if (!ub->skb) { | ||
119 | DEBUGP("ipt_ULOG: ulog_send: nothing to send\n"); | ||
120 | return; | ||
121 | } | ||
122 | |||
118 | /* last nlmsg needs NLMSG_DONE */ | 123 | /* last nlmsg needs NLMSG_DONE */ |
119 | if (ub->qlen > 1) | 124 | if (ub->qlen > 1) |
120 | ub->lastnlh->nlmsg_type = NLMSG_DONE; | 125 | ub->lastnlh->nlmsg_type = NLMSG_DONE; |
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c index 6b662449e825..3bd2368e1fc9 100644 --- a/net/ipv4/netfilter/ipt_hashlimit.c +++ b/net/ipv4/netfilter/ipt_hashlimit.c | |||
@@ -454,15 +454,12 @@ hashlimit_match(const struct sk_buff *skb, | |||
454 | dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * | 454 | dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * |
455 | hinfo->cfg.burst); | 455 | hinfo->cfg.burst); |
456 | dh->rateinfo.cost = user2credits(hinfo->cfg.avg); | 456 | dh->rateinfo.cost = user2credits(hinfo->cfg.avg); |
457 | 457 | } else { | |
458 | spin_unlock_bh(&hinfo->lock); | 458 | /* update expiration timeout */ |
459 | return 1; | 459 | dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); |
460 | rateinfo_recalc(dh, now); | ||
460 | } | 461 | } |
461 | 462 | ||
462 | /* update expiration timeout */ | ||
463 | dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); | ||
464 | |||
465 | rateinfo_recalc(dh, now); | ||
466 | if (dh->rateinfo.credit >= dh->rateinfo.cost) { | 463 | if (dh->rateinfo.credit >= dh->rateinfo.cost) { |
467 | /* We're underlimit. */ | 464 | /* We're underlimit. */ |
468 | dh->rateinfo.credit -= dh->rateinfo.cost; | 465 | dh->rateinfo.credit -= dh->rateinfo.cost; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 19bd49d69d9f..b873cbcdd0b8 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -3157,7 +3157,7 @@ int __init ip_rt_init(void) | |||
3157 | rhash_entries, | 3157 | rhash_entries, |
3158 | (num_physpages >= 128 * 1024) ? | 3158 | (num_physpages >= 128 * 1024) ? |
3159 | 15 : 17, | 3159 | 15 : 17, |
3160 | HASH_HIGHMEM, | 3160 | 0, |
3161 | &rt_hash_log, | 3161 | &rt_hash_log, |
3162 | &rt_hash_mask, | 3162 | &rt_hash_mask, |
3163 | 0); | 3163 | 0); |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 5c08ea20a18d..507adefbc17c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -466,7 +466,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
466 | if (skb->len != tcp_header_size) | 466 | if (skb->len != tcp_header_size) |
467 | tcp_event_data_sent(tp, skb, sk); | 467 | tcp_event_data_sent(tp, skb, sk); |
468 | 468 | ||
469 | TCP_INC_STATS(TCP_MIB_OUTSEGS); | 469 | if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq) |
470 | TCP_INC_STATS(TCP_MIB_OUTSEGS); | ||
470 | 471 | ||
471 | err = icsk->icsk_af_ops->queue_xmit(skb, 0); | 472 | err = icsk->icsk_af_ops->queue_xmit(skb, 0); |
472 | if (likely(err <= 0)) | 473 | if (likely(err <= 0)) |
@@ -2157,10 +2158,9 @@ int tcp_connect(struct sock *sk) | |||
2157 | skb_shinfo(buff)->gso_size = 0; | 2158 | skb_shinfo(buff)->gso_size = 0; |
2158 | skb_shinfo(buff)->gso_type = 0; | 2159 | skb_shinfo(buff)->gso_type = 0; |
2159 | buff->csum = 0; | 2160 | buff->csum = 0; |
2161 | tp->snd_nxt = tp->write_seq; | ||
2160 | TCP_SKB_CB(buff)->seq = tp->write_seq++; | 2162 | TCP_SKB_CB(buff)->seq = tp->write_seq++; |
2161 | TCP_SKB_CB(buff)->end_seq = tp->write_seq; | 2163 | TCP_SKB_CB(buff)->end_seq = tp->write_seq; |
2162 | tp->snd_nxt = tp->write_seq; | ||
2163 | tp->pushed_seq = tp->write_seq; | ||
2164 | 2164 | ||
2165 | /* Send it off. */ | 2165 | /* Send it off. */ |
2166 | TCP_SKB_CB(buff)->when = tcp_time_stamp; | 2166 | TCP_SKB_CB(buff)->when = tcp_time_stamp; |
@@ -2170,6 +2170,12 @@ int tcp_connect(struct sock *sk) | |||
2170 | sk_charge_skb(sk, buff); | 2170 | sk_charge_skb(sk, buff); |
2171 | tp->packets_out += tcp_skb_pcount(buff); | 2171 | tp->packets_out += tcp_skb_pcount(buff); |
2172 | tcp_transmit_skb(sk, buff, 1, GFP_KERNEL); | 2172 | tcp_transmit_skb(sk, buff, 1, GFP_KERNEL); |
2173 | |||
2174 | /* We change tp->snd_nxt after the tcp_transmit_skb() call | ||
2175 | * in order to make this packet get counted in tcpOutSegs. | ||
2176 | */ | ||
2177 | tp->snd_nxt = tp->write_seq; | ||
2178 | tp->pushed_seq = tp->write_seq; | ||
2173 | TCP_INC_STATS(TCP_MIB_ACTIVEOPENS); | 2179 | TCP_INC_STATS(TCP_MIB_ACTIVEOPENS); |
2174 | 2180 | ||
2175 | /* Timer for repeating the SYN until an answer. */ | 2181 | /* Timer for repeating the SYN until an answer. */ |
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index b3435324b573..dab37d2f65fc 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c | |||
@@ -130,11 +130,12 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf, | |||
130 | error = wait_event_interruptible(tcpw.wait, | 130 | error = wait_event_interruptible(tcpw.wait, |
131 | __kfifo_len(tcpw.fifo) != 0); | 131 | __kfifo_len(tcpw.fifo) != 0); |
132 | if (error) | 132 | if (error) |
133 | return error; | 133 | goto out_free; |
134 | 134 | ||
135 | cnt = kfifo_get(tcpw.fifo, tbuf, len); | 135 | cnt = kfifo_get(tcpw.fifo, tbuf, len); |
136 | error = copy_to_user(buf, tbuf, cnt); | 136 | error = copy_to_user(buf, tbuf, cnt); |
137 | 137 | ||
138 | out_free: | ||
138 | vfree(tbuf); | 139 | vfree(tbuf); |
139 | 140 | ||
140 | return error ? error : cnt; | 141 | return error ? error : cnt; |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 8ea1e36bf8eb..0c5042e7380d 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1909,11 +1909,11 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | |||
1909 | ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags); | 1909 | ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags); |
1910 | 1910 | ||
1911 | if (!IS_ERR(ifp)) { | 1911 | if (!IS_ERR(ifp)) { |
1912 | spin_lock(&ifp->lock); | 1912 | spin_lock_bh(&ifp->lock); |
1913 | ifp->valid_lft = valid_lft; | 1913 | ifp->valid_lft = valid_lft; |
1914 | ifp->prefered_lft = prefered_lft; | 1914 | ifp->prefered_lft = prefered_lft; |
1915 | ifp->tstamp = jiffies; | 1915 | ifp->tstamp = jiffies; |
1916 | spin_unlock(&ifp->lock); | 1916 | spin_unlock_bh(&ifp->lock); |
1917 | 1917 | ||
1918 | addrconf_dad_start(ifp, 0); | 1918 | addrconf_dad_start(ifp, 0); |
1919 | in6_ifa_put(ifp); | 1919 | in6_ifa_put(ifp); |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 1044b6fce0d5..3d6e9a351150 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -712,6 +712,11 @@ discard_it: | |||
712 | return 0; | 712 | return 0; |
713 | } | 713 | } |
714 | 714 | ||
715 | /* | ||
716 | * Special lock-class for __icmpv6_socket: | ||
717 | */ | ||
718 | static struct lock_class_key icmpv6_socket_sk_dst_lock_key; | ||
719 | |||
715 | int __init icmpv6_init(struct net_proto_family *ops) | 720 | int __init icmpv6_init(struct net_proto_family *ops) |
716 | { | 721 | { |
717 | struct sock *sk; | 722 | struct sock *sk; |
@@ -730,6 +735,14 @@ int __init icmpv6_init(struct net_proto_family *ops) | |||
730 | 735 | ||
731 | sk = per_cpu(__icmpv6_socket, i)->sk; | 736 | sk = per_cpu(__icmpv6_socket, i)->sk; |
732 | sk->sk_allocation = GFP_ATOMIC; | 737 | sk->sk_allocation = GFP_ATOMIC; |
738 | /* | ||
739 | * Split off their lock-class, because sk->sk_dst_lock | ||
740 | * gets used from softirqs, which is safe for | ||
741 | * __icmpv6_socket (because those never get directly used | ||
742 | * via userspace syscalls), but unsafe for normal sockets. | ||
743 | */ | ||
744 | lockdep_set_class(&sk->sk_dst_lock, | ||
745 | &icmpv6_socket_sk_dst_lock_key); | ||
733 | 746 | ||
734 | /* Enough space for 2 64K ICMP packets, including | 747 | /* Enough space for 2 64K ICMP packets, including |
735 | * sk_buff struct overhead. | 748 | * sk_buff struct overhead. |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 69451af6abe7..4fb47a252913 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1095,7 +1095,7 @@ alloc_new_skb: | |||
1095 | skb_prev->csum = csum_sub(skb_prev->csum, | 1095 | skb_prev->csum = csum_sub(skb_prev->csum, |
1096 | skb->csum); | 1096 | skb->csum); |
1097 | data += fraggap; | 1097 | data += fraggap; |
1098 | skb_trim(skb_prev, maxfraglen); | 1098 | pskb_trim_unique(skb_prev, maxfraglen); |
1099 | } | 1099 | } |
1100 | copy = datalen - transhdrlen - fraggap; | 1100 | copy = datalen - transhdrlen - fraggap; |
1101 | if (copy < 0) { | 1101 | if (copy < 0) { |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 9d697d4dcffc..639eb20c9f1f 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -268,13 +268,14 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
268 | if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) { | 268 | if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) { |
269 | struct inet6_dev *idev = in6_dev_get(dev); | 269 | struct inet6_dev *idev = in6_dev_get(dev); |
270 | 270 | ||
271 | (void) ip6_mc_leave_src(sk, mc_lst, idev); | ||
271 | if (idev) { | 272 | if (idev) { |
272 | (void) ip6_mc_leave_src(sk,mc_lst,idev); | ||
273 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); | 273 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); |
274 | in6_dev_put(idev); | 274 | in6_dev_put(idev); |
275 | } | 275 | } |
276 | dev_put(dev); | 276 | dev_put(dev); |
277 | } | 277 | } else |
278 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); | ||
278 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 279 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
279 | return 0; | 280 | return 0; |
280 | } | 281 | } |
@@ -334,13 +335,14 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
334 | if (dev) { | 335 | if (dev) { |
335 | struct inet6_dev *idev = in6_dev_get(dev); | 336 | struct inet6_dev *idev = in6_dev_get(dev); |
336 | 337 | ||
338 | (void) ip6_mc_leave_src(sk, mc_lst, idev); | ||
337 | if (idev) { | 339 | if (idev) { |
338 | (void) ip6_mc_leave_src(sk, mc_lst, idev); | ||
339 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); | 340 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); |
340 | in6_dev_put(idev); | 341 | in6_dev_put(idev); |
341 | } | 342 | } |
342 | dev_put(dev); | 343 | dev_put(dev); |
343 | } | 344 | } else |
345 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); | ||
344 | 346 | ||
345 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 347 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
346 | 348 | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index f26898b00347..c9d6b23cd3f7 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -1398,23 +1398,39 @@ static int __init ip6_tables_init(void) | |||
1398 | { | 1398 | { |
1399 | int ret; | 1399 | int ret; |
1400 | 1400 | ||
1401 | xt_proto_init(AF_INET6); | 1401 | ret = xt_proto_init(AF_INET6); |
1402 | if (ret < 0) | ||
1403 | goto err1; | ||
1402 | 1404 | ||
1403 | /* Noone else will be downing sem now, so we won't sleep */ | 1405 | /* Noone else will be downing sem now, so we won't sleep */ |
1404 | xt_register_target(&ip6t_standard_target); | 1406 | ret = xt_register_target(&ip6t_standard_target); |
1405 | xt_register_target(&ip6t_error_target); | 1407 | if (ret < 0) |
1406 | xt_register_match(&icmp6_matchstruct); | 1408 | goto err2; |
1409 | ret = xt_register_target(&ip6t_error_target); | ||
1410 | if (ret < 0) | ||
1411 | goto err3; | ||
1412 | ret = xt_register_match(&icmp6_matchstruct); | ||
1413 | if (ret < 0) | ||
1414 | goto err4; | ||
1407 | 1415 | ||
1408 | /* Register setsockopt */ | 1416 | /* Register setsockopt */ |
1409 | ret = nf_register_sockopt(&ip6t_sockopts); | 1417 | ret = nf_register_sockopt(&ip6t_sockopts); |
1410 | if (ret < 0) { | 1418 | if (ret < 0) |
1411 | duprintf("Unable to register sockopts.\n"); | 1419 | goto err5; |
1412 | xt_proto_fini(AF_INET6); | ||
1413 | return ret; | ||
1414 | } | ||
1415 | 1420 | ||
1416 | printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); | 1421 | printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); |
1417 | return 0; | 1422 | return 0; |
1423 | |||
1424 | err5: | ||
1425 | xt_unregister_match(&icmp6_matchstruct); | ||
1426 | err4: | ||
1427 | xt_unregister_target(&ip6t_error_target); | ||
1428 | err3: | ||
1429 | xt_unregister_target(&ip6t_standard_target); | ||
1430 | err2: | ||
1431 | xt_proto_fini(AF_INET6); | ||
1432 | err1: | ||
1433 | return ret; | ||
1418 | } | 1434 | } |
1419 | 1435 | ||
1420 | static void __exit ip6_tables_fini(void) | 1436 | static void __exit ip6_tables_fini(void) |
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index aa34ff4b707c..bef3f61569f7 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c | |||
@@ -1642,13 +1642,17 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty | |||
1642 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) | 1642 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) |
1643 | goto out; | 1643 | goto out; |
1644 | 1644 | ||
1645 | ipx = ipx_hdr(skb); | 1645 | if (!pskb_may_pull(skb, sizeof(struct ipxhdr))) |
1646 | ipx_pktsize = ntohs(ipx->ipx_pktsize); | 1646 | goto drop; |
1647 | |||
1648 | ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize); | ||
1647 | 1649 | ||
1648 | /* Too small or invalid header? */ | 1650 | /* Too small or invalid header? */ |
1649 | if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len) | 1651 | if (ipx_pktsize < sizeof(struct ipxhdr) || |
1652 | !pskb_may_pull(skb, ipx_pktsize)) | ||
1650 | goto drop; | 1653 | goto drop; |
1651 | 1654 | ||
1655 | ipx = ipx_hdr(skb); | ||
1652 | if (ipx->ipx_checksum != IPX_NO_CHECKSUM && | 1656 | if (ipx->ipx_checksum != IPX_NO_CHECKSUM && |
1653 | ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize)) | 1657 | ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize)) |
1654 | goto drop; | 1658 | goto drop; |
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 42eb0c3a9780..61cb8cf7d153 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c | |||
@@ -330,6 +330,9 @@ static void llc_sap_mcast(struct llc_sap *sap, | |||
330 | if (llc->laddr.lsap != laddr->lsap) | 330 | if (llc->laddr.lsap != laddr->lsap) |
331 | continue; | 331 | continue; |
332 | 332 | ||
333 | if (llc->dev != skb->dev) | ||
334 | continue; | ||
335 | |||
333 | skb1 = skb_clone(skb, GFP_ATOMIC); | 336 | skb1 = skb_clone(skb, GFP_ATOMIC); |
334 | if (!skb1) | 337 | if (!skb1) |
335 | break; | 338 | break; |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index af4845971f70..6527d4e048d8 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -429,9 +429,9 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
429 | cb->args[0], *id); | 429 | cb->args[0], *id); |
430 | 430 | ||
431 | read_lock_bh(&nf_conntrack_lock); | 431 | read_lock_bh(&nf_conntrack_lock); |
432 | last = (struct nf_conn *)cb->args[1]; | ||
432 | for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { | 433 | for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { |
433 | restart: | 434 | restart: |
434 | last = (struct nf_conn *)cb->args[1]; | ||
435 | list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) { | 435 | list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) { |
436 | h = (struct nf_conntrack_tuple_hash *) i; | 436 | h = (struct nf_conntrack_tuple_hash *) i; |
437 | if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) | 437 | if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) |
@@ -442,13 +442,10 @@ restart: | |||
442 | * then dump everything. */ | 442 | * then dump everything. */ |
443 | if (l3proto && L3PROTO(ct) != l3proto) | 443 | if (l3proto && L3PROTO(ct) != l3proto) |
444 | continue; | 444 | continue; |
445 | if (last != NULL) { | 445 | if (cb->args[1]) { |
446 | if (ct == last) { | 446 | if (ct != last) |
447 | nf_ct_put(last); | ||
448 | cb->args[1] = 0; | ||
449 | last = NULL; | ||
450 | } else | ||
451 | continue; | 447 | continue; |
448 | cb->args[1] = 0; | ||
452 | } | 449 | } |
453 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, | 450 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, |
454 | cb->nlh->nlmsg_seq, | 451 | cb->nlh->nlmsg_seq, |
@@ -459,17 +456,17 @@ restart: | |||
459 | goto out; | 456 | goto out; |
460 | } | 457 | } |
461 | } | 458 | } |
462 | if (last != NULL) { | 459 | if (cb->args[1]) { |
463 | nf_ct_put(last); | ||
464 | cb->args[1] = 0; | 460 | cb->args[1] = 0; |
465 | goto restart; | 461 | goto restart; |
466 | } | 462 | } |
467 | } | 463 | } |
468 | out: | 464 | out: |
469 | read_unlock_bh(&nf_conntrack_lock); | 465 | read_unlock_bh(&nf_conntrack_lock); |
466 | if (last) | ||
467 | nf_ct_put(last); | ||
470 | 468 | ||
471 | DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); | 469 | DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); |
472 | |||
473 | return skb->len; | 470 | return skb->len; |
474 | } | 471 | } |
475 | 472 | ||
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 61cdda4e5d3b..b59d3b2bde21 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -366,6 +366,9 @@ __nfulnl_send(struct nfulnl_instance *inst) | |||
366 | if (timer_pending(&inst->timer)) | 366 | if (timer_pending(&inst->timer)) |
367 | del_timer(&inst->timer); | 367 | del_timer(&inst->timer); |
368 | 368 | ||
369 | if (!inst->skb) | ||
370 | return 0; | ||
371 | |||
369 | if (inst->qlen > 1) | 372 | if (inst->qlen > 1) |
370 | inst->lastnlh->nlmsg_type = NLMSG_DONE; | 373 | inst->lastnlh->nlmsg_type = NLMSG_DONE; |
371 | 374 | ||
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c index a9f4f6f3c628..63a965467465 100644 --- a/net/netfilter/xt_physdev.c +++ b/net/netfilter/xt_physdev.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
13 | #include <linux/netfilter_bridge.h> | ||
13 | #include <linux/netfilter/xt_physdev.h> | 14 | #include <linux/netfilter/xt_physdev.h> |
14 | #include <linux/netfilter/x_tables.h> | 15 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter_bridge.h> | 16 | #include <linux/netfilter_bridge.h> |
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c index d8e3891b5f8b..275330fcdaaa 100644 --- a/net/netfilter/xt_string.c +++ b/net/netfilter/xt_string.c | |||
@@ -37,7 +37,7 @@ static int match(const struct sk_buff *skb, | |||
37 | 37 | ||
38 | return (skb_find_text((struct sk_buff *)skb, conf->from_offset, | 38 | return (skb_find_text((struct sk_buff *)skb, conf->from_offset, |
39 | conf->to_offset, conf->config, &state) | 39 | conf->to_offset, conf->config, &state) |
40 | != UINT_MAX) && !conf->invert; | 40 | != UINT_MAX) ^ conf->invert; |
41 | } | 41 | } |
42 | 42 | ||
43 | #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) | 43 | #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) |
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index eea366966740..0a6cfa0005be 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -796,7 +796,7 @@ static int __init init_u32(void) | |||
796 | { | 796 | { |
797 | printk("u32 classifier\n"); | 797 | printk("u32 classifier\n"); |
798 | #ifdef CONFIG_CLS_U32_PERF | 798 | #ifdef CONFIG_CLS_U32_PERF |
799 | printk(" Perfomance counters on\n"); | 799 | printk(" Performance counters on\n"); |
800 | #endif | 800 | #endif |
801 | #ifdef CONFIG_NET_CLS_POLICE | 801 | #ifdef CONFIG_NET_CLS_POLICE |
802 | printk(" OLD policer on \n"); | 802 | printk(" OLD policer on \n"); |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index f35bc676128c..3da67ca2c3ce 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -1134,12 +1134,33 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) | |||
1134 | } | 1134 | } |
1135 | EXPORT_SYMBOL(__xfrm_route_forward); | 1135 | EXPORT_SYMBOL(__xfrm_route_forward); |
1136 | 1136 | ||
1137 | /* Optimize later using cookies and generation ids. */ | ||
1138 | |||
1137 | static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) | 1139 | static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) |
1138 | { | 1140 | { |
1139 | /* If it is marked obsolete, which is how we even get here, | 1141 | /* Code (such as __xfrm4_bundle_create()) sets dst->obsolete |
1140 | * then we have purged it from the policy bundle list and we | 1142 | * to "-1" to force all XFRM destinations to get validated by |
1141 | * did that for a good reason. | 1143 | * dst_ops->check on every use. We do this because when a |
1144 | * normal route referenced by an XFRM dst is obsoleted we do | ||
1145 | * not go looking around for all parent referencing XFRM dsts | ||
1146 | * so that we can invalidate them. It is just too much work. | ||
1147 | * Instead we make the checks here on every use. For example: | ||
1148 | * | ||
1149 | * XFRM dst A --> IPv4 dst X | ||
1150 | * | ||
1151 | * X is the "xdst->route" of A (X is also the "dst->path" of A | ||
1152 | * in this example). If X is marked obsolete, "A" will not | ||
1153 | * notice. That's what we are validating here via the | ||
1154 | * stale_bundle() check. | ||
1155 | * | ||
1156 | * When a policy's bundle is pruned, we dst_free() the XFRM | ||
1157 | * dst which causes it's ->obsolete field to be set to a | ||
1158 | * positive non-zero integer. If an XFRM dst has been pruned | ||
1159 | * like this, we want to force a new route lookup. | ||
1142 | */ | 1160 | */ |
1161 | if (dst->obsolete < 0 && !stale_bundle(dst)) | ||
1162 | return dst; | ||
1163 | |||
1143 | return NULL; | 1164 | return NULL; |
1144 | } | 1165 | } |
1145 | 1166 | ||