diff options
| author | Chris Metcalf <cmetcalf@tilera.com> | 2010-08-06 10:37:02 -0400 |
|---|---|---|
| committer | Chris Metcalf <cmetcalf@tilera.com> | 2010-08-06 10:37:02 -0400 |
| commit | ab11b487402f97975f3ac1eeea09c82f4431481e (patch) | |
| tree | 86337c5cbbd2b0c4bd07c0847a1dc7de3d898147 /net/ipv6 | |
| parent | 1c689cbcf2c2b7a35cd237abddd9206bb1b6fee1 (diff) | |
| parent | fc1caf6eafb30ea185720e29f7f5eccca61ecd60 (diff) | |
Merge branch 'master' into for-linus
Diffstat (limited to 'net/ipv6')
31 files changed, 640 insertions, 625 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e1a698df5706..ab70a3fbcafa 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -121,8 +121,6 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev) | |||
| 121 | static int __ipv6_regen_rndid(struct inet6_dev *idev); | 121 | static int __ipv6_regen_rndid(struct inet6_dev *idev); |
| 122 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); | 122 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); |
| 123 | static void ipv6_regen_rndid(unsigned long data); | 123 | static void ipv6_regen_rndid(unsigned long data); |
| 124 | |||
| 125 | static int desync_factor = MAX_DESYNC_FACTOR * HZ; | ||
| 126 | #endif | 124 | #endif |
| 127 | 125 | ||
| 128 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev); | 126 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev); |
| @@ -284,13 +282,16 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
| 284 | static int snmp6_alloc_dev(struct inet6_dev *idev) | 282 | static int snmp6_alloc_dev(struct inet6_dev *idev) |
| 285 | { | 283 | { |
| 286 | if (snmp_mib_init((void __percpu **)idev->stats.ipv6, | 284 | if (snmp_mib_init((void __percpu **)idev->stats.ipv6, |
| 287 | sizeof(struct ipstats_mib)) < 0) | 285 | sizeof(struct ipstats_mib), |
| 286 | __alignof__(struct ipstats_mib)) < 0) | ||
| 288 | goto err_ip; | 287 | goto err_ip; |
| 289 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, | 288 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, |
| 290 | sizeof(struct icmpv6_mib)) < 0) | 289 | sizeof(struct icmpv6_mib), |
| 290 | __alignof__(struct icmpv6_mib)) < 0) | ||
| 291 | goto err_icmp; | 291 | goto err_icmp; |
| 292 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, | 292 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, |
| 293 | sizeof(struct icmpv6msg_mib)) < 0) | 293 | sizeof(struct icmpv6msg_mib), |
| 294 | __alignof__(struct icmpv6msg_mib)) < 0) | ||
| 294 | goto err_icmpmsg; | 295 | goto err_icmpmsg; |
| 295 | 296 | ||
| 296 | return 0; | 297 | return 0; |
| @@ -557,7 +558,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
| 557 | pr_warning("Freeing alive inet6 address %p\n", ifp); | 558 | pr_warning("Freeing alive inet6 address %p\n", ifp); |
| 558 | return; | 559 | return; |
| 559 | } | 560 | } |
| 560 | dst_release(&ifp->rt->u.dst); | 561 | dst_release(&ifp->rt->dst); |
| 561 | 562 | ||
| 562 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); | 563 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); |
| 563 | } | 564 | } |
| @@ -823,7 +824,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
| 823 | rt->rt6i_flags |= RTF_EXPIRES; | 824 | rt->rt6i_flags |= RTF_EXPIRES; |
| 824 | } | 825 | } |
| 825 | } | 826 | } |
| 826 | dst_release(&rt->u.dst); | 827 | dst_release(&rt->dst); |
| 827 | } | 828 | } |
| 828 | 829 | ||
| 829 | out: | 830 | out: |
| @@ -890,7 +891,8 @@ retry: | |||
| 890 | idev->cnf.temp_valid_lft); | 891 | idev->cnf.temp_valid_lft); |
| 891 | tmp_prefered_lft = min_t(__u32, | 892 | tmp_prefered_lft = min_t(__u32, |
| 892 | ifp->prefered_lft, | 893 | ifp->prefered_lft, |
| 893 | idev->cnf.temp_prefered_lft - desync_factor / HZ); | 894 | idev->cnf.temp_prefered_lft - |
| 895 | idev->cnf.max_desync_factor); | ||
| 894 | tmp_plen = ifp->prefix_len; | 896 | tmp_plen = ifp->prefix_len; |
| 895 | max_addresses = idev->cnf.max_addresses; | 897 | max_addresses = idev->cnf.max_addresses; |
| 896 | tmp_cstamp = ifp->cstamp; | 898 | tmp_cstamp = ifp->cstamp; |
| @@ -1650,7 +1652,8 @@ static void ipv6_regen_rndid(unsigned long data) | |||
| 1650 | 1652 | ||
| 1651 | expires = jiffies + | 1653 | expires = jiffies + |
| 1652 | idev->cnf.temp_prefered_lft * HZ - | 1654 | idev->cnf.temp_prefered_lft * HZ - |
| 1653 | idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor; | 1655 | idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - |
| 1656 | idev->cnf.max_desync_factor * HZ; | ||
| 1654 | if (time_before(expires, jiffies)) { | 1657 | if (time_before(expires, jiffies)) { |
| 1655 | printk(KERN_WARNING | 1658 | printk(KERN_WARNING |
| 1656 | "ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n", | 1659 | "ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n", |
| @@ -1760,7 +1763,10 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) | |||
| 1760 | 1763 | ||
| 1761 | idev = ipv6_find_idev(dev); | 1764 | idev = ipv6_find_idev(dev); |
| 1762 | if (!idev) | 1765 | if (!idev) |
| 1763 | return NULL; | 1766 | return ERR_PTR(-ENOBUFS); |
| 1767 | |||
| 1768 | if (idev->cnf.disable_ipv6) | ||
| 1769 | return ERR_PTR(-EACCES); | ||
| 1764 | 1770 | ||
| 1765 | /* Add default multicast route */ | 1771 | /* Add default multicast route */ |
| 1766 | addrconf_add_mroute(dev); | 1772 | addrconf_add_mroute(dev); |
| @@ -1863,7 +1869,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
| 1863 | dev, expires, flags); | 1869 | dev, expires, flags); |
| 1864 | } | 1870 | } |
| 1865 | if (rt) | 1871 | if (rt) |
| 1866 | dst_release(&rt->u.dst); | 1872 | dst_release(&rt->dst); |
| 1867 | } | 1873 | } |
| 1868 | 1874 | ||
| 1869 | /* Try to figure out our local address for this prefix */ | 1875 | /* Try to figure out our local address for this prefix */ |
| @@ -2129,8 +2135,9 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | |||
| 2129 | if (!dev) | 2135 | if (!dev) |
| 2130 | return -ENODEV; | 2136 | return -ENODEV; |
| 2131 | 2137 | ||
| 2132 | if ((idev = addrconf_add_dev(dev)) == NULL) | 2138 | idev = addrconf_add_dev(dev); |
| 2133 | return -ENOBUFS; | 2139 | if (IS_ERR(idev)) |
| 2140 | return PTR_ERR(idev); | ||
| 2134 | 2141 | ||
| 2135 | scope = ipv6_addr_scope(pfx); | 2142 | scope = ipv6_addr_scope(pfx); |
| 2136 | 2143 | ||
| @@ -2377,7 +2384,7 @@ static void addrconf_dev_config(struct net_device *dev) | |||
| 2377 | } | 2384 | } |
| 2378 | 2385 | ||
| 2379 | idev = addrconf_add_dev(dev); | 2386 | idev = addrconf_add_dev(dev); |
| 2380 | if (idev == NULL) | 2387 | if (IS_ERR(idev)) |
| 2381 | return; | 2388 | return; |
| 2382 | 2389 | ||
| 2383 | memset(&addr, 0, sizeof(struct in6_addr)); | 2390 | memset(&addr, 0, sizeof(struct in6_addr)); |
| @@ -2468,7 +2475,7 @@ static void addrconf_ip6_tnl_config(struct net_device *dev) | |||
| 2468 | ASSERT_RTNL(); | 2475 | ASSERT_RTNL(); |
| 2469 | 2476 | ||
| 2470 | idev = addrconf_add_dev(dev); | 2477 | idev = addrconf_add_dev(dev); |
| 2471 | if (!idev) { | 2478 | if (IS_ERR(idev)) { |
| 2472 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); | 2479 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); |
| 2473 | return; | 2480 | return; |
| 2474 | } | 2481 | } |
| @@ -3492,8 +3499,12 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | |||
| 3492 | preferred -= tval; | 3499 | preferred -= tval; |
| 3493 | else | 3500 | else |
| 3494 | preferred = 0; | 3501 | preferred = 0; |
| 3495 | if (valid != INFINITY_LIFE_TIME) | 3502 | if (valid != INFINITY_LIFE_TIME) { |
| 3496 | valid -= tval; | 3503 | if (valid > tval) |
| 3504 | valid -= tval; | ||
| 3505 | else | ||
| 3506 | valid = 0; | ||
| 3507 | } | ||
| 3497 | } | 3508 | } |
| 3498 | } else { | 3509 | } else { |
| 3499 | preferred = INFINITY_LIFE_TIME; | 3510 | preferred = INFINITY_LIFE_TIME; |
| @@ -3855,12 +3866,28 @@ static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, | |||
| 3855 | memset(&stats[items], 0, pad); | 3866 | memset(&stats[items], 0, pad); |
| 3856 | } | 3867 | } |
| 3857 | 3868 | ||
| 3869 | static inline void __snmp6_fill_stats64(u64 *stats, void __percpu **mib, | ||
| 3870 | int items, int bytes, size_t syncpoff) | ||
| 3871 | { | ||
| 3872 | int i; | ||
| 3873 | int pad = bytes - sizeof(u64) * items; | ||
| 3874 | BUG_ON(pad < 0); | ||
| 3875 | |||
| 3876 | /* Use put_unaligned() because stats may not be aligned for u64. */ | ||
| 3877 | put_unaligned(items, &stats[0]); | ||
| 3878 | for (i = 1; i < items; i++) | ||
| 3879 | put_unaligned(snmp_fold_field64(mib, i, syncpoff), &stats[i]); | ||
| 3880 | |||
| 3881 | memset(&stats[items], 0, pad); | ||
| 3882 | } | ||
| 3883 | |||
| 3858 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | 3884 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, |
| 3859 | int bytes) | 3885 | int bytes) |
| 3860 | { | 3886 | { |
| 3861 | switch (attrtype) { | 3887 | switch (attrtype) { |
| 3862 | case IFLA_INET6_STATS: | 3888 | case IFLA_INET6_STATS: |
| 3863 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | 3889 | __snmp6_fill_stats64(stats, (void __percpu **)idev->stats.ipv6, |
| 3890 | IPSTATS_MIB_MAX, bytes, offsetof(struct ipstats_mib, syncp)); | ||
| 3864 | break; | 3891 | break; |
| 3865 | case IFLA_INET6_ICMP6STATS: | 3892 | case IFLA_INET6_ICMP6STATS: |
| 3866 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); | 3893 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); |
| @@ -4093,11 +4120,11 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
| 4093 | if (ifp->idev->cnf.forwarding) | 4120 | if (ifp->idev->cnf.forwarding) |
| 4094 | addrconf_leave_anycast(ifp); | 4121 | addrconf_leave_anycast(ifp); |
| 4095 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4122 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
| 4096 | dst_hold(&ifp->rt->u.dst); | 4123 | dst_hold(&ifp->rt->dst); |
| 4097 | 4124 | ||
| 4098 | if (ifp->state == INET6_IFADDR_STATE_DEAD && | 4125 | if (ifp->state == INET6_IFADDR_STATE_DEAD && |
| 4099 | ip6_del_rt(ifp->rt)) | 4126 | ip6_del_rt(ifp->rt)) |
| 4100 | dst_free(&ifp->rt->u.dst); | 4127 | dst_free(&ifp->rt->dst); |
| 4101 | break; | 4128 | break; |
| 4102 | } | 4129 | } |
| 4103 | } | 4130 | } |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index 8c4348cb1950..f0e774cea386 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
| @@ -53,11 +53,7 @@ static struct ip6addrlbl_table | |||
| 53 | static inline | 53 | static inline |
| 54 | struct net *ip6addrlbl_net(const struct ip6addrlbl_entry *lbl) | 54 | struct net *ip6addrlbl_net(const struct ip6addrlbl_entry *lbl) |
| 55 | { | 55 | { |
| 56 | #ifdef CONFIG_NET_NS | 56 | return read_pnet(&lbl->lbl_net); |
| 57 | return lbl->lbl_net; | ||
| 58 | #else | ||
| 59 | return &init_net; | ||
| 60 | #endif | ||
| 61 | } | 57 | } |
| 62 | 58 | ||
| 63 | /* | 59 | /* |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e733942dafe1..56b9bf2516f4 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
| @@ -522,10 +522,10 @@ const struct proto_ops inet6_stream_ops = { | |||
| 522 | .shutdown = inet_shutdown, /* ok */ | 522 | .shutdown = inet_shutdown, /* ok */ |
| 523 | .setsockopt = sock_common_setsockopt, /* ok */ | 523 | .setsockopt = sock_common_setsockopt, /* ok */ |
| 524 | .getsockopt = sock_common_getsockopt, /* ok */ | 524 | .getsockopt = sock_common_getsockopt, /* ok */ |
| 525 | .sendmsg = tcp_sendmsg, /* ok */ | 525 | .sendmsg = inet_sendmsg, /* ok */ |
| 526 | .recvmsg = sock_common_recvmsg, /* ok */ | 526 | .recvmsg = inet_recvmsg, /* ok */ |
| 527 | .mmap = sock_no_mmap, | 527 | .mmap = sock_no_mmap, |
| 528 | .sendpage = tcp_sendpage, | 528 | .sendpage = inet_sendpage, |
| 529 | .splice_read = tcp_splice_read, | 529 | .splice_read = tcp_splice_read, |
| 530 | #ifdef CONFIG_COMPAT | 530 | #ifdef CONFIG_COMPAT |
| 531 | .compat_setsockopt = compat_sock_common_setsockopt, | 531 | .compat_setsockopt = compat_sock_common_setsockopt, |
| @@ -549,7 +549,7 @@ const struct proto_ops inet6_dgram_ops = { | |||
| 549 | .setsockopt = sock_common_setsockopt, /* ok */ | 549 | .setsockopt = sock_common_setsockopt, /* ok */ |
| 550 | .getsockopt = sock_common_getsockopt, /* ok */ | 550 | .getsockopt = sock_common_getsockopt, /* ok */ |
| 551 | .sendmsg = inet_sendmsg, /* ok */ | 551 | .sendmsg = inet_sendmsg, /* ok */ |
| 552 | .recvmsg = sock_common_recvmsg, /* ok */ | 552 | .recvmsg = inet_recvmsg, /* ok */ |
| 553 | .mmap = sock_no_mmap, | 553 | .mmap = sock_no_mmap, |
| 554 | .sendpage = sock_no_sendpage, | 554 | .sendpage = sock_no_sendpage, |
| 555 | #ifdef CONFIG_COMPAT | 555 | #ifdef CONFIG_COMPAT |
| @@ -651,7 +651,7 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
| 651 | 651 | ||
| 652 | if (dst == NULL) { | 652 | if (dst == NULL) { |
| 653 | struct inet_sock *inet = inet_sk(sk); | 653 | struct inet_sock *inet = inet_sk(sk); |
| 654 | struct in6_addr *final_p = NULL, final; | 654 | struct in6_addr *final_p, final; |
| 655 | struct flowi fl; | 655 | struct flowi fl; |
| 656 | 656 | ||
| 657 | memset(&fl, 0, sizeof(fl)); | 657 | memset(&fl, 0, sizeof(fl)); |
| @@ -665,12 +665,7 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
| 665 | fl.fl_ip_sport = inet->inet_sport; | 665 | fl.fl_ip_sport = inet->inet_sport; |
| 666 | security_sk_classify_flow(sk, &fl); | 666 | security_sk_classify_flow(sk, &fl); |
| 667 | 667 | ||
| 668 | if (np->opt && np->opt->srcrt) { | 668 | final_p = fl6_update_dst(&fl, np->opt, &final); |
| 669 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; | ||
| 670 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 671 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 672 | final_p = &final; | ||
| 673 | } | ||
| 674 | 669 | ||
| 675 | err = ip6_dst_lookup(sk, &dst, &fl); | 670 | err = ip6_dst_lookup(sk, &dst, &fl); |
| 676 | if (err) { | 671 | if (err) { |
| @@ -976,19 +971,24 @@ static void ipv6_packet_cleanup(void) | |||
| 976 | static int __net_init ipv6_init_mibs(struct net *net) | 971 | static int __net_init ipv6_init_mibs(struct net *net) |
| 977 | { | 972 | { |
| 978 | if (snmp_mib_init((void __percpu **)net->mib.udp_stats_in6, | 973 | if (snmp_mib_init((void __percpu **)net->mib.udp_stats_in6, |
| 979 | sizeof (struct udp_mib)) < 0) | 974 | sizeof(struct udp_mib), |
| 975 | __alignof__(struct udp_mib)) < 0) | ||
| 980 | return -ENOMEM; | 976 | return -ENOMEM; |
| 981 | if (snmp_mib_init((void __percpu **)net->mib.udplite_stats_in6, | 977 | if (snmp_mib_init((void __percpu **)net->mib.udplite_stats_in6, |
| 982 | sizeof (struct udp_mib)) < 0) | 978 | sizeof(struct udp_mib), |
| 979 | __alignof__(struct udp_mib)) < 0) | ||
| 983 | goto err_udplite_mib; | 980 | goto err_udplite_mib; |
| 984 | if (snmp_mib_init((void __percpu **)net->mib.ipv6_statistics, | 981 | if (snmp_mib_init((void __percpu **)net->mib.ipv6_statistics, |
| 985 | sizeof(struct ipstats_mib)) < 0) | 982 | sizeof(struct ipstats_mib), |
| 983 | __alignof__(struct ipstats_mib)) < 0) | ||
| 986 | goto err_ip_mib; | 984 | goto err_ip_mib; |
| 987 | if (snmp_mib_init((void __percpu **)net->mib.icmpv6_statistics, | 985 | if (snmp_mib_init((void __percpu **)net->mib.icmpv6_statistics, |
| 988 | sizeof(struct icmpv6_mib)) < 0) | 986 | sizeof(struct icmpv6_mib), |
| 987 | __alignof__(struct icmpv6_mib)) < 0) | ||
| 989 | goto err_icmp_mib; | 988 | goto err_icmp_mib; |
| 990 | if (snmp_mib_init((void __percpu **)net->mib.icmpv6msg_statistics, | 989 | if (snmp_mib_init((void __percpu **)net->mib.icmpv6msg_statistics, |
| 991 | sizeof(struct icmpv6msg_mib)) < 0) | 990 | sizeof(struct icmpv6msg_mib), |
| 991 | __alignof__(struct icmpv6msg_mib)) < 0) | ||
| 992 | goto err_icmpmsg_mib; | 992 | goto err_icmpmsg_mib; |
| 993 | return 0; | 993 | return 0; |
| 994 | 994 | ||
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index b5b07054508a..0e5e943446f0 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
| @@ -77,41 +77,40 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
| 77 | pac->acl_next = NULL; | 77 | pac->acl_next = NULL; |
| 78 | ipv6_addr_copy(&pac->acl_addr, addr); | 78 | ipv6_addr_copy(&pac->acl_addr, addr); |
| 79 | 79 | ||
| 80 | rcu_read_lock(); | ||
| 80 | if (ifindex == 0) { | 81 | if (ifindex == 0) { |
| 81 | struct rt6_info *rt; | 82 | struct rt6_info *rt; |
| 82 | 83 | ||
| 83 | rt = rt6_lookup(net, addr, NULL, 0, 0); | 84 | rt = rt6_lookup(net, addr, NULL, 0, 0); |
| 84 | if (rt) { | 85 | if (rt) { |
| 85 | dev = rt->rt6i_dev; | 86 | dev = rt->rt6i_dev; |
| 86 | dev_hold(dev); | 87 | dst_release(&rt->dst); |
| 87 | dst_release(&rt->u.dst); | ||
| 88 | } else if (ishost) { | 88 | } else if (ishost) { |
| 89 | err = -EADDRNOTAVAIL; | 89 | err = -EADDRNOTAVAIL; |
| 90 | goto out_free_pac; | 90 | goto error; |
| 91 | } else { | 91 | } else { |
| 92 | /* router, no matching interface: just pick one */ | 92 | /* router, no matching interface: just pick one */ |
| 93 | 93 | dev = dev_get_by_flags_rcu(net, IFF_UP, | |
| 94 | dev = dev_get_by_flags(net, IFF_UP, IFF_UP|IFF_LOOPBACK); | 94 | IFF_UP | IFF_LOOPBACK); |
| 95 | } | 95 | } |
| 96 | } else | 96 | } else |
| 97 | dev = dev_get_by_index(net, ifindex); | 97 | dev = dev_get_by_index_rcu(net, ifindex); |
| 98 | 98 | ||
| 99 | if (dev == NULL) { | 99 | if (dev == NULL) { |
| 100 | err = -ENODEV; | 100 | err = -ENODEV; |
| 101 | goto out_free_pac; | 101 | goto error; |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | idev = in6_dev_get(dev); | 104 | idev = __in6_dev_get(dev); |
| 105 | if (!idev) { | 105 | if (!idev) { |
| 106 | if (ifindex) | 106 | if (ifindex) |
| 107 | err = -ENODEV; | 107 | err = -ENODEV; |
| 108 | else | 108 | else |
| 109 | err = -EADDRNOTAVAIL; | 109 | err = -EADDRNOTAVAIL; |
| 110 | goto out_dev_put; | 110 | goto error; |
| 111 | } | 111 | } |
| 112 | /* reset ishost, now that we have a specific device */ | 112 | /* reset ishost, now that we have a specific device */ |
| 113 | ishost = !idev->cnf.forwarding; | 113 | ishost = !idev->cnf.forwarding; |
| 114 | in6_dev_put(idev); | ||
| 115 | 114 | ||
| 116 | pac->acl_ifindex = dev->ifindex; | 115 | pac->acl_ifindex = dev->ifindex; |
| 117 | 116 | ||
| @@ -124,26 +123,22 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
| 124 | if (ishost) | 123 | if (ishost) |
| 125 | err = -EADDRNOTAVAIL; | 124 | err = -EADDRNOTAVAIL; |
| 126 | if (err) | 125 | if (err) |
| 127 | goto out_dev_put; | 126 | goto error; |
| 128 | } | 127 | } |
| 129 | 128 | ||
| 130 | err = ipv6_dev_ac_inc(dev, addr); | 129 | err = ipv6_dev_ac_inc(dev, addr); |
| 131 | if (err) | 130 | if (!err) { |
| 132 | goto out_dev_put; | 131 | write_lock_bh(&ipv6_sk_ac_lock); |
| 133 | 132 | pac->acl_next = np->ipv6_ac_list; | |
| 134 | write_lock_bh(&ipv6_sk_ac_lock); | 133 | np->ipv6_ac_list = pac; |
| 135 | pac->acl_next = np->ipv6_ac_list; | 134 | write_unlock_bh(&ipv6_sk_ac_lock); |
| 136 | np->ipv6_ac_list = pac; | 135 | pac = NULL; |
| 137 | write_unlock_bh(&ipv6_sk_ac_lock); | 136 | } |
| 138 | |||
| 139 | dev_put(dev); | ||
| 140 | |||
| 141 | return 0; | ||
| 142 | 137 | ||
| 143 | out_dev_put: | 138 | error: |
| 144 | dev_put(dev); | 139 | rcu_read_unlock(); |
| 145 | out_free_pac: | 140 | if (pac) |
| 146 | sock_kfree_s(sk, pac, sizeof(*pac)); | 141 | sock_kfree_s(sk, pac, sizeof(*pac)); |
| 147 | return err; | 142 | return err; |
| 148 | } | 143 | } |
| 149 | 144 | ||
| @@ -176,11 +171,12 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
| 176 | 171 | ||
| 177 | write_unlock_bh(&ipv6_sk_ac_lock); | 172 | write_unlock_bh(&ipv6_sk_ac_lock); |
| 178 | 173 | ||
| 179 | dev = dev_get_by_index(net, pac->acl_ifindex); | 174 | rcu_read_lock(); |
| 180 | if (dev) { | 175 | dev = dev_get_by_index_rcu(net, pac->acl_ifindex); |
| 176 | if (dev) | ||
| 181 | ipv6_dev_ac_dec(dev, &pac->acl_addr); | 177 | ipv6_dev_ac_dec(dev, &pac->acl_addr); |
| 182 | dev_put(dev); | 178 | rcu_read_unlock(); |
| 183 | } | 179 | |
| 184 | sock_kfree_s(sk, pac, sizeof(*pac)); | 180 | sock_kfree_s(sk, pac, sizeof(*pac)); |
| 185 | return 0; | 181 | return 0; |
| 186 | } | 182 | } |
| @@ -199,13 +195,12 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
| 199 | write_unlock_bh(&ipv6_sk_ac_lock); | 195 | write_unlock_bh(&ipv6_sk_ac_lock); |
| 200 | 196 | ||
| 201 | prev_index = 0; | 197 | prev_index = 0; |
| 198 | rcu_read_lock(); | ||
| 202 | while (pac) { | 199 | while (pac) { |
| 203 | struct ipv6_ac_socklist *next = pac->acl_next; | 200 | struct ipv6_ac_socklist *next = pac->acl_next; |
| 204 | 201 | ||
| 205 | if (pac->acl_ifindex != prev_index) { | 202 | if (pac->acl_ifindex != prev_index) { |
| 206 | if (dev) | 203 | dev = dev_get_by_index_rcu(net, pac->acl_ifindex); |
| 207 | dev_put(dev); | ||
| 208 | dev = dev_get_by_index(net, pac->acl_ifindex); | ||
| 209 | prev_index = pac->acl_ifindex; | 204 | prev_index = pac->acl_ifindex; |
| 210 | } | 205 | } |
| 211 | if (dev) | 206 | if (dev) |
| @@ -213,8 +208,7 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
| 213 | sock_kfree_s(sk, pac, sizeof(*pac)); | 208 | sock_kfree_s(sk, pac, sizeof(*pac)); |
| 214 | pac = next; | 209 | pac = next; |
| 215 | } | 210 | } |
| 216 | if (dev) | 211 | rcu_read_unlock(); |
| 217 | dev_put(dev); | ||
| 218 | } | 212 | } |
| 219 | 213 | ||
| 220 | #if 0 | 214 | #if 0 |
| @@ -250,7 +244,7 @@ static void aca_put(struct ifacaddr6 *ac) | |||
| 250 | { | 244 | { |
| 251 | if (atomic_dec_and_test(&ac->aca_refcnt)) { | 245 | if (atomic_dec_and_test(&ac->aca_refcnt)) { |
| 252 | in6_dev_put(ac->aca_idev); | 246 | in6_dev_put(ac->aca_idev); |
| 253 | dst_release(&ac->aca_rt->u.dst); | 247 | dst_release(&ac->aca_rt->dst); |
| 254 | kfree(ac); | 248 | kfree(ac); |
| 255 | } | 249 | } |
| 256 | } | 250 | } |
| @@ -356,40 +350,39 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) | |||
| 356 | write_unlock_bh(&idev->lock); | 350 | write_unlock_bh(&idev->lock); |
| 357 | addrconf_leave_solict(idev, &aca->aca_addr); | 351 | addrconf_leave_solict(idev, &aca->aca_addr); |
| 358 | 352 | ||
| 359 | dst_hold(&aca->aca_rt->u.dst); | 353 | dst_hold(&aca->aca_rt->dst); |
| 360 | ip6_del_rt(aca->aca_rt); | 354 | ip6_del_rt(aca->aca_rt); |
| 361 | 355 | ||
| 362 | aca_put(aca); | 356 | aca_put(aca); |
| 363 | return 0; | 357 | return 0; |
| 364 | } | 358 | } |
| 365 | 359 | ||
| 360 | /* called with rcu_read_lock() */ | ||
| 366 | static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) | 361 | static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) |
| 367 | { | 362 | { |
| 368 | int ret; | 363 | struct inet6_dev *idev = __in6_dev_get(dev); |
| 369 | struct inet6_dev *idev = in6_dev_get(dev); | 364 | |
| 370 | if (idev == NULL) | 365 | if (idev == NULL) |
| 371 | return -ENODEV; | 366 | return -ENODEV; |
| 372 | ret = __ipv6_dev_ac_dec(idev, addr); | 367 | return __ipv6_dev_ac_dec(idev, addr); |
| 373 | in6_dev_put(idev); | ||
| 374 | return ret; | ||
| 375 | } | 368 | } |
| 376 | 369 | ||
| 377 | /* | 370 | /* |
| 378 | * check if the interface has this anycast address | 371 | * check if the interface has this anycast address |
| 372 | * called with rcu_read_lock() | ||
| 379 | */ | 373 | */ |
| 380 | static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr) | 374 | static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr) |
| 381 | { | 375 | { |
| 382 | struct inet6_dev *idev; | 376 | struct inet6_dev *idev; |
| 383 | struct ifacaddr6 *aca; | 377 | struct ifacaddr6 *aca; |
| 384 | 378 | ||
| 385 | idev = in6_dev_get(dev); | 379 | idev = __in6_dev_get(dev); |
| 386 | if (idev) { | 380 | if (idev) { |
| 387 | read_lock_bh(&idev->lock); | 381 | read_lock_bh(&idev->lock); |
| 388 | for (aca = idev->ac_list; aca; aca = aca->aca_next) | 382 | for (aca = idev->ac_list; aca; aca = aca->aca_next) |
| 389 | if (ipv6_addr_equal(&aca->aca_addr, addr)) | 383 | if (ipv6_addr_equal(&aca->aca_addr, addr)) |
| 390 | break; | 384 | break; |
| 391 | read_unlock_bh(&idev->lock); | 385 | read_unlock_bh(&idev->lock); |
| 392 | in6_dev_put(idev); | ||
| 393 | return aca != NULL; | 386 | return aca != NULL; |
| 394 | } | 387 | } |
| 395 | return 0; | 388 | return 0; |
| @@ -403,14 +396,15 @@ int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, | |||
| 403 | { | 396 | { |
| 404 | int found = 0; | 397 | int found = 0; |
| 405 | 398 | ||
| 406 | if (dev) | ||
| 407 | return ipv6_chk_acast_dev(dev, addr); | ||
| 408 | rcu_read_lock(); | 399 | rcu_read_lock(); |
| 409 | for_each_netdev_rcu(net, dev) | 400 | if (dev) |
| 410 | if (ipv6_chk_acast_dev(dev, addr)) { | 401 | found = ipv6_chk_acast_dev(dev, addr); |
| 411 | found = 1; | 402 | else |
| 412 | break; | 403 | for_each_netdev_rcu(net, dev) |
| 413 | } | 404 | if (ipv6_chk_acast_dev(dev, addr)) { |
| 405 | found = 1; | ||
| 406 | break; | ||
| 407 | } | ||
| 414 | rcu_read_unlock(); | 408 | rcu_read_unlock(); |
| 415 | return found; | 409 | return found; |
| 416 | } | 410 | } |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 712684687c9a..7d929a22cbc2 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
| @@ -38,10 +38,11 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
| 38 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; | 38 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; |
| 39 | struct inet_sock *inet = inet_sk(sk); | 39 | struct inet_sock *inet = inet_sk(sk); |
| 40 | struct ipv6_pinfo *np = inet6_sk(sk); | 40 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 41 | struct in6_addr *daddr, *final_p = NULL, final; | 41 | struct in6_addr *daddr, *final_p, final; |
| 42 | struct dst_entry *dst; | 42 | struct dst_entry *dst; |
| 43 | struct flowi fl; | 43 | struct flowi fl; |
| 44 | struct ip6_flowlabel *flowlabel = NULL; | 44 | struct ip6_flowlabel *flowlabel = NULL; |
| 45 | struct ipv6_txoptions *opt; | ||
| 45 | int addr_type; | 46 | int addr_type; |
| 46 | int err; | 47 | int err; |
| 47 | 48 | ||
| @@ -155,19 +156,8 @@ ipv4_connected: | |||
| 155 | 156 | ||
| 156 | security_sk_classify_flow(sk, &fl); | 157 | security_sk_classify_flow(sk, &fl); |
| 157 | 158 | ||
| 158 | if (flowlabel) { | 159 | opt = flowlabel ? flowlabel->opt : np->opt; |
| 159 | if (flowlabel->opt && flowlabel->opt->srcrt) { | 160 | final_p = fl6_update_dst(&fl, opt, &final); |
| 160 | struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; | ||
| 161 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 162 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 163 | final_p = &final; | ||
| 164 | } | ||
| 165 | } else if (np->opt && np->opt->srcrt) { | ||
| 166 | struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; | ||
| 167 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 168 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 169 | final_p = &final; | ||
| 170 | } | ||
| 171 | 161 | ||
| 172 | err = ip6_dst_lookup(sk, &dst, &fl); | 162 | err = ip6_dst_lookup(sk, &dst, &fl); |
| 173 | if (err) | 163 | if (err) |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 8a659f92d17a..262f105d23b9 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
| @@ -312,6 +312,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) | |||
| 312 | Routing header. | 312 | Routing header. |
| 313 | ********************************/ | 313 | ********************************/ |
| 314 | 314 | ||
| 315 | /* called with rcu_read_lock() */ | ||
| 315 | static int ipv6_rthdr_rcv(struct sk_buff *skb) | 316 | static int ipv6_rthdr_rcv(struct sk_buff *skb) |
| 316 | { | 317 | { |
| 317 | struct inet6_skb_parm *opt = IP6CB(skb); | 318 | struct inet6_skb_parm *opt = IP6CB(skb); |
| @@ -324,12 +325,9 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) | |||
| 324 | struct net *net = dev_net(skb->dev); | 325 | struct net *net = dev_net(skb->dev); |
| 325 | int accept_source_route = net->ipv6.devconf_all->accept_source_route; | 326 | int accept_source_route = net->ipv6.devconf_all->accept_source_route; |
| 326 | 327 | ||
| 327 | idev = in6_dev_get(skb->dev); | 328 | idev = __in6_dev_get(skb->dev); |
| 328 | if (idev) { | 329 | if (idev && accept_source_route > idev->cnf.accept_source_route) |
| 329 | if (accept_source_route > idev->cnf.accept_source_route) | 330 | accept_source_route = idev->cnf.accept_source_route; |
| 330 | accept_source_route = idev->cnf.accept_source_route; | ||
| 331 | in6_dev_put(idev); | ||
| 332 | } | ||
| 333 | 331 | ||
| 334 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || | 332 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || |
| 335 | !pskb_may_pull(skb, (skb_transport_offset(skb) + | 333 | !pskb_may_pull(skb, (skb_transport_offset(skb) + |
| @@ -874,3 +872,27 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space, | |||
| 874 | return opt; | 872 | return opt; |
| 875 | } | 873 | } |
| 876 | 874 | ||
| 875 | /** | ||
| 876 | * fl6_update_dst - update flowi destination address with info given | ||
| 877 | * by srcrt option, if any. | ||
| 878 | * | ||
| 879 | * @fl: flowi for which fl6_dst is to be updated | ||
| 880 | * @opt: struct ipv6_txoptions in which to look for srcrt opt | ||
| 881 | * @orig: copy of original fl6_dst address if modified | ||
| 882 | * | ||
| 883 | * Returns NULL if no txoptions or no srcrt, otherwise returns orig | ||
| 884 | * and initial value of fl->fl6_dst set in orig | ||
| 885 | */ | ||
| 886 | struct in6_addr *fl6_update_dst(struct flowi *fl, | ||
| 887 | const struct ipv6_txoptions *opt, | ||
| 888 | struct in6_addr *orig) | ||
| 889 | { | ||
| 890 | if (!opt || !opt->srcrt) | ||
| 891 | return NULL; | ||
| 892 | |||
| 893 | ipv6_addr_copy(orig, &fl->fl6_dst); | ||
| 894 | ipv6_addr_copy(&fl->fl6_dst, ((struct rt0_hdr *)opt->srcrt)->addr); | ||
| 895 | return orig; | ||
| 896 | } | ||
| 897 | |||
| 898 | EXPORT_SYMBOL_GPL(fl6_update_dst); | ||
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 8e44f8f9c188..b1108ede18e1 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
| @@ -43,8 +43,8 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, | |||
| 43 | if (arg.result) | 43 | if (arg.result) |
| 44 | return arg.result; | 44 | return arg.result; |
| 45 | 45 | ||
| 46 | dst_hold(&net->ipv6.ip6_null_entry->u.dst); | 46 | dst_hold(&net->ipv6.ip6_null_entry->dst); |
| 47 | return &net->ipv6.ip6_null_entry->u.dst; | 47 | return &net->ipv6.ip6_null_entry->dst; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | 50 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, |
| @@ -86,7 +86,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
| 86 | struct in6_addr saddr; | 86 | struct in6_addr saddr; |
| 87 | 87 | ||
| 88 | if (ipv6_dev_get_saddr(net, | 88 | if (ipv6_dev_get_saddr(net, |
| 89 | ip6_dst_idev(&rt->u.dst)->dev, | 89 | ip6_dst_idev(&rt->dst)->dev, |
| 90 | &flp->fl6_dst, | 90 | &flp->fl6_dst, |
| 91 | rt6_flags2srcprefs(flags), | 91 | rt6_flags2srcprefs(flags), |
| 92 | &saddr)) | 92 | &saddr)) |
| @@ -99,12 +99,12 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
| 99 | goto out; | 99 | goto out; |
| 100 | } | 100 | } |
| 101 | again: | 101 | again: |
| 102 | dst_release(&rt->u.dst); | 102 | dst_release(&rt->dst); |
| 103 | rt = NULL; | 103 | rt = NULL; |
| 104 | goto out; | 104 | goto out; |
| 105 | 105 | ||
| 106 | discard_pkt: | 106 | discard_pkt: |
| 107 | dst_hold(&rt->u.dst); | 107 | dst_hold(&rt->dst); |
| 108 | out: | 108 | out: |
| 109 | arg->result = rt; | 109 | arg->result = rt; |
| 110 | return rt == NULL ? -EAGAIN : 0; | 110 | return rt == NULL ? -EAGAIN : 0; |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 0c5e3c3b7fd5..8a1628023bd1 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
| @@ -185,7 +185,7 @@ int inet6_csk_xmit(struct sk_buff *skb) | |||
| 185 | struct ipv6_pinfo *np = inet6_sk(sk); | 185 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 186 | struct flowi fl; | 186 | struct flowi fl; |
| 187 | struct dst_entry *dst; | 187 | struct dst_entry *dst; |
| 188 | struct in6_addr *final_p = NULL, final; | 188 | struct in6_addr *final_p, final; |
| 189 | 189 | ||
| 190 | memset(&fl, 0, sizeof(fl)); | 190 | memset(&fl, 0, sizeof(fl)); |
| 191 | fl.proto = sk->sk_protocol; | 191 | fl.proto = sk->sk_protocol; |
| @@ -199,12 +199,7 @@ int inet6_csk_xmit(struct sk_buff *skb) | |||
| 199 | fl.fl_ip_dport = inet->inet_dport; | 199 | fl.fl_ip_dport = inet->inet_dport; |
| 200 | security_sk_classify_flow(sk, &fl); | 200 | security_sk_classify_flow(sk, &fl); |
| 201 | 201 | ||
| 202 | if (np->opt && np->opt->srcrt) { | 202 | final_p = fl6_update_dst(&fl, np->opt, &final); |
| 203 | struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; | ||
| 204 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 205 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 206 | final_p = &final; | ||
| 207 | } | ||
| 208 | 203 | ||
| 209 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); | 204 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); |
| 210 | 205 | ||
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 92a122b7795d..b6a585909d35 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
| @@ -165,7 +165,7 @@ static __inline__ void node_free(struct fib6_node * fn) | |||
| 165 | static __inline__ void rt6_release(struct rt6_info *rt) | 165 | static __inline__ void rt6_release(struct rt6_info *rt) |
| 166 | { | 166 | { |
| 167 | if (atomic_dec_and_test(&rt->rt6i_ref)) | 167 | if (atomic_dec_and_test(&rt->rt6i_ref)) |
| 168 | dst_free(&rt->u.dst); | 168 | dst_free(&rt->dst); |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | static void fib6_link_table(struct net *net, struct fib6_table *tb) | 171 | static void fib6_link_table(struct net *net, struct fib6_table *tb) |
| @@ -278,7 +278,7 @@ static int fib6_dump_node(struct fib6_walker_t *w) | |||
| 278 | int res; | 278 | int res; |
| 279 | struct rt6_info *rt; | 279 | struct rt6_info *rt; |
| 280 | 280 | ||
| 281 | for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) { | 281 | for (rt = w->leaf; rt; rt = rt->dst.rt6_next) { |
| 282 | res = rt6_dump_route(rt, w->args); | 282 | res = rt6_dump_route(rt, w->args); |
| 283 | if (res < 0) { | 283 | if (res < 0) { |
| 284 | /* Frame is full, suspend walking */ | 284 | /* Frame is full, suspend walking */ |
| @@ -619,7 +619,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
| 619 | 619 | ||
| 620 | ins = &fn->leaf; | 620 | ins = &fn->leaf; |
| 621 | 621 | ||
| 622 | for (iter = fn->leaf; iter; iter=iter->u.dst.rt6_next) { | 622 | for (iter = fn->leaf; iter; iter=iter->dst.rt6_next) { |
| 623 | /* | 623 | /* |
| 624 | * Search for duplicates | 624 | * Search for duplicates |
| 625 | */ | 625 | */ |
| @@ -647,7 +647,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
| 647 | if (iter->rt6i_metric > rt->rt6i_metric) | 647 | if (iter->rt6i_metric > rt->rt6i_metric) |
| 648 | break; | 648 | break; |
| 649 | 649 | ||
| 650 | ins = &iter->u.dst.rt6_next; | 650 | ins = &iter->dst.rt6_next; |
| 651 | } | 651 | } |
| 652 | 652 | ||
| 653 | /* Reset round-robin state, if necessary */ | 653 | /* Reset round-robin state, if necessary */ |
| @@ -658,7 +658,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
| 658 | * insert node | 658 | * insert node |
| 659 | */ | 659 | */ |
| 660 | 660 | ||
| 661 | rt->u.dst.rt6_next = iter; | 661 | rt->dst.rt6_next = iter; |
| 662 | *ins = rt; | 662 | *ins = rt; |
| 663 | rt->rt6i_node = fn; | 663 | rt->rt6i_node = fn; |
| 664 | atomic_inc(&rt->rt6i_ref); | 664 | atomic_inc(&rt->rt6i_ref); |
| @@ -799,7 +799,7 @@ out: | |||
| 799 | atomic_inc(&pn->leaf->rt6i_ref); | 799 | atomic_inc(&pn->leaf->rt6i_ref); |
| 800 | } | 800 | } |
| 801 | #endif | 801 | #endif |
| 802 | dst_free(&rt->u.dst); | 802 | dst_free(&rt->dst); |
| 803 | } | 803 | } |
| 804 | return err; | 804 | return err; |
| 805 | 805 | ||
| @@ -810,7 +810,7 @@ out: | |||
| 810 | st_failure: | 810 | st_failure: |
| 811 | if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) | 811 | if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) |
| 812 | fib6_repair_tree(info->nl_net, fn); | 812 | fib6_repair_tree(info->nl_net, fn); |
| 813 | dst_free(&rt->u.dst); | 813 | dst_free(&rt->dst); |
| 814 | return err; | 814 | return err; |
| 815 | #endif | 815 | #endif |
| 816 | } | 816 | } |
| @@ -1108,7 +1108,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
| 1108 | RT6_TRACE("fib6_del_route\n"); | 1108 | RT6_TRACE("fib6_del_route\n"); |
| 1109 | 1109 | ||
| 1110 | /* Unlink it */ | 1110 | /* Unlink it */ |
| 1111 | *rtp = rt->u.dst.rt6_next; | 1111 | *rtp = rt->dst.rt6_next; |
| 1112 | rt->rt6i_node = NULL; | 1112 | rt->rt6i_node = NULL; |
| 1113 | net->ipv6.rt6_stats->fib_rt_entries--; | 1113 | net->ipv6.rt6_stats->fib_rt_entries--; |
| 1114 | net->ipv6.rt6_stats->fib_discarded_routes++; | 1114 | net->ipv6.rt6_stats->fib_discarded_routes++; |
| @@ -1122,14 +1122,14 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
| 1122 | FOR_WALKERS(w) { | 1122 | FOR_WALKERS(w) { |
| 1123 | if (w->state == FWS_C && w->leaf == rt) { | 1123 | if (w->state == FWS_C && w->leaf == rt) { |
| 1124 | RT6_TRACE("walker %p adjusted by delroute\n", w); | 1124 | RT6_TRACE("walker %p adjusted by delroute\n", w); |
| 1125 | w->leaf = rt->u.dst.rt6_next; | 1125 | w->leaf = rt->dst.rt6_next; |
| 1126 | if (w->leaf == NULL) | 1126 | if (w->leaf == NULL) |
| 1127 | w->state = FWS_U; | 1127 | w->state = FWS_U; |
| 1128 | } | 1128 | } |
| 1129 | } | 1129 | } |
| 1130 | read_unlock(&fib6_walker_lock); | 1130 | read_unlock(&fib6_walker_lock); |
| 1131 | 1131 | ||
| 1132 | rt->u.dst.rt6_next = NULL; | 1132 | rt->dst.rt6_next = NULL; |
| 1133 | 1133 | ||
| 1134 | /* If it was last route, expunge its radix tree node */ | 1134 | /* If it was last route, expunge its radix tree node */ |
| 1135 | if (fn->leaf == NULL) { | 1135 | if (fn->leaf == NULL) { |
| @@ -1168,7 +1168,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) | |||
| 1168 | struct rt6_info **rtp; | 1168 | struct rt6_info **rtp; |
| 1169 | 1169 | ||
| 1170 | #if RT6_DEBUG >= 2 | 1170 | #if RT6_DEBUG >= 2 |
| 1171 | if (rt->u.dst.obsolete>0) { | 1171 | if (rt->dst.obsolete>0) { |
| 1172 | WARN_ON(fn != NULL); | 1172 | WARN_ON(fn != NULL); |
| 1173 | return -ENOENT; | 1173 | return -ENOENT; |
| 1174 | } | 1174 | } |
| @@ -1195,7 +1195,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) | |||
| 1195 | * Walk the leaf entries looking for ourself | 1195 | * Walk the leaf entries looking for ourself |
| 1196 | */ | 1196 | */ |
| 1197 | 1197 | ||
| 1198 | for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.dst.rt6_next) { | 1198 | for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->dst.rt6_next) { |
| 1199 | if (*rtp == rt) { | 1199 | if (*rtp == rt) { |
| 1200 | fib6_del_route(fn, rtp, info); | 1200 | fib6_del_route(fn, rtp, info); |
| 1201 | return 0; | 1201 | return 0; |
| @@ -1334,7 +1334,7 @@ static int fib6_clean_node(struct fib6_walker_t *w) | |||
| 1334 | .nl_net = c->net, | 1334 | .nl_net = c->net, |
| 1335 | }; | 1335 | }; |
| 1336 | 1336 | ||
| 1337 | for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) { | 1337 | for (rt = w->leaf; rt; rt = rt->dst.rt6_next) { |
| 1338 | res = c->func(rt, c->arg); | 1338 | res = c->func(rt, c->arg); |
| 1339 | if (res < 0) { | 1339 | if (res < 0) { |
| 1340 | w->leaf = rt; | 1340 | w->leaf = rt; |
| @@ -1448,8 +1448,8 @@ static int fib6_age(struct rt6_info *rt, void *arg) | |||
| 1448 | } | 1448 | } |
| 1449 | gc_args.more++; | 1449 | gc_args.more++; |
| 1450 | } else if (rt->rt6i_flags & RTF_CACHE) { | 1450 | } else if (rt->rt6i_flags & RTF_CACHE) { |
| 1451 | if (atomic_read(&rt->u.dst.__refcnt) == 0 && | 1451 | if (atomic_read(&rt->dst.__refcnt) == 0 && |
| 1452 | time_after_eq(now, rt->u.dst.lastuse + gc_args.timeout)) { | 1452 | time_after_eq(now, rt->dst.lastuse + gc_args.timeout)) { |
| 1453 | RT6_TRACE("aging clone %p\n", rt); | 1453 | RT6_TRACE("aging clone %p\n", rt); |
| 1454 | return -1; | 1454 | return -1; |
| 1455 | } else if ((rt->rt6i_flags & RTF_GATEWAY) && | 1455 | } else if ((rt->rt6i_flags & RTF_GATEWAY) && |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 89425af0684c..d40b330c0ee6 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -698,7 +698,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 698 | ipv6_hdr(skb)->payload_len = htons(first_len - | 698 | ipv6_hdr(skb)->payload_len = htons(first_len - |
| 699 | sizeof(struct ipv6hdr)); | 699 | sizeof(struct ipv6hdr)); |
| 700 | 700 | ||
| 701 | dst_hold(&rt->u.dst); | 701 | dst_hold(&rt->dst); |
| 702 | 702 | ||
| 703 | for (;;) { | 703 | for (;;) { |
| 704 | /* Prepare header of the next frame, | 704 | /* Prepare header of the next frame, |
| @@ -726,7 +726,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 726 | 726 | ||
| 727 | err = output(skb); | 727 | err = output(skb); |
| 728 | if(!err) | 728 | if(!err) |
| 729 | IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst), | 729 | IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), |
| 730 | IPSTATS_MIB_FRAGCREATES); | 730 | IPSTATS_MIB_FRAGCREATES); |
| 731 | 731 | ||
| 732 | if (err || !frag) | 732 | if (err || !frag) |
| @@ -740,9 +740,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 740 | kfree(tmp_hdr); | 740 | kfree(tmp_hdr); |
| 741 | 741 | ||
| 742 | if (err == 0) { | 742 | if (err == 0) { |
| 743 | IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst), | 743 | IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), |
| 744 | IPSTATS_MIB_FRAGOKS); | 744 | IPSTATS_MIB_FRAGOKS); |
| 745 | dst_release(&rt->u.dst); | 745 | dst_release(&rt->dst); |
| 746 | return 0; | 746 | return 0; |
| 747 | } | 747 | } |
| 748 | 748 | ||
| @@ -752,9 +752,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 752 | frag = skb; | 752 | frag = skb; |
| 753 | } | 753 | } |
| 754 | 754 | ||
| 755 | IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst), | 755 | IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), |
| 756 | IPSTATS_MIB_FRAGFAILS); | 756 | IPSTATS_MIB_FRAGFAILS); |
| 757 | dst_release(&rt->u.dst); | 757 | dst_release(&rt->dst); |
| 758 | return err; | 758 | return err; |
| 759 | } | 759 | } |
| 760 | 760 | ||
| @@ -785,7 +785,7 @@ slow_path: | |||
| 785 | * Allocate buffer. | 785 | * Allocate buffer. |
| 786 | */ | 786 | */ |
| 787 | 787 | ||
| 788 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { | 788 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->dst.dev), GFP_ATOMIC)) == NULL) { |
| 789 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); | 789 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); |
| 790 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 790 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), |
| 791 | IPSTATS_MIB_FRAGFAILS); | 791 | IPSTATS_MIB_FRAGFAILS); |
| @@ -798,7 +798,7 @@ slow_path: | |||
| 798 | */ | 798 | */ |
| 799 | 799 | ||
| 800 | ip6_copy_metadata(frag, skb); | 800 | ip6_copy_metadata(frag, skb); |
| 801 | skb_reserve(frag, LL_RESERVED_SPACE(rt->u.dst.dev)); | 801 | skb_reserve(frag, LL_RESERVED_SPACE(rt->dst.dev)); |
| 802 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); | 802 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); |
| 803 | skb_reset_network_header(frag); | 803 | skb_reset_network_header(frag); |
| 804 | fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); | 804 | fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); |
| @@ -1156,24 +1156,24 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1156 | 1156 | ||
| 1157 | /* need source address above miyazawa*/ | 1157 | /* need source address above miyazawa*/ |
| 1158 | } | 1158 | } |
| 1159 | dst_hold(&rt->u.dst); | 1159 | dst_hold(&rt->dst); |
| 1160 | inet->cork.dst = &rt->u.dst; | 1160 | inet->cork.dst = &rt->dst; |
| 1161 | inet->cork.fl = *fl; | 1161 | inet->cork.fl = *fl; |
| 1162 | np->cork.hop_limit = hlimit; | 1162 | np->cork.hop_limit = hlimit; |
| 1163 | np->cork.tclass = tclass; | 1163 | np->cork.tclass = tclass; |
| 1164 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? | 1164 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? |
| 1165 | rt->u.dst.dev->mtu : dst_mtu(rt->u.dst.path); | 1165 | rt->dst.dev->mtu : dst_mtu(rt->dst.path); |
| 1166 | if (np->frag_size < mtu) { | 1166 | if (np->frag_size < mtu) { |
| 1167 | if (np->frag_size) | 1167 | if (np->frag_size) |
| 1168 | mtu = np->frag_size; | 1168 | mtu = np->frag_size; |
| 1169 | } | 1169 | } |
| 1170 | inet->cork.fragsize = mtu; | 1170 | inet->cork.fragsize = mtu; |
| 1171 | if (dst_allfrag(rt->u.dst.path)) | 1171 | if (dst_allfrag(rt->dst.path)) |
| 1172 | inet->cork.flags |= IPCORK_ALLFRAG; | 1172 | inet->cork.flags |= IPCORK_ALLFRAG; |
| 1173 | inet->cork.length = 0; | 1173 | inet->cork.length = 0; |
| 1174 | sk->sk_sndmsg_page = NULL; | 1174 | sk->sk_sndmsg_page = NULL; |
| 1175 | sk->sk_sndmsg_off = 0; | 1175 | sk->sk_sndmsg_off = 0; |
| 1176 | exthdrlen = rt->u.dst.header_len + (opt ? opt->opt_flen : 0) - | 1176 | exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) - |
| 1177 | rt->rt6i_nfheader_len; | 1177 | rt->rt6i_nfheader_len; |
| 1178 | length += exthdrlen; | 1178 | length += exthdrlen; |
| 1179 | transhdrlen += exthdrlen; | 1179 | transhdrlen += exthdrlen; |
| @@ -1186,7 +1186,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1186 | mtu = inet->cork.fragsize; | 1186 | mtu = inet->cork.fragsize; |
| 1187 | } | 1187 | } |
| 1188 | 1188 | ||
| 1189 | hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); | 1189 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
| 1190 | 1190 | ||
| 1191 | fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + | 1191 | fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + |
| 1192 | (opt ? opt->opt_nflen : 0); | 1192 | (opt ? opt->opt_nflen : 0); |
| @@ -1224,7 +1224,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1224 | } | 1224 | } |
| 1225 | 1225 | ||
| 1226 | if (proto == IPPROTO_UDP && | 1226 | if (proto == IPPROTO_UDP && |
| 1227 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | 1227 | (rt->dst.dev->features & NETIF_F_UFO)) { |
| 1228 | 1228 | ||
| 1229 | err = ip6_ufo_append_data(sk, getfrag, from, length, | 1229 | err = ip6_ufo_append_data(sk, getfrag, from, length, |
| 1230 | hh_len, fragheaderlen, | 1230 | hh_len, fragheaderlen, |
| @@ -1270,7 +1270,7 @@ alloc_new_skb: | |||
| 1270 | 1270 | ||
| 1271 | fraglen = datalen + fragheaderlen; | 1271 | fraglen = datalen + fragheaderlen; |
| 1272 | if ((flags & MSG_MORE) && | 1272 | if ((flags & MSG_MORE) && |
| 1273 | !(rt->u.dst.dev->features&NETIF_F_SG)) | 1273 | !(rt->dst.dev->features&NETIF_F_SG)) |
| 1274 | alloclen = mtu; | 1274 | alloclen = mtu; |
| 1275 | else | 1275 | else |
| 1276 | alloclen = datalen + fragheaderlen; | 1276 | alloclen = datalen + fragheaderlen; |
| @@ -1281,7 +1281,7 @@ alloc_new_skb: | |||
| 1281 | * because we have no idea if we're the last one. | 1281 | * because we have no idea if we're the last one. |
| 1282 | */ | 1282 | */ |
| 1283 | if (datalen == length + fraggap) | 1283 | if (datalen == length + fraggap) |
| 1284 | alloclen += rt->u.dst.trailer_len; | 1284 | alloclen += rt->dst.trailer_len; |
| 1285 | 1285 | ||
| 1286 | /* | 1286 | /* |
| 1287 | * We just reserve space for fragment header. | 1287 | * We just reserve space for fragment header. |
| @@ -1358,7 +1358,7 @@ alloc_new_skb: | |||
| 1358 | if (copy > length) | 1358 | if (copy > length) |
| 1359 | copy = length; | 1359 | copy = length; |
| 1360 | 1360 | ||
| 1361 | if (!(rt->u.dst.dev->features&NETIF_F_SG)) { | 1361 | if (!(rt->dst.dev->features&NETIF_F_SG)) { |
| 1362 | unsigned int off; | 1362 | unsigned int off; |
| 1363 | 1363 | ||
| 1364 | off = skb->len; | 1364 | off = skb->len; |
| @@ -1503,7 +1503,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
| 1503 | skb->priority = sk->sk_priority; | 1503 | skb->priority = sk->sk_priority; |
| 1504 | skb->mark = sk->sk_mark; | 1504 | skb->mark = sk->sk_mark; |
| 1505 | 1505 | ||
| 1506 | skb_dst_set(skb, dst_clone(&rt->u.dst)); | 1506 | skb_dst_set(skb, dst_clone(&rt->dst)); |
| 1507 | IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); | 1507 | IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); |
| 1508 | if (proto == IPPROTO_ICMPV6) { | 1508 | if (proto == IPPROTO_ICMPV6) { |
| 1509 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 1509 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 8f39893d8081..0fd027f3f47e 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
| @@ -552,7 +552,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 552 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl)) | 552 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl)) |
| 553 | goto out; | 553 | goto out; |
| 554 | 554 | ||
| 555 | skb2->dev = rt->u.dst.dev; | 555 | skb2->dev = rt->dst.dev; |
| 556 | 556 | ||
| 557 | /* route "incoming" packet */ | 557 | /* route "incoming" packet */ |
| 558 | if (rt->rt_flags & RTCF_LOCAL) { | 558 | if (rt->rt_flags & RTCF_LOCAL) { |
| @@ -562,7 +562,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 562 | fl.fl4_src = eiph->saddr; | 562 | fl.fl4_src = eiph->saddr; |
| 563 | fl.fl4_tos = eiph->tos; | 563 | fl.fl4_tos = eiph->tos; |
| 564 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) || | 564 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) || |
| 565 | rt->u.dst.dev->type != ARPHRD_TUNNEL) { | 565 | rt->dst.dev->type != ARPHRD_TUNNEL) { |
| 566 | ip_rt_put(rt); | 566 | ip_rt_put(rt); |
| 567 | goto out; | 567 | goto out; |
| 568 | } | 568 | } |
| @@ -626,7 +626,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 626 | icmpv6_send(skb2, rel_type, rel_code, rel_info); | 626 | icmpv6_send(skb2, rel_type, rel_code, rel_info); |
| 627 | 627 | ||
| 628 | if (rt) | 628 | if (rt) |
| 629 | dst_release(&rt->u.dst); | 629 | dst_release(&rt->dst); |
| 630 | 630 | ||
| 631 | kfree_skb(skb2); | 631 | kfree_skb(skb2); |
| 632 | } | 632 | } |
| @@ -1135,7 +1135,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) | |||
| 1135 | if (dev->mtu < IPV6_MIN_MTU) | 1135 | if (dev->mtu < IPV6_MIN_MTU) |
| 1136 | dev->mtu = IPV6_MIN_MTU; | 1136 | dev->mtu = IPV6_MIN_MTU; |
| 1137 | } | 1137 | } |
| 1138 | dst_release(&rt->u.dst); | 1138 | dst_release(&rt->dst); |
| 1139 | } | 1139 | } |
| 1140 | } | 1140 | } |
| 1141 | 1141 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index bd43f0152c21..a7f66bc8f0b0 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
| @@ -55,8 +55,6 @@ | |||
| 55 | 55 | ||
| 56 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
| 57 | 57 | ||
| 58 | DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly; | ||
| 59 | |||
| 60 | struct ip6_ra_chain *ip6_ra_chain; | 58 | struct ip6_ra_chain *ip6_ra_chain; |
| 61 | DEFINE_RWLOCK(ip6_ra_lock); | 59 | DEFINE_RWLOCK(ip6_ra_lock); |
| 62 | 60 | ||
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index ab1622d7d409..d1444b95ad7e 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -152,18 +152,19 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 152 | mc_lst->next = NULL; | 152 | mc_lst->next = NULL; |
| 153 | ipv6_addr_copy(&mc_lst->addr, addr); | 153 | ipv6_addr_copy(&mc_lst->addr, addr); |
| 154 | 154 | ||
| 155 | rcu_read_lock(); | ||
| 155 | if (ifindex == 0) { | 156 | if (ifindex == 0) { |
| 156 | struct rt6_info *rt; | 157 | struct rt6_info *rt; |
| 157 | rt = rt6_lookup(net, addr, NULL, 0, 0); | 158 | rt = rt6_lookup(net, addr, NULL, 0, 0); |
| 158 | if (rt) { | 159 | if (rt) { |
| 159 | dev = rt->rt6i_dev; | 160 | dev = rt->rt6i_dev; |
| 160 | dev_hold(dev); | 161 | dst_release(&rt->dst); |
| 161 | dst_release(&rt->u.dst); | ||
| 162 | } | 162 | } |
| 163 | } else | 163 | } else |
| 164 | dev = dev_get_by_index(net, ifindex); | 164 | dev = dev_get_by_index_rcu(net, ifindex); |
| 165 | 165 | ||
| 166 | if (dev == NULL) { | 166 | if (dev == NULL) { |
| 167 | rcu_read_unlock(); | ||
| 167 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 168 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
| 168 | return -ENODEV; | 169 | return -ENODEV; |
| 169 | } | 170 | } |
| @@ -180,8 +181,8 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 180 | err = ipv6_dev_mc_inc(dev, addr); | 181 | err = ipv6_dev_mc_inc(dev, addr); |
| 181 | 182 | ||
| 182 | if (err) { | 183 | if (err) { |
| 184 | rcu_read_unlock(); | ||
| 183 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 185 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
| 184 | dev_put(dev); | ||
| 185 | return err; | 186 | return err; |
| 186 | } | 187 | } |
| 187 | 188 | ||
| @@ -190,7 +191,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 190 | np->ipv6_mc_list = mc_lst; | 191 | np->ipv6_mc_list = mc_lst; |
| 191 | write_unlock_bh(&ipv6_sk_mc_lock); | 192 | write_unlock_bh(&ipv6_sk_mc_lock); |
| 192 | 193 | ||
| 193 | dev_put(dev); | 194 | rcu_read_unlock(); |
| 194 | 195 | ||
| 195 | return 0; | 196 | return 0; |
| 196 | } | 197 | } |
| @@ -213,18 +214,17 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 213 | *lnk = mc_lst->next; | 214 | *lnk = mc_lst->next; |
| 214 | write_unlock_bh(&ipv6_sk_mc_lock); | 215 | write_unlock_bh(&ipv6_sk_mc_lock); |
| 215 | 216 | ||
| 216 | dev = dev_get_by_index(net, mc_lst->ifindex); | 217 | rcu_read_lock(); |
| 218 | dev = dev_get_by_index_rcu(net, mc_lst->ifindex); | ||
| 217 | if (dev != NULL) { | 219 | if (dev != NULL) { |
| 218 | struct inet6_dev *idev = in6_dev_get(dev); | 220 | struct inet6_dev *idev = __in6_dev_get(dev); |
| 219 | 221 | ||
| 220 | (void) ip6_mc_leave_src(sk, mc_lst, idev); | 222 | (void) ip6_mc_leave_src(sk, mc_lst, idev); |
| 221 | if (idev) { | 223 | if (idev) |
| 222 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); | 224 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); |
| 223 | in6_dev_put(idev); | ||
| 224 | } | ||
| 225 | dev_put(dev); | ||
| 226 | } else | 225 | } else |
| 227 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); | 226 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); |
| 227 | rcu_read_unlock(); | ||
| 228 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 228 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
| 229 | return 0; | 229 | return 0; |
| 230 | } | 230 | } |
| @@ -234,43 +234,36 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 234 | return -EADDRNOTAVAIL; | 234 | return -EADDRNOTAVAIL; |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | static struct inet6_dev *ip6_mc_find_dev(struct net *net, | 237 | /* called with rcu_read_lock() */ |
| 238 | struct in6_addr *group, | 238 | static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, |
| 239 | int ifindex) | 239 | struct in6_addr *group, |
| 240 | int ifindex) | ||
| 240 | { | 241 | { |
| 241 | struct net_device *dev = NULL; | 242 | struct net_device *dev = NULL; |
| 242 | struct inet6_dev *idev = NULL; | 243 | struct inet6_dev *idev = NULL; |
| 243 | 244 | ||
| 244 | if (ifindex == 0) { | 245 | if (ifindex == 0) { |
| 245 | struct rt6_info *rt; | 246 | struct rt6_info *rt = rt6_lookup(net, group, NULL, 0, 0); |
| 246 | 247 | ||
| 247 | rt = rt6_lookup(net, group, NULL, 0, 0); | ||
| 248 | if (rt) { | 248 | if (rt) { |
| 249 | dev = rt->rt6i_dev; | 249 | dev = rt->rt6i_dev; |
| 250 | dev_hold(dev); | 250 | dev_hold(dev); |
| 251 | dst_release(&rt->u.dst); | 251 | dst_release(&rt->dst); |
| 252 | } | 252 | } |
| 253 | } else | 253 | } else |
| 254 | dev = dev_get_by_index(net, ifindex); | 254 | dev = dev_get_by_index_rcu(net, ifindex); |
| 255 | 255 | ||
| 256 | if (!dev) | 256 | if (!dev) |
| 257 | goto nodev; | 257 | return NULL; |
| 258 | idev = in6_dev_get(dev); | 258 | idev = __in6_dev_get(dev); |
| 259 | if (!idev) | 259 | if (!idev) |
| 260 | goto release; | 260 | return NULL;; |
| 261 | read_lock_bh(&idev->lock); | 261 | read_lock_bh(&idev->lock); |
| 262 | if (idev->dead) | 262 | if (idev->dead) { |
| 263 | goto unlock_release; | 263 | read_unlock_bh(&idev->lock); |
| 264 | 264 | return NULL; | |
| 265 | } | ||
| 265 | return idev; | 266 | return idev; |
| 266 | |||
| 267 | unlock_release: | ||
| 268 | read_unlock_bh(&idev->lock); | ||
| 269 | in6_dev_put(idev); | ||
| 270 | release: | ||
| 271 | dev_put(dev); | ||
| 272 | nodev: | ||
| 273 | return NULL; | ||
| 274 | } | 267 | } |
| 275 | 268 | ||
| 276 | void ipv6_sock_mc_close(struct sock *sk) | 269 | void ipv6_sock_mc_close(struct sock *sk) |
| @@ -286,19 +279,17 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
| 286 | np->ipv6_mc_list = mc_lst->next; | 279 | np->ipv6_mc_list = mc_lst->next; |
| 287 | write_unlock_bh(&ipv6_sk_mc_lock); | 280 | write_unlock_bh(&ipv6_sk_mc_lock); |
| 288 | 281 | ||
| 289 | dev = dev_get_by_index(net, mc_lst->ifindex); | 282 | rcu_read_lock(); |
| 283 | dev = dev_get_by_index_rcu(net, mc_lst->ifindex); | ||
| 290 | if (dev) { | 284 | if (dev) { |
| 291 | struct inet6_dev *idev = in6_dev_get(dev); | 285 | struct inet6_dev *idev = __in6_dev_get(dev); |
| 292 | 286 | ||
| 293 | (void) ip6_mc_leave_src(sk, mc_lst, idev); | 287 | (void) ip6_mc_leave_src(sk, mc_lst, idev); |
| 294 | if (idev) { | 288 | if (idev) |
| 295 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); | 289 | __ipv6_dev_mc_dec(idev, &mc_lst->addr); |
| 296 | in6_dev_put(idev); | ||
| 297 | } | ||
| 298 | dev_put(dev); | ||
| 299 | } else | 290 | } else |
| 300 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); | 291 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); |
| 301 | 292 | rcu_read_unlock(); | |
| 302 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 293 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
| 303 | 294 | ||
| 304 | write_lock_bh(&ipv6_sk_mc_lock); | 295 | write_lock_bh(&ipv6_sk_mc_lock); |
| @@ -327,14 +318,17 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
| 327 | if (!ipv6_addr_is_multicast(group)) | 318 | if (!ipv6_addr_is_multicast(group)) |
| 328 | return -EINVAL; | 319 | return -EINVAL; |
| 329 | 320 | ||
| 330 | idev = ip6_mc_find_dev(net, group, pgsr->gsr_interface); | 321 | rcu_read_lock(); |
| 331 | if (!idev) | 322 | idev = ip6_mc_find_dev_rcu(net, group, pgsr->gsr_interface); |
| 323 | if (!idev) { | ||
| 324 | rcu_read_unlock(); | ||
| 332 | return -ENODEV; | 325 | return -ENODEV; |
| 326 | } | ||
| 333 | dev = idev->dev; | 327 | dev = idev->dev; |
| 334 | 328 | ||
| 335 | err = -EADDRNOTAVAIL; | 329 | err = -EADDRNOTAVAIL; |
| 336 | 330 | ||
| 337 | read_lock_bh(&ipv6_sk_mc_lock); | 331 | read_lock(&ipv6_sk_mc_lock); |
| 338 | for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) { | 332 | for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) { |
| 339 | if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface) | 333 | if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface) |
| 340 | continue; | 334 | continue; |
| @@ -358,7 +352,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
| 358 | pmc->sfmode = omode; | 352 | pmc->sfmode = omode; |
| 359 | } | 353 | } |
| 360 | 354 | ||
| 361 | write_lock_bh(&pmc->sflock); | 355 | write_lock(&pmc->sflock); |
| 362 | pmclocked = 1; | 356 | pmclocked = 1; |
| 363 | 357 | ||
| 364 | psl = pmc->sflist; | 358 | psl = pmc->sflist; |
| @@ -433,11 +427,10 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
| 433 | ip6_mc_add_src(idev, group, omode, 1, source, 1); | 427 | ip6_mc_add_src(idev, group, omode, 1, source, 1); |
| 434 | done: | 428 | done: |
| 435 | if (pmclocked) | 429 | if (pmclocked) |
| 436 | write_unlock_bh(&pmc->sflock); | 430 | write_unlock(&pmc->sflock); |
| 437 | read_unlock_bh(&ipv6_sk_mc_lock); | 431 | read_unlock(&ipv6_sk_mc_lock); |
| 438 | read_unlock_bh(&idev->lock); | 432 | read_unlock_bh(&idev->lock); |
| 439 | in6_dev_put(idev); | 433 | rcu_read_unlock(); |
| 440 | dev_put(dev); | ||
| 441 | if (leavegroup) | 434 | if (leavegroup) |
| 442 | return ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group); | 435 | return ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group); |
| 443 | return err; | 436 | return err; |
| @@ -463,14 +456,17 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
| 463 | gsf->gf_fmode != MCAST_EXCLUDE) | 456 | gsf->gf_fmode != MCAST_EXCLUDE) |
| 464 | return -EINVAL; | 457 | return -EINVAL; |
| 465 | 458 | ||
| 466 | idev = ip6_mc_find_dev(net, group, gsf->gf_interface); | 459 | rcu_read_lock(); |
| 460 | idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface); | ||
| 467 | 461 | ||
| 468 | if (!idev) | 462 | if (!idev) { |
| 463 | rcu_read_unlock(); | ||
| 469 | return -ENODEV; | 464 | return -ENODEV; |
| 465 | } | ||
| 470 | dev = idev->dev; | 466 | dev = idev->dev; |
| 471 | 467 | ||
| 472 | err = 0; | 468 | err = 0; |
| 473 | read_lock_bh(&ipv6_sk_mc_lock); | 469 | read_lock(&ipv6_sk_mc_lock); |
| 474 | 470 | ||
| 475 | if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) { | 471 | if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) { |
| 476 | leavegroup = 1; | 472 | leavegroup = 1; |
| @@ -512,7 +508,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
| 512 | (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0); | 508 | (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0); |
| 513 | } | 509 | } |
| 514 | 510 | ||
| 515 | write_lock_bh(&pmc->sflock); | 511 | write_lock(&pmc->sflock); |
| 516 | psl = pmc->sflist; | 512 | psl = pmc->sflist; |
| 517 | if (psl) { | 513 | if (psl) { |
| 518 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, | 514 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, |
| @@ -522,13 +518,12 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
| 522 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); | 518 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); |
| 523 | pmc->sflist = newpsl; | 519 | pmc->sflist = newpsl; |
| 524 | pmc->sfmode = gsf->gf_fmode; | 520 | pmc->sfmode = gsf->gf_fmode; |
| 525 | write_unlock_bh(&pmc->sflock); | 521 | write_unlock(&pmc->sflock); |
| 526 | err = 0; | 522 | err = 0; |
| 527 | done: | 523 | done: |
| 528 | read_unlock_bh(&ipv6_sk_mc_lock); | 524 | read_unlock(&ipv6_sk_mc_lock); |
| 529 | read_unlock_bh(&idev->lock); | 525 | read_unlock_bh(&idev->lock); |
| 530 | in6_dev_put(idev); | 526 | rcu_read_unlock(); |
| 531 | dev_put(dev); | ||
| 532 | if (leavegroup) | 527 | if (leavegroup) |
| 533 | err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group); | 528 | err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group); |
| 534 | return err; | 529 | return err; |
| @@ -551,11 +546,13 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
| 551 | if (!ipv6_addr_is_multicast(group)) | 546 | if (!ipv6_addr_is_multicast(group)) |
| 552 | return -EINVAL; | 547 | return -EINVAL; |
| 553 | 548 | ||
| 554 | idev = ip6_mc_find_dev(net, group, gsf->gf_interface); | 549 | rcu_read_lock(); |
| 550 | idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface); | ||
| 555 | 551 | ||
| 556 | if (!idev) | 552 | if (!idev) { |
| 553 | rcu_read_unlock(); | ||
| 557 | return -ENODEV; | 554 | return -ENODEV; |
| 558 | 555 | } | |
| 559 | dev = idev->dev; | 556 | dev = idev->dev; |
| 560 | 557 | ||
| 561 | err = -EADDRNOTAVAIL; | 558 | err = -EADDRNOTAVAIL; |
| @@ -577,8 +574,7 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
| 577 | psl = pmc->sflist; | 574 | psl = pmc->sflist; |
| 578 | count = psl ? psl->sl_count : 0; | 575 | count = psl ? psl->sl_count : 0; |
| 579 | read_unlock_bh(&idev->lock); | 576 | read_unlock_bh(&idev->lock); |
| 580 | in6_dev_put(idev); | 577 | rcu_read_unlock(); |
| 581 | dev_put(dev); | ||
| 582 | 578 | ||
| 583 | copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; | 579 | copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; |
| 584 | gsf->gf_numsrc = count; | 580 | gsf->gf_numsrc = count; |
| @@ -604,8 +600,7 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
| 604 | return 0; | 600 | return 0; |
| 605 | done: | 601 | done: |
| 606 | read_unlock_bh(&idev->lock); | 602 | read_unlock_bh(&idev->lock); |
| 607 | in6_dev_put(idev); | 603 | rcu_read_unlock(); |
| 608 | dev_put(dev); | ||
| 609 | return err; | 604 | return err; |
| 610 | } | 605 | } |
| 611 | 606 | ||
| @@ -822,6 +817,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) | |||
| 822 | struct ifmcaddr6 *mc; | 817 | struct ifmcaddr6 *mc; |
| 823 | struct inet6_dev *idev; | 818 | struct inet6_dev *idev; |
| 824 | 819 | ||
| 820 | /* we need to take a reference on idev */ | ||
| 825 | idev = in6_dev_get(dev); | 821 | idev = in6_dev_get(dev); |
| 826 | 822 | ||
| 827 | if (idev == NULL) | 823 | if (idev == NULL) |
| @@ -860,7 +856,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) | |||
| 860 | setup_timer(&mc->mca_timer, igmp6_timer_handler, (unsigned long)mc); | 856 | setup_timer(&mc->mca_timer, igmp6_timer_handler, (unsigned long)mc); |
| 861 | 857 | ||
| 862 | ipv6_addr_copy(&mc->mca_addr, addr); | 858 | ipv6_addr_copy(&mc->mca_addr, addr); |
| 863 | mc->idev = idev; | 859 | mc->idev = idev; /* (reference taken) */ |
| 864 | mc->mca_users = 1; | 860 | mc->mca_users = 1; |
| 865 | /* mca_stamp should be updated upon changes */ | 861 | /* mca_stamp should be updated upon changes */ |
| 866 | mc->mca_cstamp = mc->mca_tstamp = jiffies; | 862 | mc->mca_cstamp = mc->mca_tstamp = jiffies; |
| @@ -915,16 +911,18 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr) | |||
| 915 | 911 | ||
| 916 | int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr) | 912 | int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr) |
| 917 | { | 913 | { |
| 918 | struct inet6_dev *idev = in6_dev_get(dev); | 914 | struct inet6_dev *idev; |
| 919 | int err; | 915 | int err; |
| 920 | 916 | ||
| 921 | if (!idev) | 917 | rcu_read_lock(); |
| 922 | return -ENODEV; | ||
| 923 | |||
| 924 | err = __ipv6_dev_mc_dec(idev, addr); | ||
| 925 | 918 | ||
| 926 | in6_dev_put(idev); | 919 | idev = __in6_dev_get(dev); |
| 920 | if (!idev) | ||
| 921 | err = -ENODEV; | ||
| 922 | else | ||
| 923 | err = __ipv6_dev_mc_dec(idev, addr); | ||
| 927 | 924 | ||
| 925 | rcu_read_unlock(); | ||
| 928 | return err; | 926 | return err; |
| 929 | } | 927 | } |
| 930 | 928 | ||
| @@ -965,7 +963,8 @@ int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group, | |||
| 965 | struct ifmcaddr6 *mc; | 963 | struct ifmcaddr6 *mc; |
| 966 | int rv = 0; | 964 | int rv = 0; |
| 967 | 965 | ||
| 968 | idev = in6_dev_get(dev); | 966 | rcu_read_lock(); |
| 967 | idev = __in6_dev_get(dev); | ||
| 969 | if (idev) { | 968 | if (idev) { |
| 970 | read_lock_bh(&idev->lock); | 969 | read_lock_bh(&idev->lock); |
| 971 | for (mc = idev->mc_list; mc; mc=mc->next) { | 970 | for (mc = idev->mc_list; mc; mc=mc->next) { |
| @@ -992,8 +991,8 @@ int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group, | |||
| 992 | rv = 1; /* don't filter unspecified source */ | 991 | rv = 1; /* don't filter unspecified source */ |
| 993 | } | 992 | } |
| 994 | read_unlock_bh(&idev->lock); | 993 | read_unlock_bh(&idev->lock); |
| 995 | in6_dev_put(idev); | ||
| 996 | } | 994 | } |
| 995 | rcu_read_unlock(); | ||
| 997 | return rv; | 996 | return rv; |
| 998 | } | 997 | } |
| 999 | 998 | ||
| @@ -1104,6 +1103,7 @@ static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, | |||
| 1104 | return 1; | 1103 | return 1; |
| 1105 | } | 1104 | } |
| 1106 | 1105 | ||
| 1106 | /* called with rcu_read_lock() */ | ||
| 1107 | int igmp6_event_query(struct sk_buff *skb) | 1107 | int igmp6_event_query(struct sk_buff *skb) |
| 1108 | { | 1108 | { |
| 1109 | struct mld2_query *mlh2 = NULL; | 1109 | struct mld2_query *mlh2 = NULL; |
| @@ -1127,7 +1127,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1127 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) | 1127 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) |
| 1128 | return -EINVAL; | 1128 | return -EINVAL; |
| 1129 | 1129 | ||
| 1130 | idev = in6_dev_get(skb->dev); | 1130 | idev = __in6_dev_get(skb->dev); |
| 1131 | 1131 | ||
| 1132 | if (idev == NULL) | 1132 | if (idev == NULL) |
| 1133 | return 0; | 1133 | return 0; |
| @@ -1137,10 +1137,8 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1137 | group_type = ipv6_addr_type(group); | 1137 | group_type = ipv6_addr_type(group); |
| 1138 | 1138 | ||
| 1139 | if (group_type != IPV6_ADDR_ANY && | 1139 | if (group_type != IPV6_ADDR_ANY && |
| 1140 | !(group_type&IPV6_ADDR_MULTICAST)) { | 1140 | !(group_type&IPV6_ADDR_MULTICAST)) |
| 1141 | in6_dev_put(idev); | ||
| 1142 | return -EINVAL; | 1141 | return -EINVAL; |
| 1143 | } | ||
| 1144 | 1142 | ||
| 1145 | if (len == 24) { | 1143 | if (len == 24) { |
| 1146 | int switchback; | 1144 | int switchback; |
| @@ -1161,10 +1159,9 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1161 | } else if (len >= 28) { | 1159 | } else if (len >= 28) { |
| 1162 | int srcs_offset = sizeof(struct mld2_query) - | 1160 | int srcs_offset = sizeof(struct mld2_query) - |
| 1163 | sizeof(struct icmp6hdr); | 1161 | sizeof(struct icmp6hdr); |
| 1164 | if (!pskb_may_pull(skb, srcs_offset)) { | 1162 | if (!pskb_may_pull(skb, srcs_offset)) |
| 1165 | in6_dev_put(idev); | ||
| 1166 | return -EINVAL; | 1163 | return -EINVAL; |
| 1167 | } | 1164 | |
| 1168 | mlh2 = (struct mld2_query *)skb_transport_header(skb); | 1165 | mlh2 = (struct mld2_query *)skb_transport_header(skb); |
| 1169 | max_delay = (MLDV2_MRC(ntohs(mlh2->mld2q_mrc))*HZ)/1000; | 1166 | max_delay = (MLDV2_MRC(ntohs(mlh2->mld2q_mrc))*HZ)/1000; |
| 1170 | if (!max_delay) | 1167 | if (!max_delay) |
| @@ -1173,28 +1170,23 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1173 | if (mlh2->mld2q_qrv) | 1170 | if (mlh2->mld2q_qrv) |
| 1174 | idev->mc_qrv = mlh2->mld2q_qrv; | 1171 | idev->mc_qrv = mlh2->mld2q_qrv; |
| 1175 | if (group_type == IPV6_ADDR_ANY) { /* general query */ | 1172 | if (group_type == IPV6_ADDR_ANY) { /* general query */ |
| 1176 | if (mlh2->mld2q_nsrcs) { | 1173 | if (mlh2->mld2q_nsrcs) |
| 1177 | in6_dev_put(idev); | ||
| 1178 | return -EINVAL; /* no sources allowed */ | 1174 | return -EINVAL; /* no sources allowed */ |
| 1179 | } | 1175 | |
| 1180 | mld_gq_start_timer(idev); | 1176 | mld_gq_start_timer(idev); |
| 1181 | in6_dev_put(idev); | ||
| 1182 | return 0; | 1177 | return 0; |
| 1183 | } | 1178 | } |
| 1184 | /* mark sources to include, if group & source-specific */ | 1179 | /* mark sources to include, if group & source-specific */ |
| 1185 | if (mlh2->mld2q_nsrcs != 0) { | 1180 | if (mlh2->mld2q_nsrcs != 0) { |
| 1186 | if (!pskb_may_pull(skb, srcs_offset + | 1181 | if (!pskb_may_pull(skb, srcs_offset + |
| 1187 | ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) { | 1182 | ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) |
| 1188 | in6_dev_put(idev); | ||
| 1189 | return -EINVAL; | 1183 | return -EINVAL; |
| 1190 | } | 1184 | |
| 1191 | mlh2 = (struct mld2_query *)skb_transport_header(skb); | 1185 | mlh2 = (struct mld2_query *)skb_transport_header(skb); |
| 1192 | mark = 1; | 1186 | mark = 1; |
| 1193 | } | 1187 | } |
| 1194 | } else { | 1188 | } else |
| 1195 | in6_dev_put(idev); | ||
| 1196 | return -EINVAL; | 1189 | return -EINVAL; |
| 1197 | } | ||
| 1198 | 1190 | ||
| 1199 | read_lock_bh(&idev->lock); | 1191 | read_lock_bh(&idev->lock); |
| 1200 | if (group_type == IPV6_ADDR_ANY) { | 1192 | if (group_type == IPV6_ADDR_ANY) { |
| @@ -1227,12 +1219,11 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1227 | } | 1219 | } |
| 1228 | } | 1220 | } |
| 1229 | read_unlock_bh(&idev->lock); | 1221 | read_unlock_bh(&idev->lock); |
| 1230 | in6_dev_put(idev); | ||
| 1231 | 1222 | ||
| 1232 | return 0; | 1223 | return 0; |
| 1233 | } | 1224 | } |
| 1234 | 1225 | ||
| 1235 | 1226 | /* called with rcu_read_lock() */ | |
| 1236 | int igmp6_event_report(struct sk_buff *skb) | 1227 | int igmp6_event_report(struct sk_buff *skb) |
| 1237 | { | 1228 | { |
| 1238 | struct ifmcaddr6 *ma; | 1229 | struct ifmcaddr6 *ma; |
| @@ -1260,7 +1251,7 @@ int igmp6_event_report(struct sk_buff *skb) | |||
| 1260 | !(addr_type&IPV6_ADDR_LINKLOCAL)) | 1251 | !(addr_type&IPV6_ADDR_LINKLOCAL)) |
| 1261 | return -EINVAL; | 1252 | return -EINVAL; |
| 1262 | 1253 | ||
| 1263 | idev = in6_dev_get(skb->dev); | 1254 | idev = __in6_dev_get(skb->dev); |
| 1264 | if (idev == NULL) | 1255 | if (idev == NULL) |
| 1265 | return -ENODEV; | 1256 | return -ENODEV; |
| 1266 | 1257 | ||
| @@ -1280,7 +1271,6 @@ int igmp6_event_report(struct sk_buff *skb) | |||
| 1280 | } | 1271 | } |
| 1281 | } | 1272 | } |
| 1282 | read_unlock_bh(&idev->lock); | 1273 | read_unlock_bh(&idev->lock); |
| 1283 | in6_dev_put(idev); | ||
| 1284 | return 0; | 1274 | return 0; |
| 1285 | } | 1275 | } |
| 1286 | 1276 | ||
| @@ -1396,12 +1386,14 @@ static void mld_sendpack(struct sk_buff *skb) | |||
| 1396 | struct mld2_report *pmr = | 1386 | struct mld2_report *pmr = |
| 1397 | (struct mld2_report *)skb_transport_header(skb); | 1387 | (struct mld2_report *)skb_transport_header(skb); |
| 1398 | int payload_len, mldlen; | 1388 | int payload_len, mldlen; |
| 1399 | struct inet6_dev *idev = in6_dev_get(skb->dev); | 1389 | struct inet6_dev *idev; |
| 1400 | struct net *net = dev_net(skb->dev); | 1390 | struct net *net = dev_net(skb->dev); |
| 1401 | int err; | 1391 | int err; |
| 1402 | struct flowi fl; | 1392 | struct flowi fl; |
| 1403 | struct dst_entry *dst; | 1393 | struct dst_entry *dst; |
| 1404 | 1394 | ||
| 1395 | rcu_read_lock(); | ||
| 1396 | idev = __in6_dev_get(skb->dev); | ||
| 1405 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); | 1397 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); |
| 1406 | 1398 | ||
| 1407 | payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); | 1399 | payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); |
| @@ -1441,8 +1433,7 @@ out: | |||
| 1441 | } else | 1433 | } else |
| 1442 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS); | 1434 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS); |
| 1443 | 1435 | ||
| 1444 | if (likely(idev != NULL)) | 1436 | rcu_read_unlock(); |
| 1445 | in6_dev_put(idev); | ||
| 1446 | return; | 1437 | return; |
| 1447 | 1438 | ||
| 1448 | err_out: | 1439 | err_out: |
| @@ -1779,7 +1770,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
| 1779 | IPPROTO_ICMPV6, | 1770 | IPPROTO_ICMPV6, |
| 1780 | csum_partial(hdr, len, 0)); | 1771 | csum_partial(hdr, len, 0)); |
| 1781 | 1772 | ||
| 1782 | idev = in6_dev_get(skb->dev); | 1773 | rcu_read_lock(); |
| 1774 | idev = __in6_dev_get(skb->dev); | ||
| 1783 | 1775 | ||
| 1784 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); | 1776 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); |
| 1785 | if (!dst) { | 1777 | if (!dst) { |
| @@ -1806,8 +1798,7 @@ out: | |||
| 1806 | } else | 1798 | } else |
| 1807 | IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); | 1799 | IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); |
| 1808 | 1800 | ||
| 1809 | if (likely(idev != NULL)) | 1801 | rcu_read_unlock(); |
| 1810 | in6_dev_put(idev); | ||
| 1811 | return; | 1802 | return; |
| 1812 | 1803 | ||
| 1813 | err_out: | 1804 | err_out: |
| @@ -1998,8 +1989,7 @@ static int sf_setstate(struct ifmcaddr6 *pmc) | |||
| 1998 | &psf->sf_addr)) | 1989 | &psf->sf_addr)) |
| 1999 | break; | 1990 | break; |
| 2000 | if (!dpsf) { | 1991 | if (!dpsf) { |
| 2001 | dpsf = (struct ip6_sf_list *) | 1992 | dpsf = kmalloc(sizeof(*dpsf), GFP_ATOMIC); |
| 2002 | kmalloc(sizeof(*dpsf), GFP_ATOMIC); | ||
| 2003 | if (!dpsf) | 1993 | if (!dpsf) |
| 2004 | continue; | 1994 | continue; |
| 2005 | *dpsf = *psf; | 1995 | *dpsf = *psf; |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 2794b6002836..d6e9599d0705 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
| @@ -347,11 +347,12 @@ static const struct xfrm_type mip6_destopt_type = | |||
| 347 | 347 | ||
| 348 | static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb) | 348 | static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb) |
| 349 | { | 349 | { |
| 350 | struct ipv6hdr *iph = ipv6_hdr(skb); | ||
| 350 | struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data; | 351 | struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data; |
| 351 | int err = rt2->rt_hdr.nexthdr; | 352 | int err = rt2->rt_hdr.nexthdr; |
| 352 | 353 | ||
| 353 | spin_lock(&x->lock); | 354 | spin_lock(&x->lock); |
| 354 | if (!ipv6_addr_equal(&rt2->addr, (struct in6_addr *)x->coaddr) && | 355 | if (!ipv6_addr_equal(&iph->daddr, (struct in6_addr *)x->coaddr) && |
| 355 | !ipv6_addr_any((struct in6_addr *)x->coaddr)) | 356 | !ipv6_addr_any((struct in6_addr *)x->coaddr)) |
| 356 | err = -ENOENT; | 357 | err = -ENOENT; |
| 357 | spin_unlock(&x->lock); | 358 | spin_unlock(&x->lock); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 2efef52fb461..58841c4ae947 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
| @@ -1229,7 +1229,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
| 1229 | ND_PRINTK0(KERN_ERR | 1229 | ND_PRINTK0(KERN_ERR |
| 1230 | "ICMPv6 RA: %s() got default router without neighbour.\n", | 1230 | "ICMPv6 RA: %s() got default router without neighbour.\n", |
| 1231 | __func__); | 1231 | __func__); |
| 1232 | dst_release(&rt->u.dst); | 1232 | dst_release(&rt->dst); |
| 1233 | in6_dev_put(in6_dev); | 1233 | in6_dev_put(in6_dev); |
| 1234 | return; | 1234 | return; |
| 1235 | } | 1235 | } |
| @@ -1244,7 +1244,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
| 1244 | if (ra_msg->icmph.icmp6_hop_limit) { | 1244 | if (ra_msg->icmph.icmp6_hop_limit) { |
| 1245 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; | 1245 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; |
| 1246 | if (rt) | 1246 | if (rt) |
| 1247 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit; | 1247 | rt->dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit; |
| 1248 | } | 1248 | } |
| 1249 | 1249 | ||
| 1250 | skip_defrtr: | 1250 | skip_defrtr: |
| @@ -1363,7 +1363,7 @@ skip_linkparms: | |||
| 1363 | in6_dev->cnf.mtu6 = mtu; | 1363 | in6_dev->cnf.mtu6 = mtu; |
| 1364 | 1364 | ||
| 1365 | if (rt) | 1365 | if (rt) |
| 1366 | rt->u.dst.metrics[RTAX_MTU-1] = mtu; | 1366 | rt->dst.metrics[RTAX_MTU-1] = mtu; |
| 1367 | 1367 | ||
| 1368 | rt6_mtu_change(skb->dev, mtu); | 1368 | rt6_mtu_change(skb->dev, mtu); |
| 1369 | } | 1369 | } |
| @@ -1384,7 +1384,7 @@ skip_linkparms: | |||
| 1384 | } | 1384 | } |
| 1385 | out: | 1385 | out: |
| 1386 | if (rt) | 1386 | if (rt) |
| 1387 | dst_release(&rt->u.dst); | 1387 | dst_release(&rt->dst); |
| 1388 | else if (neigh) | 1388 | else if (neigh) |
| 1389 | neigh_release(neigh); | 1389 | neigh_release(neigh); |
| 1390 | in6_dev_put(in6_dev); | 1390 | in6_dev_put(in6_dev); |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index a74951c039b6..7155b2451d7c 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
| @@ -151,9 +151,7 @@ static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook, | |||
| 151 | protocol, | 151 | protocol, |
| 152 | csum_sub(0, hsum))); | 152 | csum_sub(0, hsum))); |
| 153 | skb->ip_summed = CHECKSUM_NONE; | 153 | skb->ip_summed = CHECKSUM_NONE; |
| 154 | csum = __skb_checksum_complete_head(skb, dataoff + len); | 154 | return __skb_checksum_complete_head(skb, dataoff + len); |
| 155 | if (!csum) | ||
| 156 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
| 157 | } | 155 | } |
| 158 | return csum; | 156 | return csum; |
| 159 | }; | 157 | }; |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 8c201743d96d..413ab0754e1f 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
| @@ -43,7 +43,7 @@ typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long); | |||
| 43 | 43 | ||
| 44 | static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; | 44 | static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; |
| 45 | static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; | 45 | static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; |
| 46 | static DEFINE_RWLOCK(queue_lock); | 46 | static DEFINE_SPINLOCK(queue_lock); |
| 47 | static int peer_pid __read_mostly; | 47 | static int peer_pid __read_mostly; |
| 48 | static unsigned int copy_range __read_mostly; | 48 | static unsigned int copy_range __read_mostly; |
| 49 | static unsigned int queue_total; | 49 | static unsigned int queue_total; |
| @@ -73,10 +73,10 @@ __ipq_set_mode(unsigned char mode, unsigned int range) | |||
| 73 | break; | 73 | break; |
| 74 | 74 | ||
| 75 | case IPQ_COPY_PACKET: | 75 | case IPQ_COPY_PACKET: |
| 76 | copy_mode = mode; | 76 | if (range > 0xFFFF) |
| 77 | range = 0xFFFF; | ||
| 77 | copy_range = range; | 78 | copy_range = range; |
| 78 | if (copy_range > 0xFFFF) | 79 | copy_mode = mode; |
| 79 | copy_range = 0xFFFF; | ||
| 80 | break; | 80 | break; |
| 81 | 81 | ||
| 82 | default: | 82 | default: |
| @@ -102,7 +102,7 @@ ipq_find_dequeue_entry(unsigned long id) | |||
| 102 | { | 102 | { |
| 103 | struct nf_queue_entry *entry = NULL, *i; | 103 | struct nf_queue_entry *entry = NULL, *i; |
| 104 | 104 | ||
| 105 | write_lock_bh(&queue_lock); | 105 | spin_lock_bh(&queue_lock); |
| 106 | 106 | ||
| 107 | list_for_each_entry(i, &queue_list, list) { | 107 | list_for_each_entry(i, &queue_list, list) { |
| 108 | if ((unsigned long)i == id) { | 108 | if ((unsigned long)i == id) { |
| @@ -116,7 +116,7 @@ ipq_find_dequeue_entry(unsigned long id) | |||
| 116 | queue_total--; | 116 | queue_total--; |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | write_unlock_bh(&queue_lock); | 119 | spin_unlock_bh(&queue_lock); |
| 120 | return entry; | 120 | return entry; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| @@ -137,9 +137,9 @@ __ipq_flush(ipq_cmpfn cmpfn, unsigned long data) | |||
| 137 | static void | 137 | static void |
| 138 | ipq_flush(ipq_cmpfn cmpfn, unsigned long data) | 138 | ipq_flush(ipq_cmpfn cmpfn, unsigned long data) |
| 139 | { | 139 | { |
| 140 | write_lock_bh(&queue_lock); | 140 | spin_lock_bh(&queue_lock); |
| 141 | __ipq_flush(cmpfn, data); | 141 | __ipq_flush(cmpfn, data); |
| 142 | write_unlock_bh(&queue_lock); | 142 | spin_unlock_bh(&queue_lock); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | static struct sk_buff * | 145 | static struct sk_buff * |
| @@ -153,9 +153,7 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
| 153 | struct nlmsghdr *nlh; | 153 | struct nlmsghdr *nlh; |
| 154 | struct timeval tv; | 154 | struct timeval tv; |
| 155 | 155 | ||
| 156 | read_lock_bh(&queue_lock); | 156 | switch (ACCESS_ONCE(copy_mode)) { |
| 157 | |||
| 158 | switch (copy_mode) { | ||
| 159 | case IPQ_COPY_META: | 157 | case IPQ_COPY_META: |
| 160 | case IPQ_COPY_NONE: | 158 | case IPQ_COPY_NONE: |
| 161 | size = NLMSG_SPACE(sizeof(*pmsg)); | 159 | size = NLMSG_SPACE(sizeof(*pmsg)); |
| @@ -163,26 +161,21 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
| 163 | 161 | ||
| 164 | case IPQ_COPY_PACKET: | 162 | case IPQ_COPY_PACKET: |
| 165 | if (entry->skb->ip_summed == CHECKSUM_PARTIAL && | 163 | if (entry->skb->ip_summed == CHECKSUM_PARTIAL && |
| 166 | (*errp = skb_checksum_help(entry->skb))) { | 164 | (*errp = skb_checksum_help(entry->skb))) |
| 167 | read_unlock_bh(&queue_lock); | ||
| 168 | return NULL; | 165 | return NULL; |
| 169 | } | 166 | |
| 170 | if (copy_range == 0 || copy_range > entry->skb->len) | 167 | data_len = ACCESS_ONCE(copy_range); |
| 168 | if (data_len == 0 || data_len > entry->skb->len) | ||
| 171 | data_len = entry->skb->len; | 169 | data_len = entry->skb->len; |
| 172 | else | ||
| 173 | data_len = copy_range; | ||
| 174 | 170 | ||
| 175 | size = NLMSG_SPACE(sizeof(*pmsg) + data_len); | 171 | size = NLMSG_SPACE(sizeof(*pmsg) + data_len); |
| 176 | break; | 172 | break; |
| 177 | 173 | ||
| 178 | default: | 174 | default: |
| 179 | *errp = -EINVAL; | 175 | *errp = -EINVAL; |
| 180 | read_unlock_bh(&queue_lock); | ||
| 181 | return NULL; | 176 | return NULL; |
| 182 | } | 177 | } |
| 183 | 178 | ||
| 184 | read_unlock_bh(&queue_lock); | ||
| 185 | |||
| 186 | skb = alloc_skb(size, GFP_ATOMIC); | 179 | skb = alloc_skb(size, GFP_ATOMIC); |
| 187 | if (!skb) | 180 | if (!skb) |
| 188 | goto nlmsg_failure; | 181 | goto nlmsg_failure; |
| @@ -242,7 +235,7 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) | |||
| 242 | if (nskb == NULL) | 235 | if (nskb == NULL) |
| 243 | return status; | 236 | return status; |
| 244 | 237 | ||
| 245 | write_lock_bh(&queue_lock); | 238 | spin_lock_bh(&queue_lock); |
| 246 | 239 | ||
| 247 | if (!peer_pid) | 240 | if (!peer_pid) |
| 248 | goto err_out_free_nskb; | 241 | goto err_out_free_nskb; |
| @@ -266,14 +259,14 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) | |||
| 266 | 259 | ||
| 267 | __ipq_enqueue_entry(entry); | 260 | __ipq_enqueue_entry(entry); |
| 268 | 261 | ||
| 269 | write_unlock_bh(&queue_lock); | 262 | spin_unlock_bh(&queue_lock); |
| 270 | return status; | 263 | return status; |
| 271 | 264 | ||
| 272 | err_out_free_nskb: | 265 | err_out_free_nskb: |
| 273 | kfree_skb(nskb); | 266 | kfree_skb(nskb); |
| 274 | 267 | ||
| 275 | err_out_unlock: | 268 | err_out_unlock: |
| 276 | write_unlock_bh(&queue_lock); | 269 | spin_unlock_bh(&queue_lock); |
| 277 | return status; | 270 | return status; |
| 278 | } | 271 | } |
| 279 | 272 | ||
| @@ -342,9 +335,9 @@ ipq_set_mode(unsigned char mode, unsigned int range) | |||
| 342 | { | 335 | { |
| 343 | int status; | 336 | int status; |
| 344 | 337 | ||
| 345 | write_lock_bh(&queue_lock); | 338 | spin_lock_bh(&queue_lock); |
| 346 | status = __ipq_set_mode(mode, range); | 339 | status = __ipq_set_mode(mode, range); |
| 347 | write_unlock_bh(&queue_lock); | 340 | spin_unlock_bh(&queue_lock); |
| 348 | return status; | 341 | return status; |
| 349 | } | 342 | } |
| 350 | 343 | ||
| @@ -441,11 +434,11 @@ __ipq_rcv_skb(struct sk_buff *skb) | |||
| 441 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) | 434 | if (security_netlink_recv(skb, CAP_NET_ADMIN)) |
| 442 | RCV_SKB_FAIL(-EPERM); | 435 | RCV_SKB_FAIL(-EPERM); |
| 443 | 436 | ||
| 444 | write_lock_bh(&queue_lock); | 437 | spin_lock_bh(&queue_lock); |
| 445 | 438 | ||
| 446 | if (peer_pid) { | 439 | if (peer_pid) { |
| 447 | if (peer_pid != pid) { | 440 | if (peer_pid != pid) { |
| 448 | write_unlock_bh(&queue_lock); | 441 | spin_unlock_bh(&queue_lock); |
| 449 | RCV_SKB_FAIL(-EBUSY); | 442 | RCV_SKB_FAIL(-EBUSY); |
| 450 | } | 443 | } |
| 451 | } else { | 444 | } else { |
| @@ -453,7 +446,7 @@ __ipq_rcv_skb(struct sk_buff *skb) | |||
| 453 | peer_pid = pid; | 446 | peer_pid = pid; |
| 454 | } | 447 | } |
| 455 | 448 | ||
| 456 | write_unlock_bh(&queue_lock); | 449 | spin_unlock_bh(&queue_lock); |
| 457 | 450 | ||
| 458 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, | 451 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, |
| 459 | nlmsglen - NLMSG_LENGTH(0)); | 452 | nlmsglen - NLMSG_LENGTH(0)); |
| @@ -498,10 +491,10 @@ ipq_rcv_nl_event(struct notifier_block *this, | |||
| 498 | struct netlink_notify *n = ptr; | 491 | struct netlink_notify *n = ptr; |
| 499 | 492 | ||
| 500 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_IP6_FW) { | 493 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_IP6_FW) { |
| 501 | write_lock_bh(&queue_lock); | 494 | spin_lock_bh(&queue_lock); |
| 502 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) | 495 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) |
| 503 | __ipq_reset(); | 496 | __ipq_reset(); |
| 504 | write_unlock_bh(&queue_lock); | 497 | spin_unlock_bh(&queue_lock); |
| 505 | } | 498 | } |
| 506 | return NOTIFY_DONE; | 499 | return NOTIFY_DONE; |
| 507 | } | 500 | } |
| @@ -528,7 +521,7 @@ static ctl_table ipq_table[] = { | |||
| 528 | #ifdef CONFIG_PROC_FS | 521 | #ifdef CONFIG_PROC_FS |
| 529 | static int ip6_queue_show(struct seq_file *m, void *v) | 522 | static int ip6_queue_show(struct seq_file *m, void *v) |
| 530 | { | 523 | { |
| 531 | read_lock_bh(&queue_lock); | 524 | spin_lock_bh(&queue_lock); |
| 532 | 525 | ||
| 533 | seq_printf(m, | 526 | seq_printf(m, |
| 534 | "Peer PID : %d\n" | 527 | "Peer PID : %d\n" |
| @@ -546,7 +539,7 @@ static int ip6_queue_show(struct seq_file *m, void *v) | |||
| 546 | queue_dropped, | 539 | queue_dropped, |
| 547 | queue_user_dropped); | 540 | queue_user_dropped); |
| 548 | 541 | ||
| 549 | read_unlock_bh(&queue_lock); | 542 | spin_unlock_bh(&queue_lock); |
| 550 | return 0; | 543 | return 0; |
| 551 | } | 544 | } |
| 552 | 545 | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 9d2d68f0e605..5359ef4daac5 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
| @@ -387,9 +387,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
| 387 | goto no_match; | 387 | goto no_match; |
| 388 | } | 388 | } |
| 389 | 389 | ||
| 390 | ADD_COUNTER(e->counters, | 390 | ADD_COUNTER(e->counters, skb->len, 1); |
| 391 | ntohs(ipv6_hdr(skb)->payload_len) + | ||
| 392 | sizeof(struct ipv6hdr), 1); | ||
| 393 | 391 | ||
| 394 | t = ip6t_get_target_c(e); | 392 | t = ip6t_get_target_c(e); |
| 395 | IP_NF_ASSERT(t->u.kernel.target); | 393 | IP_NF_ASSERT(t->u.kernel.target); |
| @@ -899,7 +897,7 @@ get_counters(const struct xt_table_info *t, | |||
| 899 | struct ip6t_entry *iter; | 897 | struct ip6t_entry *iter; |
| 900 | unsigned int cpu; | 898 | unsigned int cpu; |
| 901 | unsigned int i; | 899 | unsigned int i; |
| 902 | unsigned int curcpu; | 900 | unsigned int curcpu = get_cpu(); |
| 903 | 901 | ||
| 904 | /* Instead of clearing (by a previous call to memset()) | 902 | /* Instead of clearing (by a previous call to memset()) |
| 905 | * the counters and using adds, we set the counters | 903 | * the counters and using adds, we set the counters |
| @@ -909,14 +907,16 @@ get_counters(const struct xt_table_info *t, | |||
| 909 | * if new softirq were to run and call ipt_do_table | 907 | * if new softirq were to run and call ipt_do_table |
| 910 | */ | 908 | */ |
| 911 | local_bh_disable(); | 909 | local_bh_disable(); |
| 912 | curcpu = smp_processor_id(); | ||
| 913 | |||
| 914 | i = 0; | 910 | i = 0; |
| 915 | xt_entry_foreach(iter, t->entries[curcpu], t->size) { | 911 | xt_entry_foreach(iter, t->entries[curcpu], t->size) { |
| 916 | SET_COUNTER(counters[i], iter->counters.bcnt, | 912 | SET_COUNTER(counters[i], iter->counters.bcnt, |
| 917 | iter->counters.pcnt); | 913 | iter->counters.pcnt); |
| 918 | ++i; | 914 | ++i; |
| 919 | } | 915 | } |
| 916 | local_bh_enable(); | ||
| 917 | /* Processing counters from other cpus, we can let bottom half enabled, | ||
| 918 | * (preemption is disabled) | ||
| 919 | */ | ||
| 920 | 920 | ||
| 921 | for_each_possible_cpu(cpu) { | 921 | for_each_possible_cpu(cpu) { |
| 922 | if (cpu == curcpu) | 922 | if (cpu == curcpu) |
| @@ -930,7 +930,7 @@ get_counters(const struct xt_table_info *t, | |||
| 930 | } | 930 | } |
| 931 | xt_info_wrunlock(cpu); | 931 | xt_info_wrunlock(cpu); |
| 932 | } | 932 | } |
| 933 | local_bh_enable(); | 933 | put_cpu(); |
| 934 | } | 934 | } |
| 935 | 935 | ||
| 936 | static struct xt_counters *alloc_counters(const struct xt_table *table) | 936 | static struct xt_counters *alloc_counters(const struct xt_table *table) |
| @@ -943,7 +943,7 @@ static struct xt_counters *alloc_counters(const struct xt_table *table) | |||
| 943 | (other than comefrom, which userspace doesn't care | 943 | (other than comefrom, which userspace doesn't care |
| 944 | about). */ | 944 | about). */ |
| 945 | countersize = sizeof(struct xt_counters) * private->number; | 945 | countersize = sizeof(struct xt_counters) * private->number; |
| 946 | counters = vmalloc_node(countersize, numa_node_id()); | 946 | counters = vmalloc(countersize); |
| 947 | 947 | ||
| 948 | if (counters == NULL) | 948 | if (counters == NULL) |
| 949 | return ERR_PTR(-ENOMEM); | 949 | return ERR_PTR(-ENOMEM); |
| @@ -1213,8 +1213,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, | |||
| 1213 | struct ip6t_entry *iter; | 1213 | struct ip6t_entry *iter; |
| 1214 | 1214 | ||
| 1215 | ret = 0; | 1215 | ret = 0; |
| 1216 | counters = vmalloc_node(num_counters * sizeof(struct xt_counters), | 1216 | counters = vmalloc(num_counters * sizeof(struct xt_counters)); |
| 1217 | numa_node_id()); | ||
| 1218 | if (!counters) { | 1217 | if (!counters) { |
| 1219 | ret = -ENOMEM; | 1218 | ret = -ENOMEM; |
| 1220 | goto out; | 1219 | goto out; |
| @@ -1368,7 +1367,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, | |||
| 1368 | if (len != size + num_counters * sizeof(struct xt_counters)) | 1367 | if (len != size + num_counters * sizeof(struct xt_counters)) |
| 1369 | return -EINVAL; | 1368 | return -EINVAL; |
| 1370 | 1369 | ||
| 1371 | paddc = vmalloc_node(len - size, numa_node_id()); | 1370 | paddc = vmalloc(len - size); |
| 1372 | if (!paddc) | 1371 | if (!paddc) |
| 1373 | return -ENOMEM; | 1372 | return -ENOMEM; |
| 1374 | 1373 | ||
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index af4ee11f2066..0a07ae7b933f 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
| @@ -373,6 +373,56 @@ static void dump_packet(const struct nf_loginfo *info, | |||
| 373 | printk("MARK=0x%x ", skb->mark); | 373 | printk("MARK=0x%x ", skb->mark); |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | static void dump_mac_header(const struct nf_loginfo *info, | ||
| 377 | const struct sk_buff *skb) | ||
| 378 | { | ||
| 379 | struct net_device *dev = skb->dev; | ||
| 380 | unsigned int logflags = 0; | ||
| 381 | |||
| 382 | if (info->type == NF_LOG_TYPE_LOG) | ||
| 383 | logflags = info->u.log.logflags; | ||
| 384 | |||
| 385 | if (!(logflags & IP6T_LOG_MACDECODE)) | ||
| 386 | goto fallback; | ||
| 387 | |||
| 388 | switch (dev->type) { | ||
| 389 | case ARPHRD_ETHER: | ||
| 390 | printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | ||
| 391 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
| 392 | ntohs(eth_hdr(skb)->h_proto)); | ||
| 393 | return; | ||
| 394 | default: | ||
| 395 | break; | ||
| 396 | } | ||
| 397 | |||
| 398 | fallback: | ||
| 399 | printk("MAC="); | ||
| 400 | if (dev->hard_header_len && | ||
| 401 | skb->mac_header != skb->network_header) { | ||
| 402 | const unsigned char *p = skb_mac_header(skb); | ||
| 403 | unsigned int len = dev->hard_header_len; | ||
| 404 | unsigned int i; | ||
| 405 | |||
| 406 | if (dev->type == ARPHRD_SIT && | ||
| 407 | (p -= ETH_HLEN) < skb->head) | ||
| 408 | p = NULL; | ||
| 409 | |||
| 410 | if (p != NULL) { | ||
| 411 | printk("%02x", *p++); | ||
| 412 | for (i = 1; i < len; i++) | ||
| 413 | printk(":%02x", p[i]); | ||
| 414 | } | ||
| 415 | printk(" "); | ||
| 416 | |||
| 417 | if (dev->type == ARPHRD_SIT) { | ||
| 418 | const struct iphdr *iph = | ||
| 419 | (struct iphdr *)skb_mac_header(skb); | ||
| 420 | printk("TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr); | ||
| 421 | } | ||
| 422 | } else | ||
| 423 | printk(" "); | ||
| 424 | } | ||
| 425 | |||
| 376 | static struct nf_loginfo default_loginfo = { | 426 | static struct nf_loginfo default_loginfo = { |
| 377 | .type = NF_LOG_TYPE_LOG, | 427 | .type = NF_LOG_TYPE_LOG, |
| 378 | .u = { | 428 | .u = { |
| @@ -400,35 +450,10 @@ ip6t_log_packet(u_int8_t pf, | |||
| 400 | prefix, | 450 | prefix, |
| 401 | in ? in->name : "", | 451 | in ? in->name : "", |
| 402 | out ? out->name : ""); | 452 | out ? out->name : ""); |
| 403 | if (in && !out) { | ||
| 404 | unsigned int len; | ||
| 405 | /* MAC logging for input chain only. */ | ||
| 406 | printk("MAC="); | ||
| 407 | if (skb->dev && (len = skb->dev->hard_header_len) && | ||
| 408 | skb->mac_header != skb->network_header) { | ||
| 409 | const unsigned char *p = skb_mac_header(skb); | ||
| 410 | int i; | ||
| 411 | |||
| 412 | if (skb->dev->type == ARPHRD_SIT && | ||
| 413 | (p -= ETH_HLEN) < skb->head) | ||
| 414 | p = NULL; | ||
| 415 | |||
| 416 | if (p != NULL) { | ||
| 417 | for (i = 0; i < len; i++) | ||
| 418 | printk("%02x%s", p[i], | ||
| 419 | i == len - 1 ? "" : ":"); | ||
| 420 | } | ||
| 421 | printk(" "); | ||
| 422 | 453 | ||
| 423 | if (skb->dev->type == ARPHRD_SIT) { | 454 | /* MAC logging for input path only. */ |
| 424 | const struct iphdr *iph = | 455 | if (in && !out) |
| 425 | (struct iphdr *)skb_mac_header(skb); | 456 | dump_mac_header(loginfo, skb); |
| 426 | printk("TUNNEL=%pI4->%pI4 ", | ||
| 427 | &iph->saddr, &iph->daddr); | ||
| 428 | } | ||
| 429 | } else | ||
| 430 | printk(" "); | ||
| 431 | } | ||
| 432 | 457 | ||
| 433 | dump_packet(loginfo, skb, skb_network_offset(skb), 1); | 458 | dump_packet(loginfo, skb, skb_network_offset(skb), 1); |
| 434 | printk("\n"); | 459 | printk("\n"); |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 47d227713758..2933396e0281 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
| @@ -97,9 +97,11 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
| 97 | fl.fl_ip_dport = otcph.source; | 97 | fl.fl_ip_dport = otcph.source; |
| 98 | security_skb_classify_flow(oldskb, &fl); | 98 | security_skb_classify_flow(oldskb, &fl); |
| 99 | dst = ip6_route_output(net, NULL, &fl); | 99 | dst = ip6_route_output(net, NULL, &fl); |
| 100 | if (dst == NULL) | 100 | if (dst == NULL || dst->error) { |
| 101 | dst_release(dst); | ||
| 101 | return; | 102 | return; |
| 102 | if (dst->error || xfrm_lookup(net, &dst, &fl, NULL, 0)) | 103 | } |
| 104 | if (xfrm_lookup(net, &dst, &fl, NULL, 0)) | ||
| 103 | return; | 105 | return; |
| 104 | 106 | ||
| 105 | hh_len = (dst->dev->hard_header_len + 15)&~15; | 107 | hh_len = (dst->dev->hard_header_len + 15)&~15; |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 9be81776415e..1df3c8b6bf47 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
| @@ -208,7 +208,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, | |||
| 208 | type = icmp6h->icmp6_type - 130; | 208 | type = icmp6h->icmp6_type - 130; |
| 209 | if (type >= 0 && type < sizeof(noct_valid_new) && | 209 | if (type >= 0 && type < sizeof(noct_valid_new) && |
| 210 | noct_valid_new[type]) { | 210 | noct_valid_new[type]) { |
| 211 | skb->nfct = &nf_conntrack_untracked.ct_general; | 211 | skb->nfct = &nf_ct_untracked_get()->ct_general; |
| 212 | skb->nfctinfo = IP_CT_NEW; | 212 | skb->nfctinfo = IP_CT_NEW; |
| 213 | nf_conntrack_get(skb->nfct); | 213 | nf_conntrack_get(skb->nfct); |
| 214 | return NF_ACCEPT; | 214 | return NF_ACCEPT; |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 6fb890187de0..13ef5bc05cf5 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
| @@ -114,10 +114,8 @@ static void nf_skb_free(struct sk_buff *skb) | |||
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | /* Memory Tracking Functions. */ | 116 | /* Memory Tracking Functions. */ |
| 117 | static inline void frag_kfree_skb(struct sk_buff *skb, unsigned int *work) | 117 | static void frag_kfree_skb(struct sk_buff *skb) |
| 118 | { | 118 | { |
| 119 | if (work) | ||
| 120 | *work -= skb->truesize; | ||
| 121 | atomic_sub(skb->truesize, &nf_init_frags.mem); | 119 | atomic_sub(skb->truesize, &nf_init_frags.mem); |
| 122 | nf_skb_free(skb); | 120 | nf_skb_free(skb); |
| 123 | kfree_skb(skb); | 121 | kfree_skb(skb); |
| @@ -201,7 +199,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 201 | int offset, end; | 199 | int offset, end; |
| 202 | 200 | ||
| 203 | if (fq->q.last_in & INET_FRAG_COMPLETE) { | 201 | if (fq->q.last_in & INET_FRAG_COMPLETE) { |
| 204 | pr_debug("Allready completed\n"); | 202 | pr_debug("Already completed\n"); |
| 205 | goto err; | 203 | goto err; |
| 206 | } | 204 | } |
| 207 | 205 | ||
| @@ -271,6 +269,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 271 | * in the chain of fragments so far. We must know where to put | 269 | * in the chain of fragments so far. We must know where to put |
| 272 | * this fragment, right? | 270 | * this fragment, right? |
| 273 | */ | 271 | */ |
| 272 | prev = fq->q.fragments_tail; | ||
| 273 | if (!prev || NFCT_FRAG6_CB(prev)->offset < offset) { | ||
| 274 | next = NULL; | ||
| 275 | goto found; | ||
| 276 | } | ||
| 274 | prev = NULL; | 277 | prev = NULL; |
| 275 | for (next = fq->q.fragments; next != NULL; next = next->next) { | 278 | for (next = fq->q.fragments; next != NULL; next = next->next) { |
| 276 | if (NFCT_FRAG6_CB(next)->offset >= offset) | 279 | if (NFCT_FRAG6_CB(next)->offset >= offset) |
| @@ -278,6 +281,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 278 | prev = next; | 281 | prev = next; |
| 279 | } | 282 | } |
| 280 | 283 | ||
| 284 | found: | ||
| 281 | /* We found where to put this one. Check for overlap with | 285 | /* We found where to put this one. Check for overlap with |
| 282 | * preceding fragment, and, if needed, align things so that | 286 | * preceding fragment, and, if needed, align things so that |
| 283 | * any overlaps are eliminated. | 287 | * any overlaps are eliminated. |
| @@ -335,7 +339,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 335 | fq->q.fragments = next; | 339 | fq->q.fragments = next; |
| 336 | 340 | ||
| 337 | fq->q.meat -= free_it->len; | 341 | fq->q.meat -= free_it->len; |
| 338 | frag_kfree_skb(free_it, NULL); | 342 | frag_kfree_skb(free_it); |
| 339 | } | 343 | } |
| 340 | } | 344 | } |
| 341 | 345 | ||
| @@ -343,6 +347,8 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
| 343 | 347 | ||
| 344 | /* Insert this fragment in the chain of fragments. */ | 348 | /* Insert this fragment in the chain of fragments. */ |
| 345 | skb->next = next; | 349 | skb->next = next; |
| 350 | if (!next) | ||
| 351 | fq->q.fragments_tail = skb; | ||
| 346 | if (prev) | 352 | if (prev) |
| 347 | prev->next = skb; | 353 | prev->next = skb; |
| 348 | else | 354 | else |
| @@ -442,7 +448,6 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
| 442 | skb_shinfo(head)->frag_list = head->next; | 448 | skb_shinfo(head)->frag_list = head->next; |
| 443 | skb_reset_transport_header(head); | 449 | skb_reset_transport_header(head); |
| 444 | skb_push(head, head->data - skb_network_header(head)); | 450 | skb_push(head, head->data - skb_network_header(head)); |
| 445 | atomic_sub(head->truesize, &nf_init_frags.mem); | ||
| 446 | 451 | ||
| 447 | for (fp=head->next; fp; fp = fp->next) { | 452 | for (fp=head->next; fp; fp = fp->next) { |
| 448 | head->data_len += fp->len; | 453 | head->data_len += fp->len; |
| @@ -452,8 +457,8 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
| 452 | else if (head->ip_summed == CHECKSUM_COMPLETE) | 457 | else if (head->ip_summed == CHECKSUM_COMPLETE) |
| 453 | head->csum = csum_add(head->csum, fp->csum); | 458 | head->csum = csum_add(head->csum, fp->csum); |
| 454 | head->truesize += fp->truesize; | 459 | head->truesize += fp->truesize; |
| 455 | atomic_sub(fp->truesize, &nf_init_frags.mem); | ||
| 456 | } | 460 | } |
| 461 | atomic_sub(head->truesize, &nf_init_frags.mem); | ||
| 457 | 462 | ||
| 458 | head->next = NULL; | 463 | head->next = NULL; |
| 459 | head->dev = dev; | 464 | head->dev = dev; |
| @@ -467,6 +472,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
| 467 | head->csum); | 472 | head->csum); |
| 468 | 473 | ||
| 469 | fq->q.fragments = NULL; | 474 | fq->q.fragments = NULL; |
| 475 | fq->q.fragments_tail = NULL; | ||
| 470 | 476 | ||
| 471 | /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */ | 477 | /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */ |
| 472 | fp = skb_shinfo(head)->frag_list; | 478 | fp = skb_shinfo(head)->frag_list; |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 566798d69f37..d082eaeefa25 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
| @@ -174,17 +174,28 @@ static void snmp6_seq_show_item(struct seq_file *seq, void __percpu **mib, | |||
| 174 | const struct snmp_mib *itemlist) | 174 | const struct snmp_mib *itemlist) |
| 175 | { | 175 | { |
| 176 | int i; | 176 | int i; |
| 177 | for (i=0; itemlist[i].name; i++) | 177 | |
| 178 | for (i = 0; itemlist[i].name; i++) | ||
| 178 | seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, | 179 | seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name, |
| 179 | snmp_fold_field(mib, itemlist[i].entry)); | 180 | snmp_fold_field(mib, itemlist[i].entry)); |
| 180 | } | 181 | } |
| 181 | 182 | ||
| 183 | static void snmp6_seq_show_item64(struct seq_file *seq, void __percpu **mib, | ||
| 184 | const struct snmp_mib *itemlist, size_t syncpoff) | ||
| 185 | { | ||
| 186 | int i; | ||
| 187 | |||
| 188 | for (i = 0; itemlist[i].name; i++) | ||
| 189 | seq_printf(seq, "%-32s\t%llu\n", itemlist[i].name, | ||
| 190 | snmp_fold_field64(mib, itemlist[i].entry, syncpoff)); | ||
| 191 | } | ||
| 192 | |||
| 182 | static int snmp6_seq_show(struct seq_file *seq, void *v) | 193 | static int snmp6_seq_show(struct seq_file *seq, void *v) |
| 183 | { | 194 | { |
| 184 | struct net *net = (struct net *)seq->private; | 195 | struct net *net = (struct net *)seq->private; |
| 185 | 196 | ||
| 186 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.ipv6_statistics, | 197 | snmp6_seq_show_item64(seq, (void __percpu **)net->mib.ipv6_statistics, |
| 187 | snmp6_ipstats_list); | 198 | snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp)); |
| 188 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.icmpv6_statistics, | 199 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.icmpv6_statistics, |
| 189 | snmp6_icmp6_list); | 200 | snmp6_icmp6_list); |
| 190 | snmp6_seq_show_icmpv6msg(seq, | 201 | snmp6_seq_show_icmpv6msg(seq, |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 4a4dcbe4f8b2..e677937a07fc 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
| @@ -602,31 +602,33 @@ out: | |||
| 602 | } | 602 | } |
| 603 | 603 | ||
| 604 | static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | 604 | static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, |
| 605 | struct flowi *fl, struct rt6_info *rt, | 605 | struct flowi *fl, struct dst_entry **dstp, |
| 606 | unsigned int flags) | 606 | unsigned int flags) |
| 607 | { | 607 | { |
| 608 | struct ipv6_pinfo *np = inet6_sk(sk); | 608 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 609 | struct ipv6hdr *iph; | 609 | struct ipv6hdr *iph; |
| 610 | struct sk_buff *skb; | 610 | struct sk_buff *skb; |
| 611 | int err; | 611 | int err; |
| 612 | struct rt6_info *rt = (struct rt6_info *)*dstp; | ||
| 612 | 613 | ||
| 613 | if (length > rt->u.dst.dev->mtu) { | 614 | if (length > rt->dst.dev->mtu) { |
| 614 | ipv6_local_error(sk, EMSGSIZE, fl, rt->u.dst.dev->mtu); | 615 | ipv6_local_error(sk, EMSGSIZE, fl, rt->dst.dev->mtu); |
| 615 | return -EMSGSIZE; | 616 | return -EMSGSIZE; |
| 616 | } | 617 | } |
| 617 | if (flags&MSG_PROBE) | 618 | if (flags&MSG_PROBE) |
| 618 | goto out; | 619 | goto out; |
| 619 | 620 | ||
| 620 | skb = sock_alloc_send_skb(sk, | 621 | skb = sock_alloc_send_skb(sk, |
| 621 | length + LL_ALLOCATED_SPACE(rt->u.dst.dev) + 15, | 622 | length + LL_ALLOCATED_SPACE(rt->dst.dev) + 15, |
| 622 | flags & MSG_DONTWAIT, &err); | 623 | flags & MSG_DONTWAIT, &err); |
| 623 | if (skb == NULL) | 624 | if (skb == NULL) |
| 624 | goto error; | 625 | goto error; |
| 625 | skb_reserve(skb, LL_RESERVED_SPACE(rt->u.dst.dev)); | 626 | skb_reserve(skb, LL_RESERVED_SPACE(rt->dst.dev)); |
| 626 | 627 | ||
| 627 | skb->priority = sk->sk_priority; | 628 | skb->priority = sk->sk_priority; |
| 628 | skb->mark = sk->sk_mark; | 629 | skb->mark = sk->sk_mark; |
| 629 | skb_dst_set(skb, dst_clone(&rt->u.dst)); | 630 | skb_dst_set(skb, &rt->dst); |
| 631 | *dstp = NULL; | ||
| 630 | 632 | ||
| 631 | skb_put(skb, length); | 633 | skb_put(skb, length); |
| 632 | skb_reset_network_header(skb); | 634 | skb_reset_network_header(skb); |
| @@ -641,7 +643,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
| 641 | 643 | ||
| 642 | IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); | 644 | IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); |
| 643 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, | 645 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
| 644 | rt->u.dst.dev, dst_output); | 646 | rt->dst.dev, dst_output); |
| 645 | if (err > 0) | 647 | if (err > 0) |
| 646 | err = net_xmit_errno(err); | 648 | err = net_xmit_errno(err); |
| 647 | if (err) | 649 | if (err) |
| @@ -725,7 +727,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 725 | { | 727 | { |
| 726 | struct ipv6_txoptions opt_space; | 728 | struct ipv6_txoptions opt_space; |
| 727 | struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; | 729 | struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; |
| 728 | struct in6_addr *daddr, *final_p = NULL, final; | 730 | struct in6_addr *daddr, *final_p, final; |
| 729 | struct inet_sock *inet = inet_sk(sk); | 731 | struct inet_sock *inet = inet_sk(sk); |
| 730 | struct ipv6_pinfo *np = inet6_sk(sk); | 732 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 731 | struct raw6_sock *rp = raw6_sk(sk); | 733 | struct raw6_sock *rp = raw6_sk(sk); |
| @@ -847,13 +849,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 847 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 849 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
| 848 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 850 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
| 849 | 851 | ||
| 850 | /* merge ip6_build_xmit from ip6_output */ | 852 | final_p = fl6_update_dst(&fl, opt, &final); |
| 851 | if (opt && opt->srcrt) { | ||
| 852 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
| 853 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 854 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 855 | final_p = &final; | ||
| 856 | } | ||
| 857 | 853 | ||
| 858 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 854 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) |
| 859 | fl.oif = np->mcast_oif; | 855 | fl.oif = np->mcast_oif; |
| @@ -892,9 +888,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 892 | goto do_confirm; | 888 | goto do_confirm; |
| 893 | 889 | ||
| 894 | back_from_confirm: | 890 | back_from_confirm: |
| 895 | if (inet->hdrincl) { | 891 | if (inet->hdrincl) |
| 896 | err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, (struct rt6_info*)dst, msg->msg_flags); | 892 | err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, &dst, msg->msg_flags); |
| 897 | } else { | 893 | else { |
| 898 | lock_sock(sk); | 894 | lock_sock(sk); |
| 899 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, | 895 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, |
| 900 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, | 896 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 6d4292ff5854..545c4141b755 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
| @@ -150,11 +150,8 @@ int ip6_frag_match(struct inet_frag_queue *q, void *a) | |||
| 150 | EXPORT_SYMBOL(ip6_frag_match); | 150 | EXPORT_SYMBOL(ip6_frag_match); |
| 151 | 151 | ||
| 152 | /* Memory Tracking Functions. */ | 152 | /* Memory Tracking Functions. */ |
| 153 | static inline void frag_kfree_skb(struct netns_frags *nf, | 153 | static void frag_kfree_skb(struct netns_frags *nf, struct sk_buff *skb) |
| 154 | struct sk_buff *skb, int *work) | ||
| 155 | { | 154 | { |
| 156 | if (work) | ||
| 157 | *work -= skb->truesize; | ||
| 158 | atomic_sub(skb->truesize, &nf->mem); | 155 | atomic_sub(skb->truesize, &nf->mem); |
| 159 | kfree_skb(skb); | 156 | kfree_skb(skb); |
| 160 | } | 157 | } |
| @@ -336,6 +333,11 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 336 | * in the chain of fragments so far. We must know where to put | 333 | * in the chain of fragments so far. We must know where to put |
| 337 | * this fragment, right? | 334 | * this fragment, right? |
| 338 | */ | 335 | */ |
| 336 | prev = fq->q.fragments_tail; | ||
| 337 | if (!prev || FRAG6_CB(prev)->offset < offset) { | ||
| 338 | next = NULL; | ||
| 339 | goto found; | ||
| 340 | } | ||
| 339 | prev = NULL; | 341 | prev = NULL; |
| 340 | for(next = fq->q.fragments; next != NULL; next = next->next) { | 342 | for(next = fq->q.fragments; next != NULL; next = next->next) { |
| 341 | if (FRAG6_CB(next)->offset >= offset) | 343 | if (FRAG6_CB(next)->offset >= offset) |
| @@ -343,6 +345,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 343 | prev = next; | 345 | prev = next; |
| 344 | } | 346 | } |
| 345 | 347 | ||
| 348 | found: | ||
| 346 | /* We found where to put this one. Check for overlap with | 349 | /* We found where to put this one. Check for overlap with |
| 347 | * preceding fragment, and, if needed, align things so that | 350 | * preceding fragment, and, if needed, align things so that |
| 348 | * any overlaps are eliminated. | 351 | * any overlaps are eliminated. |
| @@ -392,7 +395,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 392 | fq->q.fragments = next; | 395 | fq->q.fragments = next; |
| 393 | 396 | ||
| 394 | fq->q.meat -= free_it->len; | 397 | fq->q.meat -= free_it->len; |
| 395 | frag_kfree_skb(fq->q.net, free_it, NULL); | 398 | frag_kfree_skb(fq->q.net, free_it); |
| 396 | } | 399 | } |
| 397 | } | 400 | } |
| 398 | 401 | ||
| @@ -400,6 +403,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 400 | 403 | ||
| 401 | /* Insert this fragment in the chain of fragments. */ | 404 | /* Insert this fragment in the chain of fragments. */ |
| 402 | skb->next = next; | 405 | skb->next = next; |
| 406 | if (!next) | ||
| 407 | fq->q.fragments_tail = skb; | ||
| 403 | if (prev) | 408 | if (prev) |
| 404 | prev->next = skb; | 409 | prev->next = skb; |
| 405 | else | 410 | else |
| @@ -466,6 +471,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
| 466 | goto out_oom; | 471 | goto out_oom; |
| 467 | 472 | ||
| 468 | fp->next = head->next; | 473 | fp->next = head->next; |
| 474 | if (!fp->next) | ||
| 475 | fq->q.fragments_tail = fp; | ||
| 469 | prev->next = fp; | 476 | prev->next = fp; |
| 470 | 477 | ||
| 471 | skb_morph(head, fq->q.fragments); | 478 | skb_morph(head, fq->q.fragments); |
| @@ -524,7 +531,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
| 524 | skb_shinfo(head)->frag_list = head->next; | 531 | skb_shinfo(head)->frag_list = head->next; |
| 525 | skb_reset_transport_header(head); | 532 | skb_reset_transport_header(head); |
| 526 | skb_push(head, head->data - skb_network_header(head)); | 533 | skb_push(head, head->data - skb_network_header(head)); |
| 527 | atomic_sub(head->truesize, &fq->q.net->mem); | ||
| 528 | 534 | ||
| 529 | for (fp=head->next; fp; fp = fp->next) { | 535 | for (fp=head->next; fp; fp = fp->next) { |
| 530 | head->data_len += fp->len; | 536 | head->data_len += fp->len; |
| @@ -534,8 +540,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
| 534 | else if (head->ip_summed == CHECKSUM_COMPLETE) | 540 | else if (head->ip_summed == CHECKSUM_COMPLETE) |
| 535 | head->csum = csum_add(head->csum, fp->csum); | 541 | head->csum = csum_add(head->csum, fp->csum); |
| 536 | head->truesize += fp->truesize; | 542 | head->truesize += fp->truesize; |
| 537 | atomic_sub(fp->truesize, &fq->q.net->mem); | ||
| 538 | } | 543 | } |
| 544 | atomic_sub(head->truesize, &fq->q.net->mem); | ||
| 539 | 545 | ||
| 540 | head->next = NULL; | 546 | head->next = NULL; |
| 541 | head->dev = dev; | 547 | head->dev = dev; |
| @@ -553,6 +559,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
| 553 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS); | 559 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS); |
| 554 | rcu_read_unlock(); | 560 | rcu_read_unlock(); |
| 555 | fq->q.fragments = NULL; | 561 | fq->q.fragments = NULL; |
| 562 | fq->q.fragments_tail = NULL; | ||
| 556 | return 1; | 563 | return 1; |
| 557 | 564 | ||
| 558 | out_oversize: | 565 | out_oversize: |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 252d76199c41..8f2d0400cf8a 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -126,16 +126,14 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
| 126 | }; | 126 | }; |
| 127 | 127 | ||
| 128 | static struct rt6_info ip6_null_entry_template = { | 128 | static struct rt6_info ip6_null_entry_template = { |
| 129 | .u = { | 129 | .dst = { |
| 130 | .dst = { | 130 | .__refcnt = ATOMIC_INIT(1), |
| 131 | .__refcnt = ATOMIC_INIT(1), | 131 | .__use = 1, |
| 132 | .__use = 1, | 132 | .obsolete = -1, |
| 133 | .obsolete = -1, | 133 | .error = -ENETUNREACH, |
| 134 | .error = -ENETUNREACH, | 134 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
| 135 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 135 | .input = ip6_pkt_discard, |
| 136 | .input = ip6_pkt_discard, | 136 | .output = ip6_pkt_discard_out, |
| 137 | .output = ip6_pkt_discard_out, | ||
| 138 | } | ||
| 139 | }, | 137 | }, |
| 140 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 138 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
| 141 | .rt6i_protocol = RTPROT_KERNEL, | 139 | .rt6i_protocol = RTPROT_KERNEL, |
| @@ -149,16 +147,14 @@ static int ip6_pkt_prohibit(struct sk_buff *skb); | |||
| 149 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | 147 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); |
| 150 | 148 | ||
| 151 | static struct rt6_info ip6_prohibit_entry_template = { | 149 | static struct rt6_info ip6_prohibit_entry_template = { |
| 152 | .u = { | 150 | .dst = { |
| 153 | .dst = { | 151 | .__refcnt = ATOMIC_INIT(1), |
| 154 | .__refcnt = ATOMIC_INIT(1), | 152 | .__use = 1, |
| 155 | .__use = 1, | 153 | .obsolete = -1, |
| 156 | .obsolete = -1, | 154 | .error = -EACCES, |
| 157 | .error = -EACCES, | 155 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
| 158 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 156 | .input = ip6_pkt_prohibit, |
| 159 | .input = ip6_pkt_prohibit, | 157 | .output = ip6_pkt_prohibit_out, |
| 160 | .output = ip6_pkt_prohibit_out, | ||
| 161 | } | ||
| 162 | }, | 158 | }, |
| 163 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 159 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
| 164 | .rt6i_protocol = RTPROT_KERNEL, | 160 | .rt6i_protocol = RTPROT_KERNEL, |
| @@ -167,16 +163,14 @@ static struct rt6_info ip6_prohibit_entry_template = { | |||
| 167 | }; | 163 | }; |
| 168 | 164 | ||
| 169 | static struct rt6_info ip6_blk_hole_entry_template = { | 165 | static struct rt6_info ip6_blk_hole_entry_template = { |
| 170 | .u = { | 166 | .dst = { |
| 171 | .dst = { | 167 | .__refcnt = ATOMIC_INIT(1), |
| 172 | .__refcnt = ATOMIC_INIT(1), | 168 | .__use = 1, |
| 173 | .__use = 1, | 169 | .obsolete = -1, |
| 174 | .obsolete = -1, | 170 | .error = -EINVAL, |
| 175 | .error = -EINVAL, | 171 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, |
| 176 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | 172 | .input = dst_discard, |
| 177 | .input = dst_discard, | 173 | .output = dst_discard, |
| 178 | .output = dst_discard, | ||
| 179 | } | ||
| 180 | }, | 174 | }, |
| 181 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 175 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
| 182 | .rt6i_protocol = RTPROT_KERNEL, | 176 | .rt6i_protocol = RTPROT_KERNEL, |
| @@ -249,7 +243,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net, | |||
| 249 | if (!oif && ipv6_addr_any(saddr)) | 243 | if (!oif && ipv6_addr_any(saddr)) |
| 250 | goto out; | 244 | goto out; |
| 251 | 245 | ||
| 252 | for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) { | 246 | for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) { |
| 253 | struct net_device *dev = sprt->rt6i_dev; | 247 | struct net_device *dev = sprt->rt6i_dev; |
| 254 | 248 | ||
| 255 | if (oif) { | 249 | if (oif) { |
| @@ -407,10 +401,10 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn, | |||
| 407 | 401 | ||
| 408 | match = NULL; | 402 | match = NULL; |
| 409 | for (rt = rr_head; rt && rt->rt6i_metric == metric; | 403 | for (rt = rr_head; rt && rt->rt6i_metric == metric; |
| 410 | rt = rt->u.dst.rt6_next) | 404 | rt = rt->dst.rt6_next) |
| 411 | match = find_match(rt, oif, strict, &mpri, match); | 405 | match = find_match(rt, oif, strict, &mpri, match); |
| 412 | for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric; | 406 | for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric; |
| 413 | rt = rt->u.dst.rt6_next) | 407 | rt = rt->dst.rt6_next) |
| 414 | match = find_match(rt, oif, strict, &mpri, match); | 408 | match = find_match(rt, oif, strict, &mpri, match); |
| 415 | 409 | ||
| 416 | return match; | 410 | return match; |
| @@ -432,7 +426,7 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | |||
| 432 | 426 | ||
| 433 | if (!match && | 427 | if (!match && |
| 434 | (strict & RT6_LOOKUP_F_REACHABLE)) { | 428 | (strict & RT6_LOOKUP_F_REACHABLE)) { |
| 435 | struct rt6_info *next = rt0->u.dst.rt6_next; | 429 | struct rt6_info *next = rt0->dst.rt6_next; |
| 436 | 430 | ||
| 437 | /* no entries matched; do round-robin */ | 431 | /* no entries matched; do round-robin */ |
| 438 | if (!next || next->rt6i_metric != rt0->rt6i_metric) | 432 | if (!next || next->rt6i_metric != rt0->rt6i_metric) |
| @@ -517,7 +511,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
| 517 | rt->rt6i_expires = jiffies + HZ * lifetime; | 511 | rt->rt6i_expires = jiffies + HZ * lifetime; |
| 518 | rt->rt6i_flags |= RTF_EXPIRES; | 512 | rt->rt6i_flags |= RTF_EXPIRES; |
| 519 | } | 513 | } |
| 520 | dst_release(&rt->u.dst); | 514 | dst_release(&rt->dst); |
| 521 | } | 515 | } |
| 522 | return 0; | 516 | return 0; |
| 523 | } | 517 | } |
| @@ -555,7 +549,7 @@ restart: | |||
| 555 | rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags); | 549 | rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags); |
| 556 | BACKTRACK(net, &fl->fl6_src); | 550 | BACKTRACK(net, &fl->fl6_src); |
| 557 | out: | 551 | out: |
| 558 | dst_use(&rt->u.dst, jiffies); | 552 | dst_use(&rt->dst, jiffies); |
| 559 | read_unlock_bh(&table->tb6_lock); | 553 | read_unlock_bh(&table->tb6_lock); |
| 560 | return rt; | 554 | return rt; |
| 561 | 555 | ||
| @@ -643,7 +637,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad | |||
| 643 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); | 637 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); |
| 644 | rt->rt6i_dst.plen = 128; | 638 | rt->rt6i_dst.plen = 128; |
| 645 | rt->rt6i_flags |= RTF_CACHE; | 639 | rt->rt6i_flags |= RTF_CACHE; |
| 646 | rt->u.dst.flags |= DST_HOST; | 640 | rt->dst.flags |= DST_HOST; |
| 647 | 641 | ||
| 648 | #ifdef CONFIG_IPV6_SUBTREES | 642 | #ifdef CONFIG_IPV6_SUBTREES |
| 649 | if (rt->rt6i_src.plen && saddr) { | 643 | if (rt->rt6i_src.plen && saddr) { |
| @@ -677,7 +671,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad | |||
| 677 | if (net_ratelimit()) | 671 | if (net_ratelimit()) |
| 678 | printk(KERN_WARNING | 672 | printk(KERN_WARNING |
| 679 | "Neighbour table overflow.\n"); | 673 | "Neighbour table overflow.\n"); |
| 680 | dst_free(&rt->u.dst); | 674 | dst_free(&rt->dst); |
| 681 | return NULL; | 675 | return NULL; |
| 682 | } | 676 | } |
| 683 | rt->rt6i_nexthop = neigh; | 677 | rt->rt6i_nexthop = neigh; |
| @@ -694,7 +688,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d | |||
| 694 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); | 688 | ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); |
| 695 | rt->rt6i_dst.plen = 128; | 689 | rt->rt6i_dst.plen = 128; |
| 696 | rt->rt6i_flags |= RTF_CACHE; | 690 | rt->rt6i_flags |= RTF_CACHE; |
| 697 | rt->u.dst.flags |= DST_HOST; | 691 | rt->dst.flags |= DST_HOST; |
| 698 | rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); | 692 | rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop); |
| 699 | } | 693 | } |
| 700 | return rt; | 694 | return rt; |
| @@ -726,7 +720,7 @@ restart: | |||
| 726 | rt->rt6i_flags & RTF_CACHE) | 720 | rt->rt6i_flags & RTF_CACHE) |
| 727 | goto out; | 721 | goto out; |
| 728 | 722 | ||
| 729 | dst_hold(&rt->u.dst); | 723 | dst_hold(&rt->dst); |
| 730 | read_unlock_bh(&table->tb6_lock); | 724 | read_unlock_bh(&table->tb6_lock); |
| 731 | 725 | ||
| 732 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 726 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
| @@ -739,10 +733,10 @@ restart: | |||
| 739 | #endif | 733 | #endif |
| 740 | } | 734 | } |
| 741 | 735 | ||
| 742 | dst_release(&rt->u.dst); | 736 | dst_release(&rt->dst); |
| 743 | rt = nrt ? : net->ipv6.ip6_null_entry; | 737 | rt = nrt ? : net->ipv6.ip6_null_entry; |
| 744 | 738 | ||
| 745 | dst_hold(&rt->u.dst); | 739 | dst_hold(&rt->dst); |
| 746 | if (nrt) { | 740 | if (nrt) { |
| 747 | err = ip6_ins_rt(nrt); | 741 | err = ip6_ins_rt(nrt); |
| 748 | if (!err) | 742 | if (!err) |
| @@ -756,7 +750,7 @@ restart: | |||
| 756 | * Race condition! In the gap, when table->tb6_lock was | 750 | * Race condition! In the gap, when table->tb6_lock was |
| 757 | * released someone could insert this route. Relookup. | 751 | * released someone could insert this route. Relookup. |
| 758 | */ | 752 | */ |
| 759 | dst_release(&rt->u.dst); | 753 | dst_release(&rt->dst); |
| 760 | goto relookup; | 754 | goto relookup; |
| 761 | 755 | ||
| 762 | out: | 756 | out: |
| @@ -764,11 +758,11 @@ out: | |||
| 764 | reachable = 0; | 758 | reachable = 0; |
| 765 | goto restart_2; | 759 | goto restart_2; |
| 766 | } | 760 | } |
| 767 | dst_hold(&rt->u.dst); | 761 | dst_hold(&rt->dst); |
| 768 | read_unlock_bh(&table->tb6_lock); | 762 | read_unlock_bh(&table->tb6_lock); |
| 769 | out2: | 763 | out2: |
| 770 | rt->u.dst.lastuse = jiffies; | 764 | rt->dst.lastuse = jiffies; |
| 771 | rt->u.dst.__use++; | 765 | rt->dst.__use++; |
| 772 | 766 | ||
| 773 | return rt; | 767 | return rt; |
| 774 | } | 768 | } |
| @@ -835,15 +829,15 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl | |||
| 835 | struct dst_entry *new = NULL; | 829 | struct dst_entry *new = NULL; |
| 836 | 830 | ||
| 837 | if (rt) { | 831 | if (rt) { |
| 838 | new = &rt->u.dst; | 832 | new = &rt->dst; |
| 839 | 833 | ||
| 840 | atomic_set(&new->__refcnt, 1); | 834 | atomic_set(&new->__refcnt, 1); |
| 841 | new->__use = 1; | 835 | new->__use = 1; |
| 842 | new->input = dst_discard; | 836 | new->input = dst_discard; |
| 843 | new->output = dst_discard; | 837 | new->output = dst_discard; |
| 844 | 838 | ||
| 845 | memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); | 839 | memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); |
| 846 | new->dev = ort->u.dst.dev; | 840 | new->dev = ort->dst.dev; |
| 847 | if (new->dev) | 841 | if (new->dev) |
| 848 | dev_hold(new->dev); | 842 | dev_hold(new->dev); |
| 849 | rt->rt6i_idev = ort->rt6i_idev; | 843 | rt->rt6i_idev = ort->rt6i_idev; |
| @@ -912,7 +906,7 @@ static void ip6_link_failure(struct sk_buff *skb) | |||
| 912 | rt = (struct rt6_info *) skb_dst(skb); | 906 | rt = (struct rt6_info *) skb_dst(skb); |
| 913 | if (rt) { | 907 | if (rt) { |
| 914 | if (rt->rt6i_flags&RTF_CACHE) { | 908 | if (rt->rt6i_flags&RTF_CACHE) { |
| 915 | dst_set_expires(&rt->u.dst, 0); | 909 | dst_set_expires(&rt->dst, 0); |
| 916 | rt->rt6i_flags |= RTF_EXPIRES; | 910 | rt->rt6i_flags |= RTF_EXPIRES; |
| 917 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) | 911 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) |
| 918 | rt->rt6i_node->fn_sernum = -1; | 912 | rt->rt6i_node->fn_sernum = -1; |
| @@ -986,14 +980,14 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
| 986 | rt->rt6i_dev = dev; | 980 | rt->rt6i_dev = dev; |
| 987 | rt->rt6i_idev = idev; | 981 | rt->rt6i_idev = idev; |
| 988 | rt->rt6i_nexthop = neigh; | 982 | rt->rt6i_nexthop = neigh; |
| 989 | atomic_set(&rt->u.dst.__refcnt, 1); | 983 | atomic_set(&rt->dst.__refcnt, 1); |
| 990 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255; | 984 | rt->dst.metrics[RTAX_HOPLIMIT-1] = 255; |
| 991 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 985 | rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); |
| 992 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); | 986 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); |
| 993 | rt->u.dst.output = ip6_output; | 987 | rt->dst.output = ip6_output; |
| 994 | 988 | ||
| 995 | #if 0 /* there's no chance to use these for ndisc */ | 989 | #if 0 /* there's no chance to use these for ndisc */ |
| 996 | rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST | 990 | rt->dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST |
| 997 | ? DST_HOST | 991 | ? DST_HOST |
| 998 | : 0; | 992 | : 0; |
| 999 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 993 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); |
| @@ -1001,14 +995,14 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
| 1001 | #endif | 995 | #endif |
| 1002 | 996 | ||
| 1003 | spin_lock_bh(&icmp6_dst_lock); | 997 | spin_lock_bh(&icmp6_dst_lock); |
| 1004 | rt->u.dst.next = icmp6_dst_gc_list; | 998 | rt->dst.next = icmp6_dst_gc_list; |
| 1005 | icmp6_dst_gc_list = &rt->u.dst; | 999 | icmp6_dst_gc_list = &rt->dst; |
| 1006 | spin_unlock_bh(&icmp6_dst_lock); | 1000 | spin_unlock_bh(&icmp6_dst_lock); |
| 1007 | 1001 | ||
| 1008 | fib6_force_start_gc(net); | 1002 | fib6_force_start_gc(net); |
| 1009 | 1003 | ||
| 1010 | out: | 1004 | out: |
| 1011 | return &rt->u.dst; | 1005 | return &rt->dst; |
| 1012 | } | 1006 | } |
| 1013 | 1007 | ||
| 1014 | int icmp6_dst_gc(void) | 1008 | int icmp6_dst_gc(void) |
| @@ -1090,11 +1084,11 @@ static int ipv6_get_mtu(struct net_device *dev) | |||
| 1090 | int mtu = IPV6_MIN_MTU; | 1084 | int mtu = IPV6_MIN_MTU; |
| 1091 | struct inet6_dev *idev; | 1085 | struct inet6_dev *idev; |
| 1092 | 1086 | ||
| 1093 | idev = in6_dev_get(dev); | 1087 | rcu_read_lock(); |
| 1094 | if (idev) { | 1088 | idev = __in6_dev_get(dev); |
| 1089 | if (idev) | ||
| 1095 | mtu = idev->cnf.mtu6; | 1090 | mtu = idev->cnf.mtu6; |
| 1096 | in6_dev_put(idev); | 1091 | rcu_read_unlock(); |
| 1097 | } | ||
| 1098 | return mtu; | 1092 | return mtu; |
| 1099 | } | 1093 | } |
| 1100 | 1094 | ||
| @@ -1103,12 +1097,15 @@ int ip6_dst_hoplimit(struct dst_entry *dst) | |||
| 1103 | int hoplimit = dst_metric(dst, RTAX_HOPLIMIT); | 1097 | int hoplimit = dst_metric(dst, RTAX_HOPLIMIT); |
| 1104 | if (hoplimit < 0) { | 1098 | if (hoplimit < 0) { |
| 1105 | struct net_device *dev = dst->dev; | 1099 | struct net_device *dev = dst->dev; |
| 1106 | struct inet6_dev *idev = in6_dev_get(dev); | 1100 | struct inet6_dev *idev; |
| 1107 | if (idev) { | 1101 | |
| 1102 | rcu_read_lock(); | ||
| 1103 | idev = __in6_dev_get(dev); | ||
| 1104 | if (idev) | ||
| 1108 | hoplimit = idev->cnf.hop_limit; | 1105 | hoplimit = idev->cnf.hop_limit; |
| 1109 | in6_dev_put(idev); | 1106 | else |
| 1110 | } else | ||
| 1111 | hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit; | 1107 | hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit; |
| 1108 | rcu_read_unlock(); | ||
| 1112 | } | 1109 | } |
| 1113 | return hoplimit; | 1110 | return hoplimit; |
| 1114 | } | 1111 | } |
| @@ -1159,7 +1156,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1159 | goto out; | 1156 | goto out; |
| 1160 | } | 1157 | } |
| 1161 | 1158 | ||
| 1162 | rt->u.dst.obsolete = -1; | 1159 | rt->dst.obsolete = -1; |
| 1163 | rt->rt6i_expires = (cfg->fc_flags & RTF_EXPIRES) ? | 1160 | rt->rt6i_expires = (cfg->fc_flags & RTF_EXPIRES) ? |
| 1164 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : | 1161 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : |
| 1165 | 0; | 1162 | 0; |
| @@ -1171,16 +1168,16 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1171 | addr_type = ipv6_addr_type(&cfg->fc_dst); | 1168 | addr_type = ipv6_addr_type(&cfg->fc_dst); |
| 1172 | 1169 | ||
| 1173 | if (addr_type & IPV6_ADDR_MULTICAST) | 1170 | if (addr_type & IPV6_ADDR_MULTICAST) |
| 1174 | rt->u.dst.input = ip6_mc_input; | 1171 | rt->dst.input = ip6_mc_input; |
| 1175 | else | 1172 | else |
| 1176 | rt->u.dst.input = ip6_forward; | 1173 | rt->dst.input = ip6_forward; |
| 1177 | 1174 | ||
| 1178 | rt->u.dst.output = ip6_output; | 1175 | rt->dst.output = ip6_output; |
| 1179 | 1176 | ||
| 1180 | ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); | 1177 | ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); |
| 1181 | rt->rt6i_dst.plen = cfg->fc_dst_len; | 1178 | rt->rt6i_dst.plen = cfg->fc_dst_len; |
| 1182 | if (rt->rt6i_dst.plen == 128) | 1179 | if (rt->rt6i_dst.plen == 128) |
| 1183 | rt->u.dst.flags = DST_HOST; | 1180 | rt->dst.flags = DST_HOST; |
| 1184 | 1181 | ||
| 1185 | #ifdef CONFIG_IPV6_SUBTREES | 1182 | #ifdef CONFIG_IPV6_SUBTREES |
| 1186 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); | 1183 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); |
| @@ -1208,9 +1205,9 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1208 | goto out; | 1205 | goto out; |
| 1209 | } | 1206 | } |
| 1210 | } | 1207 | } |
| 1211 | rt->u.dst.output = ip6_pkt_discard_out; | 1208 | rt->dst.output = ip6_pkt_discard_out; |
| 1212 | rt->u.dst.input = ip6_pkt_discard; | 1209 | rt->dst.input = ip6_pkt_discard; |
| 1213 | rt->u.dst.error = -ENETUNREACH; | 1210 | rt->dst.error = -ENETUNREACH; |
| 1214 | rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; | 1211 | rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; |
| 1215 | goto install_route; | 1212 | goto install_route; |
| 1216 | } | 1213 | } |
| @@ -1244,7 +1241,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1244 | goto out; | 1241 | goto out; |
| 1245 | if (dev) { | 1242 | if (dev) { |
| 1246 | if (dev != grt->rt6i_dev) { | 1243 | if (dev != grt->rt6i_dev) { |
| 1247 | dst_release(&grt->u.dst); | 1244 | dst_release(&grt->dst); |
| 1248 | goto out; | 1245 | goto out; |
| 1249 | } | 1246 | } |
| 1250 | } else { | 1247 | } else { |
| @@ -1255,7 +1252,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1255 | } | 1252 | } |
| 1256 | if (!(grt->rt6i_flags&RTF_GATEWAY)) | 1253 | if (!(grt->rt6i_flags&RTF_GATEWAY)) |
| 1257 | err = 0; | 1254 | err = 0; |
| 1258 | dst_release(&grt->u.dst); | 1255 | dst_release(&grt->dst); |
| 1259 | 1256 | ||
| 1260 | if (err) | 1257 | if (err) |
| 1261 | goto out; | 1258 | goto out; |
| @@ -1294,18 +1291,18 @@ install_route: | |||
| 1294 | goto out; | 1291 | goto out; |
| 1295 | } | 1292 | } |
| 1296 | 1293 | ||
| 1297 | rt->u.dst.metrics[type - 1] = nla_get_u32(nla); | 1294 | rt->dst.metrics[type - 1] = nla_get_u32(nla); |
| 1298 | } | 1295 | } |
| 1299 | } | 1296 | } |
| 1300 | } | 1297 | } |
| 1301 | 1298 | ||
| 1302 | if (dst_metric(&rt->u.dst, RTAX_HOPLIMIT) == 0) | 1299 | if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0) |
| 1303 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; | 1300 | rt->dst.metrics[RTAX_HOPLIMIT-1] = -1; |
| 1304 | if (!dst_mtu(&rt->u.dst)) | 1301 | if (!dst_mtu(&rt->dst)) |
| 1305 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); | 1302 | rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); |
| 1306 | if (!dst_metric(&rt->u.dst, RTAX_ADVMSS)) | 1303 | if (!dst_metric(&rt->dst, RTAX_ADVMSS)) |
| 1307 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); | 1304 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); |
| 1308 | rt->u.dst.dev = dev; | 1305 | rt->dst.dev = dev; |
| 1309 | rt->rt6i_idev = idev; | 1306 | rt->rt6i_idev = idev; |
| 1310 | rt->rt6i_table = table; | 1307 | rt->rt6i_table = table; |
| 1311 | 1308 | ||
| @@ -1319,7 +1316,7 @@ out: | |||
| 1319 | if (idev) | 1316 | if (idev) |
| 1320 | in6_dev_put(idev); | 1317 | in6_dev_put(idev); |
| 1321 | if (rt) | 1318 | if (rt) |
| 1322 | dst_free(&rt->u.dst); | 1319 | dst_free(&rt->dst); |
| 1323 | return err; | 1320 | return err; |
| 1324 | } | 1321 | } |
| 1325 | 1322 | ||
| @@ -1336,7 +1333,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
| 1336 | write_lock_bh(&table->tb6_lock); | 1333 | write_lock_bh(&table->tb6_lock); |
| 1337 | 1334 | ||
| 1338 | err = fib6_del(rt, info); | 1335 | err = fib6_del(rt, info); |
| 1339 | dst_release(&rt->u.dst); | 1336 | dst_release(&rt->dst); |
| 1340 | 1337 | ||
| 1341 | write_unlock_bh(&table->tb6_lock); | 1338 | write_unlock_bh(&table->tb6_lock); |
| 1342 | 1339 | ||
| @@ -1369,7 +1366,7 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
| 1369 | &cfg->fc_src, cfg->fc_src_len); | 1366 | &cfg->fc_src, cfg->fc_src_len); |
| 1370 | 1367 | ||
| 1371 | if (fn) { | 1368 | if (fn) { |
| 1372 | for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { | 1369 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
| 1373 | if (cfg->fc_ifindex && | 1370 | if (cfg->fc_ifindex && |
| 1374 | (rt->rt6i_dev == NULL || | 1371 | (rt->rt6i_dev == NULL || |
| 1375 | rt->rt6i_dev->ifindex != cfg->fc_ifindex)) | 1372 | rt->rt6i_dev->ifindex != cfg->fc_ifindex)) |
| @@ -1379,7 +1376,7 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
| 1379 | continue; | 1376 | continue; |
| 1380 | if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric) | 1377 | if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric) |
| 1381 | continue; | 1378 | continue; |
| 1382 | dst_hold(&rt->u.dst); | 1379 | dst_hold(&rt->dst); |
| 1383 | read_unlock_bh(&table->tb6_lock); | 1380 | read_unlock_bh(&table->tb6_lock); |
| 1384 | 1381 | ||
| 1385 | return __ip6_del_rt(rt, &cfg->fc_nlinfo); | 1382 | return __ip6_del_rt(rt, &cfg->fc_nlinfo); |
| @@ -1421,7 +1418,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, | |||
| 1421 | read_lock_bh(&table->tb6_lock); | 1418 | read_lock_bh(&table->tb6_lock); |
| 1422 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 1419 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
| 1423 | restart: | 1420 | restart: |
| 1424 | for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { | 1421 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
| 1425 | /* | 1422 | /* |
| 1426 | * Current route is on-link; redirect is always invalid. | 1423 | * Current route is on-link; redirect is always invalid. |
| 1427 | * | 1424 | * |
| @@ -1445,7 +1442,7 @@ restart: | |||
| 1445 | rt = net->ipv6.ip6_null_entry; | 1442 | rt = net->ipv6.ip6_null_entry; |
| 1446 | BACKTRACK(net, &fl->fl6_src); | 1443 | BACKTRACK(net, &fl->fl6_src); |
| 1447 | out: | 1444 | out: |
| 1448 | dst_hold(&rt->u.dst); | 1445 | dst_hold(&rt->dst); |
| 1449 | 1446 | ||
| 1450 | read_unlock_bh(&table->tb6_lock); | 1447 | read_unlock_bh(&table->tb6_lock); |
| 1451 | 1448 | ||
| @@ -1513,10 +1510,10 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
| 1513 | * Look, redirects are sent only in response to data packets, | 1510 | * Look, redirects are sent only in response to data packets, |
| 1514 | * so that this nexthop apparently is reachable. --ANK | 1511 | * so that this nexthop apparently is reachable. --ANK |
| 1515 | */ | 1512 | */ |
| 1516 | dst_confirm(&rt->u.dst); | 1513 | dst_confirm(&rt->dst); |
| 1517 | 1514 | ||
| 1518 | /* Duplicate redirect: silently ignore. */ | 1515 | /* Duplicate redirect: silently ignore. */ |
| 1519 | if (neigh == rt->u.dst.neighbour) | 1516 | if (neigh == rt->dst.neighbour) |
| 1520 | goto out; | 1517 | goto out; |
| 1521 | 1518 | ||
| 1522 | nrt = ip6_rt_copy(rt); | 1519 | nrt = ip6_rt_copy(rt); |
| @@ -1529,20 +1526,20 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
| 1529 | 1526 | ||
| 1530 | ipv6_addr_copy(&nrt->rt6i_dst.addr, dest); | 1527 | ipv6_addr_copy(&nrt->rt6i_dst.addr, dest); |
| 1531 | nrt->rt6i_dst.plen = 128; | 1528 | nrt->rt6i_dst.plen = 128; |
| 1532 | nrt->u.dst.flags |= DST_HOST; | 1529 | nrt->dst.flags |= DST_HOST; |
| 1533 | 1530 | ||
| 1534 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); | 1531 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); |
| 1535 | nrt->rt6i_nexthop = neigh_clone(neigh); | 1532 | nrt->rt6i_nexthop = neigh_clone(neigh); |
| 1536 | /* Reset pmtu, it may be better */ | 1533 | /* Reset pmtu, it may be better */ |
| 1537 | nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); | 1534 | nrt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); |
| 1538 | nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev), | 1535 | nrt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev), |
| 1539 | dst_mtu(&nrt->u.dst)); | 1536 | dst_mtu(&nrt->dst)); |
| 1540 | 1537 | ||
| 1541 | if (ip6_ins_rt(nrt)) | 1538 | if (ip6_ins_rt(nrt)) |
| 1542 | goto out; | 1539 | goto out; |
| 1543 | 1540 | ||
| 1544 | netevent.old = &rt->u.dst; | 1541 | netevent.old = &rt->dst; |
| 1545 | netevent.new = &nrt->u.dst; | 1542 | netevent.new = &nrt->dst; |
| 1546 | call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); | 1543 | call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); |
| 1547 | 1544 | ||
| 1548 | if (rt->rt6i_flags&RTF_CACHE) { | 1545 | if (rt->rt6i_flags&RTF_CACHE) { |
| @@ -1551,7 +1548,7 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
| 1551 | } | 1548 | } |
| 1552 | 1549 | ||
| 1553 | out: | 1550 | out: |
| 1554 | dst_release(&rt->u.dst); | 1551 | dst_release(&rt->dst); |
| 1555 | } | 1552 | } |
| 1556 | 1553 | ||
| 1557 | /* | 1554 | /* |
| @@ -1570,7 +1567,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
| 1570 | if (rt == NULL) | 1567 | if (rt == NULL) |
| 1571 | return; | 1568 | return; |
| 1572 | 1569 | ||
| 1573 | if (pmtu >= dst_mtu(&rt->u.dst)) | 1570 | if (pmtu >= dst_mtu(&rt->dst)) |
| 1574 | goto out; | 1571 | goto out; |
| 1575 | 1572 | ||
| 1576 | if (pmtu < IPV6_MIN_MTU) { | 1573 | if (pmtu < IPV6_MIN_MTU) { |
| @@ -1588,7 +1585,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
| 1588 | They are sent only in response to data packets, | 1585 | They are sent only in response to data packets, |
| 1589 | so that this nexthop apparently is reachable. --ANK | 1586 | so that this nexthop apparently is reachable. --ANK |
| 1590 | */ | 1587 | */ |
| 1591 | dst_confirm(&rt->u.dst); | 1588 | dst_confirm(&rt->dst); |
| 1592 | 1589 | ||
| 1593 | /* Host route. If it is static, it would be better | 1590 | /* Host route. If it is static, it would be better |
| 1594 | not to override it, but add new one, so that | 1591 | not to override it, but add new one, so that |
| @@ -1596,10 +1593,10 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
| 1596 | would return automatically. | 1593 | would return automatically. |
| 1597 | */ | 1594 | */ |
| 1598 | if (rt->rt6i_flags & RTF_CACHE) { | 1595 | if (rt->rt6i_flags & RTF_CACHE) { |
| 1599 | rt->u.dst.metrics[RTAX_MTU-1] = pmtu; | 1596 | rt->dst.metrics[RTAX_MTU-1] = pmtu; |
| 1600 | if (allfrag) | 1597 | if (allfrag) |
| 1601 | rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1598 | rt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; |
| 1602 | dst_set_expires(&rt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1599 | dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
| 1603 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; | 1600 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; |
| 1604 | goto out; | 1601 | goto out; |
| 1605 | } | 1602 | } |
| @@ -1615,9 +1612,9 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
| 1615 | nrt = rt6_alloc_clone(rt, daddr); | 1612 | nrt = rt6_alloc_clone(rt, daddr); |
| 1616 | 1613 | ||
| 1617 | if (nrt) { | 1614 | if (nrt) { |
| 1618 | nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; | 1615 | nrt->dst.metrics[RTAX_MTU-1] = pmtu; |
| 1619 | if (allfrag) | 1616 | if (allfrag) |
| 1620 | nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1617 | nrt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; |
| 1621 | 1618 | ||
| 1622 | /* According to RFC 1981, detecting PMTU increase shouldn't be | 1619 | /* According to RFC 1981, detecting PMTU increase shouldn't be |
| 1623 | * happened within 5 mins, the recommended timer is 10 mins. | 1620 | * happened within 5 mins, the recommended timer is 10 mins. |
| @@ -1625,13 +1622,13 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
| 1625 | * which is 10 mins. After 10 mins the decreased pmtu is expired | 1622 | * which is 10 mins. After 10 mins the decreased pmtu is expired |
| 1626 | * and detecting PMTU increase will be automatically happened. | 1623 | * and detecting PMTU increase will be automatically happened. |
| 1627 | */ | 1624 | */ |
| 1628 | dst_set_expires(&nrt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1625 | dst_set_expires(&nrt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
| 1629 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; | 1626 | nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; |
| 1630 | 1627 | ||
| 1631 | ip6_ins_rt(nrt); | 1628 | ip6_ins_rt(nrt); |
| 1632 | } | 1629 | } |
| 1633 | out: | 1630 | out: |
| 1634 | dst_release(&rt->u.dst); | 1631 | dst_release(&rt->dst); |
| 1635 | } | 1632 | } |
| 1636 | 1633 | ||
| 1637 | /* | 1634 | /* |
| @@ -1644,18 +1641,18 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
| 1644 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); | 1641 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); |
| 1645 | 1642 | ||
| 1646 | if (rt) { | 1643 | if (rt) { |
| 1647 | rt->u.dst.input = ort->u.dst.input; | 1644 | rt->dst.input = ort->dst.input; |
| 1648 | rt->u.dst.output = ort->u.dst.output; | 1645 | rt->dst.output = ort->dst.output; |
| 1649 | 1646 | ||
| 1650 | memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); | 1647 | memcpy(rt->dst.metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); |
| 1651 | rt->u.dst.error = ort->u.dst.error; | 1648 | rt->dst.error = ort->dst.error; |
| 1652 | rt->u.dst.dev = ort->u.dst.dev; | 1649 | rt->dst.dev = ort->dst.dev; |
| 1653 | if (rt->u.dst.dev) | 1650 | if (rt->dst.dev) |
| 1654 | dev_hold(rt->u.dst.dev); | 1651 | dev_hold(rt->dst.dev); |
| 1655 | rt->rt6i_idev = ort->rt6i_idev; | 1652 | rt->rt6i_idev = ort->rt6i_idev; |
| 1656 | if (rt->rt6i_idev) | 1653 | if (rt->rt6i_idev) |
| 1657 | in6_dev_hold(rt->rt6i_idev); | 1654 | in6_dev_hold(rt->rt6i_idev); |
| 1658 | rt->u.dst.lastuse = jiffies; | 1655 | rt->dst.lastuse = jiffies; |
| 1659 | rt->rt6i_expires = 0; | 1656 | rt->rt6i_expires = 0; |
| 1660 | 1657 | ||
| 1661 | ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); | 1658 | ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); |
| @@ -1689,14 +1686,14 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
| 1689 | if (!fn) | 1686 | if (!fn) |
| 1690 | goto out; | 1687 | goto out; |
| 1691 | 1688 | ||
| 1692 | for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) { | 1689 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
| 1693 | if (rt->rt6i_dev->ifindex != ifindex) | 1690 | if (rt->rt6i_dev->ifindex != ifindex) |
| 1694 | continue; | 1691 | continue; |
| 1695 | if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) | 1692 | if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) |
| 1696 | continue; | 1693 | continue; |
| 1697 | if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr)) | 1694 | if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr)) |
| 1698 | continue; | 1695 | continue; |
| 1699 | dst_hold(&rt->u.dst); | 1696 | dst_hold(&rt->dst); |
| 1700 | break; | 1697 | break; |
| 1701 | } | 1698 | } |
| 1702 | out: | 1699 | out: |
| @@ -1744,14 +1741,14 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d | |||
| 1744 | return NULL; | 1741 | return NULL; |
| 1745 | 1742 | ||
| 1746 | write_lock_bh(&table->tb6_lock); | 1743 | write_lock_bh(&table->tb6_lock); |
| 1747 | for (rt = table->tb6_root.leaf; rt; rt=rt->u.dst.rt6_next) { | 1744 | for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) { |
| 1748 | if (dev == rt->rt6i_dev && | 1745 | if (dev == rt->rt6i_dev && |
| 1749 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && | 1746 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && |
| 1750 | ipv6_addr_equal(&rt->rt6i_gateway, addr)) | 1747 | ipv6_addr_equal(&rt->rt6i_gateway, addr)) |
| 1751 | break; | 1748 | break; |
| 1752 | } | 1749 | } |
| 1753 | if (rt) | 1750 | if (rt) |
| 1754 | dst_hold(&rt->u.dst); | 1751 | dst_hold(&rt->dst); |
| 1755 | write_unlock_bh(&table->tb6_lock); | 1752 | write_unlock_bh(&table->tb6_lock); |
| 1756 | return rt; | 1753 | return rt; |
| 1757 | } | 1754 | } |
| @@ -1790,9 +1787,9 @@ void rt6_purge_dflt_routers(struct net *net) | |||
| 1790 | 1787 | ||
| 1791 | restart: | 1788 | restart: |
| 1792 | read_lock_bh(&table->tb6_lock); | 1789 | read_lock_bh(&table->tb6_lock); |
| 1793 | for (rt = table->tb6_root.leaf; rt; rt = rt->u.dst.rt6_next) { | 1790 | for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { |
| 1794 | if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { | 1791 | if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { |
| 1795 | dst_hold(&rt->u.dst); | 1792 | dst_hold(&rt->dst); |
| 1796 | read_unlock_bh(&table->tb6_lock); | 1793 | read_unlock_bh(&table->tb6_lock); |
| 1797 | ip6_del_rt(rt); | 1794 | ip6_del_rt(rt); |
| 1798 | goto restart; | 1795 | goto restart; |
| @@ -1930,15 +1927,15 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
| 1930 | dev_hold(net->loopback_dev); | 1927 | dev_hold(net->loopback_dev); |
| 1931 | in6_dev_hold(idev); | 1928 | in6_dev_hold(idev); |
| 1932 | 1929 | ||
| 1933 | rt->u.dst.flags = DST_HOST; | 1930 | rt->dst.flags = DST_HOST; |
| 1934 | rt->u.dst.input = ip6_input; | 1931 | rt->dst.input = ip6_input; |
| 1935 | rt->u.dst.output = ip6_output; | 1932 | rt->dst.output = ip6_output; |
| 1936 | rt->rt6i_dev = net->loopback_dev; | 1933 | rt->rt6i_dev = net->loopback_dev; |
| 1937 | rt->rt6i_idev = idev; | 1934 | rt->rt6i_idev = idev; |
| 1938 | rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 1935 | rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); |
| 1939 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst)); | 1936 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); |
| 1940 | rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1; | 1937 | rt->dst.metrics[RTAX_HOPLIMIT-1] = -1; |
| 1941 | rt->u.dst.obsolete = -1; | 1938 | rt->dst.obsolete = -1; |
| 1942 | 1939 | ||
| 1943 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; | 1940 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; |
| 1944 | if (anycast) | 1941 | if (anycast) |
| @@ -1947,7 +1944,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
| 1947 | rt->rt6i_flags |= RTF_LOCAL; | 1944 | rt->rt6i_flags |= RTF_LOCAL; |
| 1948 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | 1945 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); |
| 1949 | if (IS_ERR(neigh)) { | 1946 | if (IS_ERR(neigh)) { |
| 1950 | dst_free(&rt->u.dst); | 1947 | dst_free(&rt->dst); |
| 1951 | 1948 | ||
| 1952 | /* We are casting this because that is the return | 1949 | /* We are casting this because that is the return |
| 1953 | * value type. But an errno encoded pointer is the | 1950 | * value type. But an errno encoded pointer is the |
| @@ -1962,7 +1959,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
| 1962 | rt->rt6i_dst.plen = 128; | 1959 | rt->rt6i_dst.plen = 128; |
| 1963 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); | 1960 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); |
| 1964 | 1961 | ||
| 1965 | atomic_set(&rt->u.dst.__refcnt, 1); | 1962 | atomic_set(&rt->dst.__refcnt, 1); |
| 1966 | 1963 | ||
| 1967 | return rt; | 1964 | return rt; |
| 1968 | } | 1965 | } |
| @@ -2033,12 +2030,12 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
| 2033 | PMTU discouvery. | 2030 | PMTU discouvery. |
| 2034 | */ | 2031 | */ |
| 2035 | if (rt->rt6i_dev == arg->dev && | 2032 | if (rt->rt6i_dev == arg->dev && |
| 2036 | !dst_metric_locked(&rt->u.dst, RTAX_MTU) && | 2033 | !dst_metric_locked(&rt->dst, RTAX_MTU) && |
| 2037 | (dst_mtu(&rt->u.dst) >= arg->mtu || | 2034 | (dst_mtu(&rt->dst) >= arg->mtu || |
| 2038 | (dst_mtu(&rt->u.dst) < arg->mtu && | 2035 | (dst_mtu(&rt->dst) < arg->mtu && |
| 2039 | dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) { | 2036 | dst_mtu(&rt->dst) == idev->cnf.mtu6))) { |
| 2040 | rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu; | 2037 | rt->dst.metrics[RTAX_MTU-1] = arg->mtu; |
| 2041 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu); | 2038 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu); |
| 2042 | } | 2039 | } |
| 2043 | return 0; | 2040 | return 0; |
| 2044 | } | 2041 | } |
| @@ -2252,20 +2249,20 @@ static int rt6_fill_node(struct net *net, | |||
| 2252 | #endif | 2249 | #endif |
| 2253 | NLA_PUT_U32(skb, RTA_IIF, iif); | 2250 | NLA_PUT_U32(skb, RTA_IIF, iif); |
| 2254 | } else if (dst) { | 2251 | } else if (dst) { |
| 2255 | struct inet6_dev *idev = ip6_dst_idev(&rt->u.dst); | 2252 | struct inet6_dev *idev = ip6_dst_idev(&rt->dst); |
| 2256 | struct in6_addr saddr_buf; | 2253 | struct in6_addr saddr_buf; |
| 2257 | if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, | 2254 | if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, |
| 2258 | dst, 0, &saddr_buf) == 0) | 2255 | dst, 0, &saddr_buf) == 0) |
| 2259 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | 2256 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); |
| 2260 | } | 2257 | } |
| 2261 | 2258 | ||
| 2262 | if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) | 2259 | if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) |
| 2263 | goto nla_put_failure; | 2260 | goto nla_put_failure; |
| 2264 | 2261 | ||
| 2265 | if (rt->u.dst.neighbour) | 2262 | if (rt->dst.neighbour) |
| 2266 | NLA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key); | 2263 | NLA_PUT(skb, RTA_GATEWAY, 16, &rt->dst.neighbour->primary_key); |
| 2267 | 2264 | ||
| 2268 | if (rt->u.dst.dev) | 2265 | if (rt->dst.dev) |
| 2269 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); | 2266 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); |
| 2270 | 2267 | ||
| 2271 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); | 2268 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); |
| @@ -2277,8 +2274,8 @@ static int rt6_fill_node(struct net *net, | |||
| 2277 | else | 2274 | else |
| 2278 | expires = INT_MAX; | 2275 | expires = INT_MAX; |
| 2279 | 2276 | ||
| 2280 | if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, | 2277 | if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, |
| 2281 | expires, rt->u.dst.error) < 0) | 2278 | expires, rt->dst.error) < 0) |
| 2282 | goto nla_put_failure; | 2279 | goto nla_put_failure; |
| 2283 | 2280 | ||
| 2284 | return nlmsg_end(skb, nlh); | 2281 | return nlmsg_end(skb, nlh); |
| @@ -2364,7 +2361,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
| 2364 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); | 2361 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); |
| 2365 | 2362 | ||
| 2366 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); | 2363 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); |
| 2367 | skb_dst_set(skb, &rt->u.dst); | 2364 | skb_dst_set(skb, &rt->dst); |
| 2368 | 2365 | ||
| 2369 | err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, | 2366 | err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, |
| 2370 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, | 2367 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, |
| @@ -2416,12 +2413,12 @@ static int ip6_route_dev_notify(struct notifier_block *this, | |||
| 2416 | struct net *net = dev_net(dev); | 2413 | struct net *net = dev_net(dev); |
| 2417 | 2414 | ||
| 2418 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { | 2415 | if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { |
| 2419 | net->ipv6.ip6_null_entry->u.dst.dev = dev; | 2416 | net->ipv6.ip6_null_entry->dst.dev = dev; |
| 2420 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); | 2417 | net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); |
| 2421 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2418 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
| 2422 | net->ipv6.ip6_prohibit_entry->u.dst.dev = dev; | 2419 | net->ipv6.ip6_prohibit_entry->dst.dev = dev; |
| 2423 | net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); | 2420 | net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); |
| 2424 | net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev; | 2421 | net->ipv6.ip6_blk_hole_entry->dst.dev = dev; |
| 2425 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); | 2422 | net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); |
| 2426 | #endif | 2423 | #endif |
| 2427 | } | 2424 | } |
| @@ -2464,8 +2461,8 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
| 2464 | seq_puts(m, "00000000000000000000000000000000"); | 2461 | seq_puts(m, "00000000000000000000000000000000"); |
| 2465 | } | 2462 | } |
| 2466 | seq_printf(m, " %08x %08x %08x %08x %8s\n", | 2463 | seq_printf(m, " %08x %08x %08x %08x %8s\n", |
| 2467 | rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt), | 2464 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), |
| 2468 | rt->u.dst.__use, rt->rt6i_flags, | 2465 | rt->dst.__use, rt->rt6i_flags, |
| 2469 | rt->rt6i_dev ? rt->rt6i_dev->name : ""); | 2466 | rt->rt6i_dev ? rt->rt6i_dev->name : ""); |
| 2470 | return 0; | 2467 | return 0; |
| 2471 | } | 2468 | } |
| @@ -2646,9 +2643,9 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
| 2646 | GFP_KERNEL); | 2643 | GFP_KERNEL); |
| 2647 | if (!net->ipv6.ip6_null_entry) | 2644 | if (!net->ipv6.ip6_null_entry) |
| 2648 | goto out_ip6_dst_ops; | 2645 | goto out_ip6_dst_ops; |
| 2649 | net->ipv6.ip6_null_entry->u.dst.path = | 2646 | net->ipv6.ip6_null_entry->dst.path = |
| 2650 | (struct dst_entry *)net->ipv6.ip6_null_entry; | 2647 | (struct dst_entry *)net->ipv6.ip6_null_entry; |
| 2651 | net->ipv6.ip6_null_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; | 2648 | net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
| 2652 | 2649 | ||
| 2653 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2650 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
| 2654 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | 2651 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, |
| @@ -2656,18 +2653,18 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
| 2656 | GFP_KERNEL); | 2653 | GFP_KERNEL); |
| 2657 | if (!net->ipv6.ip6_prohibit_entry) | 2654 | if (!net->ipv6.ip6_prohibit_entry) |
| 2658 | goto out_ip6_null_entry; | 2655 | goto out_ip6_null_entry; |
| 2659 | net->ipv6.ip6_prohibit_entry->u.dst.path = | 2656 | net->ipv6.ip6_prohibit_entry->dst.path = |
| 2660 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | 2657 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; |
| 2661 | net->ipv6.ip6_prohibit_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; | 2658 | net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
| 2662 | 2659 | ||
| 2663 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | 2660 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, |
| 2664 | sizeof(*net->ipv6.ip6_blk_hole_entry), | 2661 | sizeof(*net->ipv6.ip6_blk_hole_entry), |
| 2665 | GFP_KERNEL); | 2662 | GFP_KERNEL); |
| 2666 | if (!net->ipv6.ip6_blk_hole_entry) | 2663 | if (!net->ipv6.ip6_blk_hole_entry) |
| 2667 | goto out_ip6_prohibit_entry; | 2664 | goto out_ip6_prohibit_entry; |
| 2668 | net->ipv6.ip6_blk_hole_entry->u.dst.path = | 2665 | net->ipv6.ip6_blk_hole_entry->dst.path = |
| 2669 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | 2666 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; |
| 2670 | net->ipv6.ip6_blk_hole_entry->u.dst.ops = &net->ipv6.ip6_dst_ops; | 2667 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
| 2671 | #endif | 2668 | #endif |
| 2672 | 2669 | ||
| 2673 | net->ipv6.sysctl.flush_delay = 0; | 2670 | net->ipv6.sysctl.flush_delay = 0; |
| @@ -2742,12 +2739,12 @@ int __init ip6_route_init(void) | |||
| 2742 | /* Registering of the loopback is done before this portion of code, | 2739 | /* Registering of the loopback is done before this portion of code, |
| 2743 | * the loopback reference in rt6_info will not be taken, do it | 2740 | * the loopback reference in rt6_info will not be taken, do it |
| 2744 | * manually for init_net */ | 2741 | * manually for init_net */ |
| 2745 | init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev; | 2742 | init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev; |
| 2746 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | 2743 | init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
| 2747 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2744 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
| 2748 | init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev; | 2745 | init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev; |
| 2749 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | 2746 | init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
| 2750 | init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev; | 2747 | init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; |
| 2751 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | 2748 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
| 2752 | #endif | 2749 | #endif |
| 2753 | ret = fib6_init(); | 2750 | ret = fib6_init(); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index e51e650ea80b..4699cd3c3118 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -249,8 +249,6 @@ failed: | |||
| 249 | return NULL; | 249 | return NULL; |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | static DEFINE_SPINLOCK(ipip6_prl_lock); | ||
| 253 | |||
| 254 | #define for_each_prl_rcu(start) \ | 252 | #define for_each_prl_rcu(start) \ |
| 255 | for (prl = rcu_dereference(start); \ | 253 | for (prl = rcu_dereference(start); \ |
| 256 | prl; \ | 254 | prl; \ |
| @@ -340,7 +338,7 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) | |||
| 340 | if (a->addr == htonl(INADDR_ANY)) | 338 | if (a->addr == htonl(INADDR_ANY)) |
| 341 | return -EINVAL; | 339 | return -EINVAL; |
| 342 | 340 | ||
| 343 | spin_lock(&ipip6_prl_lock); | 341 | ASSERT_RTNL(); |
| 344 | 342 | ||
| 345 | for (p = t->prl; p; p = p->next) { | 343 | for (p = t->prl; p; p = p->next) { |
| 346 | if (p->addr == a->addr) { | 344 | if (p->addr == a->addr) { |
| @@ -370,7 +368,6 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) | |||
| 370 | t->prl_count++; | 368 | t->prl_count++; |
| 371 | rcu_assign_pointer(t->prl, p); | 369 | rcu_assign_pointer(t->prl, p); |
| 372 | out: | 370 | out: |
| 373 | spin_unlock(&ipip6_prl_lock); | ||
| 374 | return err; | 371 | return err; |
| 375 | } | 372 | } |
| 376 | 373 | ||
| @@ -397,7 +394,7 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | |||
| 397 | struct ip_tunnel_prl_entry *x, **p; | 394 | struct ip_tunnel_prl_entry *x, **p; |
| 398 | int err = 0; | 395 | int err = 0; |
| 399 | 396 | ||
| 400 | spin_lock(&ipip6_prl_lock); | 397 | ASSERT_RTNL(); |
| 401 | 398 | ||
| 402 | if (a && a->addr != htonl(INADDR_ANY)) { | 399 | if (a && a->addr != htonl(INADDR_ANY)) { |
| 403 | for (p = &t->prl; *p; p = &(*p)->next) { | 400 | for (p = &t->prl; *p; p = &(*p)->next) { |
| @@ -419,7 +416,6 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | |||
| 419 | } | 416 | } |
| 420 | } | 417 | } |
| 421 | out: | 418 | out: |
| 422 | spin_unlock(&ipip6_prl_lock); | ||
| 423 | return err; | 419 | return err; |
| 424 | } | 420 | } |
| 425 | 421 | ||
| @@ -716,7 +712,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
| 716 | stats->tx_carrier_errors++; | 712 | stats->tx_carrier_errors++; |
| 717 | goto tx_error_icmp; | 713 | goto tx_error_icmp; |
| 718 | } | 714 | } |
| 719 | tdev = rt->u.dst.dev; | 715 | tdev = rt->dst.dev; |
| 720 | 716 | ||
| 721 | if (tdev == dev) { | 717 | if (tdev == dev) { |
| 722 | ip_rt_put(rt); | 718 | ip_rt_put(rt); |
| @@ -725,7 +721,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
| 725 | } | 721 | } |
| 726 | 722 | ||
| 727 | if (df) { | 723 | if (df) { |
| 728 | mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); | 724 | mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr); |
| 729 | 725 | ||
| 730 | if (mtu < 68) { | 726 | if (mtu < 68) { |
| 731 | stats->collisions++; | 727 | stats->collisions++; |
| @@ -784,7 +780,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
| 784 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 780 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
| 785 | IPCB(skb)->flags = 0; | 781 | IPCB(skb)->flags = 0; |
| 786 | skb_dst_drop(skb); | 782 | skb_dst_drop(skb); |
| 787 | skb_dst_set(skb, &rt->u.dst); | 783 | skb_dst_set(skb, &rt->dst); |
| 788 | 784 | ||
| 789 | /* | 785 | /* |
| 790 | * Push down and install the IPIP header. | 786 | * Push down and install the IPIP header. |
| @@ -833,7 +829,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
| 833 | .proto = IPPROTO_IPV6 }; | 829 | .proto = IPPROTO_IPV6 }; |
| 834 | struct rtable *rt; | 830 | struct rtable *rt; |
| 835 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { | 831 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { |
| 836 | tdev = rt->u.dst.dev; | 832 | tdev = rt->dst.dev; |
| 837 | ip_rt_put(rt); | 833 | ip_rt_put(rt); |
| 838 | } | 834 | } |
| 839 | dev->flags |= IFF_POINTOPOINT; | 835 | dev->flags |= IFF_POINTOPOINT; |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 34d1f0690d7e..09fd34f0dbf2 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
| @@ -27,28 +27,17 @@ extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; | |||
| 27 | #define COOKIEBITS 24 /* Upper bits store count */ | 27 | #define COOKIEBITS 24 /* Upper bits store count */ |
| 28 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) | 28 | #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) |
| 29 | 29 | ||
| 30 | /* | 30 | /* Table must be sorted. */ |
| 31 | * This table has to be sorted and terminated with (__u16)-1. | ||
| 32 | * XXX generate a better table. | ||
| 33 | * Unresolved Issues: HIPPI with a 64k MSS is not well supported. | ||
| 34 | * | ||
| 35 | * Taken directly from ipv4 implementation. | ||
| 36 | * Should this list be modified for ipv6 use or is it close enough? | ||
| 37 | * rfc 2460 8.3 suggests mss values 20 bytes less than ipv4 counterpart | ||
| 38 | */ | ||
| 39 | static __u16 const msstab[] = { | 31 | static __u16 const msstab[] = { |
| 40 | 64 - 1, | 32 | 64, |
| 41 | 256 - 1, | 33 | 512, |
| 42 | 512 - 1, | 34 | 536, |
| 43 | 536 - 1, | 35 | 1280 - 60, |
| 44 | 1024 - 1, | 36 | 1480 - 60, |
| 45 | 1440 - 1, | 37 | 1500 - 60, |
| 46 | 1460 - 1, | 38 | 4460 - 60, |
| 47 | 4312 - 1, | 39 | 9000 - 60, |
| 48 | (__u16)-1 | ||
| 49 | }; | 40 | }; |
| 50 | /* The number doesn't include the -1 terminator */ | ||
| 51 | #define NUM_MSS (ARRAY_SIZE(msstab) - 1) | ||
| 52 | 41 | ||
| 53 | /* | 42 | /* |
| 54 | * This (misnamed) value is the age of syncookie which is permitted. | 43 | * This (misnamed) value is the age of syncookie which is permitted. |
| @@ -134,9 +123,11 @@ __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) | |||
| 134 | 123 | ||
| 135 | tcp_synq_overflow(sk); | 124 | tcp_synq_overflow(sk); |
| 136 | 125 | ||
| 137 | for (mssind = 0; mss > msstab[mssind + 1]; mssind++) | 126 | for (mssind = ARRAY_SIZE(msstab) - 1; mssind ; mssind--) |
| 138 | ; | 127 | if (mss >= msstab[mssind]) |
| 139 | *mssp = msstab[mssind] + 1; | 128 | break; |
| 129 | |||
| 130 | *mssp = msstab[mssind]; | ||
| 140 | 131 | ||
| 141 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT); | 132 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT); |
| 142 | 133 | ||
| @@ -154,7 +145,7 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie) | |||
| 154 | th->source, th->dest, seq, | 145 | th->source, th->dest, seq, |
| 155 | jiffies / (HZ * 60), COUNTER_TRIES); | 146 | jiffies / (HZ * 60), COUNTER_TRIES); |
| 156 | 147 | ||
| 157 | return mssind < NUM_MSS ? msstab[mssind] + 1 : 0; | 148 | return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0; |
| 158 | } | 149 | } |
| 159 | 150 | ||
| 160 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | 151 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) |
| @@ -173,8 +164,9 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
| 173 | int mss; | 164 | int mss; |
| 174 | struct dst_entry *dst; | 165 | struct dst_entry *dst; |
| 175 | __u8 rcv_wscale; | 166 | __u8 rcv_wscale; |
| 167 | bool ecn_ok; | ||
| 176 | 168 | ||
| 177 | if (!sysctl_tcp_syncookies || !th->ack) | 169 | if (!sysctl_tcp_syncookies || !th->ack || th->rst) |
| 178 | goto out; | 170 | goto out; |
| 179 | 171 | ||
| 180 | if (tcp_synq_no_recent_overflow(sk) || | 172 | if (tcp_synq_no_recent_overflow(sk) || |
| @@ -189,8 +181,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
| 189 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 181 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
| 190 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); | 182 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); |
| 191 | 183 | ||
| 192 | if (tcp_opt.saw_tstamp) | 184 | if (!cookie_check_timestamp(&tcp_opt, &ecn_ok)) |
| 193 | cookie_check_timestamp(&tcp_opt); | 185 | goto out; |
| 194 | 186 | ||
| 195 | ret = NULL; | 187 | ret = NULL; |
| 196 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | 188 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); |
| @@ -224,9 +216,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
| 224 | 216 | ||
| 225 | req->expires = 0UL; | 217 | req->expires = 0UL; |
| 226 | req->retrans = 0; | 218 | req->retrans = 0; |
| 227 | ireq->ecn_ok = 0; | 219 | ireq->ecn_ok = ecn_ok; |
| 228 | ireq->snd_wscale = tcp_opt.snd_wscale; | 220 | ireq->snd_wscale = tcp_opt.snd_wscale; |
| 229 | ireq->rcv_wscale = tcp_opt.rcv_wscale; | ||
| 230 | ireq->sack_ok = tcp_opt.sack_ok; | 221 | ireq->sack_ok = tcp_opt.sack_ok; |
| 231 | ireq->wscale_ok = tcp_opt.wscale_ok; | 222 | ireq->wscale_ok = tcp_opt.wscale_ok; |
| 232 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | 223 | ireq->tstamp_ok = tcp_opt.saw_tstamp; |
| @@ -240,17 +231,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
| 240 | * me if there is a preferred way. | 231 | * me if there is a preferred way. |
| 241 | */ | 232 | */ |
| 242 | { | 233 | { |
| 243 | struct in6_addr *final_p = NULL, final; | 234 | struct in6_addr *final_p, final; |
| 244 | struct flowi fl; | 235 | struct flowi fl; |
| 245 | memset(&fl, 0, sizeof(fl)); | 236 | memset(&fl, 0, sizeof(fl)); |
| 246 | fl.proto = IPPROTO_TCP; | 237 | fl.proto = IPPROTO_TCP; |
| 247 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); | 238 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); |
| 248 | if (np->opt && np->opt->srcrt) { | 239 | final_p = fl6_update_dst(&fl, np->opt, &final); |
| 249 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; | ||
| 250 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 251 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 252 | final_p = &final; | ||
| 253 | } | ||
| 254 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); | 240 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); |
| 255 | fl.oif = sk->sk_bound_dev_if; | 241 | fl.oif = sk->sk_bound_dev_if; |
| 256 | fl.mark = sk->sk_mark; | 242 | fl.mark = sk->sk_mark; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 2b7c3a100e2c..fe6d40418c0b 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -129,7 +129,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
| 129 | struct inet_connection_sock *icsk = inet_csk(sk); | 129 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 130 | struct ipv6_pinfo *np = inet6_sk(sk); | 130 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 131 | struct tcp_sock *tp = tcp_sk(sk); | 131 | struct tcp_sock *tp = tcp_sk(sk); |
| 132 | struct in6_addr *saddr = NULL, *final_p = NULL, final; | 132 | struct in6_addr *saddr = NULL, *final_p, final; |
| 133 | struct flowi fl; | 133 | struct flowi fl; |
| 134 | struct dst_entry *dst; | 134 | struct dst_entry *dst; |
| 135 | int addr_type; | 135 | int addr_type; |
| @@ -250,12 +250,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
| 250 | fl.fl_ip_dport = usin->sin6_port; | 250 | fl.fl_ip_dport = usin->sin6_port; |
| 251 | fl.fl_ip_sport = inet->inet_sport; | 251 | fl.fl_ip_sport = inet->inet_sport; |
| 252 | 252 | ||
| 253 | if (np->opt && np->opt->srcrt) { | 253 | final_p = fl6_update_dst(&fl, np->opt, &final); |
| 254 | struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; | ||
| 255 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 256 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 257 | final_p = &final; | ||
| 258 | } | ||
| 259 | 254 | ||
| 260 | security_sk_classify_flow(sk, &fl); | 255 | security_sk_classify_flow(sk, &fl); |
| 261 | 256 | ||
| @@ -477,7 +472,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
| 477 | struct ipv6_pinfo *np = inet6_sk(sk); | 472 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 478 | struct sk_buff * skb; | 473 | struct sk_buff * skb; |
| 479 | struct ipv6_txoptions *opt = NULL; | 474 | struct ipv6_txoptions *opt = NULL; |
| 480 | struct in6_addr * final_p = NULL, final; | 475 | struct in6_addr * final_p, final; |
| 481 | struct flowi fl; | 476 | struct flowi fl; |
| 482 | struct dst_entry *dst; | 477 | struct dst_entry *dst; |
| 483 | int err = -1; | 478 | int err = -1; |
| @@ -494,12 +489,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
| 494 | security_req_classify_flow(req, &fl); | 489 | security_req_classify_flow(req, &fl); |
| 495 | 490 | ||
| 496 | opt = np->opt; | 491 | opt = np->opt; |
| 497 | if (opt && opt->srcrt) { | 492 | final_p = fl6_update_dst(&fl, opt, &final); |
| 498 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
| 499 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 500 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 501 | final_p = &final; | ||
| 502 | } | ||
| 503 | 493 | ||
| 504 | err = ip6_dst_lookup(sk, &dst, &fl); | 494 | err = ip6_dst_lookup(sk, &dst, &fl); |
| 505 | if (err) | 495 | if (err) |
| @@ -1167,7 +1157,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
| 1167 | } | 1157 | } |
| 1168 | 1158 | ||
| 1169 | #ifdef CONFIG_SYN_COOKIES | 1159 | #ifdef CONFIG_SYN_COOKIES |
| 1170 | if (!th->rst && !th->syn && th->ack) | 1160 | if (!th->syn) |
| 1171 | sk = cookie_v6_check(sk, skb); | 1161 | sk = cookie_v6_check(sk, skb); |
| 1172 | #endif | 1162 | #endif |
| 1173 | return sk; | 1163 | return sk; |
| @@ -1279,13 +1269,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
| 1279 | treq = inet6_rsk(req); | 1269 | treq = inet6_rsk(req); |
| 1280 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); | 1270 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); |
| 1281 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); | 1271 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); |
| 1282 | if (!want_cookie) | 1272 | if (!want_cookie || tmp_opt.tstamp_ok) |
| 1283 | TCP_ECN_create_request(req, tcp_hdr(skb)); | 1273 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
| 1284 | 1274 | ||
| 1285 | if (want_cookie) { | 1275 | if (!isn) { |
| 1286 | isn = cookie_v6_init_sequence(sk, skb, &req->mss); | ||
| 1287 | req->cookie_ts = tmp_opt.tstamp_ok; | ||
| 1288 | } else if (!isn) { | ||
| 1289 | if (ipv6_opt_accepted(sk, skb) || | 1276 | if (ipv6_opt_accepted(sk, skb) || |
| 1290 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | 1277 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || |
| 1291 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | 1278 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { |
| @@ -1298,8 +1285,12 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
| 1298 | if (!sk->sk_bound_dev_if && | 1285 | if (!sk->sk_bound_dev_if && |
| 1299 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) | 1286 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) |
| 1300 | treq->iif = inet6_iif(skb); | 1287 | treq->iif = inet6_iif(skb); |
| 1301 | 1288 | if (!want_cookie) { | |
| 1302 | isn = tcp_v6_init_sequence(skb); | 1289 | isn = tcp_v6_init_sequence(skb); |
| 1290 | } else { | ||
| 1291 | isn = cookie_v6_init_sequence(sk, skb, &req->mss); | ||
| 1292 | req->cookie_ts = tmp_opt.tstamp_ok; | ||
| 1293 | } | ||
| 1303 | } | 1294 | } |
| 1304 | tcp_rsk(req)->snt_isn = isn; | 1295 | tcp_rsk(req)->snt_isn = isn; |
| 1305 | 1296 | ||
| @@ -1392,18 +1383,13 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
| 1392 | goto out_overflow; | 1383 | goto out_overflow; |
| 1393 | 1384 | ||
| 1394 | if (dst == NULL) { | 1385 | if (dst == NULL) { |
| 1395 | struct in6_addr *final_p = NULL, final; | 1386 | struct in6_addr *final_p, final; |
| 1396 | struct flowi fl; | 1387 | struct flowi fl; |
| 1397 | 1388 | ||
| 1398 | memset(&fl, 0, sizeof(fl)); | 1389 | memset(&fl, 0, sizeof(fl)); |
| 1399 | fl.proto = IPPROTO_TCP; | 1390 | fl.proto = IPPROTO_TCP; |
| 1400 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | 1391 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); |
| 1401 | if (opt && opt->srcrt) { | 1392 | final_p = fl6_update_dst(&fl, opt, &final); |
| 1402 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
| 1403 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 1404 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 1405 | final_p = &final; | ||
| 1406 | } | ||
| 1407 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); | 1393 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); |
| 1408 | fl.oif = sk->sk_bound_dev_if; | 1394 | fl.oif = sk->sk_bound_dev_if; |
| 1409 | fl.mark = sk->sk_mark; | 1395 | fl.mark = sk->sk_mark; |
| @@ -2156,6 +2142,8 @@ struct proto tcpv6_prot = { | |||
| 2156 | .setsockopt = tcp_setsockopt, | 2142 | .setsockopt = tcp_setsockopt, |
| 2157 | .getsockopt = tcp_getsockopt, | 2143 | .getsockopt = tcp_getsockopt, |
| 2158 | .recvmsg = tcp_recvmsg, | 2144 | .recvmsg = tcp_recvmsg, |
| 2145 | .sendmsg = tcp_sendmsg, | ||
| 2146 | .sendpage = tcp_sendpage, | ||
| 2159 | .backlog_rcv = tcp_v6_do_rcv, | 2147 | .backlog_rcv = tcp_v6_do_rcv, |
| 2160 | .hash = tcp_v6_hash, | 2148 | .hash = tcp_v6_hash, |
| 2161 | .unhash = inet_unhash, | 2149 | .unhash = inet_unhash, |
| @@ -2174,6 +2162,7 @@ struct proto tcpv6_prot = { | |||
| 2174 | .twsk_prot = &tcp6_timewait_sock_ops, | 2162 | .twsk_prot = &tcp6_timewait_sock_ops, |
| 2175 | .rsk_prot = &tcp6_request_sock_ops, | 2163 | .rsk_prot = &tcp6_request_sock_ops, |
| 2176 | .h.hashinfo = &tcp_hashinfo, | 2164 | .h.hashinfo = &tcp_hashinfo, |
| 2165 | .no_autobind = true, | ||
| 2177 | #ifdef CONFIG_COMPAT | 2166 | #ifdef CONFIG_COMPAT |
| 2178 | .compat_setsockopt = compat_tcp_setsockopt, | 2167 | .compat_setsockopt = compat_tcp_setsockopt, |
| 2179 | .compat_getsockopt = compat_tcp_getsockopt, | 2168 | .compat_getsockopt = compat_tcp_getsockopt, |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 87be58673b55..1dd1affdead2 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -927,7 +927,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 927 | struct inet_sock *inet = inet_sk(sk); | 927 | struct inet_sock *inet = inet_sk(sk); |
| 928 | struct ipv6_pinfo *np = inet6_sk(sk); | 928 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 929 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; | 929 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; |
| 930 | struct in6_addr *daddr, *final_p = NULL, final; | 930 | struct in6_addr *daddr, *final_p, final; |
| 931 | struct ipv6_txoptions *opt = NULL; | 931 | struct ipv6_txoptions *opt = NULL; |
| 932 | struct ip6_flowlabel *flowlabel = NULL; | 932 | struct ip6_flowlabel *flowlabel = NULL; |
| 933 | struct flowi fl; | 933 | struct flowi fl; |
| @@ -1097,14 +1097,9 @@ do_udp_sendmsg: | |||
| 1097 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 1097 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
| 1098 | fl.fl_ip_sport = inet->inet_sport; | 1098 | fl.fl_ip_sport = inet->inet_sport; |
| 1099 | 1099 | ||
| 1100 | /* merge ip6_build_xmit from ip6_output */ | 1100 | final_p = fl6_update_dst(&fl, opt, &final); |
| 1101 | if (opt && opt->srcrt) { | 1101 | if (final_p) |
| 1102 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
| 1103 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 1104 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 1105 | final_p = &final; | ||
| 1106 | connected = 0; | 1102 | connected = 0; |
| 1107 | } | ||
| 1108 | 1103 | ||
| 1109 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { | 1104 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { |
| 1110 | fl.oif = np->mcast_oif; | 1105 | fl.oif = np->mcast_oif; |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 4a0e77e14468..6baeabbbca82 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
| @@ -124,6 +124,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
| 124 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; | 124 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; |
| 125 | 125 | ||
| 126 | memset(fl, 0, sizeof(struct flowi)); | 126 | memset(fl, 0, sizeof(struct flowi)); |
| 127 | fl->mark = skb->mark; | ||
| 128 | |||
| 127 | ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr); | 129 | ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr); |
| 128 | ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr); | 130 | ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr); |
| 129 | 131 | ||
