diff options
Diffstat (limited to 'net/ipv6')
39 files changed, 774 insertions, 498 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 36806def8cfd..0ba0866230c9 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -630,13 +630,13 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
630 | goto out; | 630 | goto out; |
631 | } | 631 | } |
632 | 632 | ||
633 | rt = addrconf_dst_alloc(idev, addr, 0); | 633 | rt = addrconf_dst_alloc(idev, addr, false); |
634 | if (IS_ERR(rt)) { | 634 | if (IS_ERR(rt)) { |
635 | err = PTR_ERR(rt); | 635 | err = PTR_ERR(rt); |
636 | goto out; | 636 | goto out; |
637 | } | 637 | } |
638 | 638 | ||
639 | ipv6_addr_copy(&ifa->addr, addr); | 639 | ifa->addr = *addr; |
640 | 640 | ||
641 | spin_lock_init(&ifa->lock); | 641 | spin_lock_init(&ifa->lock); |
642 | spin_lock_init(&ifa->state_lock); | 642 | spin_lock_init(&ifa->state_lock); |
@@ -650,16 +650,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
650 | 650 | ||
651 | ifa->rt = rt; | 651 | ifa->rt = rt; |
652 | 652 | ||
653 | /* | ||
654 | * part one of RFC 4429, section 3.3 | ||
655 | * We should not configure an address as | ||
656 | * optimistic if we do not yet know the link | ||
657 | * layer address of our nexhop router | ||
658 | */ | ||
659 | |||
660 | if (dst_get_neighbour_raw(&rt->dst) == NULL) | ||
661 | ifa->flags &= ~IFA_F_OPTIMISTIC; | ||
662 | |||
663 | ifa->idev = idev; | 653 | ifa->idev = idev; |
664 | in6_dev_hold(idev); | 654 | in6_dev_hold(idev); |
665 | /* For caller */ | 655 | /* For caller */ |
@@ -807,7 +797,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
807 | ip6_del_rt(rt); | 797 | ip6_del_rt(rt); |
808 | rt = NULL; | 798 | rt = NULL; |
809 | } else if (!(rt->rt6i_flags & RTF_EXPIRES)) { | 799 | } else if (!(rt->rt6i_flags & RTF_EXPIRES)) { |
810 | rt->rt6i_expires = expires; | 800 | rt->dst.expires = expires; |
811 | rt->rt6i_flags |= RTF_EXPIRES; | 801 | rt->rt6i_flags |= RTF_EXPIRES; |
812 | } | 802 | } |
813 | } | 803 | } |
@@ -1228,7 +1218,7 @@ try_nextdev: | |||
1228 | if (!hiscore->ifa) | 1218 | if (!hiscore->ifa) |
1229 | return -EADDRNOTAVAIL; | 1219 | return -EADDRNOTAVAIL; |
1230 | 1220 | ||
1231 | ipv6_addr_copy(saddr, &hiscore->ifa->addr); | 1221 | *saddr = hiscore->ifa->addr; |
1232 | in6_ifa_put(hiscore->ifa); | 1222 | in6_ifa_put(hiscore->ifa); |
1233 | return 0; | 1223 | return 0; |
1234 | } | 1224 | } |
@@ -1249,7 +1239,7 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | |||
1249 | list_for_each_entry(ifp, &idev->addr_list, if_list) { | 1239 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
1250 | if (ifp->scope == IFA_LINK && | 1240 | if (ifp->scope == IFA_LINK && |
1251 | !(ifp->flags & banned_flags)) { | 1241 | !(ifp->flags & banned_flags)) { |
1252 | ipv6_addr_copy(addr, &ifp->addr); | 1242 | *addr = ifp->addr; |
1253 | err = 0; | 1243 | err = 0; |
1254 | break; | 1244 | break; |
1255 | } | 1245 | } |
@@ -1700,7 +1690,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, | |||
1700 | .fc_protocol = RTPROT_KERNEL, | 1690 | .fc_protocol = RTPROT_KERNEL, |
1701 | }; | 1691 | }; |
1702 | 1692 | ||
1703 | ipv6_addr_copy(&cfg.fc_dst, pfx); | 1693 | cfg.fc_dst = *pfx; |
1704 | 1694 | ||
1705 | /* Prevent useless cloning on PtP SIT. | 1695 | /* Prevent useless cloning on PtP SIT. |
1706 | This thing is done here expecting that the whole | 1696 | This thing is done here expecting that the whole |
@@ -1733,7 +1723,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, | |||
1733 | if (!fn) | 1723 | if (!fn) |
1734 | goto out; | 1724 | goto out; |
1735 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { | 1725 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
1736 | if (rt->rt6i_dev->ifindex != dev->ifindex) | 1726 | if (rt->dst.dev->ifindex != dev->ifindex) |
1737 | continue; | 1727 | continue; |
1738 | if ((rt->rt6i_flags & flags) != flags) | 1728 | if ((rt->rt6i_flags & flags) != flags) |
1739 | continue; | 1729 | continue; |
@@ -1813,7 +1803,7 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) | |||
1813 | return idev; | 1803 | return idev; |
1814 | } | 1804 | } |
1815 | 1805 | ||
1816 | void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | 1806 | void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) |
1817 | { | 1807 | { |
1818 | struct prefix_info *pinfo; | 1808 | struct prefix_info *pinfo; |
1819 | __u32 valid_lft; | 1809 | __u32 valid_lft; |
@@ -1891,11 +1881,11 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1891 | rt = NULL; | 1881 | rt = NULL; |
1892 | } else if (addrconf_finite_timeout(rt_expires)) { | 1882 | } else if (addrconf_finite_timeout(rt_expires)) { |
1893 | /* not infinity */ | 1883 | /* not infinity */ |
1894 | rt->rt6i_expires = jiffies + rt_expires; | 1884 | rt->dst.expires = jiffies + rt_expires; |
1895 | rt->rt6i_flags |= RTF_EXPIRES; | 1885 | rt->rt6i_flags |= RTF_EXPIRES; |
1896 | } else { | 1886 | } else { |
1897 | rt->rt6i_flags &= ~RTF_EXPIRES; | 1887 | rt->rt6i_flags &= ~RTF_EXPIRES; |
1898 | rt->rt6i_expires = 0; | 1888 | rt->dst.expires = 0; |
1899 | } | 1889 | } |
1900 | } else if (valid_lft) { | 1890 | } else if (valid_lft) { |
1901 | clock_t expires = 0; | 1891 | clock_t expires = 0; |
@@ -1944,7 +1934,7 @@ ok: | |||
1944 | 1934 | ||
1945 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 1935 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
1946 | if (in6_dev->cnf.optimistic_dad && | 1936 | if (in6_dev->cnf.optimistic_dad && |
1947 | !net->ipv6.devconf_all->forwarding) | 1937 | !net->ipv6.devconf_all->forwarding && sllao) |
1948 | addr_flags = IFA_F_OPTIMISTIC; | 1938 | addr_flags = IFA_F_OPTIMISTIC; |
1949 | #endif | 1939 | #endif |
1950 | 1940 | ||
@@ -3078,20 +3068,39 @@ static void addrconf_dad_run(struct inet6_dev *idev) | |||
3078 | struct if6_iter_state { | 3068 | struct if6_iter_state { |
3079 | struct seq_net_private p; | 3069 | struct seq_net_private p; |
3080 | int bucket; | 3070 | int bucket; |
3071 | int offset; | ||
3081 | }; | 3072 | }; |
3082 | 3073 | ||
3083 | static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | 3074 | static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos) |
3084 | { | 3075 | { |
3085 | struct inet6_ifaddr *ifa = NULL; | 3076 | struct inet6_ifaddr *ifa = NULL; |
3086 | struct if6_iter_state *state = seq->private; | 3077 | struct if6_iter_state *state = seq->private; |
3087 | struct net *net = seq_file_net(seq); | 3078 | struct net *net = seq_file_net(seq); |
3079 | int p = 0; | ||
3088 | 3080 | ||
3089 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { | 3081 | /* initial bucket if pos is 0 */ |
3082 | if (pos == 0) { | ||
3083 | state->bucket = 0; | ||
3084 | state->offset = 0; | ||
3085 | } | ||
3086 | |||
3087 | for (; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { | ||
3090 | struct hlist_node *n; | 3088 | struct hlist_node *n; |
3091 | hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], | 3089 | hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], |
3092 | addr_lst) | 3090 | addr_lst) { |
3091 | /* sync with offset */ | ||
3092 | if (p < state->offset) { | ||
3093 | p++; | ||
3094 | continue; | ||
3095 | } | ||
3096 | state->offset++; | ||
3093 | if (net_eq(dev_net(ifa->idev->dev), net)) | 3097 | if (net_eq(dev_net(ifa->idev->dev), net)) |
3094 | return ifa; | 3098 | return ifa; |
3099 | } | ||
3100 | |||
3101 | /* prepare for next bucket */ | ||
3102 | state->offset = 0; | ||
3103 | p = 0; | ||
3095 | } | 3104 | } |
3096 | return NULL; | 3105 | return NULL; |
3097 | } | 3106 | } |
@@ -3103,13 +3112,17 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, | |||
3103 | struct net *net = seq_file_net(seq); | 3112 | struct net *net = seq_file_net(seq); |
3104 | struct hlist_node *n = &ifa->addr_lst; | 3113 | struct hlist_node *n = &ifa->addr_lst; |
3105 | 3114 | ||
3106 | hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) | 3115 | hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) { |
3116 | state->offset++; | ||
3107 | if (net_eq(dev_net(ifa->idev->dev), net)) | 3117 | if (net_eq(dev_net(ifa->idev->dev), net)) |
3108 | return ifa; | 3118 | return ifa; |
3119 | } | ||
3109 | 3120 | ||
3110 | while (++state->bucket < IN6_ADDR_HSIZE) { | 3121 | while (++state->bucket < IN6_ADDR_HSIZE) { |
3122 | state->offset = 0; | ||
3111 | hlist_for_each_entry_rcu_bh(ifa, n, | 3123 | hlist_for_each_entry_rcu_bh(ifa, n, |
3112 | &inet6_addr_lst[state->bucket], addr_lst) { | 3124 | &inet6_addr_lst[state->bucket], addr_lst) { |
3125 | state->offset++; | ||
3113 | if (net_eq(dev_net(ifa->idev->dev), net)) | 3126 | if (net_eq(dev_net(ifa->idev->dev), net)) |
3114 | return ifa; | 3127 | return ifa; |
3115 | } | 3128 | } |
@@ -3118,21 +3131,11 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, | |||
3118 | return NULL; | 3131 | return NULL; |
3119 | } | 3132 | } |
3120 | 3133 | ||
3121 | static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | ||
3122 | { | ||
3123 | struct inet6_ifaddr *ifa = if6_get_first(seq); | ||
3124 | |||
3125 | if (ifa) | ||
3126 | while (pos && (ifa = if6_get_next(seq, ifa)) != NULL) | ||
3127 | --pos; | ||
3128 | return pos ? NULL : ifa; | ||
3129 | } | ||
3130 | |||
3131 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) | 3134 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) |
3132 | __acquires(rcu_bh) | 3135 | __acquires(rcu_bh) |
3133 | { | 3136 | { |
3134 | rcu_read_lock_bh(); | 3137 | rcu_read_lock_bh(); |
3135 | return if6_get_idx(seq, *pos); | 3138 | return if6_get_first(seq, *pos); |
3136 | } | 3139 | } |
3137 | 3140 | ||
3138 | static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 3141 | static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index d27c797f9f05..273f48d1df2e 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -347,7 +347,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
347 | */ | 347 | */ |
348 | v4addr = LOOPBACK4_IPV6; | 348 | v4addr = LOOPBACK4_IPV6; |
349 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { | 349 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { |
350 | if (!inet->transparent && | 350 | if (!(inet->freebind || inet->transparent) && |
351 | !ipv6_chk_addr(net, &addr->sin6_addr, | 351 | !ipv6_chk_addr(net, &addr->sin6_addr, |
352 | dev, 0)) { | 352 | dev, 0)) { |
353 | err = -EADDRNOTAVAIL; | 353 | err = -EADDRNOTAVAIL; |
@@ -361,10 +361,10 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
361 | inet->inet_rcv_saddr = v4addr; | 361 | inet->inet_rcv_saddr = v4addr; |
362 | inet->inet_saddr = v4addr; | 362 | inet->inet_saddr = v4addr; |
363 | 363 | ||
364 | ipv6_addr_copy(&np->rcv_saddr, &addr->sin6_addr); | 364 | np->rcv_saddr = addr->sin6_addr; |
365 | 365 | ||
366 | if (!(addr_type & IPV6_ADDR_MULTICAST)) | 366 | if (!(addr_type & IPV6_ADDR_MULTICAST)) |
367 | ipv6_addr_copy(&np->saddr, &addr->sin6_addr); | 367 | np->saddr = addr->sin6_addr; |
368 | 368 | ||
369 | /* Make sure we are allowed to bind here. */ | 369 | /* Make sure we are allowed to bind here. */ |
370 | if (sk->sk_prot->get_port(sk, snum)) { | 370 | if (sk->sk_prot->get_port(sk, snum)) { |
@@ -458,14 +458,14 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr, | |||
458 | peer == 1) | 458 | peer == 1) |
459 | return -ENOTCONN; | 459 | return -ENOTCONN; |
460 | sin->sin6_port = inet->inet_dport; | 460 | sin->sin6_port = inet->inet_dport; |
461 | ipv6_addr_copy(&sin->sin6_addr, &np->daddr); | 461 | sin->sin6_addr = np->daddr; |
462 | if (np->sndflow) | 462 | if (np->sndflow) |
463 | sin->sin6_flowinfo = np->flow_label; | 463 | sin->sin6_flowinfo = np->flow_label; |
464 | } else { | 464 | } else { |
465 | if (ipv6_addr_any(&np->rcv_saddr)) | 465 | if (ipv6_addr_any(&np->rcv_saddr)) |
466 | ipv6_addr_copy(&sin->sin6_addr, &np->saddr); | 466 | sin->sin6_addr = np->saddr; |
467 | else | 467 | else |
468 | ipv6_addr_copy(&sin->sin6_addr, &np->rcv_saddr); | 468 | sin->sin6_addr = np->rcv_saddr; |
469 | 469 | ||
470 | sin->sin6_port = inet->inet_sport; | 470 | sin->sin6_port = inet->inet_sport; |
471 | } | 471 | } |
@@ -660,8 +660,8 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
660 | 660 | ||
661 | memset(&fl6, 0, sizeof(fl6)); | 661 | memset(&fl6, 0, sizeof(fl6)); |
662 | fl6.flowi6_proto = sk->sk_protocol; | 662 | fl6.flowi6_proto = sk->sk_protocol; |
663 | ipv6_addr_copy(&fl6.daddr, &np->daddr); | 663 | fl6.daddr = np->daddr; |
664 | ipv6_addr_copy(&fl6.saddr, &np->saddr); | 664 | fl6.saddr = np->saddr; |
665 | fl6.flowlabel = np->flow_label; | 665 | fl6.flowlabel = np->flow_label; |
666 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 666 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
667 | fl6.flowi6_mark = sk->sk_mark; | 667 | fl6.flowi6_mark = sk->sk_mark; |
@@ -769,7 +769,8 @@ out: | |||
769 | return err; | 769 | return err; |
770 | } | 770 | } |
771 | 771 | ||
772 | static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, u32 features) | 772 | static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, |
773 | netdev_features_t features) | ||
773 | { | 774 | { |
774 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 775 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
775 | struct ipv6hdr *ipv6h; | 776 | struct ipv6hdr *ipv6h; |
@@ -985,9 +986,9 @@ static int __net_init ipv6_init_mibs(struct net *net) | |||
985 | sizeof(struct icmpv6_mib), | 986 | sizeof(struct icmpv6_mib), |
986 | __alignof__(struct icmpv6_mib)) < 0) | 987 | __alignof__(struct icmpv6_mib)) < 0) |
987 | goto err_icmp_mib; | 988 | goto err_icmp_mib; |
988 | if (snmp_mib_init((void __percpu **)net->mib.icmpv6msg_statistics, | 989 | net->mib.icmpv6msg_statistics = kzalloc(sizeof(struct icmpv6msg_mib), |
989 | sizeof(struct icmpv6msg_mib), | 990 | GFP_KERNEL); |
990 | __alignof__(struct icmpv6msg_mib)) < 0) | 991 | if (!net->mib.icmpv6msg_statistics) |
991 | goto err_icmpmsg_mib; | 992 | goto err_icmpmsg_mib; |
992 | return 0; | 993 | return 0; |
993 | 994 | ||
@@ -1008,7 +1009,7 @@ static void ipv6_cleanup_mibs(struct net *net) | |||
1008 | snmp_mib_free((void __percpu **)net->mib.udplite_stats_in6); | 1009 | snmp_mib_free((void __percpu **)net->mib.udplite_stats_in6); |
1009 | snmp_mib_free((void __percpu **)net->mib.ipv6_statistics); | 1010 | snmp_mib_free((void __percpu **)net->mib.ipv6_statistics); |
1010 | snmp_mib_free((void __percpu **)net->mib.icmpv6_statistics); | 1011 | snmp_mib_free((void __percpu **)net->mib.icmpv6_statistics); |
1011 | snmp_mib_free((void __percpu **)net->mib.icmpv6msg_statistics); | 1012 | kfree(net->mib.icmpv6msg_statistics); |
1012 | } | 1013 | } |
1013 | 1014 | ||
1014 | static int __net_init inet6_net_init(struct net *net) | 1015 | static int __net_init inet6_net_init(struct net *net) |
@@ -1115,6 +1116,8 @@ static int __init inet6_init(void) | |||
1115 | if (err) | 1116 | if (err) |
1116 | goto static_sysctl_fail; | 1117 | goto static_sysctl_fail; |
1117 | #endif | 1118 | #endif |
1119 | tcpv6_prot.sysctl_mem = init_net.ipv4.sysctl_tcp_mem; | ||
1120 | |||
1118 | /* | 1121 | /* |
1119 | * ipngwg API draft makes clear that the correct semantics | 1122 | * ipngwg API draft makes clear that the correct semantics |
1120 | * for TCP and UDP is to consider one TCP and UDP instance | 1123 | * for TCP and UDP is to consider one TCP and UDP instance |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 4c0f894d0843..2ae79dbeec2f 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -193,9 +193,9 @@ static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *des | |||
193 | printk(KERN_WARNING "destopt hao: invalid header length: %u\n", hao->length); | 193 | printk(KERN_WARNING "destopt hao: invalid header length: %u\n", hao->length); |
194 | goto bad; | 194 | goto bad; |
195 | } | 195 | } |
196 | ipv6_addr_copy(&final_addr, &hao->addr); | 196 | final_addr = hao->addr; |
197 | ipv6_addr_copy(&hao->addr, &iph->saddr); | 197 | hao->addr = iph->saddr; |
198 | ipv6_addr_copy(&iph->saddr, &final_addr); | 198 | iph->saddr = final_addr; |
199 | } | 199 | } |
200 | break; | 200 | break; |
201 | } | 201 | } |
@@ -241,13 +241,13 @@ static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr) | |||
241 | segments = rthdr->hdrlen >> 1; | 241 | segments = rthdr->hdrlen >> 1; |
242 | 242 | ||
243 | addrs = ((struct rt0_hdr *)rthdr)->addr; | 243 | addrs = ((struct rt0_hdr *)rthdr)->addr; |
244 | ipv6_addr_copy(&final_addr, addrs + segments - 1); | 244 | final_addr = addrs[segments - 1]; |
245 | 245 | ||
246 | addrs += segments - segments_left; | 246 | addrs += segments - segments_left; |
247 | memmove(addrs + 1, addrs, (segments_left - 1) * sizeof(*addrs)); | 247 | memmove(addrs + 1, addrs, (segments_left - 1) * sizeof(*addrs)); |
248 | 248 | ||
249 | ipv6_addr_copy(addrs, &iph->daddr); | 249 | addrs[0] = iph->daddr; |
250 | ipv6_addr_copy(&iph->daddr, &final_addr); | 250 | iph->daddr = final_addr; |
251 | } | 251 | } |
252 | 252 | ||
253 | static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir) | 253 | static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir) |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 674255f5e6b7..59402b4637f9 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -75,7 +75,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
75 | if (pac == NULL) | 75 | if (pac == NULL) |
76 | return -ENOMEM; | 76 | return -ENOMEM; |
77 | pac->acl_next = NULL; | 77 | pac->acl_next = NULL; |
78 | ipv6_addr_copy(&pac->acl_addr, addr); | 78 | pac->acl_addr = *addr; |
79 | 79 | ||
80 | rcu_read_lock(); | 80 | rcu_read_lock(); |
81 | if (ifindex == 0) { | 81 | if (ifindex == 0) { |
@@ -83,7 +83,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
83 | 83 | ||
84 | rt = rt6_lookup(net, addr, NULL, 0, 0); | 84 | rt = rt6_lookup(net, addr, NULL, 0, 0); |
85 | if (rt) { | 85 | if (rt) { |
86 | dev = rt->rt6i_dev; | 86 | dev = rt->dst.dev; |
87 | dst_release(&rt->dst); | 87 | dst_release(&rt->dst); |
88 | } else if (ishost) { | 88 | } else if (ishost) { |
89 | err = -EADDRNOTAVAIL; | 89 | err = -EADDRNOTAVAIL; |
@@ -289,14 +289,14 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr) | |||
289 | goto out; | 289 | goto out; |
290 | } | 290 | } |
291 | 291 | ||
292 | rt = addrconf_dst_alloc(idev, addr, 1); | 292 | rt = addrconf_dst_alloc(idev, addr, true); |
293 | if (IS_ERR(rt)) { | 293 | if (IS_ERR(rt)) { |
294 | kfree(aca); | 294 | kfree(aca); |
295 | err = PTR_ERR(rt); | 295 | err = PTR_ERR(rt); |
296 | goto out; | 296 | goto out; |
297 | } | 297 | } |
298 | 298 | ||
299 | ipv6_addr_copy(&aca->aca_addr, addr); | 299 | aca->aca_addr = *addr; |
300 | aca->aca_idev = idev; | 300 | aca->aca_idev = idev; |
301 | aca->aca_rt = rt; | 301 | aca->aca_rt = rt; |
302 | aca->aca_users = 1; | 302 | aca->aca_users = 1; |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index e2480691c220..ae08aee1773c 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -71,7 +71,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
71 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 71 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
72 | if (flowlabel == NULL) | 72 | if (flowlabel == NULL) |
73 | return -EINVAL; | 73 | return -EINVAL; |
74 | ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); | 74 | usin->sin6_addr = flowlabel->dst; |
75 | } | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
@@ -143,7 +143,7 @@ ipv4_connected: | |||
143 | } | 143 | } |
144 | } | 144 | } |
145 | 145 | ||
146 | ipv6_addr_copy(&np->daddr, daddr); | 146 | np->daddr = *daddr; |
147 | np->flow_label = fl6.flowlabel; | 147 | np->flow_label = fl6.flowlabel; |
148 | 148 | ||
149 | inet->inet_dport = usin->sin6_port; | 149 | inet->inet_dport = usin->sin6_port; |
@@ -154,8 +154,8 @@ ipv4_connected: | |||
154 | */ | 154 | */ |
155 | 155 | ||
156 | fl6.flowi6_proto = sk->sk_protocol; | 156 | fl6.flowi6_proto = sk->sk_protocol; |
157 | ipv6_addr_copy(&fl6.daddr, &np->daddr); | 157 | fl6.daddr = np->daddr; |
158 | ipv6_addr_copy(&fl6.saddr, &np->saddr); | 158 | fl6.saddr = np->saddr; |
159 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 159 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
160 | fl6.flowi6_mark = sk->sk_mark; | 160 | fl6.flowi6_mark = sk->sk_mark; |
161 | fl6.fl6_dport = inet->inet_dport; | 161 | fl6.fl6_dport = inet->inet_dport; |
@@ -179,10 +179,10 @@ ipv4_connected: | |||
179 | /* source address lookup done in ip6_dst_lookup */ | 179 | /* source address lookup done in ip6_dst_lookup */ |
180 | 180 | ||
181 | if (ipv6_addr_any(&np->saddr)) | 181 | if (ipv6_addr_any(&np->saddr)) |
182 | ipv6_addr_copy(&np->saddr, &fl6.saddr); | 182 | np->saddr = fl6.saddr; |
183 | 183 | ||
184 | if (ipv6_addr_any(&np->rcv_saddr)) { | 184 | if (ipv6_addr_any(&np->rcv_saddr)) { |
185 | ipv6_addr_copy(&np->rcv_saddr, &fl6.saddr); | 185 | np->rcv_saddr = fl6.saddr; |
186 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; | 186 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; |
187 | if (sk->sk_prot->rehash) | 187 | if (sk->sk_prot->rehash) |
188 | sk->sk_prot->rehash(sk); | 188 | sk->sk_prot->rehash(sk); |
@@ -257,7 +257,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info) | |||
257 | skb_put(skb, sizeof(struct ipv6hdr)); | 257 | skb_put(skb, sizeof(struct ipv6hdr)); |
258 | skb_reset_network_header(skb); | 258 | skb_reset_network_header(skb); |
259 | iph = ipv6_hdr(skb); | 259 | iph = ipv6_hdr(skb); |
260 | ipv6_addr_copy(&iph->daddr, &fl6->daddr); | 260 | iph->daddr = fl6->daddr; |
261 | 261 | ||
262 | serr = SKB_EXT_ERR(skb); | 262 | serr = SKB_EXT_ERR(skb); |
263 | serr->ee.ee_errno = err; | 263 | serr->ee.ee_errno = err; |
@@ -294,7 +294,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu) | |||
294 | skb_put(skb, sizeof(struct ipv6hdr)); | 294 | skb_put(skb, sizeof(struct ipv6hdr)); |
295 | skb_reset_network_header(skb); | 295 | skb_reset_network_header(skb); |
296 | iph = ipv6_hdr(skb); | 296 | iph = ipv6_hdr(skb); |
297 | ipv6_addr_copy(&iph->daddr, &fl6->daddr); | 297 | iph->daddr = fl6->daddr; |
298 | 298 | ||
299 | mtu_info = IP6CBMTU(skb); | 299 | mtu_info = IP6CBMTU(skb); |
300 | 300 | ||
@@ -303,7 +303,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu) | |||
303 | mtu_info->ip6m_addr.sin6_port = 0; | 303 | mtu_info->ip6m_addr.sin6_port = 0; |
304 | mtu_info->ip6m_addr.sin6_flowinfo = 0; | 304 | mtu_info->ip6m_addr.sin6_flowinfo = 0; |
305 | mtu_info->ip6m_addr.sin6_scope_id = fl6->flowi6_oif; | 305 | mtu_info->ip6m_addr.sin6_scope_id = fl6->flowi6_oif; |
306 | ipv6_addr_copy(&mtu_info->ip6m_addr.sin6_addr, &ipv6_hdr(skb)->daddr); | 306 | mtu_info->ip6m_addr.sin6_addr = ipv6_hdr(skb)->daddr; |
307 | 307 | ||
308 | __skb_pull(skb, skb_tail_pointer(skb) - skb->data); | 308 | __skb_pull(skb, skb_tail_pointer(skb) - skb->data); |
309 | skb_reset_transport_header(skb); | 309 | skb_reset_transport_header(skb); |
@@ -354,8 +354,8 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
354 | sin->sin6_port = serr->port; | 354 | sin->sin6_port = serr->port; |
355 | sin->sin6_scope_id = 0; | 355 | sin->sin6_scope_id = 0; |
356 | if (skb->protocol == htons(ETH_P_IPV6)) { | 356 | if (skb->protocol == htons(ETH_P_IPV6)) { |
357 | ipv6_addr_copy(&sin->sin6_addr, | 357 | sin->sin6_addr = |
358 | (struct in6_addr *)(nh + serr->addr_offset)); | 358 | *(struct in6_addr *)(nh + serr->addr_offset); |
359 | if (np->sndflow) | 359 | if (np->sndflow) |
360 | sin->sin6_flowinfo = | 360 | sin->sin6_flowinfo = |
361 | (*(__be32 *)(nh + serr->addr_offset - 24) & | 361 | (*(__be32 *)(nh + serr->addr_offset - 24) & |
@@ -376,7 +376,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
376 | sin->sin6_flowinfo = 0; | 376 | sin->sin6_flowinfo = 0; |
377 | sin->sin6_scope_id = 0; | 377 | sin->sin6_scope_id = 0; |
378 | if (skb->protocol == htons(ETH_P_IPV6)) { | 378 | if (skb->protocol == htons(ETH_P_IPV6)) { |
379 | ipv6_addr_copy(&sin->sin6_addr, &ipv6_hdr(skb)->saddr); | 379 | sin->sin6_addr = ipv6_hdr(skb)->saddr; |
380 | if (np->rxopt.all) | 380 | if (np->rxopt.all) |
381 | datagram_recv_ctl(sk, msg, skb); | 381 | datagram_recv_ctl(sk, msg, skb); |
382 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 382 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
@@ -451,7 +451,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) | |||
451 | sin->sin6_flowinfo = 0; | 451 | sin->sin6_flowinfo = 0; |
452 | sin->sin6_port = 0; | 452 | sin->sin6_port = 0; |
453 | sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id; | 453 | sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id; |
454 | ipv6_addr_copy(&sin->sin6_addr, &mtu_info.ip6m_addr.sin6_addr); | 454 | sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr; |
455 | } | 455 | } |
456 | 456 | ||
457 | put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info); | 457 | put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info); |
@@ -475,7 +475,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
475 | struct in6_pktinfo src_info; | 475 | struct in6_pktinfo src_info; |
476 | 476 | ||
477 | src_info.ipi6_ifindex = opt->iif; | 477 | src_info.ipi6_ifindex = opt->iif; |
478 | ipv6_addr_copy(&src_info.ipi6_addr, &ipv6_hdr(skb)->daddr); | 478 | src_info.ipi6_addr = ipv6_hdr(skb)->daddr; |
479 | put_cmsg(msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); | 479 | put_cmsg(msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); |
480 | } | 480 | } |
481 | 481 | ||
@@ -550,7 +550,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
550 | struct in6_pktinfo src_info; | 550 | struct in6_pktinfo src_info; |
551 | 551 | ||
552 | src_info.ipi6_ifindex = opt->iif; | 552 | src_info.ipi6_ifindex = opt->iif; |
553 | ipv6_addr_copy(&src_info.ipi6_addr, &ipv6_hdr(skb)->daddr); | 553 | src_info.ipi6_addr = ipv6_hdr(skb)->daddr; |
554 | put_cmsg(msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); | 554 | put_cmsg(msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); |
555 | } | 555 | } |
556 | if (np->rxopt.bits.rxohlim) { | 556 | if (np->rxopt.bits.rxohlim) { |
@@ -584,7 +584,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
584 | */ | 584 | */ |
585 | 585 | ||
586 | sin6.sin6_family = AF_INET6; | 586 | sin6.sin6_family = AF_INET6; |
587 | ipv6_addr_copy(&sin6.sin6_addr, &ipv6_hdr(skb)->daddr); | 587 | sin6.sin6_addr = ipv6_hdr(skb)->daddr; |
588 | sin6.sin6_port = ports[1]; | 588 | sin6.sin6_port = ports[1]; |
589 | sin6.sin6_flowinfo = 0; | 589 | sin6.sin6_flowinfo = 0; |
590 | sin6.sin6_scope_id = 0; | 590 | sin6.sin6_scope_id = 0; |
@@ -654,12 +654,12 @@ int datagram_send_ctl(struct net *net, struct sock *sk, | |||
654 | 654 | ||
655 | if (addr_type != IPV6_ADDR_ANY) { | 655 | if (addr_type != IPV6_ADDR_ANY) { |
656 | int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; | 656 | int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; |
657 | if (!inet_sk(sk)->transparent && | 657 | if (!(inet_sk(sk)->freebind || inet_sk(sk)->transparent) && |
658 | !ipv6_chk_addr(net, &src_info->ipi6_addr, | 658 | !ipv6_chk_addr(net, &src_info->ipi6_addr, |
659 | strict ? dev : NULL, 0)) | 659 | strict ? dev : NULL, 0)) |
660 | err = -EINVAL; | 660 | err = -EINVAL; |
661 | else | 661 | else |
662 | ipv6_addr_copy(&fl6->saddr, &src_info->ipi6_addr); | 662 | fl6->saddr = src_info->ipi6_addr; |
663 | } | 663 | } |
664 | 664 | ||
665 | rcu_read_unlock(); | 665 | rcu_read_unlock(); |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index bf22a225f422..3d641b6e9b09 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -243,9 +243,9 @@ static int ipv6_dest_hao(struct sk_buff *skb, int optoff) | |||
243 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 243 | if (skb->ip_summed == CHECKSUM_COMPLETE) |
244 | skb->ip_summed = CHECKSUM_NONE; | 244 | skb->ip_summed = CHECKSUM_NONE; |
245 | 245 | ||
246 | ipv6_addr_copy(&tmp_addr, &ipv6h->saddr); | 246 | tmp_addr = ipv6h->saddr; |
247 | ipv6_addr_copy(&ipv6h->saddr, &hao->addr); | 247 | ipv6h->saddr = hao->addr; |
248 | ipv6_addr_copy(&hao->addr, &tmp_addr); | 248 | hao->addr = tmp_addr; |
249 | 249 | ||
250 | if (skb->tstamp.tv64 == 0) | 250 | if (skb->tstamp.tv64 == 0) |
251 | __net_timestamp(skb); | 251 | __net_timestamp(skb); |
@@ -461,9 +461,9 @@ looped_back: | |||
461 | return -1; | 461 | return -1; |
462 | } | 462 | } |
463 | 463 | ||
464 | ipv6_addr_copy(&daddr, addr); | 464 | daddr = *addr; |
465 | ipv6_addr_copy(addr, &ipv6_hdr(skb)->daddr); | 465 | *addr = ipv6_hdr(skb)->daddr; |
466 | ipv6_addr_copy(&ipv6_hdr(skb)->daddr, &daddr); | 466 | ipv6_hdr(skb)->daddr = daddr; |
467 | 467 | ||
468 | skb_dst_drop(skb); | 468 | skb_dst_drop(skb); |
469 | ip6_route_input(skb); | 469 | ip6_route_input(skb); |
@@ -690,7 +690,7 @@ static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto, | |||
690 | memcpy(phdr->addr, ihdr->addr + 1, | 690 | memcpy(phdr->addr, ihdr->addr + 1, |
691 | (hops - 1) * sizeof(struct in6_addr)); | 691 | (hops - 1) * sizeof(struct in6_addr)); |
692 | 692 | ||
693 | ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p); | 693 | phdr->addr[hops - 1] = **addr_p; |
694 | *addr_p = ihdr->addr; | 694 | *addr_p = ihdr->addr; |
695 | 695 | ||
696 | phdr->rt_hdr.nexthdr = *proto; | 696 | phdr->rt_hdr.nexthdr = *proto; |
@@ -888,8 +888,8 @@ struct in6_addr *fl6_update_dst(struct flowi6 *fl6, | |||
888 | if (!opt || !opt->srcrt) | 888 | if (!opt || !opt->srcrt) |
889 | return NULL; | 889 | return NULL; |
890 | 890 | ||
891 | ipv6_addr_copy(orig, &fl6->daddr); | 891 | *orig = fl6->daddr; |
892 | ipv6_addr_copy(&fl6->daddr, ((struct rt0_hdr *)opt->srcrt)->addr); | 892 | fl6->daddr = *((struct rt0_hdr *)opt->srcrt)->addr; |
893 | return orig; | 893 | return orig; |
894 | } | 894 | } |
895 | 895 | ||
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 37f548b7f6dc..72957f4a7c6c 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c | |||
@@ -57,6 +57,9 @@ int ipv6_ext_hdr(u8 nexthdr) | |||
57 | * it returns NULL. | 57 | * it returns NULL. |
58 | * - First fragment header is skipped, not-first ones | 58 | * - First fragment header is skipped, not-first ones |
59 | * are considered as unparsable. | 59 | * are considered as unparsable. |
60 | * - Reports the offset field of the final fragment header so it is | ||
61 | * possible to tell whether this is a first fragment, later fragment, | ||
62 | * or not fragmented. | ||
60 | * - ESP is unparsable for now and considered like | 63 | * - ESP is unparsable for now and considered like |
61 | * normal payload protocol. | 64 | * normal payload protocol. |
62 | * - Note also special handling of AUTH header. Thanks to IPsec wizards. | 65 | * - Note also special handling of AUTH header. Thanks to IPsec wizards. |
@@ -64,10 +67,13 @@ int ipv6_ext_hdr(u8 nexthdr) | |||
64 | * --ANK (980726) | 67 | * --ANK (980726) |
65 | */ | 68 | */ |
66 | 69 | ||
67 | int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp) | 70 | int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, |
71 | __be16 *frag_offp) | ||
68 | { | 72 | { |
69 | u8 nexthdr = *nexthdrp; | 73 | u8 nexthdr = *nexthdrp; |
70 | 74 | ||
75 | *frag_offp = 0; | ||
76 | |||
71 | while (ipv6_ext_hdr(nexthdr)) { | 77 | while (ipv6_ext_hdr(nexthdr)) { |
72 | struct ipv6_opt_hdr _hdr, *hp; | 78 | struct ipv6_opt_hdr _hdr, *hp; |
73 | int hdrlen; | 79 | int hdrlen; |
@@ -87,7 +93,8 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp) | |||
87 | if (fp == NULL) | 93 | if (fp == NULL) |
88 | return -1; | 94 | return -1; |
89 | 95 | ||
90 | if (ntohs(*fp) & ~0x7) | 96 | *frag_offp = *fp; |
97 | if (ntohs(*frag_offp) & ~0x7) | ||
91 | break; | 98 | break; |
92 | hdrlen = 8; | 99 | hdrlen = 8; |
93 | } else if (nexthdr == NEXTHDR_AUTH) | 100 | } else if (nexthdr == NEXTHDR_AUTH) |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 295571576f83..b6c573152067 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -96,7 +96,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
96 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, | 96 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, |
97 | r->src.plen)) | 97 | r->src.plen)) |
98 | goto again; | 98 | goto again; |
99 | ipv6_addr_copy(&flp6->saddr, &saddr); | 99 | flp6->saddr = saddr; |
100 | } | 100 | } |
101 | goto out; | 101 | goto out; |
102 | } | 102 | } |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 90868fb42757..01d46bff63c3 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -135,11 +135,12 @@ static int is_ineligible(struct sk_buff *skb) | |||
135 | int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; | 135 | int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; |
136 | int len = skb->len - ptr; | 136 | int len = skb->len - ptr; |
137 | __u8 nexthdr = ipv6_hdr(skb)->nexthdr; | 137 | __u8 nexthdr = ipv6_hdr(skb)->nexthdr; |
138 | __be16 frag_off; | ||
138 | 139 | ||
139 | if (len < 0) | 140 | if (len < 0) |
140 | return 1; | 141 | return 1; |
141 | 142 | ||
142 | ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr); | 143 | ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, &frag_off); |
143 | if (ptr < 0) | 144 | if (ptr < 0) |
144 | return 0; | 145 | return 0; |
145 | if (nexthdr == IPPROTO_ICMPV6) { | 146 | if (nexthdr == IPPROTO_ICMPV6) { |
@@ -290,9 +291,9 @@ static void mip6_addr_swap(struct sk_buff *skb) | |||
290 | if (likely(off >= 0)) { | 291 | if (likely(off >= 0)) { |
291 | hao = (struct ipv6_destopt_hao *) | 292 | hao = (struct ipv6_destopt_hao *) |
292 | (skb_network_header(skb) + off); | 293 | (skb_network_header(skb) + off); |
293 | ipv6_addr_copy(&tmp, &iph->saddr); | 294 | tmp = iph->saddr; |
294 | ipv6_addr_copy(&iph->saddr, &hao->addr); | 295 | iph->saddr = hao->addr; |
295 | ipv6_addr_copy(&hao->addr, &tmp); | 296 | hao->addr = tmp; |
296 | } | 297 | } |
297 | } | 298 | } |
298 | } | 299 | } |
@@ -444,9 +445,9 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
444 | 445 | ||
445 | memset(&fl6, 0, sizeof(fl6)); | 446 | memset(&fl6, 0, sizeof(fl6)); |
446 | fl6.flowi6_proto = IPPROTO_ICMPV6; | 447 | fl6.flowi6_proto = IPPROTO_ICMPV6; |
447 | ipv6_addr_copy(&fl6.daddr, &hdr->saddr); | 448 | fl6.daddr = hdr->saddr; |
448 | if (saddr) | 449 | if (saddr) |
449 | ipv6_addr_copy(&fl6.saddr, saddr); | 450 | fl6.saddr = *saddr; |
450 | fl6.flowi6_oif = iif; | 451 | fl6.flowi6_oif = iif; |
451 | fl6.fl6_icmp_type = type; | 452 | fl6.fl6_icmp_type = type; |
452 | fl6.fl6_icmp_code = code; | 453 | fl6.fl6_icmp_code = code; |
@@ -538,9 +539,9 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
538 | 539 | ||
539 | memset(&fl6, 0, sizeof(fl6)); | 540 | memset(&fl6, 0, sizeof(fl6)); |
540 | fl6.flowi6_proto = IPPROTO_ICMPV6; | 541 | fl6.flowi6_proto = IPPROTO_ICMPV6; |
541 | ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->saddr); | 542 | fl6.daddr = ipv6_hdr(skb)->saddr; |
542 | if (saddr) | 543 | if (saddr) |
543 | ipv6_addr_copy(&fl6.saddr, saddr); | 544 | fl6.saddr = *saddr; |
544 | fl6.flowi6_oif = skb->dev->ifindex; | 545 | fl6.flowi6_oif = skb->dev->ifindex; |
545 | fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY; | 546 | fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY; |
546 | security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); | 547 | security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); |
@@ -596,6 +597,7 @@ static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
596 | int inner_offset; | 597 | int inner_offset; |
597 | int hash; | 598 | int hash; |
598 | u8 nexthdr; | 599 | u8 nexthdr; |
600 | __be16 frag_off; | ||
599 | 601 | ||
600 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 602 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
601 | return; | 603 | return; |
@@ -603,7 +605,8 @@ static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
603 | nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; | 605 | nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; |
604 | if (ipv6_ext_hdr(nexthdr)) { | 606 | if (ipv6_ext_hdr(nexthdr)) { |
605 | /* now skip over extension headers */ | 607 | /* now skip over extension headers */ |
606 | inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr); | 608 | inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), |
609 | &nexthdr, &frag_off); | ||
607 | if (inner_offset<0) | 610 | if (inner_offset<0) |
608 | return; | 611 | return; |
609 | } else { | 612 | } else { |
@@ -786,8 +789,8 @@ void icmpv6_flow_init(struct sock *sk, struct flowi6 *fl6, | |||
786 | int oif) | 789 | int oif) |
787 | { | 790 | { |
788 | memset(fl6, 0, sizeof(*fl6)); | 791 | memset(fl6, 0, sizeof(*fl6)); |
789 | ipv6_addr_copy(&fl6->saddr, saddr); | 792 | fl6->saddr = *saddr; |
790 | ipv6_addr_copy(&fl6->daddr, daddr); | 793 | fl6->daddr = *daddr; |
791 | fl6->flowi6_proto = IPPROTO_ICMPV6; | 794 | fl6->flowi6_proto = IPPROTO_ICMPV6; |
792 | fl6->fl6_icmp_type = type; | 795 | fl6->fl6_icmp_type = type; |
793 | fl6->fl6_icmp_code = 0; | 796 | fl6->fl6_icmp_code = 0; |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 1567fb120392..02dd203d9eac 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -65,9 +65,9 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk, | |||
65 | 65 | ||
66 | memset(&fl6, 0, sizeof(fl6)); | 66 | memset(&fl6, 0, sizeof(fl6)); |
67 | fl6.flowi6_proto = IPPROTO_TCP; | 67 | fl6.flowi6_proto = IPPROTO_TCP; |
68 | ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr); | 68 | fl6.daddr = treq->rmt_addr; |
69 | final_p = fl6_update_dst(&fl6, np->opt, &final); | 69 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
70 | ipv6_addr_copy(&fl6.saddr, &treq->loc_addr); | 70 | fl6.saddr = treq->loc_addr; |
71 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 71 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
72 | fl6.flowi6_mark = sk->sk_mark; | 72 | fl6.flowi6_mark = sk->sk_mark; |
73 | fl6.fl6_dport = inet_rsk(req)->rmt_port; | 73 | fl6.fl6_dport = inet_rsk(req)->rmt_port; |
@@ -157,7 +157,7 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr) | |||
157 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) uaddr; | 157 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) uaddr; |
158 | 158 | ||
159 | sin6->sin6_family = AF_INET6; | 159 | sin6->sin6_family = AF_INET6; |
160 | ipv6_addr_copy(&sin6->sin6_addr, &np->daddr); | 160 | sin6->sin6_addr = np->daddr; |
161 | sin6->sin6_port = inet_sk(sk)->inet_dport; | 161 | sin6->sin6_port = inet_sk(sk)->inet_dport; |
162 | /* We do not store received flowlabel for TCP */ | 162 | /* We do not store received flowlabel for TCP */ |
163 | sin6->sin6_flowinfo = 0; | 163 | sin6->sin6_flowinfo = 0; |
@@ -215,8 +215,8 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) | |||
215 | 215 | ||
216 | memset(&fl6, 0, sizeof(fl6)); | 216 | memset(&fl6, 0, sizeof(fl6)); |
217 | fl6.flowi6_proto = sk->sk_protocol; | 217 | fl6.flowi6_proto = sk->sk_protocol; |
218 | ipv6_addr_copy(&fl6.daddr, &np->daddr); | 218 | fl6.daddr = np->daddr; |
219 | ipv6_addr_copy(&fl6.saddr, &np->saddr); | 219 | fl6.saddr = np->saddr; |
220 | fl6.flowlabel = np->flow_label; | 220 | fl6.flowlabel = np->flow_label; |
221 | IP6_ECN_flow_xmit(sk, fl6.flowlabel); | 221 | IP6_ECN_flow_xmit(sk, fl6.flowlabel); |
222 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 222 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
@@ -246,7 +246,7 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) | |||
246 | skb_dst_set_noref(skb, dst); | 246 | skb_dst_set_noref(skb, dst); |
247 | 247 | ||
248 | /* Restore final destination back after routing done */ | 248 | /* Restore final destination back after routing done */ |
249 | ipv6_addr_copy(&fl6.daddr, &np->daddr); | 249 | fl6.daddr = np->daddr; |
250 | 250 | ||
251 | res = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); | 251 | res = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); |
252 | rcu_read_unlock(); | 252 | rcu_read_unlock(); |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 93718f3db79b..b82bcde53f7a 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -190,7 +190,7 @@ static struct fib6_table *fib6_alloc_table(struct net *net, u32 id) | |||
190 | struct fib6_table *table; | 190 | struct fib6_table *table; |
191 | 191 | ||
192 | table = kzalloc(sizeof(*table), GFP_ATOMIC); | 192 | table = kzalloc(sizeof(*table), GFP_ATOMIC); |
193 | if (table != NULL) { | 193 | if (table) { |
194 | table->tb6_id = id; | 194 | table->tb6_id = id; |
195 | table->tb6_root.leaf = net->ipv6.ip6_null_entry; | 195 | table->tb6_root.leaf = net->ipv6.ip6_null_entry; |
196 | table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; | 196 | table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; |
@@ -210,7 +210,7 @@ struct fib6_table *fib6_new_table(struct net *net, u32 id) | |||
210 | return tb; | 210 | return tb; |
211 | 211 | ||
212 | tb = fib6_alloc_table(net, id); | 212 | tb = fib6_alloc_table(net, id); |
213 | if (tb != NULL) | 213 | if (tb) |
214 | fib6_link_table(net, tb); | 214 | fib6_link_table(net, tb); |
215 | 215 | ||
216 | return tb; | 216 | return tb; |
@@ -367,7 +367,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
367 | s_e = cb->args[1]; | 367 | s_e = cb->args[1]; |
368 | 368 | ||
369 | w = (void *)cb->args[2]; | 369 | w = (void *)cb->args[2]; |
370 | if (w == NULL) { | 370 | if (!w) { |
371 | /* New dump: | 371 | /* New dump: |
372 | * | 372 | * |
373 | * 1. hook callback destructor. | 373 | * 1. hook callback destructor. |
@@ -379,7 +379,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
379 | * 2. allocate and initialize walker. | 379 | * 2. allocate and initialize walker. |
380 | */ | 380 | */ |
381 | w = kzalloc(sizeof(*w), GFP_ATOMIC); | 381 | w = kzalloc(sizeof(*w), GFP_ATOMIC); |
382 | if (w == NULL) | 382 | if (!w) |
383 | return -ENOMEM; | 383 | return -ENOMEM; |
384 | w->func = fib6_dump_node; | 384 | w->func = fib6_dump_node; |
385 | cb->args[2] = (long)w; | 385 | cb->args[2] = (long)w; |
@@ -425,7 +425,8 @@ out: | |||
425 | 425 | ||
426 | static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, | 426 | static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, |
427 | int addrlen, int plen, | 427 | int addrlen, int plen, |
428 | int offset) | 428 | int offset, int allow_create, |
429 | int replace_required) | ||
429 | { | 430 | { |
430 | struct fib6_node *fn, *in, *ln; | 431 | struct fib6_node *fn, *in, *ln; |
431 | struct fib6_node *pn = NULL; | 432 | struct fib6_node *pn = NULL; |
@@ -447,8 +448,18 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, | |||
447 | * Prefix match | 448 | * Prefix match |
448 | */ | 449 | */ |
449 | if (plen < fn->fn_bit || | 450 | if (plen < fn->fn_bit || |
450 | !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit)) | 451 | !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit)) { |
452 | if (!allow_create) { | ||
453 | if (replace_required) { | ||
454 | pr_warn("IPv6: Can't replace route, " | ||
455 | "no match found\n"); | ||
456 | return ERR_PTR(-ENOENT); | ||
457 | } | ||
458 | pr_warn("IPv6: NLM_F_CREATE should be set " | ||
459 | "when creating new route\n"); | ||
460 | } | ||
451 | goto insert_above; | 461 | goto insert_above; |
462 | } | ||
452 | 463 | ||
453 | /* | 464 | /* |
454 | * Exact match ? | 465 | * Exact match ? |
@@ -456,7 +467,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, | |||
456 | 467 | ||
457 | if (plen == fn->fn_bit) { | 468 | if (plen == fn->fn_bit) { |
458 | /* clean up an intermediate node */ | 469 | /* clean up an intermediate node */ |
459 | if ((fn->fn_flags & RTN_RTINFO) == 0) { | 470 | if (!(fn->fn_flags & RTN_RTINFO)) { |
460 | rt6_release(fn->leaf); | 471 | rt6_release(fn->leaf); |
461 | fn->leaf = NULL; | 472 | fn->leaf = NULL; |
462 | } | 473 | } |
@@ -477,6 +488,23 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, | |||
477 | fn = dir ? fn->right: fn->left; | 488 | fn = dir ? fn->right: fn->left; |
478 | } while (fn); | 489 | } while (fn); |
479 | 490 | ||
491 | if (!allow_create) { | ||
492 | /* We should not create new node because | ||
493 | * NLM_F_REPLACE was specified without NLM_F_CREATE | ||
494 | * I assume it is safe to require NLM_F_CREATE when | ||
495 | * REPLACE flag is used! Later we may want to remove the | ||
496 | * check for replace_required, because according | ||
497 | * to netlink specification, NLM_F_CREATE | ||
498 | * MUST be specified if new route is created. | ||
499 | * That would keep IPv6 consistent with IPv4 | ||
500 | */ | ||
501 | if (replace_required) { | ||
502 | pr_warn("IPv6: Can't replace route, no match found\n"); | ||
503 | return ERR_PTR(-ENOENT); | ||
504 | } | ||
505 | pr_warn("IPv6: NLM_F_CREATE should be set " | ||
506 | "when creating new route\n"); | ||
507 | } | ||
480 | /* | 508 | /* |
481 | * We walked to the bottom of tree. | 509 | * We walked to the bottom of tree. |
482 | * Create new leaf node without children. | 510 | * Create new leaf node without children. |
@@ -484,7 +512,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, | |||
484 | 512 | ||
485 | ln = node_alloc(); | 513 | ln = node_alloc(); |
486 | 514 | ||
487 | if (ln == NULL) | 515 | if (!ln) |
488 | return NULL; | 516 | return NULL; |
489 | ln->fn_bit = plen; | 517 | ln->fn_bit = plen; |
490 | 518 | ||
@@ -527,7 +555,7 @@ insert_above: | |||
527 | in = node_alloc(); | 555 | in = node_alloc(); |
528 | ln = node_alloc(); | 556 | ln = node_alloc(); |
529 | 557 | ||
530 | if (in == NULL || ln == NULL) { | 558 | if (!in || !ln) { |
531 | if (in) | 559 | if (in) |
532 | node_free(in); | 560 | node_free(in); |
533 | if (ln) | 561 | if (ln) |
@@ -581,7 +609,7 @@ insert_above: | |||
581 | 609 | ||
582 | ln = node_alloc(); | 610 | ln = node_alloc(); |
583 | 611 | ||
584 | if (ln == NULL) | 612 | if (!ln) |
585 | return NULL; | 613 | return NULL; |
586 | 614 | ||
587 | ln->fn_bit = plen; | 615 | ln->fn_bit = plen; |
@@ -614,10 +642,15 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
614 | { | 642 | { |
615 | struct rt6_info *iter = NULL; | 643 | struct rt6_info *iter = NULL; |
616 | struct rt6_info **ins; | 644 | struct rt6_info **ins; |
645 | int replace = (info->nlh && | ||
646 | (info->nlh->nlmsg_flags & NLM_F_REPLACE)); | ||
647 | int add = (!info->nlh || | ||
648 | (info->nlh->nlmsg_flags & NLM_F_CREATE)); | ||
649 | int found = 0; | ||
617 | 650 | ||
618 | ins = &fn->leaf; | 651 | ins = &fn->leaf; |
619 | 652 | ||
620 | for (iter = fn->leaf; iter; iter=iter->dst.rt6_next) { | 653 | for (iter = fn->leaf; iter; iter = iter->dst.rt6_next) { |
621 | /* | 654 | /* |
622 | * Search for duplicates | 655 | * Search for duplicates |
623 | */ | 656 | */ |
@@ -626,17 +659,24 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
626 | /* | 659 | /* |
627 | * Same priority level | 660 | * Same priority level |
628 | */ | 661 | */ |
662 | if (info->nlh && | ||
663 | (info->nlh->nlmsg_flags & NLM_F_EXCL)) | ||
664 | return -EEXIST; | ||
665 | if (replace) { | ||
666 | found++; | ||
667 | break; | ||
668 | } | ||
629 | 669 | ||
630 | if (iter->rt6i_dev == rt->rt6i_dev && | 670 | if (iter->dst.dev == rt->dst.dev && |
631 | iter->rt6i_idev == rt->rt6i_idev && | 671 | iter->rt6i_idev == rt->rt6i_idev && |
632 | ipv6_addr_equal(&iter->rt6i_gateway, | 672 | ipv6_addr_equal(&iter->rt6i_gateway, |
633 | &rt->rt6i_gateway)) { | 673 | &rt->rt6i_gateway)) { |
634 | if (!(iter->rt6i_flags&RTF_EXPIRES)) | 674 | if (!(iter->rt6i_flags & RTF_EXPIRES)) |
635 | return -EEXIST; | 675 | return -EEXIST; |
636 | iter->rt6i_expires = rt->rt6i_expires; | 676 | iter->dst.expires = rt->dst.expires; |
637 | if (!(rt->rt6i_flags&RTF_EXPIRES)) { | 677 | if (!(rt->rt6i_flags & RTF_EXPIRES)) { |
638 | iter->rt6i_flags &= ~RTF_EXPIRES; | 678 | iter->rt6i_flags &= ~RTF_EXPIRES; |
639 | iter->rt6i_expires = 0; | 679 | iter->dst.expires = 0; |
640 | } | 680 | } |
641 | return -EEXIST; | 681 | return -EEXIST; |
642 | } | 682 | } |
@@ -655,17 +695,40 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
655 | /* | 695 | /* |
656 | * insert node | 696 | * insert node |
657 | */ | 697 | */ |
698 | if (!replace) { | ||
699 | if (!add) | ||
700 | pr_warn("IPv6: NLM_F_CREATE should be set when creating new route\n"); | ||
701 | |||
702 | add: | ||
703 | rt->dst.rt6_next = iter; | ||
704 | *ins = rt; | ||
705 | rt->rt6i_node = fn; | ||
706 | atomic_inc(&rt->rt6i_ref); | ||
707 | inet6_rt_notify(RTM_NEWROUTE, rt, info); | ||
708 | info->nl_net->ipv6.rt6_stats->fib_rt_entries++; | ||
709 | |||
710 | if (!(fn->fn_flags & RTN_RTINFO)) { | ||
711 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; | ||
712 | fn->fn_flags |= RTN_RTINFO; | ||
713 | } | ||
658 | 714 | ||
659 | rt->dst.rt6_next = iter; | 715 | } else { |
660 | *ins = rt; | 716 | if (!found) { |
661 | rt->rt6i_node = fn; | 717 | if (add) |
662 | atomic_inc(&rt->rt6i_ref); | 718 | goto add; |
663 | inet6_rt_notify(RTM_NEWROUTE, rt, info); | 719 | pr_warn("IPv6: NLM_F_REPLACE set, but no existing node found!\n"); |
664 | info->nl_net->ipv6.rt6_stats->fib_rt_entries++; | 720 | return -ENOENT; |
665 | 721 | } | |
666 | if ((fn->fn_flags & RTN_RTINFO) == 0) { | 722 | *ins = rt; |
667 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; | 723 | rt->rt6i_node = fn; |
668 | fn->fn_flags |= RTN_RTINFO; | 724 | rt->dst.rt6_next = iter->dst.rt6_next; |
725 | atomic_inc(&rt->rt6i_ref); | ||
726 | inet6_rt_notify(RTM_NEWROUTE, rt, info); | ||
727 | rt6_release(iter); | ||
728 | if (!(fn->fn_flags & RTN_RTINFO)) { | ||
729 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; | ||
730 | fn->fn_flags |= RTN_RTINFO; | ||
731 | } | ||
669 | } | 732 | } |
670 | 733 | ||
671 | return 0; | 734 | return 0; |
@@ -674,7 +737,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
674 | static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt) | 737 | static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt) |
675 | { | 738 | { |
676 | if (!timer_pending(&net->ipv6.ip6_fib_timer) && | 739 | if (!timer_pending(&net->ipv6.ip6_fib_timer) && |
677 | (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE))) | 740 | (rt->rt6i_flags & (RTF_EXPIRES | RTF_CACHE))) |
678 | mod_timer(&net->ipv6.ip6_fib_timer, | 741 | mod_timer(&net->ipv6.ip6_fib_timer, |
679 | jiffies + net->ipv6.sysctl.ip6_rt_gc_interval); | 742 | jiffies + net->ipv6.sysctl.ip6_rt_gc_interval); |
680 | } | 743 | } |
@@ -696,11 +759,28 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
696 | { | 759 | { |
697 | struct fib6_node *fn, *pn = NULL; | 760 | struct fib6_node *fn, *pn = NULL; |
698 | int err = -ENOMEM; | 761 | int err = -ENOMEM; |
762 | int allow_create = 1; | ||
763 | int replace_required = 0; | ||
764 | |||
765 | if (info->nlh) { | ||
766 | if (!(info->nlh->nlmsg_flags & NLM_F_CREATE)) | ||
767 | allow_create = 0; | ||
768 | if (info->nlh->nlmsg_flags & NLM_F_REPLACE) | ||
769 | replace_required = 1; | ||
770 | } | ||
771 | if (!allow_create && !replace_required) | ||
772 | pr_warn("IPv6: RTM_NEWROUTE with no NLM_F_CREATE or NLM_F_REPLACE\n"); | ||
699 | 773 | ||
700 | fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr), | 774 | fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr), |
701 | rt->rt6i_dst.plen, offsetof(struct rt6_info, rt6i_dst)); | 775 | rt->rt6i_dst.plen, offsetof(struct rt6_info, rt6i_dst), |
776 | allow_create, replace_required); | ||
777 | |||
778 | if (IS_ERR(fn)) { | ||
779 | err = PTR_ERR(fn); | ||
780 | fn = NULL; | ||
781 | } | ||
702 | 782 | ||
703 | if (fn == NULL) | 783 | if (!fn) |
704 | goto out; | 784 | goto out; |
705 | 785 | ||
706 | pn = fn; | 786 | pn = fn; |
@@ -709,7 +789,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
709 | if (rt->rt6i_src.plen) { | 789 | if (rt->rt6i_src.plen) { |
710 | struct fib6_node *sn; | 790 | struct fib6_node *sn; |
711 | 791 | ||
712 | if (fn->subtree == NULL) { | 792 | if (!fn->subtree) { |
713 | struct fib6_node *sfn; | 793 | struct fib6_node *sfn; |
714 | 794 | ||
715 | /* | 795 | /* |
@@ -724,7 +804,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
724 | 804 | ||
725 | /* Create subtree root node */ | 805 | /* Create subtree root node */ |
726 | sfn = node_alloc(); | 806 | sfn = node_alloc(); |
727 | if (sfn == NULL) | 807 | if (!sfn) |
728 | goto st_failure; | 808 | goto st_failure; |
729 | 809 | ||
730 | sfn->leaf = info->nl_net->ipv6.ip6_null_entry; | 810 | sfn->leaf = info->nl_net->ipv6.ip6_null_entry; |
@@ -736,9 +816,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
736 | 816 | ||
737 | sn = fib6_add_1(sfn, &rt->rt6i_src.addr, | 817 | sn = fib6_add_1(sfn, &rt->rt6i_src.addr, |
738 | sizeof(struct in6_addr), rt->rt6i_src.plen, | 818 | sizeof(struct in6_addr), rt->rt6i_src.plen, |
739 | offsetof(struct rt6_info, rt6i_src)); | 819 | offsetof(struct rt6_info, rt6i_src), |
820 | allow_create, replace_required); | ||
740 | 821 | ||
741 | if (sn == NULL) { | 822 | if (!sn) { |
742 | /* If it is failed, discard just allocated | 823 | /* If it is failed, discard just allocated |
743 | root, and then (in st_failure) stale node | 824 | root, and then (in st_failure) stale node |
744 | in main tree. | 825 | in main tree. |
@@ -753,13 +834,18 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
753 | } else { | 834 | } else { |
754 | sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr, | 835 | sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr, |
755 | sizeof(struct in6_addr), rt->rt6i_src.plen, | 836 | sizeof(struct in6_addr), rt->rt6i_src.plen, |
756 | offsetof(struct rt6_info, rt6i_src)); | 837 | offsetof(struct rt6_info, rt6i_src), |
838 | allow_create, replace_required); | ||
757 | 839 | ||
758 | if (sn == NULL) | 840 | if (IS_ERR(sn)) { |
841 | err = PTR_ERR(sn); | ||
842 | sn = NULL; | ||
843 | } | ||
844 | if (!sn) | ||
759 | goto st_failure; | 845 | goto st_failure; |
760 | } | 846 | } |
761 | 847 | ||
762 | if (fn->leaf == NULL) { | 848 | if (!fn->leaf) { |
763 | fn->leaf = rt; | 849 | fn->leaf = rt; |
764 | atomic_inc(&rt->rt6i_ref); | 850 | atomic_inc(&rt->rt6i_ref); |
765 | } | 851 | } |
@@ -768,10 +854,9 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
768 | #endif | 854 | #endif |
769 | 855 | ||
770 | err = fib6_add_rt2node(fn, rt, info); | 856 | err = fib6_add_rt2node(fn, rt, info); |
771 | 857 | if (!err) { | |
772 | if (err == 0) { | ||
773 | fib6_start_gc(info->nl_net, rt); | 858 | fib6_start_gc(info->nl_net, rt); |
774 | if (!(rt->rt6i_flags&RTF_CACHE)) | 859 | if (!(rt->rt6i_flags & RTF_CACHE)) |
775 | fib6_prune_clones(info->nl_net, pn, rt); | 860 | fib6_prune_clones(info->nl_net, pn, rt); |
776 | } | 861 | } |
777 | 862 | ||
@@ -819,7 +904,7 @@ st_failure: | |||
819 | */ | 904 | */ |
820 | 905 | ||
821 | struct lookup_args { | 906 | struct lookup_args { |
822 | int offset; /* key offset on rt6_info */ | 907 | int offset; /* key offset on rt6_info */ |
823 | const struct in6_addr *addr; /* search key */ | 908 | const struct in6_addr *addr; /* search key */ |
824 | }; | 909 | }; |
825 | 910 | ||
@@ -849,11 +934,10 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, | |||
849 | fn = next; | 934 | fn = next; |
850 | continue; | 935 | continue; |
851 | } | 936 | } |
852 | |||
853 | break; | 937 | break; |
854 | } | 938 | } |
855 | 939 | ||
856 | while(fn) { | 940 | while (fn) { |
857 | if (FIB6_SUBTREE(fn) || fn->fn_flags & RTN_RTINFO) { | 941 | if (FIB6_SUBTREE(fn) || fn->fn_flags & RTN_RTINFO) { |
858 | struct rt6key *key; | 942 | struct rt6key *key; |
859 | 943 | ||
@@ -900,8 +984,7 @@ struct fib6_node * fib6_lookup(struct fib6_node *root, const struct in6_addr *da | |||
900 | }; | 984 | }; |
901 | 985 | ||
902 | fn = fib6_lookup_1(root, daddr ? args : args + 1); | 986 | fn = fib6_lookup_1(root, daddr ? args : args + 1); |
903 | 987 | if (!fn || fn->fn_flags & RTN_TL_ROOT) | |
904 | if (fn == NULL || fn->fn_flags & RTN_TL_ROOT) | ||
905 | fn = root; | 988 | fn = root; |
906 | 989 | ||
907 | return fn; | 990 | return fn; |
@@ -961,7 +1044,7 @@ struct fib6_node * fib6_locate(struct fib6_node *root, | |||
961 | } | 1044 | } |
962 | #endif | 1045 | #endif |
963 | 1046 | ||
964 | if (fn && fn->fn_flags&RTN_RTINFO) | 1047 | if (fn && fn->fn_flags & RTN_RTINFO) |
965 | return fn; | 1048 | return fn; |
966 | 1049 | ||
967 | return NULL; | 1050 | return NULL; |
@@ -975,14 +1058,13 @@ struct fib6_node * fib6_locate(struct fib6_node *root, | |||
975 | 1058 | ||
976 | static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn) | 1059 | static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn) |
977 | { | 1060 | { |
978 | if (fn->fn_flags&RTN_ROOT) | 1061 | if (fn->fn_flags & RTN_ROOT) |
979 | return net->ipv6.ip6_null_entry; | 1062 | return net->ipv6.ip6_null_entry; |
980 | 1063 | ||
981 | while(fn) { | 1064 | while (fn) { |
982 | if(fn->left) | 1065 | if (fn->left) |
983 | return fn->left->leaf; | 1066 | return fn->left->leaf; |
984 | 1067 | if (fn->right) | |
985 | if(fn->right) | ||
986 | return fn->right->leaf; | 1068 | return fn->right->leaf; |
987 | 1069 | ||
988 | fn = FIB6_SUBTREE(fn); | 1070 | fn = FIB6_SUBTREE(fn); |
@@ -1020,12 +1102,12 @@ static struct fib6_node *fib6_repair_tree(struct net *net, | |||
1020 | if (children == 3 || FIB6_SUBTREE(fn) | 1102 | if (children == 3 || FIB6_SUBTREE(fn) |
1021 | #ifdef CONFIG_IPV6_SUBTREES | 1103 | #ifdef CONFIG_IPV6_SUBTREES |
1022 | /* Subtree root (i.e. fn) may have one child */ | 1104 | /* Subtree root (i.e. fn) may have one child */ |
1023 | || (children && fn->fn_flags&RTN_ROOT) | 1105 | || (children && fn->fn_flags & RTN_ROOT) |
1024 | #endif | 1106 | #endif |
1025 | ) { | 1107 | ) { |
1026 | fn->leaf = fib6_find_prefix(net, fn); | 1108 | fn->leaf = fib6_find_prefix(net, fn); |
1027 | #if RT6_DEBUG >= 2 | 1109 | #if RT6_DEBUG >= 2 |
1028 | if (fn->leaf==NULL) { | 1110 | if (!fn->leaf) { |
1029 | WARN_ON(!fn->leaf); | 1111 | WARN_ON(!fn->leaf); |
1030 | fn->leaf = net->ipv6.ip6_null_entry; | 1112 | fn->leaf = net->ipv6.ip6_null_entry; |
1031 | } | 1113 | } |
@@ -1058,7 +1140,7 @@ static struct fib6_node *fib6_repair_tree(struct net *net, | |||
1058 | 1140 | ||
1059 | read_lock(&fib6_walker_lock); | 1141 | read_lock(&fib6_walker_lock); |
1060 | FOR_WALKERS(w) { | 1142 | FOR_WALKERS(w) { |
1061 | if (child == NULL) { | 1143 | if (!child) { |
1062 | if (w->root == fn) { | 1144 | if (w->root == fn) { |
1063 | w->root = w->node = NULL; | 1145 | w->root = w->node = NULL; |
1064 | RT6_TRACE("W %p adjusted by delroot 1\n", w); | 1146 | RT6_TRACE("W %p adjusted by delroot 1\n", w); |
@@ -1087,7 +1169,7 @@ static struct fib6_node *fib6_repair_tree(struct net *net, | |||
1087 | read_unlock(&fib6_walker_lock); | 1169 | read_unlock(&fib6_walker_lock); |
1088 | 1170 | ||
1089 | node_free(fn); | 1171 | node_free(fn); |
1090 | if (pn->fn_flags&RTN_RTINFO || FIB6_SUBTREE(pn)) | 1172 | if (pn->fn_flags & RTN_RTINFO || FIB6_SUBTREE(pn)) |
1091 | return pn; | 1173 | return pn; |
1092 | 1174 | ||
1093 | rt6_release(pn->leaf); | 1175 | rt6_release(pn->leaf); |
@@ -1121,7 +1203,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1121 | if (w->state == FWS_C && w->leaf == rt) { | 1203 | if (w->state == FWS_C && w->leaf == rt) { |
1122 | RT6_TRACE("walker %p adjusted by delroute\n", w); | 1204 | RT6_TRACE("walker %p adjusted by delroute\n", w); |
1123 | w->leaf = rt->dst.rt6_next; | 1205 | w->leaf = rt->dst.rt6_next; |
1124 | if (w->leaf == NULL) | 1206 | if (!w->leaf) |
1125 | w->state = FWS_U; | 1207 | w->state = FWS_U; |
1126 | } | 1208 | } |
1127 | } | 1209 | } |
@@ -1130,7 +1212,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1130 | rt->dst.rt6_next = NULL; | 1212 | rt->dst.rt6_next = NULL; |
1131 | 1213 | ||
1132 | /* If it was last route, expunge its radix tree node */ | 1214 | /* If it was last route, expunge its radix tree node */ |
1133 | if (fn->leaf == NULL) { | 1215 | if (!fn->leaf) { |
1134 | fn->fn_flags &= ~RTN_RTINFO; | 1216 | fn->fn_flags &= ~RTN_RTINFO; |
1135 | net->ipv6.rt6_stats->fib_route_nodes--; | 1217 | net->ipv6.rt6_stats->fib_route_nodes--; |
1136 | fn = fib6_repair_tree(net, fn); | 1218 | fn = fib6_repair_tree(net, fn); |
@@ -1144,7 +1226,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1144 | * to still alive ones. | 1226 | * to still alive ones. |
1145 | */ | 1227 | */ |
1146 | while (fn) { | 1228 | while (fn) { |
1147 | if (!(fn->fn_flags&RTN_RTINFO) && fn->leaf == rt) { | 1229 | if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { |
1148 | fn->leaf = fib6_find_prefix(net, fn); | 1230 | fn->leaf = fib6_find_prefix(net, fn); |
1149 | atomic_inc(&fn->leaf->rt6i_ref); | 1231 | atomic_inc(&fn->leaf->rt6i_ref); |
1150 | rt6_release(rt); | 1232 | rt6_release(rt); |
@@ -1171,17 +1253,17 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) | |||
1171 | return -ENOENT; | 1253 | return -ENOENT; |
1172 | } | 1254 | } |
1173 | #endif | 1255 | #endif |
1174 | if (fn == NULL || rt == net->ipv6.ip6_null_entry) | 1256 | if (!fn || rt == net->ipv6.ip6_null_entry) |
1175 | return -ENOENT; | 1257 | return -ENOENT; |
1176 | 1258 | ||
1177 | WARN_ON(!(fn->fn_flags & RTN_RTINFO)); | 1259 | WARN_ON(!(fn->fn_flags & RTN_RTINFO)); |
1178 | 1260 | ||
1179 | if (!(rt->rt6i_flags&RTF_CACHE)) { | 1261 | if (!(rt->rt6i_flags & RTF_CACHE)) { |
1180 | struct fib6_node *pn = fn; | 1262 | struct fib6_node *pn = fn; |
1181 | #ifdef CONFIG_IPV6_SUBTREES | 1263 | #ifdef CONFIG_IPV6_SUBTREES |
1182 | /* clones of this route might be in another subtree */ | 1264 | /* clones of this route might be in another subtree */ |
1183 | if (rt->rt6i_src.plen) { | 1265 | if (rt->rt6i_src.plen) { |
1184 | while (!(pn->fn_flags&RTN_ROOT)) | 1266 | while (!(pn->fn_flags & RTN_ROOT)) |
1185 | pn = pn->parent; | 1267 | pn = pn->parent; |
1186 | pn = pn->parent; | 1268 | pn = pn->parent; |
1187 | } | 1269 | } |
@@ -1232,11 +1314,11 @@ static int fib6_walk_continue(struct fib6_walker_t *w) | |||
1232 | 1314 | ||
1233 | for (;;) { | 1315 | for (;;) { |
1234 | fn = w->node; | 1316 | fn = w->node; |
1235 | if (fn == NULL) | 1317 | if (!fn) |
1236 | return 0; | 1318 | return 0; |
1237 | 1319 | ||
1238 | if (w->prune && fn != w->root && | 1320 | if (w->prune && fn != w->root && |
1239 | fn->fn_flags&RTN_RTINFO && w->state < FWS_C) { | 1321 | fn->fn_flags & RTN_RTINFO && w->state < FWS_C) { |
1240 | w->state = FWS_C; | 1322 | w->state = FWS_C; |
1241 | w->leaf = fn->leaf; | 1323 | w->leaf = fn->leaf; |
1242 | } | 1324 | } |
@@ -1265,7 +1347,7 @@ static int fib6_walk_continue(struct fib6_walker_t *w) | |||
1265 | w->state = FWS_C; | 1347 | w->state = FWS_C; |
1266 | w->leaf = fn->leaf; | 1348 | w->leaf = fn->leaf; |
1267 | case FWS_C: | 1349 | case FWS_C: |
1268 | if (w->leaf && fn->fn_flags&RTN_RTINFO) { | 1350 | if (w->leaf && fn->fn_flags & RTN_RTINFO) { |
1269 | int err; | 1351 | int err; |
1270 | 1352 | ||
1271 | if (w->count < w->skip) { | 1353 | if (w->count < w->skip) { |
@@ -1380,6 +1462,26 @@ static void fib6_clean_tree(struct net *net, struct fib6_node *root, | |||
1380 | fib6_walk(&c.w); | 1462 | fib6_walk(&c.w); |
1381 | } | 1463 | } |
1382 | 1464 | ||
1465 | void fib6_clean_all_ro(struct net *net, int (*func)(struct rt6_info *, void *arg), | ||
1466 | int prune, void *arg) | ||
1467 | { | ||
1468 | struct fib6_table *table; | ||
1469 | struct hlist_node *node; | ||
1470 | struct hlist_head *head; | ||
1471 | unsigned int h; | ||
1472 | |||
1473 | rcu_read_lock(); | ||
1474 | for (h = 0; h < FIB6_TABLE_HASHSZ; h++) { | ||
1475 | head = &net->ipv6.fib_table_hash[h]; | ||
1476 | hlist_for_each_entry_rcu(table, node, head, tb6_hlist) { | ||
1477 | read_lock_bh(&table->tb6_lock); | ||
1478 | fib6_clean_tree(net, &table->tb6_root, | ||
1479 | func, prune, arg); | ||
1480 | read_unlock_bh(&table->tb6_lock); | ||
1481 | } | ||
1482 | } | ||
1483 | rcu_read_unlock(); | ||
1484 | } | ||
1383 | void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), | 1485 | void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), |
1384 | int prune, void *arg) | 1486 | int prune, void *arg) |
1385 | { | 1487 | { |
@@ -1439,8 +1541,8 @@ static int fib6_age(struct rt6_info *rt, void *arg) | |||
1439 | * only if they are not in use now. | 1541 | * only if they are not in use now. |
1440 | */ | 1542 | */ |
1441 | 1543 | ||
1442 | if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) { | 1544 | if (rt->rt6i_flags & RTF_EXPIRES && rt->dst.expires) { |
1443 | if (time_after(now, rt->rt6i_expires)) { | 1545 | if (time_after(now, rt->dst.expires)) { |
1444 | RT6_TRACE("expiring %p\n", rt); | 1546 | RT6_TRACE("expiring %p\n", rt); |
1445 | return -1; | 1547 | return -1; |
1446 | } | 1548 | } |
@@ -1451,7 +1553,7 @@ static int fib6_age(struct rt6_info *rt, void *arg) | |||
1451 | RT6_TRACE("aging clone %p\n", rt); | 1553 | RT6_TRACE("aging clone %p\n", rt); |
1452 | return -1; | 1554 | return -1; |
1453 | } else if ((rt->rt6i_flags & RTF_GATEWAY) && | 1555 | } else if ((rt->rt6i_flags & RTF_GATEWAY) && |
1454 | (!(dst_get_neighbour_raw(&rt->dst)->flags & NTF_ROUTER))) { | 1556 | (!(dst_get_neighbour_noref_raw(&rt->dst)->flags & NTF_ROUTER))) { |
1455 | RT6_TRACE("purging route %p via non-router but gateway\n", | 1557 | RT6_TRACE("purging route %p via non-router but gateway\n", |
1456 | rt); | 1558 | rt); |
1457 | return -1; | 1559 | return -1; |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 4566dbd916d3..b7867a1215b1 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -386,7 +386,7 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, | |||
386 | err = -EINVAL; | 386 | err = -EINVAL; |
387 | goto done; | 387 | goto done; |
388 | } | 388 | } |
389 | ipv6_addr_copy(&fl->dst, &freq->flr_dst); | 389 | fl->dst = freq->flr_dst; |
390 | atomic_set(&fl->users, 1); | 390 | atomic_set(&fl->users, 1); |
391 | switch (fl->share) { | 391 | switch (fl->share) { |
392 | case IPV6_FL_S_EXCL: | 392 | case IPV6_FL_S_EXCL: |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index a46c64eb0a66..1ca5d45a12e8 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -280,6 +280,7 @@ int ip6_mc_input(struct sk_buff *skb) | |||
280 | u8 *ptr = skb_network_header(skb) + opt->ra; | 280 | u8 *ptr = skb_network_header(skb) + opt->ra; |
281 | struct icmp6hdr *icmp6; | 281 | struct icmp6hdr *icmp6; |
282 | u8 nexthdr = hdr->nexthdr; | 282 | u8 nexthdr = hdr->nexthdr; |
283 | __be16 frag_off; | ||
283 | int offset; | 284 | int offset; |
284 | 285 | ||
285 | /* Check if the value of Router Alert | 286 | /* Check if the value of Router Alert |
@@ -293,7 +294,7 @@ int ip6_mc_input(struct sk_buff *skb) | |||
293 | goto out; | 294 | goto out; |
294 | } | 295 | } |
295 | offset = ipv6_skip_exthdr(skb, sizeof(*hdr), | 296 | offset = ipv6_skip_exthdr(skb, sizeof(*hdr), |
296 | &nexthdr); | 297 | &nexthdr, &frag_off); |
297 | if (offset < 0) | 298 | if (offset < 0) |
298 | goto out; | 299 | goto out; |
299 | 300 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ec562713db9b..d97e07183ce9 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -136,7 +136,7 @@ static int ip6_finish_output2(struct sk_buff *skb) | |||
136 | } | 136 | } |
137 | 137 | ||
138 | rcu_read_lock(); | 138 | rcu_read_lock(); |
139 | neigh = dst_get_neighbour(dst); | 139 | neigh = dst_get_neighbour_noref(dst); |
140 | if (neigh) { | 140 | if (neigh) { |
141 | int res = neigh_output(neigh, skb); | 141 | int res = neigh_output(neigh, skb); |
142 | 142 | ||
@@ -238,8 +238,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, | |||
238 | hdr->nexthdr = proto; | 238 | hdr->nexthdr = proto; |
239 | hdr->hop_limit = hlimit; | 239 | hdr->hop_limit = hlimit; |
240 | 240 | ||
241 | ipv6_addr_copy(&hdr->saddr, &fl6->saddr); | 241 | hdr->saddr = fl6->saddr; |
242 | ipv6_addr_copy(&hdr->daddr, first_hop); | 242 | hdr->daddr = *first_hop; |
243 | 243 | ||
244 | skb->priority = sk->sk_priority; | 244 | skb->priority = sk->sk_priority; |
245 | skb->mark = sk->sk_mark; | 245 | skb->mark = sk->sk_mark; |
@@ -290,8 +290,8 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, | |||
290 | hdr->nexthdr = proto; | 290 | hdr->nexthdr = proto; |
291 | hdr->hop_limit = np->hop_limit; | 291 | hdr->hop_limit = np->hop_limit; |
292 | 292 | ||
293 | ipv6_addr_copy(&hdr->saddr, saddr); | 293 | hdr->saddr = *saddr; |
294 | ipv6_addr_copy(&hdr->daddr, daddr); | 294 | hdr->daddr = *daddr; |
295 | 295 | ||
296 | return 0; | 296 | return 0; |
297 | } | 297 | } |
@@ -329,10 +329,11 @@ static int ip6_forward_proxy_check(struct sk_buff *skb) | |||
329 | { | 329 | { |
330 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 330 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
331 | u8 nexthdr = hdr->nexthdr; | 331 | u8 nexthdr = hdr->nexthdr; |
332 | __be16 frag_off; | ||
332 | int offset; | 333 | int offset; |
333 | 334 | ||
334 | if (ipv6_ext_hdr(nexthdr)) { | 335 | if (ipv6_ext_hdr(nexthdr)) { |
335 | offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr); | 336 | offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr, &frag_off); |
336 | if (offset < 0) | 337 | if (offset < 0) |
337 | return 0; | 338 | return 0; |
338 | } else | 339 | } else |
@@ -462,7 +463,7 @@ int ip6_forward(struct sk_buff *skb) | |||
462 | send redirects to source routed frames. | 463 | send redirects to source routed frames. |
463 | We don't send redirects to frames decapsulated from IPsec. | 464 | We don't send redirects to frames decapsulated from IPsec. |
464 | */ | 465 | */ |
465 | n = dst_get_neighbour(dst); | 466 | n = dst_get_neighbour_noref(dst); |
466 | if (skb->dev == dst->dev && n && opt->srcrt == 0 && !skb_sec_path(skb)) { | 467 | if (skb->dev == dst->dev && n && opt->srcrt == 0 && !skb_sec_path(skb)) { |
467 | struct in6_addr *target = NULL; | 468 | struct in6_addr *target = NULL; |
468 | struct rt6_info *rt; | 469 | struct rt6_info *rt; |
@@ -631,6 +632,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
631 | struct ipv6hdr *tmp_hdr; | 632 | struct ipv6hdr *tmp_hdr; |
632 | struct frag_hdr *fh; | 633 | struct frag_hdr *fh; |
633 | unsigned int mtu, hlen, left, len; | 634 | unsigned int mtu, hlen, left, len; |
635 | int hroom, troom; | ||
634 | __be32 frag_id = 0; | 636 | __be32 frag_id = 0; |
635 | int ptr, offset = 0, err=0; | 637 | int ptr, offset = 0, err=0; |
636 | u8 *prevhdr, nexthdr = 0; | 638 | u8 *prevhdr, nexthdr = 0; |
@@ -797,6 +799,8 @@ slow_path: | |||
797 | */ | 799 | */ |
798 | 800 | ||
799 | *prevhdr = NEXTHDR_FRAGMENT; | 801 | *prevhdr = NEXTHDR_FRAGMENT; |
802 | hroom = LL_RESERVED_SPACE(rt->dst.dev); | ||
803 | troom = rt->dst.dev->needed_tailroom; | ||
800 | 804 | ||
801 | /* | 805 | /* |
802 | * Keep copying data until we run out. | 806 | * Keep copying data until we run out. |
@@ -815,7 +819,8 @@ slow_path: | |||
815 | * Allocate buffer. | 819 | * Allocate buffer. |
816 | */ | 820 | */ |
817 | 821 | ||
818 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->dst.dev), GFP_ATOMIC)) == NULL) { | 822 | if ((frag = alloc_skb(len + hlen + sizeof(struct frag_hdr) + |
823 | hroom + troom, GFP_ATOMIC)) == NULL) { | ||
819 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); | 824 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); |
820 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 825 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), |
821 | IPSTATS_MIB_FRAGFAILS); | 826 | IPSTATS_MIB_FRAGFAILS); |
@@ -828,7 +833,7 @@ slow_path: | |||
828 | */ | 833 | */ |
829 | 834 | ||
830 | ip6_copy_metadata(frag, skb); | 835 | ip6_copy_metadata(frag, skb); |
831 | skb_reserve(frag, LL_RESERVED_SPACE(rt->dst.dev)); | 836 | skb_reserve(frag, hroom); |
832 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); | 837 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); |
833 | skb_reset_network_header(frag); | 838 | skb_reset_network_header(frag); |
834 | fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); | 839 | fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); |
@@ -978,7 +983,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
978 | * dst entry of the nexthop router | 983 | * dst entry of the nexthop router |
979 | */ | 984 | */ |
980 | rcu_read_lock(); | 985 | rcu_read_lock(); |
981 | n = dst_get_neighbour(*dst); | 986 | n = dst_get_neighbour_noref(*dst); |
982 | if (n && !(n->nud_state & NUD_VALID)) { | 987 | if (n && !(n->nud_state & NUD_VALID)) { |
983 | struct inet6_ifaddr *ifp; | 988 | struct inet6_ifaddr *ifp; |
984 | struct flowi6 fl_gw6; | 989 | struct flowi6 fl_gw6; |
@@ -1059,7 +1064,7 @@ struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, | |||
1059 | if (err) | 1064 | if (err) |
1060 | return ERR_PTR(err); | 1065 | return ERR_PTR(err); |
1061 | if (final_dst) | 1066 | if (final_dst) |
1062 | ipv6_addr_copy(&fl6->daddr, final_dst); | 1067 | fl6->daddr = *final_dst; |
1063 | if (can_sleep) | 1068 | if (can_sleep) |
1064 | fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP; | 1069 | fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP; |
1065 | 1070 | ||
@@ -1095,7 +1100,7 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, | |||
1095 | if (err) | 1100 | if (err) |
1096 | return ERR_PTR(err); | 1101 | return ERR_PTR(err); |
1097 | if (final_dst) | 1102 | if (final_dst) |
1098 | ipv6_addr_copy(&fl6->daddr, final_dst); | 1103 | fl6->daddr = *final_dst; |
1099 | if (can_sleep) | 1104 | if (can_sleep) |
1100 | fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP; | 1105 | fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP; |
1101 | 1106 | ||
@@ -1588,7 +1593,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1588 | if (np->pmtudisc < IPV6_PMTUDISC_DO) | 1593 | if (np->pmtudisc < IPV6_PMTUDISC_DO) |
1589 | skb->local_df = 1; | 1594 | skb->local_df = 1; |
1590 | 1595 | ||
1591 | ipv6_addr_copy(final_dst, &fl6->daddr); | 1596 | *final_dst = fl6->daddr; |
1592 | __skb_pull(skb, skb_network_header_len(skb)); | 1597 | __skb_pull(skb, skb_network_header_len(skb)); |
1593 | if (opt && opt->opt_flen) | 1598 | if (opt && opt->opt_flen) |
1594 | ipv6_push_frag_opts(skb, opt, &proto); | 1599 | ipv6_push_frag_opts(skb, opt, &proto); |
@@ -1604,8 +1609,8 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1604 | 1609 | ||
1605 | hdr->hop_limit = np->cork.hop_limit; | 1610 | hdr->hop_limit = np->cork.hop_limit; |
1606 | hdr->nexthdr = proto; | 1611 | hdr->nexthdr = proto; |
1607 | ipv6_addr_copy(&hdr->saddr, &fl6->saddr); | 1612 | hdr->saddr = fl6->saddr; |
1608 | ipv6_addr_copy(&hdr->daddr, final_dst); | 1613 | hdr->daddr = *final_dst; |
1609 | 1614 | ||
1610 | skb->priority = sk->sk_priority; | 1615 | skb->priority = sk->sk_priority; |
1611 | skb->mark = sk->sk_mark; | 1616 | skb->mark = sk->sk_mark; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 4e2e9ff67ef2..e1f7761815f3 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -93,7 +93,7 @@ struct pcpu_tstats { | |||
93 | unsigned long rx_bytes; | 93 | unsigned long rx_bytes; |
94 | unsigned long tx_packets; | 94 | unsigned long tx_packets; |
95 | unsigned long tx_bytes; | 95 | unsigned long tx_bytes; |
96 | }; | 96 | } __attribute__((aligned(4*sizeof(unsigned long)))); |
97 | 97 | ||
98 | static struct net_device_stats *ip6_get_stats(struct net_device *dev) | 98 | static struct net_device_stats *ip6_get_stats(struct net_device *dev) |
99 | { | 99 | { |
@@ -653,8 +653,8 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
653 | rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, | 653 | rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, |
654 | NULL, 0, 0); | 654 | NULL, 0, 0); |
655 | 655 | ||
656 | if (rt && rt->rt6i_dev) | 656 | if (rt && rt->dst.dev) |
657 | skb2->dev = rt->rt6i_dev; | 657 | skb2->dev = rt->dst.dev; |
658 | 658 | ||
659 | icmpv6_send(skb2, rel_type, rel_code, rel_info); | 659 | icmpv6_send(skb2, rel_type, rel_code, rel_info); |
660 | 660 | ||
@@ -979,8 +979,8 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
979 | ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); | 979 | ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); |
980 | ipv6h->hop_limit = t->parms.hop_limit; | 980 | ipv6h->hop_limit = t->parms.hop_limit; |
981 | ipv6h->nexthdr = proto; | 981 | ipv6h->nexthdr = proto; |
982 | ipv6_addr_copy(&ipv6h->saddr, &fl6->saddr); | 982 | ipv6h->saddr = fl6->saddr; |
983 | ipv6_addr_copy(&ipv6h->daddr, &fl6->daddr); | 983 | ipv6h->daddr = fl6->daddr; |
984 | nf_reset(skb); | 984 | nf_reset(skb); |
985 | pkt_len = skb->len; | 985 | pkt_len = skb->len; |
986 | err = ip6_local_out(skb); | 986 | err = ip6_local_out(skb); |
@@ -1155,8 +1155,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) | |||
1155 | memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); | 1155 | memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); |
1156 | 1156 | ||
1157 | /* Set up flowi template */ | 1157 | /* Set up flowi template */ |
1158 | ipv6_addr_copy(&fl6->saddr, &p->laddr); | 1158 | fl6->saddr = p->laddr; |
1159 | ipv6_addr_copy(&fl6->daddr, &p->raddr); | 1159 | fl6->daddr = p->raddr; |
1160 | fl6->flowi6_oif = p->link; | 1160 | fl6->flowi6_oif = p->link; |
1161 | fl6->flowlabel = 0; | 1161 | fl6->flowlabel = 0; |
1162 | 1162 | ||
@@ -1185,11 +1185,11 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) | |||
1185 | if (rt == NULL) | 1185 | if (rt == NULL) |
1186 | return; | 1186 | return; |
1187 | 1187 | ||
1188 | if (rt->rt6i_dev) { | 1188 | if (rt->dst.dev) { |
1189 | dev->hard_header_len = rt->rt6i_dev->hard_header_len + | 1189 | dev->hard_header_len = rt->dst.dev->hard_header_len + |
1190 | sizeof (struct ipv6hdr); | 1190 | sizeof (struct ipv6hdr); |
1191 | 1191 | ||
1192 | dev->mtu = rt->rt6i_dev->mtu - sizeof (struct ipv6hdr); | 1192 | dev->mtu = rt->dst.dev->mtu - sizeof (struct ipv6hdr); |
1193 | if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | 1193 | if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) |
1194 | dev->mtu-=8; | 1194 | dev->mtu-=8; |
1195 | 1195 | ||
@@ -1212,8 +1212,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) | |||
1212 | static int | 1212 | static int |
1213 | ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) | 1213 | ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) |
1214 | { | 1214 | { |
1215 | ipv6_addr_copy(&t->parms.laddr, &p->laddr); | 1215 | t->parms.laddr = p->laddr; |
1216 | ipv6_addr_copy(&t->parms.raddr, &p->raddr); | 1216 | t->parms.raddr = p->raddr; |
1217 | t->parms.flags = p->flags; | 1217 | t->parms.flags = p->flags; |
1218 | t->parms.hop_limit = p->hop_limit; | 1218 | t->parms.hop_limit = p->hop_limit; |
1219 | t->parms.encap_limit = p->encap_limit; | 1219 | t->parms.encap_limit = p->encap_limit; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 449a9185b8f2..c7e95c8c579f 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -1105,8 +1105,8 @@ static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt, | |||
1105 | msg->im6_msgtype = MRT6MSG_WHOLEPKT; | 1105 | msg->im6_msgtype = MRT6MSG_WHOLEPKT; |
1106 | msg->im6_mif = mrt->mroute_reg_vif_num; | 1106 | msg->im6_mif = mrt->mroute_reg_vif_num; |
1107 | msg->im6_pad = 0; | 1107 | msg->im6_pad = 0; |
1108 | ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); | 1108 | msg->im6_src = ipv6_hdr(pkt)->saddr; |
1109 | ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr); | 1109 | msg->im6_dst = ipv6_hdr(pkt)->daddr; |
1110 | 1110 | ||
1111 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1111 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
1112 | } else | 1112 | } else |
@@ -1131,8 +1131,8 @@ static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt, | |||
1131 | msg->im6_msgtype = assert; | 1131 | msg->im6_msgtype = assert; |
1132 | msg->im6_mif = mifi; | 1132 | msg->im6_mif = mifi; |
1133 | msg->im6_pad = 0; | 1133 | msg->im6_pad = 0; |
1134 | ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); | 1134 | msg->im6_src = ipv6_hdr(pkt)->saddr; |
1135 | ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr); | 1135 | msg->im6_dst = ipv6_hdr(pkt)->daddr; |
1136 | 1136 | ||
1137 | skb_dst_set(skb, dst_clone(skb_dst(pkt))); | 1137 | skb_dst_set(skb, dst_clone(skb_dst(pkt))); |
1138 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1138 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
@@ -2181,8 +2181,8 @@ int ip6mr_get_route(struct net *net, | |||
2181 | iph->payload_len = 0; | 2181 | iph->payload_len = 0; |
2182 | iph->nexthdr = IPPROTO_NONE; | 2182 | iph->nexthdr = IPPROTO_NONE; |
2183 | iph->hop_limit = 0; | 2183 | iph->hop_limit = 0; |
2184 | ipv6_addr_copy(&iph->saddr, &rt->rt6i_src.addr); | 2184 | iph->saddr = rt->rt6i_src.addr; |
2185 | ipv6_addr_copy(&iph->daddr, &rt->rt6i_dst.addr); | 2185 | iph->daddr = rt->rt6i_dst.addr; |
2186 | 2186 | ||
2187 | err = ip6mr_cache_unresolved(mrt, vif, skb2); | 2187 | err = ip6mr_cache_unresolved(mrt, vif, skb2); |
2188 | read_unlock(&mrt_lock); | 2188 | read_unlock(&mrt_lock); |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 26cb08c84b74..18a2719003c3 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -435,7 +435,7 @@ sticky_done: | |||
435 | goto e_inval; | 435 | goto e_inval; |
436 | 436 | ||
437 | np->sticky_pktinfo.ipi6_ifindex = pkt.ipi6_ifindex; | 437 | np->sticky_pktinfo.ipi6_ifindex = pkt.ipi6_ifindex; |
438 | ipv6_addr_copy(&np->sticky_pktinfo.ipi6_addr, &pkt.ipi6_addr); | 438 | np->sticky_pktinfo.ipi6_addr = pkt.ipi6_addr; |
439 | retv = 0; | 439 | retv = 0; |
440 | break; | 440 | break; |
441 | } | 441 | } |
@@ -980,8 +980,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
980 | struct in6_pktinfo src_info; | 980 | struct in6_pktinfo src_info; |
981 | src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : | 981 | src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : |
982 | np->sticky_pktinfo.ipi6_ifindex; | 982 | np->sticky_pktinfo.ipi6_ifindex; |
983 | np->mcast_oif? ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr) : | 983 | src_info.ipi6_addr = np->mcast_oif ? np->daddr : np->sticky_pktinfo.ipi6_addr; |
984 | ipv6_addr_copy(&src_info.ipi6_addr, &(np->sticky_pktinfo.ipi6_addr)); | ||
985 | put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); | 984 | put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info); |
986 | } | 985 | } |
987 | if (np->rxopt.bits.rxhlim) { | 986 | if (np->rxopt.bits.rxhlim) { |
@@ -992,8 +991,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
992 | struct in6_pktinfo src_info; | 991 | struct in6_pktinfo src_info; |
993 | src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : | 992 | src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif : |
994 | np->sticky_pktinfo.ipi6_ifindex; | 993 | np->sticky_pktinfo.ipi6_ifindex; |
995 | np->mcast_oif? ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr) : | 994 | src_info.ipi6_addr = np->mcast_oif ? np->daddr : np->sticky_pktinfo.ipi6_addr; |
996 | ipv6_addr_copy(&src_info.ipi6_addr, &(np->sticky_pktinfo.ipi6_addr)); | ||
997 | put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); | 995 | put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); |
998 | } | 996 | } |
999 | if (np->rxopt.bits.rxohlim) { | 997 | if (np->rxopt.bits.rxohlim) { |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index ee7839f4d6e3..b853f06cc148 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -155,14 +155,14 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
155 | return -ENOMEM; | 155 | return -ENOMEM; |
156 | 156 | ||
157 | mc_lst->next = NULL; | 157 | mc_lst->next = NULL; |
158 | ipv6_addr_copy(&mc_lst->addr, addr); | 158 | mc_lst->addr = *addr; |
159 | 159 | ||
160 | rcu_read_lock(); | 160 | rcu_read_lock(); |
161 | if (ifindex == 0) { | 161 | if (ifindex == 0) { |
162 | struct rt6_info *rt; | 162 | struct rt6_info *rt; |
163 | rt = rt6_lookup(net, addr, NULL, 0, 0); | 163 | rt = rt6_lookup(net, addr, NULL, 0, 0); |
164 | if (rt) { | 164 | if (rt) { |
165 | dev = rt->rt6i_dev; | 165 | dev = rt->dst.dev; |
166 | dst_release(&rt->dst); | 166 | dst_release(&rt->dst); |
167 | } | 167 | } |
168 | } else | 168 | } else |
@@ -256,7 +256,7 @@ static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, | |||
256 | struct rt6_info *rt = rt6_lookup(net, group, NULL, 0, 0); | 256 | struct rt6_info *rt = rt6_lookup(net, group, NULL, 0, 0); |
257 | 257 | ||
258 | if (rt) { | 258 | if (rt) { |
259 | dev = rt->rt6i_dev; | 259 | dev = rt->dst.dev; |
260 | dev_hold(dev); | 260 | dev_hold(dev); |
261 | dst_release(&rt->dst); | 261 | dst_release(&rt->dst); |
262 | } | 262 | } |
@@ -858,7 +858,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) | |||
858 | 858 | ||
859 | setup_timer(&mc->mca_timer, igmp6_timer_handler, (unsigned long)mc); | 859 | setup_timer(&mc->mca_timer, igmp6_timer_handler, (unsigned long)mc); |
860 | 860 | ||
861 | ipv6_addr_copy(&mc->mca_addr, addr); | 861 | mc->mca_addr = *addr; |
862 | mc->idev = idev; /* (reference taken) */ | 862 | mc->idev = idev; /* (reference taken) */ |
863 | mc->mca_users = 1; | 863 | mc->mca_users = 1; |
864 | /* mca_stamp should be updated upon changes */ | 864 | /* mca_stamp should be updated upon changes */ |
@@ -1343,13 +1343,15 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1343 | struct mld2_report *pmr; | 1343 | struct mld2_report *pmr; |
1344 | struct in6_addr addr_buf; | 1344 | struct in6_addr addr_buf; |
1345 | const struct in6_addr *saddr; | 1345 | const struct in6_addr *saddr; |
1346 | int hlen = LL_RESERVED_SPACE(dev); | ||
1347 | int tlen = dev->needed_tailroom; | ||
1346 | int err; | 1348 | int err; |
1347 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1349 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
1348 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1350 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
1349 | IPV6_TLV_PADN, 0 }; | 1351 | IPV6_TLV_PADN, 0 }; |
1350 | 1352 | ||
1351 | /* we assume size > sizeof(ra) here */ | 1353 | /* we assume size > sizeof(ra) here */ |
1352 | size += LL_ALLOCATED_SPACE(dev); | 1354 | size += hlen + tlen; |
1353 | /* limit our allocations to order-0 page */ | 1355 | /* limit our allocations to order-0 page */ |
1354 | size = min_t(int, size, SKB_MAX_ORDER(0, 0)); | 1356 | size = min_t(int, size, SKB_MAX_ORDER(0, 0)); |
1355 | skb = sock_alloc_send_skb(sk, size, 1, &err); | 1357 | skb = sock_alloc_send_skb(sk, size, 1, &err); |
@@ -1357,7 +1359,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1357 | if (!skb) | 1359 | if (!skb) |
1358 | return NULL; | 1360 | return NULL; |
1359 | 1361 | ||
1360 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 1362 | skb_reserve(skb, hlen); |
1361 | 1363 | ||
1362 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { | 1364 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { |
1363 | /* <draft-ietf-magma-mld-source-05.txt>: | 1365 | /* <draft-ietf-magma-mld-source-05.txt>: |
@@ -1408,18 +1410,11 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1408 | csum_partial(skb_transport_header(skb), | 1410 | csum_partial(skb_transport_header(skb), |
1409 | mldlen, 0)); | 1411 | mldlen, 0)); |
1410 | 1412 | ||
1411 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); | ||
1412 | |||
1413 | if (!dst) { | ||
1414 | err = -ENOMEM; | ||
1415 | goto err_out; | ||
1416 | } | ||
1417 | |||
1418 | icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT, | 1413 | icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT, |
1419 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, | 1414 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, |
1420 | skb->dev->ifindex); | 1415 | skb->dev->ifindex); |
1416 | dst = icmp6_dst_alloc(skb->dev, NULL, &fl6); | ||
1421 | 1417 | ||
1422 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); | ||
1423 | err = 0; | 1418 | err = 0; |
1424 | if (IS_ERR(dst)) { | 1419 | if (IS_ERR(dst)) { |
1425 | err = PTR_ERR(dst); | 1420 | err = PTR_ERR(dst); |
@@ -1723,6 +1718,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1723 | struct mld_msg *hdr; | 1718 | struct mld_msg *hdr; |
1724 | const struct in6_addr *snd_addr, *saddr; | 1719 | const struct in6_addr *snd_addr, *saddr; |
1725 | struct in6_addr addr_buf; | 1720 | struct in6_addr addr_buf; |
1721 | int hlen = LL_RESERVED_SPACE(dev); | ||
1722 | int tlen = dev->needed_tailroom; | ||
1726 | int err, len, payload_len, full_len; | 1723 | int err, len, payload_len, full_len; |
1727 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1724 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
1728 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1725 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
@@ -1744,7 +1741,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1744 | IPSTATS_MIB_OUT, full_len); | 1741 | IPSTATS_MIB_OUT, full_len); |
1745 | rcu_read_unlock(); | 1742 | rcu_read_unlock(); |
1746 | 1743 | ||
1747 | skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err); | 1744 | skb = sock_alloc_send_skb(sk, hlen + tlen + full_len, 1, &err); |
1748 | 1745 | ||
1749 | if (skb == NULL) { | 1746 | if (skb == NULL) { |
1750 | rcu_read_lock(); | 1747 | rcu_read_lock(); |
@@ -1754,7 +1751,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1754 | return; | 1751 | return; |
1755 | } | 1752 | } |
1756 | 1753 | ||
1757 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 1754 | skb_reserve(skb, hlen); |
1758 | 1755 | ||
1759 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { | 1756 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { |
1760 | /* <draft-ietf-magma-mld-source-05.txt>: | 1757 | /* <draft-ietf-magma-mld-source-05.txt>: |
@@ -1772,7 +1769,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1772 | hdr = (struct mld_msg *) skb_put(skb, sizeof(struct mld_msg)); | 1769 | hdr = (struct mld_msg *) skb_put(skb, sizeof(struct mld_msg)); |
1773 | memset(hdr, 0, sizeof(struct mld_msg)); | 1770 | memset(hdr, 0, sizeof(struct mld_msg)); |
1774 | hdr->mld_type = type; | 1771 | hdr->mld_type = type; |
1775 | ipv6_addr_copy(&hdr->mld_mca, addr); | 1772 | hdr->mld_mca = *addr; |
1776 | 1773 | ||
1777 | hdr->mld_cksum = csum_ipv6_magic(saddr, snd_addr, len, | 1774 | hdr->mld_cksum = csum_ipv6_magic(saddr, snd_addr, len, |
1778 | IPPROTO_ICMPV6, | 1775 | IPPROTO_ICMPV6, |
@@ -1781,17 +1778,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1781 | rcu_read_lock(); | 1778 | rcu_read_lock(); |
1782 | idev = __in6_dev_get(skb->dev); | 1779 | idev = __in6_dev_get(skb->dev); |
1783 | 1780 | ||
1784 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); | ||
1785 | if (!dst) { | ||
1786 | err = -ENOMEM; | ||
1787 | goto err_out; | ||
1788 | } | ||
1789 | |||
1790 | icmpv6_flow_init(sk, &fl6, type, | 1781 | icmpv6_flow_init(sk, &fl6, type, |
1791 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, | 1782 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, |
1792 | skb->dev->ifindex); | 1783 | skb->dev->ifindex); |
1793 | 1784 | dst = icmp6_dst_alloc(skb->dev, NULL, &fl6); | |
1794 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); | ||
1795 | if (IS_ERR(dst)) { | 1785 | if (IS_ERR(dst)) { |
1796 | err = PTR_ERR(dst); | 1786 | err = PTR_ERR(dst); |
1797 | goto err_out; | 1787 | goto err_out; |
@@ -1914,7 +1904,7 @@ static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca, | |||
1914 | * Add multicast single-source filter to the interface list | 1904 | * Add multicast single-source filter to the interface list |
1915 | */ | 1905 | */ |
1916 | static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode, | 1906 | static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode, |
1917 | const struct in6_addr *psfsrc, int delta) | 1907 | const struct in6_addr *psfsrc) |
1918 | { | 1908 | { |
1919 | struct ip6_sf_list *psf, *psf_prev; | 1909 | struct ip6_sf_list *psf, *psf_prev; |
1920 | 1910 | ||
@@ -2045,7 +2035,7 @@ static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca, | |||
2045 | pmc->mca_sfcount[sfmode]++; | 2035 | pmc->mca_sfcount[sfmode]++; |
2046 | err = 0; | 2036 | err = 0; |
2047 | for (i=0; i<sfcount; i++) { | 2037 | for (i=0; i<sfcount; i++) { |
2048 | err = ip6_mc_add1_src(pmc, sfmode, &psfsrc[i], delta); | 2038 | err = ip6_mc_add1_src(pmc, sfmode, &psfsrc[i]); |
2049 | if (err) | 2039 | if (err) |
2050 | break; | 2040 | break; |
2051 | } | 2041 | } |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 43242e6e6103..7e1e0fbfef21 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -195,8 +195,8 @@ static inline int mip6_report_rl_allow(struct timeval *stamp, | |||
195 | mip6_report_rl.stamp.tv_sec = stamp->tv_sec; | 195 | mip6_report_rl.stamp.tv_sec = stamp->tv_sec; |
196 | mip6_report_rl.stamp.tv_usec = stamp->tv_usec; | 196 | mip6_report_rl.stamp.tv_usec = stamp->tv_usec; |
197 | mip6_report_rl.iif = iif; | 197 | mip6_report_rl.iif = iif; |
198 | ipv6_addr_copy(&mip6_report_rl.src, src); | 198 | mip6_report_rl.src = *src; |
199 | ipv6_addr_copy(&mip6_report_rl.dst, dst); | 199 | mip6_report_rl.dst = *dst; |
200 | allow = 1; | 200 | allow = 1; |
201 | } | 201 | } |
202 | spin_unlock_bh(&mip6_report_rl.lock); | 202 | spin_unlock_bh(&mip6_report_rl.lock); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 0cb78d7ddaf5..d8f02ef88e59 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -93,7 +93,7 @@ | |||
93 | 93 | ||
94 | static u32 ndisc_hash(const void *pkey, | 94 | static u32 ndisc_hash(const void *pkey, |
95 | const struct net_device *dev, | 95 | const struct net_device *dev, |
96 | __u32 rnd); | 96 | __u32 *hash_rnd); |
97 | static int ndisc_constructor(struct neighbour *neigh); | 97 | static int ndisc_constructor(struct neighbour *neigh); |
98 | static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb); | 98 | static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb); |
99 | static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb); | 99 | static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb); |
@@ -126,7 +126,6 @@ static const struct neigh_ops ndisc_direct_ops = { | |||
126 | 126 | ||
127 | struct neigh_table nd_tbl = { | 127 | struct neigh_table nd_tbl = { |
128 | .family = AF_INET6, | 128 | .family = AF_INET6, |
129 | .entry_size = sizeof(struct neighbour) + sizeof(struct in6_addr), | ||
130 | .key_len = sizeof(struct in6_addr), | 129 | .key_len = sizeof(struct in6_addr), |
131 | .hash = ndisc_hash, | 130 | .hash = ndisc_hash, |
132 | .constructor = ndisc_constructor, | 131 | .constructor = ndisc_constructor, |
@@ -141,7 +140,7 @@ struct neigh_table nd_tbl = { | |||
141 | .gc_staletime = 60 * HZ, | 140 | .gc_staletime = 60 * HZ, |
142 | .reachable_time = ND_REACHABLE_TIME, | 141 | .reachable_time = ND_REACHABLE_TIME, |
143 | .delay_probe_time = 5 * HZ, | 142 | .delay_probe_time = 5 * HZ, |
144 | .queue_len = 3, | 143 | .queue_len_bytes = 64*1024, |
145 | .ucast_probes = 3, | 144 | .ucast_probes = 3, |
146 | .mcast_probes = 3, | 145 | .mcast_probes = 3, |
147 | .anycast_delay = 1 * HZ, | 146 | .anycast_delay = 1 * HZ, |
@@ -350,16 +349,9 @@ EXPORT_SYMBOL(ndisc_mc_map); | |||
350 | 349 | ||
351 | static u32 ndisc_hash(const void *pkey, | 350 | static u32 ndisc_hash(const void *pkey, |
352 | const struct net_device *dev, | 351 | const struct net_device *dev, |
353 | __u32 hash_rnd) | 352 | __u32 *hash_rnd) |
354 | { | 353 | { |
355 | const u32 *p32 = pkey; | 354 | return ndisc_hashfn(pkey, dev, hash_rnd); |
356 | u32 addr_hash, i; | ||
357 | |||
358 | addr_hash = 0; | ||
359 | for (i = 0; i < (sizeof(struct in6_addr) / sizeof(u32)); i++) | ||
360 | addr_hash ^= *p32++; | ||
361 | |||
362 | return jhash_2words(addr_hash, dev->ifindex, hash_rnd); | ||
363 | } | 355 | } |
364 | 356 | ||
365 | static int ndisc_constructor(struct neighbour *neigh) | 357 | static int ndisc_constructor(struct neighbour *neigh) |
@@ -446,6 +438,8 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, | |||
446 | struct sock *sk = net->ipv6.ndisc_sk; | 438 | struct sock *sk = net->ipv6.ndisc_sk; |
447 | struct sk_buff *skb; | 439 | struct sk_buff *skb; |
448 | struct icmp6hdr *hdr; | 440 | struct icmp6hdr *hdr; |
441 | int hlen = LL_RESERVED_SPACE(dev); | ||
442 | int tlen = dev->needed_tailroom; | ||
449 | int len; | 443 | int len; |
450 | int err; | 444 | int err; |
451 | u8 *opt; | 445 | u8 *opt; |
@@ -459,7 +453,7 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, | |||
459 | 453 | ||
460 | skb = sock_alloc_send_skb(sk, | 454 | skb = sock_alloc_send_skb(sk, |
461 | (MAX_HEADER + sizeof(struct ipv6hdr) + | 455 | (MAX_HEADER + sizeof(struct ipv6hdr) + |
462 | len + LL_ALLOCATED_SPACE(dev)), | 456 | len + hlen + tlen), |
463 | 1, &err); | 457 | 1, &err); |
464 | if (!skb) { | 458 | if (!skb) { |
465 | ND_PRINTK0(KERN_ERR | 459 | ND_PRINTK0(KERN_ERR |
@@ -468,7 +462,7 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, | |||
468 | return NULL; | 462 | return NULL; |
469 | } | 463 | } |
470 | 464 | ||
471 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 465 | skb_reserve(skb, hlen); |
472 | ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len); | 466 | ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len); |
473 | 467 | ||
474 | skb->transport_header = skb->tail; | 468 | skb->transport_header = skb->tail; |
@@ -479,7 +473,7 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, | |||
479 | 473 | ||
480 | opt = skb_transport_header(skb) + sizeof(struct icmp6hdr); | 474 | opt = skb_transport_header(skb) + sizeof(struct icmp6hdr); |
481 | if (target) { | 475 | if (target) { |
482 | ipv6_addr_copy((struct in6_addr *)opt, target); | 476 | *(struct in6_addr *)opt = *target; |
483 | opt += sizeof(*target); | 477 | opt += sizeof(*target); |
484 | } | 478 | } |
485 | 479 | ||
@@ -515,14 +509,7 @@ void ndisc_send_skb(struct sk_buff *skb, | |||
515 | type = icmp6h->icmp6_type; | 509 | type = icmp6h->icmp6_type; |
516 | 510 | ||
517 | icmpv6_flow_init(sk, &fl6, type, saddr, daddr, dev->ifindex); | 511 | icmpv6_flow_init(sk, &fl6, type, saddr, daddr, dev->ifindex); |
518 | 512 | dst = icmp6_dst_alloc(dev, neigh, &fl6); | |
519 | dst = icmp6_dst_alloc(dev, neigh, daddr); | ||
520 | if (!dst) { | ||
521 | kfree_skb(skb); | ||
522 | return; | ||
523 | } | ||
524 | |||
525 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); | ||
526 | if (IS_ERR(dst)) { | 513 | if (IS_ERR(dst)) { |
527 | kfree_skb(skb); | 514 | kfree_skb(skb); |
528 | return; | 515 | return; |
@@ -1237,7 +1224,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1237 | rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev); | 1224 | rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev); |
1238 | 1225 | ||
1239 | if (rt) | 1226 | if (rt) |
1240 | neigh = dst_get_neighbour(&rt->dst); | 1227 | neigh = dst_get_neighbour_noref(&rt->dst); |
1241 | 1228 | ||
1242 | if (rt && lifetime == 0) { | 1229 | if (rt && lifetime == 0) { |
1243 | neigh_clone(neigh); | 1230 | neigh_clone(neigh); |
@@ -1257,7 +1244,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1257 | return; | 1244 | return; |
1258 | } | 1245 | } |
1259 | 1246 | ||
1260 | neigh = dst_get_neighbour(&rt->dst); | 1247 | neigh = dst_get_neighbour_noref(&rt->dst); |
1261 | if (neigh == NULL) { | 1248 | if (neigh == NULL) { |
1262 | ND_PRINTK0(KERN_ERR | 1249 | ND_PRINTK0(KERN_ERR |
1263 | "ICMPv6 RA: %s() got default router without neighbour.\n", | 1250 | "ICMPv6 RA: %s() got default router without neighbour.\n", |
@@ -1271,7 +1258,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1271 | } | 1258 | } |
1272 | 1259 | ||
1273 | if (rt) | 1260 | if (rt) |
1274 | rt->rt6i_expires = jiffies + (HZ * lifetime); | 1261 | rt->dst.expires = jiffies + (HZ * lifetime); |
1275 | 1262 | ||
1276 | if (ra_msg->icmph.icmp6_hop_limit) { | 1263 | if (ra_msg->icmph.icmp6_hop_limit) { |
1277 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; | 1264 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; |
@@ -1381,7 +1368,9 @@ skip_routeinfo: | |||
1381 | for (p = ndopts.nd_opts_pi; | 1368 | for (p = ndopts.nd_opts_pi; |
1382 | p; | 1369 | p; |
1383 | p = ndisc_next_option(p, ndopts.nd_opts_pi_end)) { | 1370 | p = ndisc_next_option(p, ndopts.nd_opts_pi_end)) { |
1384 | addrconf_prefix_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3); | 1371 | addrconf_prefix_rcv(skb->dev, (u8 *)p, |
1372 | (p->nd_opt_len) << 3, | ||
1373 | ndopts.nd_opts_src_lladdr != NULL); | ||
1385 | } | 1374 | } |
1386 | } | 1375 | } |
1387 | 1376 | ||
@@ -1533,6 +1522,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1533 | struct inet6_dev *idev; | 1522 | struct inet6_dev *idev; |
1534 | struct flowi6 fl6; | 1523 | struct flowi6 fl6; |
1535 | u8 *opt; | 1524 | u8 *opt; |
1525 | int hlen, tlen; | ||
1536 | int rd_len; | 1526 | int rd_len; |
1537 | int err; | 1527 | int err; |
1538 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; | 1528 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; |
@@ -1590,9 +1580,11 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1590 | rd_len &= ~0x7; | 1580 | rd_len &= ~0x7; |
1591 | len += rd_len; | 1581 | len += rd_len; |
1592 | 1582 | ||
1583 | hlen = LL_RESERVED_SPACE(dev); | ||
1584 | tlen = dev->needed_tailroom; | ||
1593 | buff = sock_alloc_send_skb(sk, | 1585 | buff = sock_alloc_send_skb(sk, |
1594 | (MAX_HEADER + sizeof(struct ipv6hdr) + | 1586 | (MAX_HEADER + sizeof(struct ipv6hdr) + |
1595 | len + LL_ALLOCATED_SPACE(dev)), | 1587 | len + hlen + tlen), |
1596 | 1, &err); | 1588 | 1, &err); |
1597 | if (buff == NULL) { | 1589 | if (buff == NULL) { |
1598 | ND_PRINTK0(KERN_ERR | 1590 | ND_PRINTK0(KERN_ERR |
@@ -1601,7 +1593,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1601 | goto release; | 1593 | goto release; |
1602 | } | 1594 | } |
1603 | 1595 | ||
1604 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); | 1596 | skb_reserve(buff, hlen); |
1605 | ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr, | 1597 | ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr, |
1606 | IPPROTO_ICMPV6, len); | 1598 | IPPROTO_ICMPV6, len); |
1607 | 1599 | ||
@@ -1617,9 +1609,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1617 | */ | 1609 | */ |
1618 | 1610 | ||
1619 | addrp = (struct in6_addr *)(icmph + 1); | 1611 | addrp = (struct in6_addr *)(icmph + 1); |
1620 | ipv6_addr_copy(addrp, target); | 1612 | *addrp = *target; |
1621 | addrp++; | 1613 | addrp++; |
1622 | ipv6_addr_copy(addrp, &ipv6_hdr(skb)->daddr); | 1614 | *addrp = ipv6_hdr(skb)->daddr; |
1623 | 1615 | ||
1624 | opt = (u8*) (addrp + 1); | 1616 | opt = (u8*) (addrp + 1); |
1625 | 1617 | ||
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index f792b34cbe9c..9a68fb5b9e77 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -125,6 +125,16 @@ config IP6_NF_MATCH_MH | |||
125 | 125 | ||
126 | To compile it as a module, choose M here. If unsure, say N. | 126 | To compile it as a module, choose M here. If unsure, say N. |
127 | 127 | ||
128 | config IP6_NF_MATCH_RPFILTER | ||
129 | tristate '"rpfilter" reverse path filter match support' | ||
130 | depends on NETFILTER_ADVANCED | ||
131 | ---help--- | ||
132 | This option allows you to match packets whose replies would | ||
133 | go out via the interface the packet came in. | ||
134 | |||
135 | To compile it as a module, choose M here. If unsure, say N. | ||
136 | The module will be called ip6t_rpfilter. | ||
137 | |||
128 | config IP6_NF_MATCH_RT | 138 | config IP6_NF_MATCH_RT |
129 | tristate '"rt" Routing header match support' | 139 | tristate '"rt" Routing header match support' |
130 | depends on NETFILTER_ADVANCED | 140 | depends on NETFILTER_ADVANCED |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index abfee91ce816..2eaed96db02c 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -27,6 +27,7 @@ obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o | |||
27 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o | 27 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o |
28 | obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o | 28 | obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o |
29 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o | 29 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o |
30 | obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o | ||
30 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o | 31 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o |
31 | 32 | ||
32 | # targets | 33 | # targets |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index e63c3972a739..fb80a23c6640 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -405,6 +405,7 @@ __ipq_rcv_skb(struct sk_buff *skb) | |||
405 | int status, type, pid, flags; | 405 | int status, type, pid, flags; |
406 | unsigned int nlmsglen, skblen; | 406 | unsigned int nlmsglen, skblen; |
407 | struct nlmsghdr *nlh; | 407 | struct nlmsghdr *nlh; |
408 | bool enable_timestamp = false; | ||
408 | 409 | ||
409 | skblen = skb->len; | 410 | skblen = skb->len; |
410 | if (skblen < sizeof(*nlh)) | 411 | if (skblen < sizeof(*nlh)) |
@@ -442,11 +443,13 @@ __ipq_rcv_skb(struct sk_buff *skb) | |||
442 | RCV_SKB_FAIL(-EBUSY); | 443 | RCV_SKB_FAIL(-EBUSY); |
443 | } | 444 | } |
444 | } else { | 445 | } else { |
445 | net_enable_timestamp(); | 446 | enable_timestamp = true; |
446 | peer_pid = pid; | 447 | peer_pid = pid; |
447 | } | 448 | } |
448 | 449 | ||
449 | spin_unlock_bh(&queue_lock); | 450 | spin_unlock_bh(&queue_lock); |
451 | if (enable_timestamp) | ||
452 | net_enable_timestamp(); | ||
450 | 453 | ||
451 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, | 454 | status = ipq_receive_peer(NLMSG_DATA(nlh), type, |
452 | nlmsglen - NLMSG_LENGTH(0)); | 455 | nlmsglen - NLMSG_LENGTH(0)); |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index a5a4c5dd5396..aad2fa41cf46 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -49,6 +49,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
49 | const __u8 tclass = DEFAULT_TOS_VALUE; | 49 | const __u8 tclass = DEFAULT_TOS_VALUE; |
50 | struct dst_entry *dst = NULL; | 50 | struct dst_entry *dst = NULL; |
51 | u8 proto; | 51 | u8 proto; |
52 | __be16 frag_off; | ||
52 | struct flowi6 fl6; | 53 | struct flowi6 fl6; |
53 | 54 | ||
54 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | 55 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || |
@@ -58,7 +59,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
58 | } | 59 | } |
59 | 60 | ||
60 | proto = oip6h->nexthdr; | 61 | proto = oip6h->nexthdr; |
61 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); | 62 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off); |
62 | 63 | ||
63 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { | 64 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { |
64 | pr_debug("Cannot get TCP header.\n"); | 65 | pr_debug("Cannot get TCP header.\n"); |
@@ -93,8 +94,8 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
93 | 94 | ||
94 | memset(&fl6, 0, sizeof(fl6)); | 95 | memset(&fl6, 0, sizeof(fl6)); |
95 | fl6.flowi6_proto = IPPROTO_TCP; | 96 | fl6.flowi6_proto = IPPROTO_TCP; |
96 | ipv6_addr_copy(&fl6.saddr, &oip6h->daddr); | 97 | fl6.saddr = oip6h->daddr; |
97 | ipv6_addr_copy(&fl6.daddr, &oip6h->saddr); | 98 | fl6.daddr = oip6h->saddr; |
98 | fl6.fl6_sport = otcph.dest; | 99 | fl6.fl6_sport = otcph.dest; |
99 | fl6.fl6_dport = otcph.source; | 100 | fl6.fl6_dport = otcph.source; |
100 | security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); | 101 | security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); |
@@ -129,8 +130,8 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
129 | *(__be32 *)ip6h = htonl(0x60000000 | (tclass << 20)); | 130 | *(__be32 *)ip6h = htonl(0x60000000 | (tclass << 20)); |
130 | ip6h->hop_limit = ip6_dst_hoplimit(dst); | 131 | ip6h->hop_limit = ip6_dst_hoplimit(dst); |
131 | ip6h->nexthdr = IPPROTO_TCP; | 132 | ip6h->nexthdr = IPPROTO_TCP; |
132 | ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr); | 133 | ip6h->saddr = oip6h->daddr; |
133 | ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr); | 134 | ip6h->daddr = oip6h->saddr; |
134 | 135 | ||
135 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); | 136 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); |
136 | /* Truncate to length (no data) */ | 137 | /* Truncate to length (no data) */ |
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c new file mode 100644 index 000000000000..5d1d8b04d694 --- /dev/null +++ b/net/ipv6/netfilter/ip6t_rpfilter.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Florian Westphal <fw@strlen.de> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/skbuff.h> | ||
11 | #include <linux/netdevice.h> | ||
12 | #include <linux/route.h> | ||
13 | #include <net/ip6_fib.h> | ||
14 | #include <net/ip6_route.h> | ||
15 | |||
16 | #include <linux/netfilter/xt_rpfilter.h> | ||
17 | #include <linux/netfilter/x_tables.h> | ||
18 | |||
19 | MODULE_LICENSE("GPL"); | ||
20 | MODULE_AUTHOR("Florian Westphal <fw@strlen.de>"); | ||
21 | MODULE_DESCRIPTION("Xtables: IPv6 reverse path filter match"); | ||
22 | |||
23 | static bool rpfilter_addr_unicast(const struct in6_addr *addr) | ||
24 | { | ||
25 | int addr_type = ipv6_addr_type(addr); | ||
26 | return addr_type & IPV6_ADDR_UNICAST; | ||
27 | } | ||
28 | |||
29 | static bool rpfilter_lookup_reverse6(const struct sk_buff *skb, | ||
30 | const struct net_device *dev, u8 flags) | ||
31 | { | ||
32 | struct rt6_info *rt; | ||
33 | struct ipv6hdr *iph = ipv6_hdr(skb); | ||
34 | bool ret = false; | ||
35 | struct flowi6 fl6 = { | ||
36 | .flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK, | ||
37 | .flowi6_proto = iph->nexthdr, | ||
38 | .daddr = iph->saddr, | ||
39 | }; | ||
40 | int lookup_flags; | ||
41 | |||
42 | if (rpfilter_addr_unicast(&iph->daddr)) { | ||
43 | memcpy(&fl6.saddr, &iph->daddr, sizeof(struct in6_addr)); | ||
44 | lookup_flags = RT6_LOOKUP_F_HAS_SADDR; | ||
45 | } else { | ||
46 | lookup_flags = 0; | ||
47 | } | ||
48 | |||
49 | fl6.flowi6_mark = flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0; | ||
50 | if ((flags & XT_RPFILTER_LOOSE) == 0) { | ||
51 | fl6.flowi6_oif = dev->ifindex; | ||
52 | lookup_flags |= RT6_LOOKUP_F_IFACE; | ||
53 | } | ||
54 | |||
55 | rt = (void *) ip6_route_lookup(dev_net(dev), &fl6, lookup_flags); | ||
56 | if (rt->dst.error) | ||
57 | goto out; | ||
58 | |||
59 | if (rt->rt6i_flags & (RTF_REJECT|RTF_ANYCAST)) | ||
60 | goto out; | ||
61 | |||
62 | if (rt->rt6i_flags & RTF_LOCAL) { | ||
63 | ret = flags & XT_RPFILTER_ACCEPT_LOCAL; | ||
64 | goto out; | ||
65 | } | ||
66 | |||
67 | if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE)) | ||
68 | ret = true; | ||
69 | out: | ||
70 | dst_release(&rt->dst); | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | ||
75 | { | ||
76 | const struct xt_rpfilter_info *info = par->matchinfo; | ||
77 | int saddrtype; | ||
78 | struct ipv6hdr *iph; | ||
79 | bool invert = info->flags & XT_RPFILTER_INVERT; | ||
80 | |||
81 | if (par->in->flags & IFF_LOOPBACK) | ||
82 | return true ^ invert; | ||
83 | |||
84 | iph = ipv6_hdr(skb); | ||
85 | saddrtype = ipv6_addr_type(&iph->saddr); | ||
86 | if (unlikely(saddrtype == IPV6_ADDR_ANY)) | ||
87 | return true ^ invert; /* not routable: forward path will drop it */ | ||
88 | |||
89 | return rpfilter_lookup_reverse6(skb, par->in, info->flags) ^ invert; | ||
90 | } | ||
91 | |||
92 | static int rpfilter_check(const struct xt_mtchk_param *par) | ||
93 | { | ||
94 | const struct xt_rpfilter_info *info = par->matchinfo; | ||
95 | unsigned int options = ~XT_RPFILTER_OPTION_MASK; | ||
96 | |||
97 | if (info->flags & options) { | ||
98 | pr_info("unknown options encountered"); | ||
99 | return -EINVAL; | ||
100 | } | ||
101 | |||
102 | if (strcmp(par->table, "mangle") != 0 && | ||
103 | strcmp(par->table, "raw") != 0) { | ||
104 | pr_info("match only valid in the \'raw\' " | ||
105 | "or \'mangle\' tables, not \'%s\'.\n", par->table); | ||
106 | return -EINVAL; | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static struct xt_match rpfilter_mt_reg __read_mostly = { | ||
113 | .name = "rpfilter", | ||
114 | .family = NFPROTO_IPV6, | ||
115 | .checkentry = rpfilter_check, | ||
116 | .match = rpfilter_mt, | ||
117 | .matchsize = sizeof(struct xt_rpfilter_info), | ||
118 | .hooks = (1 << NF_INET_PRE_ROUTING), | ||
119 | .me = THIS_MODULE | ||
120 | }; | ||
121 | |||
122 | static int __init rpfilter_mt_init(void) | ||
123 | { | ||
124 | return xt_register_match(&rpfilter_mt_reg); | ||
125 | } | ||
126 | |||
127 | static void __exit rpfilter_mt_exit(void) | ||
128 | { | ||
129 | xt_unregister_match(&rpfilter_mt_reg); | ||
130 | } | ||
131 | |||
132 | module_init(rpfilter_mt_init); | ||
133 | module_exit(rpfilter_mt_exit); | ||
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index c9e37c8fd62c..a8f6da97e3b2 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -44,7 +44,7 @@ ip6table_filter_hook(unsigned int hook, struct sk_buff *skb, | |||
44 | static struct nf_hook_ops *filter_ops __read_mostly; | 44 | static struct nf_hook_ops *filter_ops __read_mostly; |
45 | 45 | ||
46 | /* Default to forward because I got too much mail already. */ | 46 | /* Default to forward because I got too much mail already. */ |
47 | static int forward = NF_ACCEPT; | 47 | static bool forward = NF_ACCEPT; |
48 | module_param(forward, bool, 0000); | 48 | module_param(forward, bool, 0000); |
49 | 49 | ||
50 | static int __net_init ip6table_filter_net_init(struct net *net) | 50 | static int __net_init ip6table_filter_net_init(struct net *net) |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 1008ce94bc33..fdeb6d03da81 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -142,11 +142,7 @@ static const struct snmp_mib snmp6_udplite6_list[] = { | |||
142 | SNMP_MIB_SENTINEL | 142 | SNMP_MIB_SENTINEL |
143 | }; | 143 | }; |
144 | 144 | ||
145 | /* can be called either with percpu mib (pcpumib != NULL), | 145 | static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, atomic_long_t *smib) |
146 | * or shared one (smib != NULL) | ||
147 | */ | ||
148 | static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void __percpu **pcpumib, | ||
149 | atomic_long_t *smib) | ||
150 | { | 146 | { |
151 | char name[32]; | 147 | char name[32]; |
152 | int i; | 148 | int i; |
@@ -163,14 +159,14 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void __percpu **pcpum | |||
163 | snprintf(name, sizeof(name), "Icmp6%s%s", | 159 | snprintf(name, sizeof(name), "Icmp6%s%s", |
164 | i & 0x100 ? "Out" : "In", p); | 160 | i & 0x100 ? "Out" : "In", p); |
165 | seq_printf(seq, "%-32s\t%lu\n", name, | 161 | seq_printf(seq, "%-32s\t%lu\n", name, |
166 | pcpumib ? snmp_fold_field(pcpumib, i) : atomic_long_read(smib + i)); | 162 | atomic_long_read(smib + i)); |
167 | } | 163 | } |
168 | 164 | ||
169 | /* print by number (nonzero only) - ICMPMsgStat format */ | 165 | /* print by number (nonzero only) - ICMPMsgStat format */ |
170 | for (i = 0; i < ICMP6MSG_MIB_MAX; i++) { | 166 | for (i = 0; i < ICMP6MSG_MIB_MAX; i++) { |
171 | unsigned long val; | 167 | unsigned long val; |
172 | 168 | ||
173 | val = pcpumib ? snmp_fold_field(pcpumib, i) : atomic_long_read(smib + i); | 169 | val = atomic_long_read(smib + i); |
174 | if (!val) | 170 | if (!val) |
175 | continue; | 171 | continue; |
176 | snprintf(name, sizeof(name), "Icmp6%sType%u", | 172 | snprintf(name, sizeof(name), "Icmp6%sType%u", |
@@ -215,8 +211,7 @@ static int snmp6_seq_show(struct seq_file *seq, void *v) | |||
215 | snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp)); | 211 | snmp6_ipstats_list, offsetof(struct ipstats_mib, syncp)); |
216 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.icmpv6_statistics, | 212 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.icmpv6_statistics, |
217 | NULL, snmp6_icmp6_list); | 213 | NULL, snmp6_icmp6_list); |
218 | snmp6_seq_show_icmpv6msg(seq, | 214 | snmp6_seq_show_icmpv6msg(seq, net->mib.icmpv6msg_statistics->mibs); |
219 | (void __percpu **)net->mib.icmpv6msg_statistics, NULL); | ||
220 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.udp_stats_in6, | 215 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.udp_stats_in6, |
221 | NULL, snmp6_udp6_list); | 216 | NULL, snmp6_udp6_list); |
222 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.udplite_stats_in6, | 217 | snmp6_seq_show_item(seq, (void __percpu **)net->mib.udplite_stats_in6, |
@@ -246,7 +241,7 @@ static int snmp6_dev_seq_show(struct seq_file *seq, void *v) | |||
246 | snmp6_ipstats_list); | 241 | snmp6_ipstats_list); |
247 | snmp6_seq_show_item(seq, NULL, idev->stats.icmpv6dev->mibs, | 242 | snmp6_seq_show_item(seq, NULL, idev->stats.icmpv6dev->mibs, |
248 | snmp6_icmp6_list); | 243 | snmp6_icmp6_list); |
249 | snmp6_seq_show_icmpv6msg(seq, NULL, idev->stats.icmpv6msgdev->mibs); | 244 | snmp6_seq_show_icmpv6msg(seq, idev->stats.icmpv6msgdev->mibs); |
250 | return 0; | 245 | return 0; |
251 | } | 246 | } |
252 | 247 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 331af3b882ac..a4894f4f1944 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -299,9 +299,9 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
299 | } | 299 | } |
300 | 300 | ||
301 | inet->inet_rcv_saddr = inet->inet_saddr = v4addr; | 301 | inet->inet_rcv_saddr = inet->inet_saddr = v4addr; |
302 | ipv6_addr_copy(&np->rcv_saddr, &addr->sin6_addr); | 302 | np->rcv_saddr = addr->sin6_addr; |
303 | if (!(addr_type & IPV6_ADDR_MULTICAST)) | 303 | if (!(addr_type & IPV6_ADDR_MULTICAST)) |
304 | ipv6_addr_copy(&np->saddr, &addr->sin6_addr); | 304 | np->saddr = addr->sin6_addr; |
305 | err = 0; | 305 | err = 0; |
306 | out_unlock: | 306 | out_unlock: |
307 | rcu_read_unlock(); | 307 | rcu_read_unlock(); |
@@ -383,7 +383,8 @@ static inline int rawv6_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
383 | } | 383 | } |
384 | 384 | ||
385 | /* Charge it to the socket. */ | 385 | /* Charge it to the socket. */ |
386 | if (ip_queue_rcv_skb(sk, skb) < 0) { | 386 | skb_dst_drop(skb); |
387 | if (sock_queue_rcv_skb(sk, skb) < 0) { | ||
387 | kfree_skb(skb); | 388 | kfree_skb(skb); |
388 | return NET_RX_DROP; | 389 | return NET_RX_DROP; |
389 | } | 390 | } |
@@ -494,7 +495,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
494 | if (sin6) { | 495 | if (sin6) { |
495 | sin6->sin6_family = AF_INET6; | 496 | sin6->sin6_family = AF_INET6; |
496 | sin6->sin6_port = 0; | 497 | sin6->sin6_port = 0; |
497 | ipv6_addr_copy(&sin6->sin6_addr, &ipv6_hdr(skb)->saddr); | 498 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; |
498 | sin6->sin6_flowinfo = 0; | 499 | sin6->sin6_flowinfo = 0; |
499 | sin6->sin6_scope_id = 0; | 500 | sin6->sin6_scope_id = 0; |
500 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 501 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
@@ -610,6 +611,8 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
610 | struct sk_buff *skb; | 611 | struct sk_buff *skb; |
611 | int err; | 612 | int err; |
612 | struct rt6_info *rt = (struct rt6_info *)*dstp; | 613 | struct rt6_info *rt = (struct rt6_info *)*dstp; |
614 | int hlen = LL_RESERVED_SPACE(rt->dst.dev); | ||
615 | int tlen = rt->dst.dev->needed_tailroom; | ||
613 | 616 | ||
614 | if (length > rt->dst.dev->mtu) { | 617 | if (length > rt->dst.dev->mtu) { |
615 | ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu); | 618 | ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu); |
@@ -619,11 +622,11 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
619 | goto out; | 622 | goto out; |
620 | 623 | ||
621 | skb = sock_alloc_send_skb(sk, | 624 | skb = sock_alloc_send_skb(sk, |
622 | length + LL_ALLOCATED_SPACE(rt->dst.dev) + 15, | 625 | length + hlen + tlen + 15, |
623 | flags & MSG_DONTWAIT, &err); | 626 | flags & MSG_DONTWAIT, &err); |
624 | if (skb == NULL) | 627 | if (skb == NULL) |
625 | goto error; | 628 | goto error; |
626 | skb_reserve(skb, LL_RESERVED_SPACE(rt->dst.dev)); | 629 | skb_reserve(skb, hlen); |
627 | 630 | ||
628 | skb->priority = sk->sk_priority; | 631 | skb->priority = sk->sk_priority; |
629 | skb->mark = sk->sk_mark; | 632 | skb->mark = sk->sk_mark; |
@@ -843,11 +846,11 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
843 | goto out; | 846 | goto out; |
844 | 847 | ||
845 | if (!ipv6_addr_any(daddr)) | 848 | if (!ipv6_addr_any(daddr)) |
846 | ipv6_addr_copy(&fl6.daddr, daddr); | 849 | fl6.daddr = *daddr; |
847 | else | 850 | else |
848 | fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | 851 | fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ |
849 | if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) | 852 | if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) |
850 | ipv6_addr_copy(&fl6.saddr, &np->saddr); | 853 | fl6.saddr = np->saddr; |
851 | 854 | ||
852 | final_p = fl6_update_dst(&fl6, opt, &final); | 855 | final_p = fl6_update_dst(&fl6, opt, &final); |
853 | 856 | ||
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index dfb164e9051a..b69fae76a6f1 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -153,8 +153,8 @@ void ip6_frag_init(struct inet_frag_queue *q, void *a) | |||
153 | 153 | ||
154 | fq->id = arg->id; | 154 | fq->id = arg->id; |
155 | fq->user = arg->user; | 155 | fq->user = arg->user; |
156 | ipv6_addr_copy(&fq->saddr, arg->src); | 156 | fq->saddr = *arg->src; |
157 | ipv6_addr_copy(&fq->daddr, arg->dst); | 157 | fq->daddr = *arg->dst; |
158 | } | 158 | } |
159 | EXPORT_SYMBOL(ip6_frag_init); | 159 | EXPORT_SYMBOL(ip6_frag_init); |
160 | 160 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b582a0a0f1c5..07361dfa8085 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -62,17 +62,6 @@ | |||
62 | #include <linux/sysctl.h> | 62 | #include <linux/sysctl.h> |
63 | #endif | 63 | #endif |
64 | 64 | ||
65 | /* Set to 3 to get tracing. */ | ||
66 | #define RT6_DEBUG 2 | ||
67 | |||
68 | #if RT6_DEBUG >= 3 | ||
69 | #define RDBG(x) printk x | ||
70 | #define RT6_TRACE(x...) printk(KERN_DEBUG x) | ||
71 | #else | ||
72 | #define RDBG(x) | ||
73 | #define RT6_TRACE(x...) do { ; } while (0) | ||
74 | #endif | ||
75 | |||
76 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | 65 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, |
77 | const struct in6_addr *dest); | 66 | const struct in6_addr *dest); |
78 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); | 67 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); |
@@ -134,7 +123,23 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
134 | 123 | ||
135 | static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr) | 124 | static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr) |
136 | { | 125 | { |
137 | return __neigh_lookup_errno(&nd_tbl, daddr, dst->dev); | 126 | struct neighbour *n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr); |
127 | if (n) | ||
128 | return n; | ||
129 | return neigh_create(&nd_tbl, daddr, dst->dev); | ||
130 | } | ||
131 | |||
132 | static int rt6_bind_neighbour(struct rt6_info *rt, struct net_device *dev) | ||
133 | { | ||
134 | struct neighbour *n = __ipv6_neigh_lookup(&nd_tbl, dev, &rt->rt6i_gateway); | ||
135 | if (!n) { | ||
136 | n = neigh_create(&nd_tbl, &rt->rt6i_gateway, dev); | ||
137 | if (IS_ERR(n)) | ||
138 | return PTR_ERR(n); | ||
139 | } | ||
140 | dst_set_neighbour(&rt->dst, n); | ||
141 | |||
142 | return 0; | ||
138 | } | 143 | } |
139 | 144 | ||
140 | static struct dst_ops ip6_dst_ops_template = { | 145 | static struct dst_ops ip6_dst_ops_template = { |
@@ -247,9 +252,9 @@ static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, | |||
247 | { | 252 | { |
248 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); | 253 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); |
249 | 254 | ||
250 | if (rt != NULL) | 255 | if (rt) |
251 | memset(&rt->rt6i_table, 0, | 256 | memset(&rt->rt6i_table, 0, |
252 | sizeof(*rt) - sizeof(struct dst_entry)); | 257 | sizeof(*rt) - sizeof(struct dst_entry)); |
253 | 258 | ||
254 | return rt; | 259 | return rt; |
255 | } | 260 | } |
@@ -263,7 +268,7 @@ static void ip6_dst_destroy(struct dst_entry *dst) | |||
263 | if (!(rt->dst.flags & DST_HOST)) | 268 | if (!(rt->dst.flags & DST_HOST)) |
264 | dst_destroy_metrics_generic(dst); | 269 | dst_destroy_metrics_generic(dst); |
265 | 270 | ||
266 | if (idev != NULL) { | 271 | if (idev) { |
267 | rt->rt6i_idev = NULL; | 272 | rt->rt6i_idev = NULL; |
268 | in6_dev_put(idev); | 273 | in6_dev_put(idev); |
269 | } | 274 | } |
@@ -299,10 +304,10 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
299 | struct net_device *loopback_dev = | 304 | struct net_device *loopback_dev = |
300 | dev_net(dev)->loopback_dev; | 305 | dev_net(dev)->loopback_dev; |
301 | 306 | ||
302 | if (dev != loopback_dev && idev != NULL && idev->dev == dev) { | 307 | if (dev != loopback_dev && idev && idev->dev == dev) { |
303 | struct inet6_dev *loopback_idev = | 308 | struct inet6_dev *loopback_idev = |
304 | in6_dev_get(loopback_dev); | 309 | in6_dev_get(loopback_dev); |
305 | if (loopback_idev != NULL) { | 310 | if (loopback_idev) { |
306 | rt->rt6i_idev = loopback_idev; | 311 | rt->rt6i_idev = loopback_idev; |
307 | in6_dev_put(idev); | 312 | in6_dev_put(idev); |
308 | } | 313 | } |
@@ -312,7 +317,7 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
312 | static __inline__ int rt6_check_expired(const struct rt6_info *rt) | 317 | static __inline__ int rt6_check_expired(const struct rt6_info *rt) |
313 | { | 318 | { |
314 | return (rt->rt6i_flags & RTF_EXPIRES) && | 319 | return (rt->rt6i_flags & RTF_EXPIRES) && |
315 | time_after(jiffies, rt->rt6i_expires); | 320 | time_after(jiffies, rt->dst.expires); |
316 | } | 321 | } |
317 | 322 | ||
318 | static inline int rt6_need_strict(const struct in6_addr *daddr) | 323 | static inline int rt6_need_strict(const struct in6_addr *daddr) |
@@ -338,13 +343,13 @@ static inline struct rt6_info *rt6_device_match(struct net *net, | |||
338 | goto out; | 343 | goto out; |
339 | 344 | ||
340 | for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) { | 345 | for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) { |
341 | struct net_device *dev = sprt->rt6i_dev; | 346 | struct net_device *dev = sprt->dst.dev; |
342 | 347 | ||
343 | if (oif) { | 348 | if (oif) { |
344 | if (dev->ifindex == oif) | 349 | if (dev->ifindex == oif) |
345 | return sprt; | 350 | return sprt; |
346 | if (dev->flags & IFF_LOOPBACK) { | 351 | if (dev->flags & IFF_LOOPBACK) { |
347 | if (sprt->rt6i_idev == NULL || | 352 | if (!sprt->rt6i_idev || |
348 | sprt->rt6i_idev->dev->ifindex != oif) { | 353 | sprt->rt6i_idev->dev->ifindex != oif) { |
349 | if (flags & RT6_LOOKUP_F_IFACE && oif) | 354 | if (flags & RT6_LOOKUP_F_IFACE && oif) |
350 | continue; | 355 | continue; |
@@ -385,7 +390,7 @@ static void rt6_probe(struct rt6_info *rt) | |||
385 | * to no more than one per minute. | 390 | * to no more than one per minute. |
386 | */ | 391 | */ |
387 | rcu_read_lock(); | 392 | rcu_read_lock(); |
388 | neigh = rt ? dst_get_neighbour(&rt->dst) : NULL; | 393 | neigh = rt ? dst_get_neighbour_noref(&rt->dst) : NULL; |
389 | if (!neigh || (neigh->nud_state & NUD_VALID)) | 394 | if (!neigh || (neigh->nud_state & NUD_VALID)) |
390 | goto out; | 395 | goto out; |
391 | read_lock_bh(&neigh->lock); | 396 | read_lock_bh(&neigh->lock); |
@@ -399,7 +404,7 @@ static void rt6_probe(struct rt6_info *rt) | |||
399 | 404 | ||
400 | target = (struct in6_addr *)&neigh->primary_key; | 405 | target = (struct in6_addr *)&neigh->primary_key; |
401 | addrconf_addr_solict_mult(target, &mcaddr); | 406 | addrconf_addr_solict_mult(target, &mcaddr); |
402 | ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL); | 407 | ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL); |
403 | } else { | 408 | } else { |
404 | read_unlock_bh(&neigh->lock); | 409 | read_unlock_bh(&neigh->lock); |
405 | } | 410 | } |
@@ -417,7 +422,7 @@ static inline void rt6_probe(struct rt6_info *rt) | |||
417 | */ | 422 | */ |
418 | static inline int rt6_check_dev(struct rt6_info *rt, int oif) | 423 | static inline int rt6_check_dev(struct rt6_info *rt, int oif) |
419 | { | 424 | { |
420 | struct net_device *dev = rt->rt6i_dev; | 425 | struct net_device *dev = rt->dst.dev; |
421 | if (!oif || dev->ifindex == oif) | 426 | if (!oif || dev->ifindex == oif) |
422 | return 2; | 427 | return 2; |
423 | if ((dev->flags & IFF_LOOPBACK) && | 428 | if ((dev->flags & IFF_LOOPBACK) && |
@@ -432,7 +437,7 @@ static inline int rt6_check_neigh(struct rt6_info *rt) | |||
432 | int m; | 437 | int m; |
433 | 438 | ||
434 | rcu_read_lock(); | 439 | rcu_read_lock(); |
435 | neigh = dst_get_neighbour(&rt->dst); | 440 | neigh = dst_get_neighbour_noref(&rt->dst); |
436 | if (rt->rt6i_flags & RTF_NONEXTHOP || | 441 | if (rt->rt6i_flags & RTF_NONEXTHOP || |
437 | !(rt->rt6i_flags & RTF_GATEWAY)) | 442 | !(rt->rt6i_flags & RTF_GATEWAY)) |
438 | m = 1; | 443 | m = 1; |
@@ -518,9 +523,6 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | |||
518 | struct rt6_info *match, *rt0; | 523 | struct rt6_info *match, *rt0; |
519 | struct net *net; | 524 | struct net *net; |
520 | 525 | ||
521 | RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n", | ||
522 | __func__, fn->leaf, oif); | ||
523 | |||
524 | rt0 = fn->rr_ptr; | 526 | rt0 = fn->rr_ptr; |
525 | if (!rt0) | 527 | if (!rt0) |
526 | fn->rr_ptr = rt0 = fn->leaf; | 528 | fn->rr_ptr = rt0 = fn->leaf; |
@@ -539,10 +541,7 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | |||
539 | fn->rr_ptr = next; | 541 | fn->rr_ptr = next; |
540 | } | 542 | } |
541 | 543 | ||
542 | RT6_TRACE("%s() => %p\n", | 544 | net = dev_net(rt0->dst.dev); |
543 | __func__, match); | ||
544 | |||
545 | net = dev_net(rt0->rt6i_dev); | ||
546 | return match ? match : net->ipv6.ip6_null_entry; | 545 | return match ? match : net->ipv6.ip6_null_entry; |
547 | } | 546 | } |
548 | 547 | ||
@@ -611,7 +610,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
611 | if (!addrconf_finite_timeout(lifetime)) { | 610 | if (!addrconf_finite_timeout(lifetime)) { |
612 | rt->rt6i_flags &= ~RTF_EXPIRES; | 611 | rt->rt6i_flags &= ~RTF_EXPIRES; |
613 | } else { | 612 | } else { |
614 | rt->rt6i_expires = jiffies + HZ * lifetime; | 613 | rt->dst.expires = jiffies + HZ * lifetime; |
615 | rt->rt6i_flags |= RTF_EXPIRES; | 614 | rt->rt6i_flags |= RTF_EXPIRES; |
616 | } | 615 | } |
617 | dst_release(&rt->dst); | 616 | dst_release(&rt->dst); |
@@ -636,7 +635,7 @@ do { \ | |||
636 | goto restart; \ | 635 | goto restart; \ |
637 | } \ | 636 | } \ |
638 | } \ | 637 | } \ |
639 | } while(0) | 638 | } while (0) |
640 | 639 | ||
641 | static struct rt6_info *ip6_pol_route_lookup(struct net *net, | 640 | static struct rt6_info *ip6_pol_route_lookup(struct net *net, |
642 | struct fib6_table *table, | 641 | struct fib6_table *table, |
@@ -658,6 +657,13 @@ out: | |||
658 | 657 | ||
659 | } | 658 | } |
660 | 659 | ||
660 | struct dst_entry * ip6_route_lookup(struct net *net, struct flowi6 *fl6, | ||
661 | int flags) | ||
662 | { | ||
663 | return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup); | ||
664 | } | ||
665 | EXPORT_SYMBOL_GPL(ip6_route_lookup); | ||
666 | |||
661 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, | 667 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, |
662 | const struct in6_addr *saddr, int oif, int strict) | 668 | const struct in6_addr *saddr, int oif, int strict) |
663 | { | 669 | { |
@@ -706,7 +712,7 @@ static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info) | |||
706 | int ip6_ins_rt(struct rt6_info *rt) | 712 | int ip6_ins_rt(struct rt6_info *rt) |
707 | { | 713 | { |
708 | struct nl_info info = { | 714 | struct nl_info info = { |
709 | .nl_net = dev_net(rt->rt6i_dev), | 715 | .nl_net = dev_net(rt->dst.dev), |
710 | }; | 716 | }; |
711 | return __ip6_ins_rt(rt, &info); | 717 | return __ip6_ins_rt(rt, &info); |
712 | } | 718 | } |
@@ -724,29 +730,27 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, | |||
724 | rt = ip6_rt_copy(ort, daddr); | 730 | rt = ip6_rt_copy(ort, daddr); |
725 | 731 | ||
726 | if (rt) { | 732 | if (rt) { |
727 | struct neighbour *neigh; | ||
728 | int attempts = !in_softirq(); | 733 | int attempts = !in_softirq(); |
729 | 734 | ||
730 | if (!(rt->rt6i_flags&RTF_GATEWAY)) { | 735 | if (!(rt->rt6i_flags & RTF_GATEWAY)) { |
731 | if (ort->rt6i_dst.plen != 128 && | 736 | if (ort->rt6i_dst.plen != 128 && |
732 | ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) | 737 | ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) |
733 | rt->rt6i_flags |= RTF_ANYCAST; | 738 | rt->rt6i_flags |= RTF_ANYCAST; |
734 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); | 739 | rt->rt6i_gateway = *daddr; |
735 | } | 740 | } |
736 | 741 | ||
737 | rt->rt6i_flags |= RTF_CACHE; | 742 | rt->rt6i_flags |= RTF_CACHE; |
738 | 743 | ||
739 | #ifdef CONFIG_IPV6_SUBTREES | 744 | #ifdef CONFIG_IPV6_SUBTREES |
740 | if (rt->rt6i_src.plen && saddr) { | 745 | if (rt->rt6i_src.plen && saddr) { |
741 | ipv6_addr_copy(&rt->rt6i_src.addr, saddr); | 746 | rt->rt6i_src.addr = *saddr; |
742 | rt->rt6i_src.plen = 128; | 747 | rt->rt6i_src.plen = 128; |
743 | } | 748 | } |
744 | #endif | 749 | #endif |
745 | 750 | ||
746 | retry: | 751 | retry: |
747 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | 752 | if (rt6_bind_neighbour(rt, rt->dst.dev)) { |
748 | if (IS_ERR(neigh)) { | 753 | struct net *net = dev_net(rt->dst.dev); |
749 | struct net *net = dev_net(rt->rt6i_dev); | ||
750 | int saved_rt_min_interval = | 754 | int saved_rt_min_interval = |
751 | net->ipv6.sysctl.ip6_rt_gc_min_interval; | 755 | net->ipv6.sysctl.ip6_rt_gc_min_interval; |
752 | int saved_rt_elasticity = | 756 | int saved_rt_elasticity = |
@@ -771,8 +775,6 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, | |||
771 | dst_free(&rt->dst); | 775 | dst_free(&rt->dst); |
772 | return NULL; | 776 | return NULL; |
773 | } | 777 | } |
774 | dst_set_neighbour(&rt->dst, neigh); | ||
775 | |||
776 | } | 778 | } |
777 | 779 | ||
778 | return rt; | 780 | return rt; |
@@ -785,7 +787,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, | |||
785 | 787 | ||
786 | if (rt) { | 788 | if (rt) { |
787 | rt->rt6i_flags |= RTF_CACHE; | 789 | rt->rt6i_flags |= RTF_CACHE; |
788 | dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst))); | 790 | dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_noref_raw(&ort->dst))); |
789 | } | 791 | } |
790 | return rt; | 792 | return rt; |
791 | } | 793 | } |
@@ -819,7 +821,7 @@ restart: | |||
819 | dst_hold(&rt->dst); | 821 | dst_hold(&rt->dst); |
820 | read_unlock_bh(&table->tb6_lock); | 822 | read_unlock_bh(&table->tb6_lock); |
821 | 823 | ||
822 | if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 824 | if (!dst_get_neighbour_noref_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
823 | nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); | 825 | nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); |
824 | else if (!(rt->dst.flags & DST_HOST)) | 826 | else if (!(rt->dst.flags & DST_HOST)) |
825 | nrt = rt6_alloc_clone(rt, &fl6->daddr); | 827 | nrt = rt6_alloc_clone(rt, &fl6->daddr); |
@@ -875,7 +877,7 @@ void ip6_route_input(struct sk_buff *skb) | |||
875 | .flowi6_iif = skb->dev->ifindex, | 877 | .flowi6_iif = skb->dev->ifindex, |
876 | .daddr = iph->daddr, | 878 | .daddr = iph->daddr, |
877 | .saddr = iph->saddr, | 879 | .saddr = iph->saddr, |
878 | .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, | 880 | .flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK, |
879 | .flowi6_mark = skb->mark, | 881 | .flowi6_mark = skb->mark, |
880 | .flowi6_proto = iph->nexthdr, | 882 | .flowi6_proto = iph->nexthdr, |
881 | }; | 883 | }; |
@@ -932,9 +934,9 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori | |||
932 | rt->rt6i_idev = ort->rt6i_idev; | 934 | rt->rt6i_idev = ort->rt6i_idev; |
933 | if (rt->rt6i_idev) | 935 | if (rt->rt6i_idev) |
934 | in6_dev_hold(rt->rt6i_idev); | 936 | in6_dev_hold(rt->rt6i_idev); |
935 | rt->rt6i_expires = 0; | 937 | rt->dst.expires = 0; |
936 | 938 | ||
937 | ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); | 939 | rt->rt6i_gateway = ort->rt6i_gateway; |
938 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; | 940 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; |
939 | rt->rt6i_metric = 0; | 941 | rt->rt6i_metric = 0; |
940 | 942 | ||
@@ -997,7 +999,7 @@ static void ip6_link_failure(struct sk_buff *skb) | |||
997 | 999 | ||
998 | rt = (struct rt6_info *) skb_dst(skb); | 1000 | rt = (struct rt6_info *) skb_dst(skb); |
999 | if (rt) { | 1001 | if (rt) { |
1000 | if (rt->rt6i_flags&RTF_CACHE) { | 1002 | if (rt->rt6i_flags & RTF_CACHE) { |
1001 | dst_set_expires(&rt->dst, 0); | 1003 | dst_set_expires(&rt->dst, 0); |
1002 | rt->rt6i_flags |= RTF_EXPIRES; | 1004 | rt->rt6i_flags |= RTF_EXPIRES; |
1003 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) | 1005 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) |
@@ -1067,34 +1069,38 @@ static DEFINE_SPINLOCK(icmp6_dst_lock); | |||
1067 | 1069 | ||
1068 | struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | 1070 | struct dst_entry *icmp6_dst_alloc(struct net_device *dev, |
1069 | struct neighbour *neigh, | 1071 | struct neighbour *neigh, |
1070 | const struct in6_addr *addr) | 1072 | struct flowi6 *fl6) |
1071 | { | 1073 | { |
1074 | struct dst_entry *dst; | ||
1072 | struct rt6_info *rt; | 1075 | struct rt6_info *rt; |
1073 | struct inet6_dev *idev = in6_dev_get(dev); | 1076 | struct inet6_dev *idev = in6_dev_get(dev); |
1074 | struct net *net = dev_net(dev); | 1077 | struct net *net = dev_net(dev); |
1075 | 1078 | ||
1076 | if (unlikely(idev == NULL)) | 1079 | if (unlikely(!idev)) |
1077 | return NULL; | 1080 | return NULL; |
1078 | 1081 | ||
1079 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); | 1082 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); |
1080 | if (unlikely(rt == NULL)) { | 1083 | if (unlikely(!rt)) { |
1081 | in6_dev_put(idev); | 1084 | in6_dev_put(idev); |
1085 | dst = ERR_PTR(-ENOMEM); | ||
1082 | goto out; | 1086 | goto out; |
1083 | } | 1087 | } |
1084 | 1088 | ||
1085 | if (neigh) | 1089 | if (neigh) |
1086 | neigh_hold(neigh); | 1090 | neigh_hold(neigh); |
1087 | else { | 1091 | else { |
1088 | neigh = ndisc_get_neigh(dev, addr); | 1092 | neigh = ip6_neigh_lookup(&rt->dst, &fl6->daddr); |
1089 | if (IS_ERR(neigh)) | 1093 | if (IS_ERR(neigh)) { |
1090 | neigh = NULL; | 1094 | dst_free(&rt->dst); |
1095 | return ERR_CAST(neigh); | ||
1096 | } | ||
1091 | } | 1097 | } |
1092 | 1098 | ||
1093 | rt->dst.flags |= DST_HOST; | 1099 | rt->dst.flags |= DST_HOST; |
1094 | rt->dst.output = ip6_output; | 1100 | rt->dst.output = ip6_output; |
1095 | dst_set_neighbour(&rt->dst, neigh); | 1101 | dst_set_neighbour(&rt->dst, neigh); |
1096 | atomic_set(&rt->dst.__refcnt, 1); | 1102 | atomic_set(&rt->dst.__refcnt, 1); |
1097 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 1103 | rt->rt6i_dst.addr = fl6->daddr; |
1098 | rt->rt6i_dst.plen = 128; | 1104 | rt->rt6i_dst.plen = 128; |
1099 | rt->rt6i_idev = idev; | 1105 | rt->rt6i_idev = idev; |
1100 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); | 1106 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); |
@@ -1106,8 +1112,10 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1106 | 1112 | ||
1107 | fib6_force_start_gc(net); | 1113 | fib6_force_start_gc(net); |
1108 | 1114 | ||
1115 | dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0); | ||
1116 | |||
1109 | out: | 1117 | out: |
1110 | return &rt->dst; | 1118 | return dst; |
1111 | } | 1119 | } |
1112 | 1120 | ||
1113 | int icmp6_dst_gc(void) | 1121 | int icmp6_dst_gc(void) |
@@ -1237,21 +1245,30 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1237 | if (cfg->fc_metric == 0) | 1245 | if (cfg->fc_metric == 0) |
1238 | cfg->fc_metric = IP6_RT_PRIO_USER; | 1246 | cfg->fc_metric = IP6_RT_PRIO_USER; |
1239 | 1247 | ||
1240 | table = fib6_new_table(net, cfg->fc_table); | 1248 | err = -ENOBUFS; |
1241 | if (table == NULL) { | 1249 | if (cfg->fc_nlinfo.nlh && |
1242 | err = -ENOBUFS; | 1250 | !(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) { |
1243 | goto out; | 1251 | table = fib6_get_table(net, cfg->fc_table); |
1252 | if (!table) { | ||
1253 | printk(KERN_WARNING "IPv6: NLM_F_CREATE should be specified when creating new route\n"); | ||
1254 | table = fib6_new_table(net, cfg->fc_table); | ||
1255 | } | ||
1256 | } else { | ||
1257 | table = fib6_new_table(net, cfg->fc_table); | ||
1244 | } | 1258 | } |
1245 | 1259 | ||
1260 | if (!table) | ||
1261 | goto out; | ||
1262 | |||
1246 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, DST_NOCOUNT); | 1263 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, DST_NOCOUNT); |
1247 | 1264 | ||
1248 | if (rt == NULL) { | 1265 | if (!rt) { |
1249 | err = -ENOMEM; | 1266 | err = -ENOMEM; |
1250 | goto out; | 1267 | goto out; |
1251 | } | 1268 | } |
1252 | 1269 | ||
1253 | rt->dst.obsolete = -1; | 1270 | rt->dst.obsolete = -1; |
1254 | rt->rt6i_expires = (cfg->fc_flags & RTF_EXPIRES) ? | 1271 | rt->dst.expires = (cfg->fc_flags & RTF_EXPIRES) ? |
1255 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : | 1272 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : |
1256 | 0; | 1273 | 0; |
1257 | 1274 | ||
@@ -1294,8 +1311,9 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1294 | they would result in kernel looping; promote them to reject routes | 1311 | they would result in kernel looping; promote them to reject routes |
1295 | */ | 1312 | */ |
1296 | if ((cfg->fc_flags & RTF_REJECT) || | 1313 | if ((cfg->fc_flags & RTF_REJECT) || |
1297 | (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK) | 1314 | (dev && (dev->flags & IFF_LOOPBACK) && |
1298 | && !(cfg->fc_flags&RTF_LOCAL))) { | 1315 | !(addr_type & IPV6_ADDR_LOOPBACK) && |
1316 | !(cfg->fc_flags & RTF_LOCAL))) { | ||
1299 | /* hold loopback dev/idev if we haven't done so. */ | 1317 | /* hold loopback dev/idev if we haven't done so. */ |
1300 | if (dev != net->loopback_dev) { | 1318 | if (dev != net->loopback_dev) { |
1301 | if (dev) { | 1319 | if (dev) { |
@@ -1322,7 +1340,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1322 | int gwa_type; | 1340 | int gwa_type; |
1323 | 1341 | ||
1324 | gw_addr = &cfg->fc_gateway; | 1342 | gw_addr = &cfg->fc_gateway; |
1325 | ipv6_addr_copy(&rt->rt6i_gateway, gw_addr); | 1343 | rt->rt6i_gateway = *gw_addr; |
1326 | gwa_type = ipv6_addr_type(gw_addr); | 1344 | gwa_type = ipv6_addr_type(gw_addr); |
1327 | 1345 | ||
1328 | if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { | 1346 | if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { |
@@ -1336,26 +1354,26 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1336 | some exceptions. --ANK | 1354 | some exceptions. --ANK |
1337 | */ | 1355 | */ |
1338 | err = -EINVAL; | 1356 | err = -EINVAL; |
1339 | if (!(gwa_type&IPV6_ADDR_UNICAST)) | 1357 | if (!(gwa_type & IPV6_ADDR_UNICAST)) |
1340 | goto out; | 1358 | goto out; |
1341 | 1359 | ||
1342 | grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1); | 1360 | grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1); |
1343 | 1361 | ||
1344 | err = -EHOSTUNREACH; | 1362 | err = -EHOSTUNREACH; |
1345 | if (grt == NULL) | 1363 | if (!grt) |
1346 | goto out; | 1364 | goto out; |
1347 | if (dev) { | 1365 | if (dev) { |
1348 | if (dev != grt->rt6i_dev) { | 1366 | if (dev != grt->dst.dev) { |
1349 | dst_release(&grt->dst); | 1367 | dst_release(&grt->dst); |
1350 | goto out; | 1368 | goto out; |
1351 | } | 1369 | } |
1352 | } else { | 1370 | } else { |
1353 | dev = grt->rt6i_dev; | 1371 | dev = grt->dst.dev; |
1354 | idev = grt->rt6i_idev; | 1372 | idev = grt->rt6i_idev; |
1355 | dev_hold(dev); | 1373 | dev_hold(dev); |
1356 | in6_dev_hold(grt->rt6i_idev); | 1374 | in6_dev_hold(grt->rt6i_idev); |
1357 | } | 1375 | } |
1358 | if (!(grt->rt6i_flags&RTF_GATEWAY)) | 1376 | if (!(grt->rt6i_flags & RTF_GATEWAY)) |
1359 | err = 0; | 1377 | err = 0; |
1360 | dst_release(&grt->dst); | 1378 | dst_release(&grt->dst); |
1361 | 1379 | ||
@@ -1363,12 +1381,12 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1363 | goto out; | 1381 | goto out; |
1364 | } | 1382 | } |
1365 | err = -EINVAL; | 1383 | err = -EINVAL; |
1366 | if (dev == NULL || (dev->flags&IFF_LOOPBACK)) | 1384 | if (!dev || (dev->flags & IFF_LOOPBACK)) |
1367 | goto out; | 1385 | goto out; |
1368 | } | 1386 | } |
1369 | 1387 | ||
1370 | err = -ENODEV; | 1388 | err = -ENODEV; |
1371 | if (dev == NULL) | 1389 | if (!dev) |
1372 | goto out; | 1390 | goto out; |
1373 | 1391 | ||
1374 | if (!ipv6_addr_any(&cfg->fc_prefsrc)) { | 1392 | if (!ipv6_addr_any(&cfg->fc_prefsrc)) { |
@@ -1376,18 +1394,15 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1376 | err = -EINVAL; | 1394 | err = -EINVAL; |
1377 | goto out; | 1395 | goto out; |
1378 | } | 1396 | } |
1379 | ipv6_addr_copy(&rt->rt6i_prefsrc.addr, &cfg->fc_prefsrc); | 1397 | rt->rt6i_prefsrc.addr = cfg->fc_prefsrc; |
1380 | rt->rt6i_prefsrc.plen = 128; | 1398 | rt->rt6i_prefsrc.plen = 128; |
1381 | } else | 1399 | } else |
1382 | rt->rt6i_prefsrc.plen = 0; | 1400 | rt->rt6i_prefsrc.plen = 0; |
1383 | 1401 | ||
1384 | if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { | 1402 | if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { |
1385 | struct neighbour *n = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); | 1403 | err = rt6_bind_neighbour(rt, dev); |
1386 | if (IS_ERR(n)) { | 1404 | if (err) |
1387 | err = PTR_ERR(n); | ||
1388 | goto out; | 1405 | goto out; |
1389 | } | ||
1390 | dst_set_neighbour(&rt->dst, n); | ||
1391 | } | 1406 | } |
1392 | 1407 | ||
1393 | rt->rt6i_flags = cfg->fc_flags; | 1408 | rt->rt6i_flags = cfg->fc_flags; |
@@ -1433,7 +1448,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1433 | { | 1448 | { |
1434 | int err; | 1449 | int err; |
1435 | struct fib6_table *table; | 1450 | struct fib6_table *table; |
1436 | struct net *net = dev_net(rt->rt6i_dev); | 1451 | struct net *net = dev_net(rt->dst.dev); |
1437 | 1452 | ||
1438 | if (rt == net->ipv6.ip6_null_entry) | 1453 | if (rt == net->ipv6.ip6_null_entry) |
1439 | return -ENOENT; | 1454 | return -ENOENT; |
@@ -1452,7 +1467,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1452 | int ip6_del_rt(struct rt6_info *rt) | 1467 | int ip6_del_rt(struct rt6_info *rt) |
1453 | { | 1468 | { |
1454 | struct nl_info info = { | 1469 | struct nl_info info = { |
1455 | .nl_net = dev_net(rt->rt6i_dev), | 1470 | .nl_net = dev_net(rt->dst.dev), |
1456 | }; | 1471 | }; |
1457 | return __ip6_del_rt(rt, &info); | 1472 | return __ip6_del_rt(rt, &info); |
1458 | } | 1473 | } |
@@ -1465,7 +1480,7 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
1465 | int err = -ESRCH; | 1480 | int err = -ESRCH; |
1466 | 1481 | ||
1467 | table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table); | 1482 | table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table); |
1468 | if (table == NULL) | 1483 | if (!table) |
1469 | return err; | 1484 | return err; |
1470 | 1485 | ||
1471 | read_lock_bh(&table->tb6_lock); | 1486 | read_lock_bh(&table->tb6_lock); |
@@ -1477,8 +1492,8 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
1477 | if (fn) { | 1492 | if (fn) { |
1478 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { | 1493 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
1479 | if (cfg->fc_ifindex && | 1494 | if (cfg->fc_ifindex && |
1480 | (rt->rt6i_dev == NULL || | 1495 | (!rt->dst.dev || |
1481 | rt->rt6i_dev->ifindex != cfg->fc_ifindex)) | 1496 | rt->dst.dev->ifindex != cfg->fc_ifindex)) |
1482 | continue; | 1497 | continue; |
1483 | if (cfg->fc_flags & RTF_GATEWAY && | 1498 | if (cfg->fc_flags & RTF_GATEWAY && |
1484 | !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway)) | 1499 | !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway)) |
@@ -1540,7 +1555,7 @@ restart: | |||
1540 | continue; | 1555 | continue; |
1541 | if (!(rt->rt6i_flags & RTF_GATEWAY)) | 1556 | if (!(rt->rt6i_flags & RTF_GATEWAY)) |
1542 | continue; | 1557 | continue; |
1543 | if (fl6->flowi6_oif != rt->rt6i_dev->ifindex) | 1558 | if (fl6->flowi6_oif != rt->dst.dev->ifindex) |
1544 | continue; | 1559 | continue; |
1545 | if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) | 1560 | if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) |
1546 | continue; | 1561 | continue; |
@@ -1573,7 +1588,7 @@ static struct rt6_info *ip6_route_redirect(const struct in6_addr *dest, | |||
1573 | }, | 1588 | }, |
1574 | }; | 1589 | }; |
1575 | 1590 | ||
1576 | ipv6_addr_copy(&rdfl.gateway, gateway); | 1591 | rdfl.gateway = *gateway; |
1577 | 1592 | ||
1578 | if (rt6_need_strict(dest)) | 1593 | if (rt6_need_strict(dest)) |
1579 | flags |= RT6_LOOKUP_F_IFACE; | 1594 | flags |= RT6_LOOKUP_F_IFACE; |
@@ -1618,18 +1633,18 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, | |||
1618 | dst_confirm(&rt->dst); | 1633 | dst_confirm(&rt->dst); |
1619 | 1634 | ||
1620 | /* Duplicate redirect: silently ignore. */ | 1635 | /* Duplicate redirect: silently ignore. */ |
1621 | if (neigh == dst_get_neighbour_raw(&rt->dst)) | 1636 | if (neigh == dst_get_neighbour_noref_raw(&rt->dst)) |
1622 | goto out; | 1637 | goto out; |
1623 | 1638 | ||
1624 | nrt = ip6_rt_copy(rt, dest); | 1639 | nrt = ip6_rt_copy(rt, dest); |
1625 | if (nrt == NULL) | 1640 | if (!nrt) |
1626 | goto out; | 1641 | goto out; |
1627 | 1642 | ||
1628 | nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE; | 1643 | nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE; |
1629 | if (on_link) | 1644 | if (on_link) |
1630 | nrt->rt6i_flags &= ~RTF_GATEWAY; | 1645 | nrt->rt6i_flags &= ~RTF_GATEWAY; |
1631 | 1646 | ||
1632 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); | 1647 | nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key; |
1633 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); | 1648 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); |
1634 | 1649 | ||
1635 | if (ip6_ins_rt(nrt)) | 1650 | if (ip6_ins_rt(nrt)) |
@@ -1639,7 +1654,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, | |||
1639 | netevent.new = &nrt->dst; | 1654 | netevent.new = &nrt->dst; |
1640 | call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); | 1655 | call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); |
1641 | 1656 | ||
1642 | if (rt->rt6i_flags&RTF_CACHE) { | 1657 | if (rt->rt6i_flags & RTF_CACHE) { |
1643 | ip6_del_rt(rt); | 1658 | ip6_del_rt(rt); |
1644 | return; | 1659 | return; |
1645 | } | 1660 | } |
@@ -1660,7 +1675,7 @@ static void rt6_do_pmtu_disc(const struct in6_addr *daddr, const struct in6_addr | |||
1660 | int allfrag = 0; | 1675 | int allfrag = 0; |
1661 | again: | 1676 | again: |
1662 | rt = rt6_lookup(net, daddr, saddr, ifindex, 0); | 1677 | rt = rt6_lookup(net, daddr, saddr, ifindex, 0); |
1663 | if (rt == NULL) | 1678 | if (!rt) |
1664 | return; | 1679 | return; |
1665 | 1680 | ||
1666 | if (rt6_check_expired(rt)) { | 1681 | if (rt6_check_expired(rt)) { |
@@ -1710,7 +1725,7 @@ again: | |||
1710 | 1. It is connected route. Action: COW | 1725 | 1. It is connected route. Action: COW |
1711 | 2. It is gatewayed route or NONEXTHOP route. Action: clone it. | 1726 | 2. It is gatewayed route or NONEXTHOP route. Action: clone it. |
1712 | */ | 1727 | */ |
1713 | if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 1728 | if (!dst_get_neighbour_noref_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
1714 | nrt = rt6_alloc_cow(rt, daddr, saddr); | 1729 | nrt = rt6_alloc_cow(rt, daddr, saddr); |
1715 | else | 1730 | else |
1716 | nrt = rt6_alloc_clone(rt, daddr); | 1731 | nrt = rt6_alloc_clone(rt, daddr); |
@@ -1766,7 +1781,7 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad | |||
1766 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | 1781 | static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, |
1767 | const struct in6_addr *dest) | 1782 | const struct in6_addr *dest) |
1768 | { | 1783 | { |
1769 | struct net *net = dev_net(ort->rt6i_dev); | 1784 | struct net *net = dev_net(ort->dst.dev); |
1770 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, | 1785 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, |
1771 | ort->dst.dev, 0); | 1786 | ort->dst.dev, 0); |
1772 | 1787 | ||
@@ -1775,7 +1790,7 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | |||
1775 | rt->dst.output = ort->dst.output; | 1790 | rt->dst.output = ort->dst.output; |
1776 | rt->dst.flags |= DST_HOST; | 1791 | rt->dst.flags |= DST_HOST; |
1777 | 1792 | ||
1778 | ipv6_addr_copy(&rt->rt6i_dst.addr, dest); | 1793 | rt->rt6i_dst.addr = *dest; |
1779 | rt->rt6i_dst.plen = 128; | 1794 | rt->rt6i_dst.plen = 128; |
1780 | dst_copy_metrics(&rt->dst, &ort->dst); | 1795 | dst_copy_metrics(&rt->dst, &ort->dst); |
1781 | rt->dst.error = ort->dst.error; | 1796 | rt->dst.error = ort->dst.error; |
@@ -1783,9 +1798,9 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | |||
1783 | if (rt->rt6i_idev) | 1798 | if (rt->rt6i_idev) |
1784 | in6_dev_hold(rt->rt6i_idev); | 1799 | in6_dev_hold(rt->rt6i_idev); |
1785 | rt->dst.lastuse = jiffies; | 1800 | rt->dst.lastuse = jiffies; |
1786 | rt->rt6i_expires = 0; | 1801 | rt->dst.expires = 0; |
1787 | 1802 | ||
1788 | ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); | 1803 | rt->rt6i_gateway = ort->rt6i_gateway; |
1789 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; | 1804 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; |
1790 | rt->rt6i_metric = 0; | 1805 | rt->rt6i_metric = 0; |
1791 | 1806 | ||
@@ -1808,7 +1823,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
1808 | struct fib6_table *table; | 1823 | struct fib6_table *table; |
1809 | 1824 | ||
1810 | table = fib6_get_table(net, RT6_TABLE_INFO); | 1825 | table = fib6_get_table(net, RT6_TABLE_INFO); |
1811 | if (table == NULL) | 1826 | if (!table) |
1812 | return NULL; | 1827 | return NULL; |
1813 | 1828 | ||
1814 | write_lock_bh(&table->tb6_lock); | 1829 | write_lock_bh(&table->tb6_lock); |
@@ -1817,7 +1832,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
1817 | goto out; | 1832 | goto out; |
1818 | 1833 | ||
1819 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { | 1834 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
1820 | if (rt->rt6i_dev->ifindex != ifindex) | 1835 | if (rt->dst.dev->ifindex != ifindex) |
1821 | continue; | 1836 | continue; |
1822 | if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) | 1837 | if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY)) |
1823 | continue; | 1838 | continue; |
@@ -1848,8 +1863,8 @@ static struct rt6_info *rt6_add_route_info(struct net *net, | |||
1848 | .fc_nlinfo.nl_net = net, | 1863 | .fc_nlinfo.nl_net = net, |
1849 | }; | 1864 | }; |
1850 | 1865 | ||
1851 | ipv6_addr_copy(&cfg.fc_dst, prefix); | 1866 | cfg.fc_dst = *prefix; |
1852 | ipv6_addr_copy(&cfg.fc_gateway, gwaddr); | 1867 | cfg.fc_gateway = *gwaddr; |
1853 | 1868 | ||
1854 | /* We should treat it as a default route if prefix length is 0. */ | 1869 | /* We should treat it as a default route if prefix length is 0. */ |
1855 | if (!prefixlen) | 1870 | if (!prefixlen) |
@@ -1867,12 +1882,12 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev | |||
1867 | struct fib6_table *table; | 1882 | struct fib6_table *table; |
1868 | 1883 | ||
1869 | table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT); | 1884 | table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT); |
1870 | if (table == NULL) | 1885 | if (!table) |
1871 | return NULL; | 1886 | return NULL; |
1872 | 1887 | ||
1873 | write_lock_bh(&table->tb6_lock); | 1888 | write_lock_bh(&table->tb6_lock); |
1874 | for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) { | 1889 | for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) { |
1875 | if (dev == rt->rt6i_dev && | 1890 | if (dev == rt->dst.dev && |
1876 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && | 1891 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && |
1877 | ipv6_addr_equal(&rt->rt6i_gateway, addr)) | 1892 | ipv6_addr_equal(&rt->rt6i_gateway, addr)) |
1878 | break; | 1893 | break; |
@@ -1898,7 +1913,7 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr, | |||
1898 | .fc_nlinfo.nl_net = dev_net(dev), | 1913 | .fc_nlinfo.nl_net = dev_net(dev), |
1899 | }; | 1914 | }; |
1900 | 1915 | ||
1901 | ipv6_addr_copy(&cfg.fc_gateway, gwaddr); | 1916 | cfg.fc_gateway = *gwaddr; |
1902 | 1917 | ||
1903 | ip6_route_add(&cfg); | 1918 | ip6_route_add(&cfg); |
1904 | 1919 | ||
@@ -1912,7 +1927,7 @@ void rt6_purge_dflt_routers(struct net *net) | |||
1912 | 1927 | ||
1913 | /* NOTE: Keep consistent with rt6_get_dflt_router */ | 1928 | /* NOTE: Keep consistent with rt6_get_dflt_router */ |
1914 | table = fib6_get_table(net, RT6_TABLE_DFLT); | 1929 | table = fib6_get_table(net, RT6_TABLE_DFLT); |
1915 | if (table == NULL) | 1930 | if (!table) |
1916 | return; | 1931 | return; |
1917 | 1932 | ||
1918 | restart: | 1933 | restart: |
@@ -1944,9 +1959,9 @@ static void rtmsg_to_fib6_config(struct net *net, | |||
1944 | 1959 | ||
1945 | cfg->fc_nlinfo.nl_net = net; | 1960 | cfg->fc_nlinfo.nl_net = net; |
1946 | 1961 | ||
1947 | ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst); | 1962 | cfg->fc_dst = rtmsg->rtmsg_dst; |
1948 | ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src); | 1963 | cfg->fc_src = rtmsg->rtmsg_src; |
1949 | ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway); | 1964 | cfg->fc_gateway = rtmsg->rtmsg_gateway; |
1950 | } | 1965 | } |
1951 | 1966 | ||
1952 | int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) | 1967 | int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) |
@@ -2045,14 +2060,14 @@ static int ip6_pkt_prohibit_out(struct sk_buff *skb) | |||
2045 | 2060 | ||
2046 | struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | 2061 | struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, |
2047 | const struct in6_addr *addr, | 2062 | const struct in6_addr *addr, |
2048 | int anycast) | 2063 | bool anycast) |
2049 | { | 2064 | { |
2050 | struct net *net = dev_net(idev->dev); | 2065 | struct net *net = dev_net(idev->dev); |
2051 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, | 2066 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, |
2052 | net->loopback_dev, 0); | 2067 | net->loopback_dev, 0); |
2053 | struct neighbour *neigh; | 2068 | int err; |
2054 | 2069 | ||
2055 | if (rt == NULL) { | 2070 | if (!rt) { |
2056 | if (net_ratelimit()) | 2071 | if (net_ratelimit()) |
2057 | pr_warning("IPv6: Maximum number of routes reached," | 2072 | pr_warning("IPv6: Maximum number of routes reached," |
2058 | " consider increasing route/max_size.\n"); | 2073 | " consider increasing route/max_size.\n"); |
@@ -2072,15 +2087,13 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2072 | rt->rt6i_flags |= RTF_ANYCAST; | 2087 | rt->rt6i_flags |= RTF_ANYCAST; |
2073 | else | 2088 | else |
2074 | rt->rt6i_flags |= RTF_LOCAL; | 2089 | rt->rt6i_flags |= RTF_LOCAL; |
2075 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | 2090 | err = rt6_bind_neighbour(rt, rt->dst.dev); |
2076 | if (IS_ERR(neigh)) { | 2091 | if (err) { |
2077 | dst_free(&rt->dst); | 2092 | dst_free(&rt->dst); |
2078 | 2093 | return ERR_PTR(err); | |
2079 | return ERR_CAST(neigh); | ||
2080 | } | 2094 | } |
2081 | dst_set_neighbour(&rt->dst, neigh); | ||
2082 | 2095 | ||
2083 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 2096 | rt->rt6i_dst.addr = *addr; |
2084 | rt->rt6i_dst.plen = 128; | 2097 | rt->rt6i_dst.plen = 128; |
2085 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); | 2098 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); |
2086 | 2099 | ||
@@ -2098,7 +2111,7 @@ int ip6_route_get_saddr(struct net *net, | |||
2098 | struct inet6_dev *idev = ip6_dst_idev((struct dst_entry*)rt); | 2111 | struct inet6_dev *idev = ip6_dst_idev((struct dst_entry*)rt); |
2099 | int err = 0; | 2112 | int err = 0; |
2100 | if (rt->rt6i_prefsrc.plen) | 2113 | if (rt->rt6i_prefsrc.plen) |
2101 | ipv6_addr_copy(saddr, &rt->rt6i_prefsrc.addr); | 2114 | *saddr = rt->rt6i_prefsrc.addr; |
2102 | else | 2115 | else |
2103 | err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, | 2116 | err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, |
2104 | daddr, prefs, saddr); | 2117 | daddr, prefs, saddr); |
@@ -2118,7 +2131,7 @@ static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg) | |||
2118 | struct net *net = ((struct arg_dev_net_ip *)arg)->net; | 2131 | struct net *net = ((struct arg_dev_net_ip *)arg)->net; |
2119 | struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr; | 2132 | struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr; |
2120 | 2133 | ||
2121 | if (((void *)rt->rt6i_dev == dev || dev == NULL) && | 2134 | if (((void *)rt->dst.dev == dev || !dev) && |
2122 | rt != net->ipv6.ip6_null_entry && | 2135 | rt != net->ipv6.ip6_null_entry && |
2123 | ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) { | 2136 | ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) { |
2124 | /* remove prefsrc entry */ | 2137 | /* remove prefsrc entry */ |
@@ -2148,11 +2161,10 @@ static int fib6_ifdown(struct rt6_info *rt, void *arg) | |||
2148 | const struct arg_dev_net *adn = arg; | 2161 | const struct arg_dev_net *adn = arg; |
2149 | const struct net_device *dev = adn->dev; | 2162 | const struct net_device *dev = adn->dev; |
2150 | 2163 | ||
2151 | if ((rt->rt6i_dev == dev || dev == NULL) && | 2164 | if ((rt->dst.dev == dev || !dev) && |
2152 | rt != adn->net->ipv6.ip6_null_entry) { | 2165 | rt != adn->net->ipv6.ip6_null_entry) |
2153 | RT6_TRACE("deleted by ifdown %p\n", rt); | ||
2154 | return -1; | 2166 | return -1; |
2155 | } | 2167 | |
2156 | return 0; | 2168 | return 0; |
2157 | } | 2169 | } |
2158 | 2170 | ||
@@ -2185,7 +2197,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
2185 | */ | 2197 | */ |
2186 | 2198 | ||
2187 | idev = __in6_dev_get(arg->dev); | 2199 | idev = __in6_dev_get(arg->dev); |
2188 | if (idev == NULL) | 2200 | if (!idev) |
2189 | return 0; | 2201 | return 0; |
2190 | 2202 | ||
2191 | /* For administrative MTU increase, there is no way to discover | 2203 | /* For administrative MTU increase, there is no way to discover |
@@ -2202,7 +2214,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
2202 | also have the lowest MTU, TOO BIG MESSAGE will be lead to | 2214 | also have the lowest MTU, TOO BIG MESSAGE will be lead to |
2203 | PMTU discouvery. | 2215 | PMTU discouvery. |
2204 | */ | 2216 | */ |
2205 | if (rt->rt6i_dev == arg->dev && | 2217 | if (rt->dst.dev == arg->dev && |
2206 | !dst_metric_locked(&rt->dst, RTAX_MTU) && | 2218 | !dst_metric_locked(&rt->dst, RTAX_MTU) && |
2207 | (dst_mtu(&rt->dst) >= arg->mtu || | 2219 | (dst_mtu(&rt->dst) >= arg->mtu || |
2208 | (dst_mtu(&rt->dst) < arg->mtu && | 2220 | (dst_mtu(&rt->dst) < arg->mtu && |
@@ -2351,11 +2363,13 @@ static int rt6_fill_node(struct net *net, | |||
2351 | int iif, int type, u32 pid, u32 seq, | 2363 | int iif, int type, u32 pid, u32 seq, |
2352 | int prefix, int nowait, unsigned int flags) | 2364 | int prefix, int nowait, unsigned int flags) |
2353 | { | 2365 | { |
2366 | const struct inet_peer *peer; | ||
2354 | struct rtmsg *rtm; | 2367 | struct rtmsg *rtm; |
2355 | struct nlmsghdr *nlh; | 2368 | struct nlmsghdr *nlh; |
2356 | long expires; | 2369 | long expires; |
2357 | u32 table; | 2370 | u32 table; |
2358 | struct neighbour *n; | 2371 | struct neighbour *n; |
2372 | u32 ts, tsage; | ||
2359 | 2373 | ||
2360 | if (prefix) { /* user wants prefix routes only */ | 2374 | if (prefix) { /* user wants prefix routes only */ |
2361 | if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { | 2375 | if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { |
@@ -2365,7 +2379,7 @@ static int rt6_fill_node(struct net *net, | |||
2365 | } | 2379 | } |
2366 | 2380 | ||
2367 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags); | 2381 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags); |
2368 | if (nlh == NULL) | 2382 | if (!nlh) |
2369 | return -EMSGSIZE; | 2383 | return -EMSGSIZE; |
2370 | 2384 | ||
2371 | rtm = nlmsg_data(nlh); | 2385 | rtm = nlmsg_data(nlh); |
@@ -2379,25 +2393,25 @@ static int rt6_fill_node(struct net *net, | |||
2379 | table = RT6_TABLE_UNSPEC; | 2393 | table = RT6_TABLE_UNSPEC; |
2380 | rtm->rtm_table = table; | 2394 | rtm->rtm_table = table; |
2381 | NLA_PUT_U32(skb, RTA_TABLE, table); | 2395 | NLA_PUT_U32(skb, RTA_TABLE, table); |
2382 | if (rt->rt6i_flags&RTF_REJECT) | 2396 | if (rt->rt6i_flags & RTF_REJECT) |
2383 | rtm->rtm_type = RTN_UNREACHABLE; | 2397 | rtm->rtm_type = RTN_UNREACHABLE; |
2384 | else if (rt->rt6i_flags&RTF_LOCAL) | 2398 | else if (rt->rt6i_flags & RTF_LOCAL) |
2385 | rtm->rtm_type = RTN_LOCAL; | 2399 | rtm->rtm_type = RTN_LOCAL; |
2386 | else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK)) | 2400 | else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK)) |
2387 | rtm->rtm_type = RTN_LOCAL; | 2401 | rtm->rtm_type = RTN_LOCAL; |
2388 | else | 2402 | else |
2389 | rtm->rtm_type = RTN_UNICAST; | 2403 | rtm->rtm_type = RTN_UNICAST; |
2390 | rtm->rtm_flags = 0; | 2404 | rtm->rtm_flags = 0; |
2391 | rtm->rtm_scope = RT_SCOPE_UNIVERSE; | 2405 | rtm->rtm_scope = RT_SCOPE_UNIVERSE; |
2392 | rtm->rtm_protocol = rt->rt6i_protocol; | 2406 | rtm->rtm_protocol = rt->rt6i_protocol; |
2393 | if (rt->rt6i_flags&RTF_DYNAMIC) | 2407 | if (rt->rt6i_flags & RTF_DYNAMIC) |
2394 | rtm->rtm_protocol = RTPROT_REDIRECT; | 2408 | rtm->rtm_protocol = RTPROT_REDIRECT; |
2395 | else if (rt->rt6i_flags & RTF_ADDRCONF) | 2409 | else if (rt->rt6i_flags & RTF_ADDRCONF) |
2396 | rtm->rtm_protocol = RTPROT_KERNEL; | 2410 | rtm->rtm_protocol = RTPROT_KERNEL; |
2397 | else if (rt->rt6i_flags&RTF_DEFAULT) | 2411 | else if (rt->rt6i_flags & RTF_DEFAULT) |
2398 | rtm->rtm_protocol = RTPROT_RA; | 2412 | rtm->rtm_protocol = RTPROT_RA; |
2399 | 2413 | ||
2400 | if (rt->rt6i_flags&RTF_CACHE) | 2414 | if (rt->rt6i_flags & RTF_CACHE) |
2401 | rtm->rtm_flags |= RTM_F_CLONED; | 2415 | rtm->rtm_flags |= RTM_F_CLONED; |
2402 | 2416 | ||
2403 | if (dst) { | 2417 | if (dst) { |
@@ -2437,7 +2451,7 @@ static int rt6_fill_node(struct net *net, | |||
2437 | 2451 | ||
2438 | if (rt->rt6i_prefsrc.plen) { | 2452 | if (rt->rt6i_prefsrc.plen) { |
2439 | struct in6_addr saddr_buf; | 2453 | struct in6_addr saddr_buf; |
2440 | ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr); | 2454 | saddr_buf = rt->rt6i_prefsrc.addr; |
2441 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | 2455 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); |
2442 | } | 2456 | } |
2443 | 2457 | ||
@@ -2445,24 +2459,31 @@ static int rt6_fill_node(struct net *net, | |||
2445 | goto nla_put_failure; | 2459 | goto nla_put_failure; |
2446 | 2460 | ||
2447 | rcu_read_lock(); | 2461 | rcu_read_lock(); |
2448 | n = dst_get_neighbour(&rt->dst); | 2462 | n = dst_get_neighbour_noref(&rt->dst); |
2449 | if (n) | 2463 | if (n) |
2450 | NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key); | 2464 | NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key); |
2451 | rcu_read_unlock(); | 2465 | rcu_read_unlock(); |
2452 | 2466 | ||
2453 | if (rt->dst.dev) | 2467 | if (rt->dst.dev) |
2454 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); | 2468 | NLA_PUT_U32(skb, RTA_OIF, rt->dst.dev->ifindex); |
2455 | 2469 | ||
2456 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); | 2470 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); |
2457 | 2471 | ||
2458 | if (!(rt->rt6i_flags & RTF_EXPIRES)) | 2472 | if (!(rt->rt6i_flags & RTF_EXPIRES)) |
2459 | expires = 0; | 2473 | expires = 0; |
2460 | else if (rt->rt6i_expires - jiffies < INT_MAX) | 2474 | else if (rt->dst.expires - jiffies < INT_MAX) |
2461 | expires = rt->rt6i_expires - jiffies; | 2475 | expires = rt->dst.expires - jiffies; |
2462 | else | 2476 | else |
2463 | expires = INT_MAX; | 2477 | expires = INT_MAX; |
2464 | 2478 | ||
2465 | if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, | 2479 | peer = rt->rt6i_peer; |
2480 | ts = tsage = 0; | ||
2481 | if (peer && peer->tcp_ts_stamp) { | ||
2482 | ts = peer->tcp_ts; | ||
2483 | tsage = get_seconds() - peer->tcp_ts_stamp; | ||
2484 | } | ||
2485 | |||
2486 | if (rtnl_put_cacheinfo(skb, &rt->dst, 0, ts, tsage, | ||
2466 | expires, rt->dst.error) < 0) | 2487 | expires, rt->dst.error) < 0) |
2467 | goto nla_put_failure; | 2488 | goto nla_put_failure; |
2468 | 2489 | ||
@@ -2511,14 +2532,14 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2511 | if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) | 2532 | if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) |
2512 | goto errout; | 2533 | goto errout; |
2513 | 2534 | ||
2514 | ipv6_addr_copy(&fl6.saddr, nla_data(tb[RTA_SRC])); | 2535 | fl6.saddr = *(struct in6_addr *)nla_data(tb[RTA_SRC]); |
2515 | } | 2536 | } |
2516 | 2537 | ||
2517 | if (tb[RTA_DST]) { | 2538 | if (tb[RTA_DST]) { |
2518 | if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr)) | 2539 | if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr)) |
2519 | goto errout; | 2540 | goto errout; |
2520 | 2541 | ||
2521 | ipv6_addr_copy(&fl6.daddr, nla_data(tb[RTA_DST])); | 2542 | fl6.daddr = *(struct in6_addr *)nla_data(tb[RTA_DST]); |
2522 | } | 2543 | } |
2523 | 2544 | ||
2524 | if (tb[RTA_IIF]) | 2545 | if (tb[RTA_IIF]) |
@@ -2537,7 +2558,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2537 | } | 2558 | } |
2538 | 2559 | ||
2539 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | 2560 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
2540 | if (skb == NULL) { | 2561 | if (!skb) { |
2541 | err = -ENOBUFS; | 2562 | err = -ENOBUFS; |
2542 | goto errout; | 2563 | goto errout; |
2543 | } | 2564 | } |
@@ -2572,10 +2593,10 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2572 | int err; | 2593 | int err; |
2573 | 2594 | ||
2574 | err = -ENOBUFS; | 2595 | err = -ENOBUFS; |
2575 | seq = info->nlh != NULL ? info->nlh->nlmsg_seq : 0; | 2596 | seq = info->nlh ? info->nlh->nlmsg_seq : 0; |
2576 | 2597 | ||
2577 | skb = nlmsg_new(rt6_nlmsg_size(), gfp_any()); | 2598 | skb = nlmsg_new(rt6_nlmsg_size(), gfp_any()); |
2578 | if (skb == NULL) | 2599 | if (!skb) |
2579 | goto errout; | 2600 | goto errout; |
2580 | 2601 | ||
2581 | err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, | 2602 | err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, |
@@ -2642,7 +2663,7 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2642 | seq_puts(m, "00000000000000000000000000000000 00 "); | 2663 | seq_puts(m, "00000000000000000000000000000000 00 "); |
2643 | #endif | 2664 | #endif |
2644 | rcu_read_lock(); | 2665 | rcu_read_lock(); |
2645 | n = dst_get_neighbour(&rt->dst); | 2666 | n = dst_get_neighbour_noref(&rt->dst); |
2646 | if (n) { | 2667 | if (n) { |
2647 | seq_printf(m, "%pi6", n->primary_key); | 2668 | seq_printf(m, "%pi6", n->primary_key); |
2648 | } else { | 2669 | } else { |
@@ -2652,14 +2673,14 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2652 | seq_printf(m, " %08x %08x %08x %08x %8s\n", | 2673 | seq_printf(m, " %08x %08x %08x %08x %8s\n", |
2653 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), | 2674 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), |
2654 | rt->dst.__use, rt->rt6i_flags, | 2675 | rt->dst.__use, rt->rt6i_flags, |
2655 | rt->rt6i_dev ? rt->rt6i_dev->name : ""); | 2676 | rt->dst.dev ? rt->dst.dev->name : ""); |
2656 | return 0; | 2677 | return 0; |
2657 | } | 2678 | } |
2658 | 2679 | ||
2659 | static int ipv6_route_show(struct seq_file *m, void *v) | 2680 | static int ipv6_route_show(struct seq_file *m, void *v) |
2660 | { | 2681 | { |
2661 | struct net *net = (struct net *)m->private; | 2682 | struct net *net = (struct net *)m->private; |
2662 | fib6_clean_all(net, rt6_info_route, 0, m); | 2683 | fib6_clean_all_ro(net, rt6_info_route, 0, m); |
2663 | return 0; | 2684 | return 0; |
2664 | } | 2685 | } |
2665 | 2686 | ||
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 96f3623618e3..3b6dac956bb0 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -91,7 +91,7 @@ struct pcpu_tstats { | |||
91 | unsigned long rx_bytes; | 91 | unsigned long rx_bytes; |
92 | unsigned long tx_packets; | 92 | unsigned long tx_packets; |
93 | unsigned long tx_bytes; | 93 | unsigned long tx_bytes; |
94 | }; | 94 | } __attribute__((aligned(4*sizeof(unsigned long)))); |
95 | 95 | ||
96 | static struct net_device_stats *ipip6_get_stats(struct net_device *dev) | 96 | static struct net_device_stats *ipip6_get_stats(struct net_device *dev) |
97 | { | 97 | { |
@@ -682,7 +682,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
682 | struct neighbour *neigh = NULL; | 682 | struct neighbour *neigh = NULL; |
683 | 683 | ||
684 | if (skb_dst(skb)) | 684 | if (skb_dst(skb)) |
685 | neigh = dst_get_neighbour(skb_dst(skb)); | 685 | neigh = dst_get_neighbour_noref(skb_dst(skb)); |
686 | 686 | ||
687 | if (neigh == NULL) { | 687 | if (neigh == NULL) { |
688 | if (net_ratelimit()) | 688 | if (net_ratelimit()) |
@@ -707,7 +707,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
707 | struct neighbour *neigh = NULL; | 707 | struct neighbour *neigh = NULL; |
708 | 708 | ||
709 | if (skb_dst(skb)) | 709 | if (skb_dst(skb)) |
710 | neigh = dst_get_neighbour(skb_dst(skb)); | 710 | neigh = dst_get_neighbour_noref(skb_dst(skb)); |
711 | 711 | ||
712 | if (neigh == NULL) { | 712 | if (neigh == NULL) { |
713 | if (net_ratelimit()) | 713 | if (net_ratelimit()) |
@@ -916,7 +916,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
916 | goto done; | 916 | goto done; |
917 | #ifdef CONFIG_IPV6_SIT_6RD | 917 | #ifdef CONFIG_IPV6_SIT_6RD |
918 | } else { | 918 | } else { |
919 | ipv6_addr_copy(&ip6rd.prefix, &t->ip6rd.prefix); | 919 | ip6rd.prefix = t->ip6rd.prefix; |
920 | ip6rd.relay_prefix = t->ip6rd.relay_prefix; | 920 | ip6rd.relay_prefix = t->ip6rd.relay_prefix; |
921 | ip6rd.prefixlen = t->ip6rd.prefixlen; | 921 | ip6rd.prefixlen = t->ip6rd.prefixlen; |
922 | ip6rd.relay_prefixlen = t->ip6rd.relay_prefixlen; | 922 | ip6rd.relay_prefixlen = t->ip6rd.relay_prefixlen; |
@@ -1084,7 +1084,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1084 | if (relay_prefix != ip6rd.relay_prefix) | 1084 | if (relay_prefix != ip6rd.relay_prefix) |
1085 | goto done; | 1085 | goto done; |
1086 | 1086 | ||
1087 | ipv6_addr_copy(&t->ip6rd.prefix, &prefix); | 1087 | t->ip6rd.prefix = prefix; |
1088 | t->ip6rd.relay_prefix = relay_prefix; | 1088 | t->ip6rd.relay_prefix = relay_prefix; |
1089 | t->ip6rd.prefixlen = ip6rd.prefixlen; | 1089 | t->ip6rd.prefixlen = ip6rd.prefixlen; |
1090 | t->ip6rd.relay_prefixlen = ip6rd.relay_prefixlen; | 1090 | t->ip6rd.relay_prefixlen = ip6rd.relay_prefixlen; |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 5a0d6648bbbc..8e951d8d3b81 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -200,8 +200,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
200 | req->mss = mss; | 200 | req->mss = mss; |
201 | ireq->rmt_port = th->source; | 201 | ireq->rmt_port = th->source; |
202 | ireq->loc_port = th->dest; | 202 | ireq->loc_port = th->dest; |
203 | ipv6_addr_copy(&ireq6->rmt_addr, &ipv6_hdr(skb)->saddr); | 203 | ireq6->rmt_addr = ipv6_hdr(skb)->saddr; |
204 | ipv6_addr_copy(&ireq6->loc_addr, &ipv6_hdr(skb)->daddr); | 204 | ireq6->loc_addr = ipv6_hdr(skb)->daddr; |
205 | if (ipv6_opt_accepted(sk, skb) || | 205 | if (ipv6_opt_accepted(sk, skb) || |
206 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | 206 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || |
207 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | 207 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { |
@@ -237,9 +237,9 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
237 | struct flowi6 fl6; | 237 | struct flowi6 fl6; |
238 | memset(&fl6, 0, sizeof(fl6)); | 238 | memset(&fl6, 0, sizeof(fl6)); |
239 | fl6.flowi6_proto = IPPROTO_TCP; | 239 | fl6.flowi6_proto = IPPROTO_TCP; |
240 | ipv6_addr_copy(&fl6.daddr, &ireq6->rmt_addr); | 240 | fl6.daddr = ireq6->rmt_addr; |
241 | final_p = fl6_update_dst(&fl6, np->opt, &final); | 241 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
242 | ipv6_addr_copy(&fl6.saddr, &ireq6->loc_addr); | 242 | fl6.saddr = ireq6->loc_addr; |
243 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 243 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
244 | fl6.flowi6_mark = sk->sk_mark; | 244 | fl6.flowi6_mark = sk->sk_mark; |
245 | fl6.fl6_dport = inet_rsk(req)->rmt_port; | 245 | fl6.fl6_dport = inet_rsk(req)->rmt_port; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 2dea4bb7b54a..906c7ca43542 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <net/netdma.h> | 62 | #include <net/netdma.h> |
63 | #include <net/inet_common.h> | 63 | #include <net/inet_common.h> |
64 | #include <net/secure_seq.h> | 64 | #include <net/secure_seq.h> |
65 | #include <net/tcp_memcontrol.h> | ||
65 | 66 | ||
66 | #include <asm/uaccess.h> | 67 | #include <asm/uaccess.h> |
67 | 68 | ||
@@ -153,7 +154,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
153 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); | 154 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
154 | if (flowlabel == NULL) | 155 | if (flowlabel == NULL) |
155 | return -EINVAL; | 156 | return -EINVAL; |
156 | ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); | 157 | usin->sin6_addr = flowlabel->dst; |
157 | fl6_sock_release(flowlabel); | 158 | fl6_sock_release(flowlabel); |
158 | } | 159 | } |
159 | } | 160 | } |
@@ -195,7 +196,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
195 | tp->write_seq = 0; | 196 | tp->write_seq = 0; |
196 | } | 197 | } |
197 | 198 | ||
198 | ipv6_addr_copy(&np->daddr, &usin->sin6_addr); | 199 | np->daddr = usin->sin6_addr; |
199 | np->flow_label = fl6.flowlabel; | 200 | np->flow_label = fl6.flowlabel; |
200 | 201 | ||
201 | /* | 202 | /* |
@@ -244,9 +245,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
244 | saddr = &np->rcv_saddr; | 245 | saddr = &np->rcv_saddr; |
245 | 246 | ||
246 | fl6.flowi6_proto = IPPROTO_TCP; | 247 | fl6.flowi6_proto = IPPROTO_TCP; |
247 | ipv6_addr_copy(&fl6.daddr, &np->daddr); | 248 | fl6.daddr = np->daddr; |
248 | ipv6_addr_copy(&fl6.saddr, | 249 | fl6.saddr = saddr ? *saddr : np->saddr; |
249 | (saddr ? saddr : &np->saddr)); | ||
250 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 250 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
251 | fl6.flowi6_mark = sk->sk_mark; | 251 | fl6.flowi6_mark = sk->sk_mark; |
252 | fl6.fl6_dport = usin->sin6_port; | 252 | fl6.fl6_dport = usin->sin6_port; |
@@ -264,11 +264,11 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
264 | 264 | ||
265 | if (saddr == NULL) { | 265 | if (saddr == NULL) { |
266 | saddr = &fl6.saddr; | 266 | saddr = &fl6.saddr; |
267 | ipv6_addr_copy(&np->rcv_saddr, saddr); | 267 | np->rcv_saddr = *saddr; |
268 | } | 268 | } |
269 | 269 | ||
270 | /* set the source address */ | 270 | /* set the source address */ |
271 | ipv6_addr_copy(&np->saddr, saddr); | 271 | np->saddr = *saddr; |
272 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; | 272 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; |
273 | 273 | ||
274 | sk->sk_gso_type = SKB_GSO_TCPV6; | 274 | sk->sk_gso_type = SKB_GSO_TCPV6; |
@@ -398,8 +398,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
398 | */ | 398 | */ |
399 | memset(&fl6, 0, sizeof(fl6)); | 399 | memset(&fl6, 0, sizeof(fl6)); |
400 | fl6.flowi6_proto = IPPROTO_TCP; | 400 | fl6.flowi6_proto = IPPROTO_TCP; |
401 | ipv6_addr_copy(&fl6.daddr, &np->daddr); | 401 | fl6.daddr = np->daddr; |
402 | ipv6_addr_copy(&fl6.saddr, &np->saddr); | 402 | fl6.saddr = np->saddr; |
403 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 403 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
404 | fl6.flowi6_mark = sk->sk_mark; | 404 | fl6.flowi6_mark = sk->sk_mark; |
405 | fl6.fl6_dport = inet->inet_dport; | 405 | fl6.fl6_dport = inet->inet_dport; |
@@ -489,8 +489,8 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
489 | 489 | ||
490 | memset(&fl6, 0, sizeof(fl6)); | 490 | memset(&fl6, 0, sizeof(fl6)); |
491 | fl6.flowi6_proto = IPPROTO_TCP; | 491 | fl6.flowi6_proto = IPPROTO_TCP; |
492 | ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr); | 492 | fl6.daddr = treq->rmt_addr; |
493 | ipv6_addr_copy(&fl6.saddr, &treq->loc_addr); | 493 | fl6.saddr = treq->loc_addr; |
494 | fl6.flowlabel = 0; | 494 | fl6.flowlabel = 0; |
495 | fl6.flowi6_oif = treq->iif; | 495 | fl6.flowi6_oif = treq->iif; |
496 | fl6.flowi6_mark = sk->sk_mark; | 496 | fl6.flowi6_mark = sk->sk_mark; |
@@ -512,7 +512,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
512 | if (skb) { | 512 | if (skb) { |
513 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); | 513 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); |
514 | 514 | ||
515 | ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr); | 515 | fl6.daddr = treq->rmt_addr; |
516 | err = ip6_xmit(sk, skb, &fl6, opt, np->tclass); | 516 | err = ip6_xmit(sk, skb, &fl6, opt, np->tclass); |
517 | err = net_xmit_eval(err); | 517 | err = net_xmit_eval(err); |
518 | } | 518 | } |
@@ -617,8 +617,7 @@ static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer, | |||
617 | tp->md5sig_info->alloced6++; | 617 | tp->md5sig_info->alloced6++; |
618 | } | 618 | } |
619 | 619 | ||
620 | ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr, | 620 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr = *peer; |
621 | peer); | ||
622 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.key = newkey; | 621 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.key = newkey; |
623 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.keylen = newkeylen; | 622 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.keylen = newkeylen; |
624 | 623 | ||
@@ -750,8 +749,8 @@ static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, | |||
750 | 749 | ||
751 | bp = &hp->md5_blk.ip6; | 750 | bp = &hp->md5_blk.ip6; |
752 | /* 1. TCP pseudo-header (RFC2460) */ | 751 | /* 1. TCP pseudo-header (RFC2460) */ |
753 | ipv6_addr_copy(&bp->saddr, saddr); | 752 | bp->saddr = *saddr; |
754 | ipv6_addr_copy(&bp->daddr, daddr); | 753 | bp->daddr = *daddr; |
755 | bp->protocol = cpu_to_be32(IPPROTO_TCP); | 754 | bp->protocol = cpu_to_be32(IPPROTO_TCP); |
756 | bp->len = cpu_to_be32(nbytes); | 755 | bp->len = cpu_to_be32(nbytes); |
757 | 756 | ||
@@ -1039,8 +1038,8 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1039 | #endif | 1038 | #endif |
1040 | 1039 | ||
1041 | memset(&fl6, 0, sizeof(fl6)); | 1040 | memset(&fl6, 0, sizeof(fl6)); |
1042 | ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->saddr); | 1041 | fl6.daddr = ipv6_hdr(skb)->saddr; |
1043 | ipv6_addr_copy(&fl6.saddr, &ipv6_hdr(skb)->daddr); | 1042 | fl6.saddr = ipv6_hdr(skb)->daddr; |
1044 | 1043 | ||
1045 | buff->ip_summed = CHECKSUM_PARTIAL; | 1044 | buff->ip_summed = CHECKSUM_PARTIAL; |
1046 | buff->csum = 0; | 1045 | buff->csum = 0; |
@@ -1250,8 +1249,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1250 | tcp_openreq_init(req, &tmp_opt, skb); | 1249 | tcp_openreq_init(req, &tmp_opt, skb); |
1251 | 1250 | ||
1252 | treq = inet6_rsk(req); | 1251 | treq = inet6_rsk(req); |
1253 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); | 1252 | treq->rmt_addr = ipv6_hdr(skb)->saddr; |
1254 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); | 1253 | treq->loc_addr = ipv6_hdr(skb)->daddr; |
1255 | if (!want_cookie || tmp_opt.tstamp_ok) | 1254 | if (!want_cookie || tmp_opt.tstamp_ok) |
1256 | TCP_ECN_create_request(req, tcp_hdr(skb)); | 1255 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
1257 | 1256 | ||
@@ -1381,7 +1380,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1381 | 1380 | ||
1382 | ipv6_addr_set_v4mapped(newinet->inet_saddr, &newnp->saddr); | 1381 | ipv6_addr_set_v4mapped(newinet->inet_saddr, &newnp->saddr); |
1383 | 1382 | ||
1384 | ipv6_addr_copy(&newnp->rcv_saddr, &newnp->saddr); | 1383 | newnp->rcv_saddr = newnp->saddr; |
1385 | 1384 | ||
1386 | inet_csk(newsk)->icsk_af_ops = &ipv6_mapped; | 1385 | inet_csk(newsk)->icsk_af_ops = &ipv6_mapped; |
1387 | newsk->sk_backlog_rcv = tcp_v4_do_rcv; | 1386 | newsk->sk_backlog_rcv = tcp_v4_do_rcv; |
@@ -1445,9 +1444,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1445 | 1444 | ||
1446 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); | 1445 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); |
1447 | 1446 | ||
1448 | ipv6_addr_copy(&newnp->daddr, &treq->rmt_addr); | 1447 | newnp->daddr = treq->rmt_addr; |
1449 | ipv6_addr_copy(&newnp->saddr, &treq->loc_addr); | 1448 | newnp->saddr = treq->loc_addr; |
1450 | ipv6_addr_copy(&newnp->rcv_saddr, &treq->loc_addr); | 1449 | newnp->rcv_saddr = treq->loc_addr; |
1451 | newsk->sk_bound_dev_if = treq->iif; | 1450 | newsk->sk_bound_dev_if = treq->iif; |
1452 | 1451 | ||
1453 | /* Now IPv6 options... | 1452 | /* Now IPv6 options... |
@@ -1996,7 +1995,8 @@ static int tcp_v6_init_sock(struct sock *sk) | |||
1996 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; | 1995 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; |
1997 | 1996 | ||
1998 | local_bh_disable(); | 1997 | local_bh_disable(); |
1999 | percpu_counter_inc(&tcp_sockets_allocated); | 1998 | sock_update_memcg(sk); |
1999 | sk_sockets_allocated_inc(sk); | ||
2000 | local_bh_enable(); | 2000 | local_bh_enable(); |
2001 | 2001 | ||
2002 | return 0; | 2002 | return 0; |
@@ -2215,7 +2215,6 @@ struct proto tcpv6_prot = { | |||
2215 | .memory_allocated = &tcp_memory_allocated, | 2215 | .memory_allocated = &tcp_memory_allocated, |
2216 | .memory_pressure = &tcp_memory_pressure, | 2216 | .memory_pressure = &tcp_memory_pressure, |
2217 | .orphan_count = &tcp_orphan_count, | 2217 | .orphan_count = &tcp_orphan_count, |
2218 | .sysctl_mem = sysctl_tcp_mem, | ||
2219 | .sysctl_wmem = sysctl_tcp_wmem, | 2218 | .sysctl_wmem = sysctl_tcp_wmem, |
2220 | .sysctl_rmem = sysctl_tcp_rmem, | 2219 | .sysctl_rmem = sysctl_tcp_rmem, |
2221 | .max_header = MAX_TCP_HEADER, | 2220 | .max_header = MAX_TCP_HEADER, |
@@ -2229,6 +2228,9 @@ struct proto tcpv6_prot = { | |||
2229 | .compat_setsockopt = compat_tcp_setsockopt, | 2228 | .compat_setsockopt = compat_tcp_setsockopt, |
2230 | .compat_getsockopt = compat_tcp_getsockopt, | 2229 | .compat_getsockopt = compat_tcp_getsockopt, |
2231 | #endif | 2230 | #endif |
2231 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM | ||
2232 | .proto_cgroup = tcp_proto_cgroup, | ||
2233 | #endif | ||
2232 | }; | 2234 | }; |
2233 | 2235 | ||
2234 | static const struct inet6_protocol tcpv6_protocol = { | 2236 | static const struct inet6_protocol tcpv6_protocol = { |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 8c2541915183..4f96b5c63685 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -238,7 +238,7 @@ exact_match: | |||
238 | return result; | 238 | return result; |
239 | } | 239 | } |
240 | 240 | ||
241 | static struct sock *__udp6_lib_lookup(struct net *net, | 241 | struct sock *__udp6_lib_lookup(struct net *net, |
242 | const struct in6_addr *saddr, __be16 sport, | 242 | const struct in6_addr *saddr, __be16 sport, |
243 | const struct in6_addr *daddr, __be16 dport, | 243 | const struct in6_addr *daddr, __be16 dport, |
244 | int dif, struct udp_table *udptable) | 244 | int dif, struct udp_table *udptable) |
@@ -305,6 +305,7 @@ begin: | |||
305 | rcu_read_unlock(); | 305 | rcu_read_unlock(); |
306 | return result; | 306 | return result; |
307 | } | 307 | } |
308 | EXPORT_SYMBOL_GPL(__udp6_lib_lookup); | ||
308 | 309 | ||
309 | static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, | 310 | static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, |
310 | __be16 sport, __be16 dport, | 311 | __be16 sport, __be16 dport, |
@@ -418,8 +419,7 @@ try_again: | |||
418 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, | 419 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, |
419 | &sin6->sin6_addr); | 420 | &sin6->sin6_addr); |
420 | else { | 421 | else { |
421 | ipv6_addr_copy(&sin6->sin6_addr, | 422 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; |
422 | &ipv6_hdr(skb)->saddr); | ||
423 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 423 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
424 | sin6->sin6_scope_id = IP6CB(skb)->iif; | 424 | sin6->sin6_scope_id = IP6CB(skb)->iif; |
425 | } | 425 | } |
@@ -539,7 +539,9 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
539 | goto drop; | 539 | goto drop; |
540 | } | 540 | } |
541 | 541 | ||
542 | if ((rc = ip_queue_rcv_skb(sk, skb)) < 0) { | 542 | skb_dst_drop(skb); |
543 | rc = sock_queue_rcv_skb(sk, skb); | ||
544 | if (rc < 0) { | ||
543 | /* Note that an ENOMEM error is charged twice */ | 545 | /* Note that an ENOMEM error is charged twice */ |
544 | if (rc == -ENOMEM) | 546 | if (rc == -ENOMEM) |
545 | UDP6_INC_STATS_BH(sock_net(sk), | 547 | UDP6_INC_STATS_BH(sock_net(sk), |
@@ -1114,11 +1116,11 @@ do_udp_sendmsg: | |||
1114 | 1116 | ||
1115 | fl6.flowi6_proto = sk->sk_protocol; | 1117 | fl6.flowi6_proto = sk->sk_protocol; |
1116 | if (!ipv6_addr_any(daddr)) | 1118 | if (!ipv6_addr_any(daddr)) |
1117 | ipv6_addr_copy(&fl6.daddr, daddr); | 1119 | fl6.daddr = *daddr; |
1118 | else | 1120 | else |
1119 | fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | 1121 | fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ |
1120 | if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) | 1122 | if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) |
1121 | ipv6_addr_copy(&fl6.saddr, &np->saddr); | 1123 | fl6.saddr = np->saddr; |
1122 | fl6.fl6_sport = inet->inet_sport; | 1124 | fl6.fl6_sport = inet->inet_sport; |
1123 | 1125 | ||
1124 | final_p = fl6_update_dst(&fl6, opt, &final); | 1126 | final_p = fl6_update_dst(&fl6, opt, &final); |
@@ -1299,7 +1301,8 @@ static int udp6_ufo_send_check(struct sk_buff *skb) | |||
1299 | return 0; | 1301 | return 0; |
1300 | } | 1302 | } |
1301 | 1303 | ||
1302 | static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) | 1304 | static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, |
1305 | netdev_features_t features) | ||
1303 | { | 1306 | { |
1304 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 1307 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
1305 | unsigned int mss; | 1308 | unsigned int mss; |
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index 3437d7d4eed6..a81ce9450750 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c | |||
@@ -72,8 +72,8 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) | |||
72 | top_iph->nexthdr = IPPROTO_BEETPH; | 72 | top_iph->nexthdr = IPPROTO_BEETPH; |
73 | } | 73 | } |
74 | 74 | ||
75 | ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); | 75 | top_iph->saddr = *(struct in6_addr *)&x->props.saddr; |
76 | ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); | 76 | top_iph->daddr = *(struct in6_addr *)&x->id.daddr; |
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
79 | 79 | ||
@@ -99,8 +99,8 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) | |||
99 | 99 | ||
100 | ip6h = ipv6_hdr(skb); | 100 | ip6h = ipv6_hdr(skb); |
101 | ip6h->payload_len = htons(skb->len - size); | 101 | ip6h->payload_len = htons(skb->len - size); |
102 | ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6); | 102 | ip6h->daddr = *(struct in6_addr *)&x->sel.daddr.a6; |
103 | ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6); | 103 | ip6h->saddr = *(struct in6_addr *)&x->sel.saddr.a6; |
104 | err = 0; | 104 | err = 0; |
105 | out: | 105 | out: |
106 | return err; | 106 | return err; |
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 4d6edff0498f..261e6e6f487e 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c | |||
@@ -55,8 +55,8 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
55 | dsfield &= ~INET_ECN_MASK; | 55 | dsfield &= ~INET_ECN_MASK; |
56 | ipv6_change_dsfield(top_iph, 0, dsfield); | 56 | ipv6_change_dsfield(top_iph, 0, dsfield); |
57 | top_iph->hop_limit = ip6_dst_hoplimit(dst->child); | 57 | top_iph->hop_limit = ip6_dst_hoplimit(dst->child); |
58 | ipv6_addr_copy(&top_iph->saddr, (const struct in6_addr *)&x->props.saddr); | 58 | top_iph->saddr = *(struct in6_addr *)&x->props.saddr; |
59 | ipv6_addr_copy(&top_iph->daddr, (const struct in6_addr *)&x->id.daddr); | 59 | top_iph->daddr = *(struct in6_addr *)&x->id.daddr; |
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index faae41737fca..4eeff89c1aaa 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -49,7 +49,7 @@ static void xfrm6_local_rxpmtu(struct sk_buff *skb, u32 mtu) | |||
49 | struct sock *sk = skb->sk; | 49 | struct sock *sk = skb->sk; |
50 | 50 | ||
51 | fl6.flowi6_oif = sk->sk_bound_dev_if; | 51 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
52 | ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->daddr); | 52 | fl6.daddr = ipv6_hdr(skb)->daddr; |
53 | 53 | ||
54 | ipv6_local_rxpmtu(sk, &fl6, mtu); | 54 | ipv6_local_rxpmtu(sk, &fl6, mtu); |
55 | } | 55 | } |
@@ -60,7 +60,7 @@ static void xfrm6_local_error(struct sk_buff *skb, u32 mtu) | |||
60 | struct sock *sk = skb->sk; | 60 | struct sock *sk = skb->sk; |
61 | 61 | ||
62 | fl6.fl6_dport = inet_sk(sk)->inet_dport; | 62 | fl6.fl6_dport = inet_sk(sk)->inet_dport; |
63 | ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->daddr); | 63 | fl6.daddr = ipv6_hdr(skb)->daddr; |
64 | 64 | ||
65 | ipv6_local_error(sk, EMSGSIZE, &fl6, mtu); | 65 | ipv6_local_error(sk, EMSGSIZE, &fl6, mtu); |
66 | } | 66 | } |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index d879f7efbd10..8ea65e032733 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -132,8 +132,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
132 | memset(fl6, 0, sizeof(struct flowi6)); | 132 | memset(fl6, 0, sizeof(struct flowi6)); |
133 | fl6->flowi6_mark = skb->mark; | 133 | fl6->flowi6_mark = skb->mark; |
134 | 134 | ||
135 | ipv6_addr_copy(&fl6->daddr, reverse ? &hdr->saddr : &hdr->daddr); | 135 | fl6->daddr = reverse ? hdr->saddr : hdr->daddr; |
136 | ipv6_addr_copy(&fl6->saddr, reverse ? &hdr->daddr : &hdr->saddr); | 136 | fl6->saddr = reverse ? hdr->daddr : hdr->saddr; |
137 | 137 | ||
138 | while (nh + offset + 1 < skb->data || | 138 | while (nh + offset + 1 < skb->data || |
139 | pskb_may_pull(skb, nh + offset + 1 - skb->data)) { | 139 | pskb_may_pull(skb, nh + offset + 1 - skb->data)) { |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index f2d72b8a3faa..3f2f7c4ab721 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -27,8 +27,8 @@ __xfrm6_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl) | |||
27 | 27 | ||
28 | /* Initialize temporary selector matching only | 28 | /* Initialize temporary selector matching only |
29 | * to current session. */ | 29 | * to current session. */ |
30 | ipv6_addr_copy((struct in6_addr *)&sel->daddr, &fl6->daddr); | 30 | *(struct in6_addr *)&sel->daddr = fl6->daddr; |
31 | ipv6_addr_copy((struct in6_addr *)&sel->saddr, &fl6->saddr); | 31 | *(struct in6_addr *)&sel->saddr = fl6->saddr; |
32 | sel->dport = xfrm_flowi_dport(fl, &fl6->uli); | 32 | sel->dport = xfrm_flowi_dport(fl, &fl6->uli); |
33 | sel->dport_mask = htons(0xffff); | 33 | sel->dport_mask = htons(0xffff); |
34 | sel->sport = xfrm_flowi_sport(fl, &fl6->uli); | 34 | sel->sport = xfrm_flowi_sport(fl, &fl6->uli); |