diff options
Diffstat (limited to 'net/ipv6')
33 files changed, 1109 insertions, 864 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 5b189c97c2fc..3daaf3c7703c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -420,9 +420,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
420 | dev->type == ARPHRD_TUNNEL6 || | 420 | dev->type == ARPHRD_TUNNEL6 || |
421 | dev->type == ARPHRD_SIT || | 421 | dev->type == ARPHRD_SIT || |
422 | dev->type == ARPHRD_NONE) { | 422 | dev->type == ARPHRD_NONE) { |
423 | printk(KERN_INFO | ||
424 | "%s: Disabled Privacy Extensions\n", | ||
425 | dev->name); | ||
426 | ndev->cnf.use_tempaddr = -1; | 423 | ndev->cnf.use_tempaddr = -1; |
427 | } else { | 424 | } else { |
428 | in6_dev_hold(ndev); | 425 | in6_dev_hold(ndev); |
@@ -721,12 +718,9 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
721 | struct inet6_ifaddr *ifa, *ifn; | 718 | struct inet6_ifaddr *ifa, *ifn; |
722 | struct inet6_dev *idev = ifp->idev; | 719 | struct inet6_dev *idev = ifp->idev; |
723 | int state; | 720 | int state; |
724 | int hash; | ||
725 | int deleted = 0, onlink = 0; | 721 | int deleted = 0, onlink = 0; |
726 | unsigned long expires = jiffies; | 722 | unsigned long expires = jiffies; |
727 | 723 | ||
728 | hash = ipv6_addr_hash(&ifp->addr); | ||
729 | |||
730 | spin_lock_bh(&ifp->state_lock); | 724 | spin_lock_bh(&ifp->state_lock); |
731 | state = ifp->state; | 725 | state = ifp->state; |
732 | ifp->state = INET6_IFADDR_STATE_DEAD; | 726 | ifp->state = INET6_IFADDR_STATE_DEAD; |
@@ -2664,14 +2658,12 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2664 | struct net *net = dev_net(dev); | 2658 | struct net *net = dev_net(dev); |
2665 | struct inet6_dev *idev; | 2659 | struct inet6_dev *idev; |
2666 | struct inet6_ifaddr *ifa; | 2660 | struct inet6_ifaddr *ifa; |
2667 | LIST_HEAD(keep_list); | 2661 | int state, i; |
2668 | int state; | ||
2669 | 2662 | ||
2670 | ASSERT_RTNL(); | 2663 | ASSERT_RTNL(); |
2671 | 2664 | ||
2672 | /* Flush routes if device is being removed or it is not loopback */ | 2665 | rt6_ifdown(net, dev); |
2673 | if (how || !(dev->flags & IFF_LOOPBACK)) | 2666 | neigh_ifdown(&nd_tbl, dev); |
2674 | rt6_ifdown(net, dev); | ||
2675 | 2667 | ||
2676 | idev = __in6_dev_get(dev); | 2668 | idev = __in6_dev_get(dev); |
2677 | if (idev == NULL) | 2669 | if (idev == NULL) |
@@ -2692,6 +2684,23 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2692 | 2684 | ||
2693 | } | 2685 | } |
2694 | 2686 | ||
2687 | /* Step 2: clear hash table */ | ||
2688 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { | ||
2689 | struct hlist_head *h = &inet6_addr_lst[i]; | ||
2690 | struct hlist_node *n; | ||
2691 | |||
2692 | spin_lock_bh(&addrconf_hash_lock); | ||
2693 | restart: | ||
2694 | hlist_for_each_entry_rcu(ifa, n, h, addr_lst) { | ||
2695 | if (ifa->idev == idev) { | ||
2696 | hlist_del_init_rcu(&ifa->addr_lst); | ||
2697 | addrconf_del_timer(ifa); | ||
2698 | goto restart; | ||
2699 | } | ||
2700 | } | ||
2701 | spin_unlock_bh(&addrconf_hash_lock); | ||
2702 | } | ||
2703 | |||
2695 | write_lock_bh(&idev->lock); | 2704 | write_lock_bh(&idev->lock); |
2696 | 2705 | ||
2697 | /* Step 2: clear flags for stateless addrconf */ | 2706 | /* Step 2: clear flags for stateless addrconf */ |
@@ -2725,52 +2734,23 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2725 | struct inet6_ifaddr, if_list); | 2734 | struct inet6_ifaddr, if_list); |
2726 | addrconf_del_timer(ifa); | 2735 | addrconf_del_timer(ifa); |
2727 | 2736 | ||
2728 | /* If just doing link down, and address is permanent | 2737 | list_del(&ifa->if_list); |
2729 | and not link-local, then retain it. */ | ||
2730 | if (!how && | ||
2731 | (ifa->flags&IFA_F_PERMANENT) && | ||
2732 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | ||
2733 | list_move_tail(&ifa->if_list, &keep_list); | ||
2734 | |||
2735 | /* If not doing DAD on this address, just keep it. */ | ||
2736 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || | ||
2737 | idev->cnf.accept_dad <= 0 || | ||
2738 | (ifa->flags & IFA_F_NODAD)) | ||
2739 | continue; | ||
2740 | 2738 | ||
2741 | /* If it was tentative already, no need to notify */ | 2739 | write_unlock_bh(&idev->lock); |
2742 | if (ifa->flags & IFA_F_TENTATIVE) | ||
2743 | continue; | ||
2744 | 2740 | ||
2745 | /* Flag it for later restoration when link comes up */ | 2741 | spin_lock_bh(&ifa->state_lock); |
2746 | ifa->flags |= IFA_F_TENTATIVE; | 2742 | state = ifa->state; |
2747 | ifa->state = INET6_IFADDR_STATE_DAD; | 2743 | ifa->state = INET6_IFADDR_STATE_DEAD; |
2748 | } else { | 2744 | spin_unlock_bh(&ifa->state_lock); |
2749 | list_del(&ifa->if_list); | ||
2750 | |||
2751 | /* clear hash table */ | ||
2752 | spin_lock_bh(&addrconf_hash_lock); | ||
2753 | hlist_del_init_rcu(&ifa->addr_lst); | ||
2754 | spin_unlock_bh(&addrconf_hash_lock); | ||
2755 | |||
2756 | write_unlock_bh(&idev->lock); | ||
2757 | spin_lock_bh(&ifa->state_lock); | ||
2758 | state = ifa->state; | ||
2759 | ifa->state = INET6_IFADDR_STATE_DEAD; | ||
2760 | spin_unlock_bh(&ifa->state_lock); | ||
2761 | |||
2762 | if (state != INET6_IFADDR_STATE_DEAD) { | ||
2763 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | ||
2764 | atomic_notifier_call_chain(&inet6addr_chain, | ||
2765 | NETDEV_DOWN, ifa); | ||
2766 | } | ||
2767 | 2745 | ||
2768 | in6_ifa_put(ifa); | 2746 | if (state != INET6_IFADDR_STATE_DEAD) { |
2769 | write_lock_bh(&idev->lock); | 2747 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
2748 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | ||
2770 | } | 2749 | } |
2771 | } | 2750 | in6_ifa_put(ifa); |
2772 | 2751 | ||
2773 | list_splice(&keep_list, &idev->addr_list); | 2752 | write_lock_bh(&idev->lock); |
2753 | } | ||
2774 | 2754 | ||
2775 | write_unlock_bh(&idev->lock); | 2755 | write_unlock_bh(&idev->lock); |
2776 | 2756 | ||
@@ -4159,8 +4139,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4159 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4139 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
4160 | dst_hold(&ifp->rt->dst); | 4140 | dst_hold(&ifp->rt->dst); |
4161 | 4141 | ||
4162 | if (ifp->state == INET6_IFADDR_STATE_DEAD && | 4142 | if (ip6_del_rt(ifp->rt)) |
4163 | ip6_del_rt(ifp->rt)) | ||
4164 | dst_free(&ifp->rt->dst); | 4143 | dst_free(&ifp->rt->dst); |
4165 | break; | 4144 | break; |
4166 | } | 4145 | } |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 978e80e2c4a8..4b13d5d8890e 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -644,41 +644,34 @@ EXPORT_SYMBOL(inet6_unregister_protosw); | |||
644 | 644 | ||
645 | int inet6_sk_rebuild_header(struct sock *sk) | 645 | int inet6_sk_rebuild_header(struct sock *sk) |
646 | { | 646 | { |
647 | int err; | ||
648 | struct dst_entry *dst; | ||
649 | struct ipv6_pinfo *np = inet6_sk(sk); | 647 | struct ipv6_pinfo *np = inet6_sk(sk); |
648 | struct dst_entry *dst; | ||
650 | 649 | ||
651 | dst = __sk_dst_check(sk, np->dst_cookie); | 650 | dst = __sk_dst_check(sk, np->dst_cookie); |
652 | 651 | ||
653 | if (dst == NULL) { | 652 | if (dst == NULL) { |
654 | struct inet_sock *inet = inet_sk(sk); | 653 | struct inet_sock *inet = inet_sk(sk); |
655 | struct in6_addr *final_p, final; | 654 | struct in6_addr *final_p, final; |
656 | struct flowi fl; | 655 | struct flowi6 fl6; |
657 | 656 | ||
658 | memset(&fl, 0, sizeof(fl)); | 657 | memset(&fl6, 0, sizeof(fl6)); |
659 | fl.proto = sk->sk_protocol; | 658 | fl6.flowi6_proto = sk->sk_protocol; |
660 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 659 | ipv6_addr_copy(&fl6.daddr, &np->daddr); |
661 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 660 | ipv6_addr_copy(&fl6.saddr, &np->saddr); |
662 | fl.fl6_flowlabel = np->flow_label; | 661 | fl6.flowlabel = np->flow_label; |
663 | fl.oif = sk->sk_bound_dev_if; | 662 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
664 | fl.mark = sk->sk_mark; | 663 | fl6.flowi6_mark = sk->sk_mark; |
665 | fl.fl_ip_dport = inet->inet_dport; | 664 | fl6.fl6_dport = inet->inet_dport; |
666 | fl.fl_ip_sport = inet->inet_sport; | 665 | fl6.fl6_sport = inet->inet_sport; |
667 | security_sk_classify_flow(sk, &fl); | 666 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
668 | 667 | ||
669 | final_p = fl6_update_dst(&fl, np->opt, &final); | 668 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
670 | 669 | ||
671 | err = ip6_dst_lookup(sk, &dst, &fl); | 670 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); |
672 | if (err) { | 671 | if (IS_ERR(dst)) { |
673 | sk->sk_route_caps = 0; | 672 | sk->sk_route_caps = 0; |
674 | return err; | 673 | sk->sk_err_soft = -PTR_ERR(dst); |
675 | } | 674 | return PTR_ERR(dst); |
676 | if (final_p) | ||
677 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
678 | |||
679 | if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) { | ||
680 | sk->sk_err_soft = -err; | ||
681 | return err; | ||
682 | } | 675 | } |
683 | 676 | ||
684 | __ip6_dst_store(sk, dst, NULL, NULL); | 677 | __ip6_dst_store(sk, dst, NULL, NULL); |
@@ -772,7 +765,7 @@ out: | |||
772 | return err; | 765 | return err; |
773 | } | 766 | } |
774 | 767 | ||
775 | static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) | 768 | static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, u32 features) |
776 | { | 769 | { |
777 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 770 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
778 | struct ipv6hdr *ipv6h; | 771 | struct ipv6hdr *ipv6h; |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 1aba54ae53c4..2195ae651923 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -409,7 +409,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
409 | 409 | ||
410 | ah->reserved = 0; | 410 | ah->reserved = 0; |
411 | ah->spi = x->id.spi; | 411 | ah->spi = x->id.spi; |
412 | ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output); | 412 | ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); |
413 | 413 | ||
414 | sg_init_table(sg, nfrags); | 414 | sg_init_table(sg, nfrags); |
415 | skb_to_sgvec(skb, sg, 0, skb->len); | 415 | skb_to_sgvec(skb, sg, 0, skb->len); |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 320bdb877eed..16560336eb72 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -40,7 +40,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
40 | struct ipv6_pinfo *np = inet6_sk(sk); | 40 | struct ipv6_pinfo *np = inet6_sk(sk); |
41 | struct in6_addr *daddr, *final_p, final; | 41 | struct in6_addr *daddr, *final_p, final; |
42 | struct dst_entry *dst; | 42 | struct dst_entry *dst; |
43 | struct flowi fl; | 43 | struct flowi6 fl6; |
44 | struct ip6_flowlabel *flowlabel = NULL; | 44 | struct ip6_flowlabel *flowlabel = NULL; |
45 | struct ipv6_txoptions *opt; | 45 | struct ipv6_txoptions *opt; |
46 | int addr_type; | 46 | int addr_type; |
@@ -59,11 +59,11 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
59 | if (usin->sin6_family != AF_INET6) | 59 | if (usin->sin6_family != AF_INET6) |
60 | return -EAFNOSUPPORT; | 60 | return -EAFNOSUPPORT; |
61 | 61 | ||
62 | memset(&fl, 0, sizeof(fl)); | 62 | memset(&fl6, 0, sizeof(fl6)); |
63 | if (np->sndflow) { | 63 | if (np->sndflow) { |
64 | fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; | 64 | fl6.flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; |
65 | if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { | 65 | if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { |
66 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); | 66 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
67 | if (flowlabel == NULL) | 67 | if (flowlabel == NULL) |
68 | return -EINVAL; | 68 | return -EINVAL; |
69 | ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); | 69 | ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); |
@@ -137,7 +137,7 @@ ipv4_connected: | |||
137 | } | 137 | } |
138 | 138 | ||
139 | ipv6_addr_copy(&np->daddr, daddr); | 139 | ipv6_addr_copy(&np->daddr, daddr); |
140 | np->flow_label = fl.fl6_flowlabel; | 140 | np->flow_label = fl6.flowlabel; |
141 | 141 | ||
142 | inet->inet_dport = usin->sin6_port; | 142 | inet->inet_dport = usin->sin6_port; |
143 | 143 | ||
@@ -146,53 +146,46 @@ ipv4_connected: | |||
146 | * destination cache for it. | 146 | * destination cache for it. |
147 | */ | 147 | */ |
148 | 148 | ||
149 | fl.proto = sk->sk_protocol; | 149 | fl6.flowi6_proto = sk->sk_protocol; |
150 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 150 | ipv6_addr_copy(&fl6.daddr, &np->daddr); |
151 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 151 | ipv6_addr_copy(&fl6.saddr, &np->saddr); |
152 | fl.oif = sk->sk_bound_dev_if; | 152 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
153 | fl.mark = sk->sk_mark; | 153 | fl6.flowi6_mark = sk->sk_mark; |
154 | fl.fl_ip_dport = inet->inet_dport; | 154 | fl6.fl6_dport = inet->inet_dport; |
155 | fl.fl_ip_sport = inet->inet_sport; | 155 | fl6.fl6_sport = inet->inet_sport; |
156 | 156 | ||
157 | if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST)) | 157 | if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST)) |
158 | fl.oif = np->mcast_oif; | 158 | fl6.flowi6_oif = np->mcast_oif; |
159 | 159 | ||
160 | security_sk_classify_flow(sk, &fl); | 160 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
161 | 161 | ||
162 | opt = flowlabel ? flowlabel->opt : np->opt; | 162 | opt = flowlabel ? flowlabel->opt : np->opt; |
163 | final_p = fl6_update_dst(&fl, opt, &final); | 163 | final_p = fl6_update_dst(&fl6, opt, &final); |
164 | 164 | ||
165 | err = ip6_dst_lookup(sk, &dst, &fl); | 165 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); |
166 | if (err) | 166 | err = 0; |
167 | if (IS_ERR(dst)) { | ||
168 | err = PTR_ERR(dst); | ||
167 | goto out; | 169 | goto out; |
168 | if (final_p) | ||
169 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
170 | |||
171 | err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT); | ||
172 | if (err < 0) { | ||
173 | if (err == -EREMOTE) | ||
174 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
175 | if (err < 0) | ||
176 | goto out; | ||
177 | } | 170 | } |
178 | 171 | ||
179 | /* source address lookup done in ip6_dst_lookup */ | 172 | /* source address lookup done in ip6_dst_lookup */ |
180 | 173 | ||
181 | if (ipv6_addr_any(&np->saddr)) | 174 | if (ipv6_addr_any(&np->saddr)) |
182 | ipv6_addr_copy(&np->saddr, &fl.fl6_src); | 175 | ipv6_addr_copy(&np->saddr, &fl6.saddr); |
183 | 176 | ||
184 | if (ipv6_addr_any(&np->rcv_saddr)) { | 177 | if (ipv6_addr_any(&np->rcv_saddr)) { |
185 | ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src); | 178 | ipv6_addr_copy(&np->rcv_saddr, &fl6.saddr); |
186 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; | 179 | inet->inet_rcv_saddr = LOOPBACK4_IPV6; |
187 | if (sk->sk_prot->rehash) | 180 | if (sk->sk_prot->rehash) |
188 | sk->sk_prot->rehash(sk); | 181 | sk->sk_prot->rehash(sk); |
189 | } | 182 | } |
190 | 183 | ||
191 | ip6_dst_store(sk, dst, | 184 | ip6_dst_store(sk, dst, |
192 | ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ? | 185 | ipv6_addr_equal(&fl6.daddr, &np->daddr) ? |
193 | &np->daddr : NULL, | 186 | &np->daddr : NULL, |
194 | #ifdef CONFIG_IPV6_SUBTREES | 187 | #ifdef CONFIG_IPV6_SUBTREES |
195 | ipv6_addr_equal(&fl.fl6_src, &np->saddr) ? | 188 | ipv6_addr_equal(&fl6.saddr, &np->saddr) ? |
196 | &np->saddr : | 189 | &np->saddr : |
197 | #endif | 190 | #endif |
198 | NULL); | 191 | NULL); |
@@ -238,7 +231,7 @@ void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, | |||
238 | kfree_skb(skb); | 231 | kfree_skb(skb); |
239 | } | 232 | } |
240 | 233 | ||
241 | void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) | 234 | void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info) |
242 | { | 235 | { |
243 | struct ipv6_pinfo *np = inet6_sk(sk); | 236 | struct ipv6_pinfo *np = inet6_sk(sk); |
244 | struct sock_exterr_skb *serr; | 237 | struct sock_exterr_skb *serr; |
@@ -257,7 +250,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) | |||
257 | skb_put(skb, sizeof(struct ipv6hdr)); | 250 | skb_put(skb, sizeof(struct ipv6hdr)); |
258 | skb_reset_network_header(skb); | 251 | skb_reset_network_header(skb); |
259 | iph = ipv6_hdr(skb); | 252 | iph = ipv6_hdr(skb); |
260 | ipv6_addr_copy(&iph->daddr, &fl->fl6_dst); | 253 | ipv6_addr_copy(&iph->daddr, &fl6->daddr); |
261 | 254 | ||
262 | serr = SKB_EXT_ERR(skb); | 255 | serr = SKB_EXT_ERR(skb); |
263 | serr->ee.ee_errno = err; | 256 | serr->ee.ee_errno = err; |
@@ -268,7 +261,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) | |||
268 | serr->ee.ee_info = info; | 261 | serr->ee.ee_info = info; |
269 | serr->ee.ee_data = 0; | 262 | serr->ee.ee_data = 0; |
270 | serr->addr_offset = (u8 *)&iph->daddr - skb_network_header(skb); | 263 | serr->addr_offset = (u8 *)&iph->daddr - skb_network_header(skb); |
271 | serr->port = fl->fl_ip_dport; | 264 | serr->port = fl6->fl6_dport; |
272 | 265 | ||
273 | __skb_pull(skb, skb_tail_pointer(skb) - skb->data); | 266 | __skb_pull(skb, skb_tail_pointer(skb) - skb->data); |
274 | skb_reset_transport_header(skb); | 267 | skb_reset_transport_header(skb); |
@@ -277,7 +270,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) | |||
277 | kfree_skb(skb); | 270 | kfree_skb(skb); |
278 | } | 271 | } |
279 | 272 | ||
280 | void ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu) | 273 | void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu) |
281 | { | 274 | { |
282 | struct ipv6_pinfo *np = inet6_sk(sk); | 275 | struct ipv6_pinfo *np = inet6_sk(sk); |
283 | struct ipv6hdr *iph; | 276 | struct ipv6hdr *iph; |
@@ -294,7 +287,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu) | |||
294 | skb_put(skb, sizeof(struct ipv6hdr)); | 287 | skb_put(skb, sizeof(struct ipv6hdr)); |
295 | skb_reset_network_header(skb); | 288 | skb_reset_network_header(skb); |
296 | iph = ipv6_hdr(skb); | 289 | iph = ipv6_hdr(skb); |
297 | ipv6_addr_copy(&iph->daddr, &fl->fl6_dst); | 290 | ipv6_addr_copy(&iph->daddr, &fl6->daddr); |
298 | 291 | ||
299 | mtu_info = IP6CBMTU(skb); | 292 | mtu_info = IP6CBMTU(skb); |
300 | if (!mtu_info) { | 293 | if (!mtu_info) { |
@@ -306,7 +299,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu) | |||
306 | mtu_info->ip6m_addr.sin6_family = AF_INET6; | 299 | mtu_info->ip6m_addr.sin6_family = AF_INET6; |
307 | mtu_info->ip6m_addr.sin6_port = 0; | 300 | mtu_info->ip6m_addr.sin6_port = 0; |
308 | mtu_info->ip6m_addr.sin6_flowinfo = 0; | 301 | mtu_info->ip6m_addr.sin6_flowinfo = 0; |
309 | mtu_info->ip6m_addr.sin6_scope_id = fl->oif; | 302 | mtu_info->ip6m_addr.sin6_scope_id = fl6->flowi6_oif; |
310 | ipv6_addr_copy(&mtu_info->ip6m_addr.sin6_addr, &ipv6_hdr(skb)->daddr); | 303 | ipv6_addr_copy(&mtu_info->ip6m_addr.sin6_addr, &ipv6_hdr(skb)->daddr); |
311 | 304 | ||
312 | __skb_pull(skb, skb_tail_pointer(skb) - skb->data); | 305 | __skb_pull(skb, skb_tail_pointer(skb) - skb->data); |
@@ -600,7 +593,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
600 | } | 593 | } |
601 | 594 | ||
602 | int datagram_send_ctl(struct net *net, | 595 | int datagram_send_ctl(struct net *net, |
603 | struct msghdr *msg, struct flowi *fl, | 596 | struct msghdr *msg, struct flowi6 *fl6, |
604 | struct ipv6_txoptions *opt, | 597 | struct ipv6_txoptions *opt, |
605 | int *hlimit, int *tclass, int *dontfrag) | 598 | int *hlimit, int *tclass, int *dontfrag) |
606 | { | 599 | { |
@@ -636,16 +629,17 @@ int datagram_send_ctl(struct net *net, | |||
636 | src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); | 629 | src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); |
637 | 630 | ||
638 | if (src_info->ipi6_ifindex) { | 631 | if (src_info->ipi6_ifindex) { |
639 | if (fl->oif && src_info->ipi6_ifindex != fl->oif) | 632 | if (fl6->flowi6_oif && |
633 | src_info->ipi6_ifindex != fl6->flowi6_oif) | ||
640 | return -EINVAL; | 634 | return -EINVAL; |
641 | fl->oif = src_info->ipi6_ifindex; | 635 | fl6->flowi6_oif = src_info->ipi6_ifindex; |
642 | } | 636 | } |
643 | 637 | ||
644 | addr_type = __ipv6_addr_type(&src_info->ipi6_addr); | 638 | addr_type = __ipv6_addr_type(&src_info->ipi6_addr); |
645 | 639 | ||
646 | rcu_read_lock(); | 640 | rcu_read_lock(); |
647 | if (fl->oif) { | 641 | if (fl6->flowi6_oif) { |
648 | dev = dev_get_by_index_rcu(net, fl->oif); | 642 | dev = dev_get_by_index_rcu(net, fl6->flowi6_oif); |
649 | if (!dev) { | 643 | if (!dev) { |
650 | rcu_read_unlock(); | 644 | rcu_read_unlock(); |
651 | return -ENODEV; | 645 | return -ENODEV; |
@@ -661,7 +655,7 @@ int datagram_send_ctl(struct net *net, | |||
661 | strict ? dev : NULL, 0)) | 655 | strict ? dev : NULL, 0)) |
662 | err = -EINVAL; | 656 | err = -EINVAL; |
663 | else | 657 | else |
664 | ipv6_addr_copy(&fl->fl6_src, &src_info->ipi6_addr); | 658 | ipv6_addr_copy(&fl6->saddr, &src_info->ipi6_addr); |
665 | } | 659 | } |
666 | 660 | ||
667 | rcu_read_unlock(); | 661 | rcu_read_unlock(); |
@@ -678,13 +672,13 @@ int datagram_send_ctl(struct net *net, | |||
678 | goto exit_f; | 672 | goto exit_f; |
679 | } | 673 | } |
680 | 674 | ||
681 | if (fl->fl6_flowlabel&IPV6_FLOWINFO_MASK) { | 675 | if (fl6->flowlabel&IPV6_FLOWINFO_MASK) { |
682 | if ((fl->fl6_flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) { | 676 | if ((fl6->flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) { |
683 | err = -EINVAL; | 677 | err = -EINVAL; |
684 | goto exit_f; | 678 | goto exit_f; |
685 | } | 679 | } |
686 | } | 680 | } |
687 | fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg); | 681 | fl6->flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg); |
688 | break; | 682 | break; |
689 | 683 | ||
690 | case IPV6_2292HOPOPTS: | 684 | case IPV6_2292HOPOPTS: |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 1b5c9825743b..5aa8ec88f194 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -54,16 +54,20 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu); | |||
54 | /* | 54 | /* |
55 | * Allocate an AEAD request structure with extra space for SG and IV. | 55 | * Allocate an AEAD request structure with extra space for SG and IV. |
56 | * | 56 | * |
57 | * For alignment considerations the IV is placed at the front, followed | 57 | * For alignment considerations the upper 32 bits of the sequence number are |
58 | * by the request and finally the SG list. | 58 | * placed at the front, if present. Followed by the IV, the request and finally |
59 | * the SG list. | ||
59 | * | 60 | * |
60 | * TODO: Use spare space in skb for this where possible. | 61 | * TODO: Use spare space in skb for this where possible. |
61 | */ | 62 | */ |
62 | static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags) | 63 | static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqihlen) |
63 | { | 64 | { |
64 | unsigned int len; | 65 | unsigned int len; |
65 | 66 | ||
66 | len = crypto_aead_ivsize(aead); | 67 | len = seqihlen; |
68 | |||
69 | len += crypto_aead_ivsize(aead); | ||
70 | |||
67 | if (len) { | 71 | if (len) { |
68 | len += crypto_aead_alignmask(aead) & | 72 | len += crypto_aead_alignmask(aead) & |
69 | ~(crypto_tfm_ctx_alignment() - 1); | 73 | ~(crypto_tfm_ctx_alignment() - 1); |
@@ -78,10 +82,16 @@ static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags) | |||
78 | return kmalloc(len, GFP_ATOMIC); | 82 | return kmalloc(len, GFP_ATOMIC); |
79 | } | 83 | } |
80 | 84 | ||
81 | static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp) | 85 | static inline __be32 *esp_tmp_seqhi(void *tmp) |
86 | { | ||
87 | return PTR_ALIGN((__be32 *)tmp, __alignof__(__be32)); | ||
88 | } | ||
89 | |||
90 | static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int seqhilen) | ||
82 | { | 91 | { |
83 | return crypto_aead_ivsize(aead) ? | 92 | return crypto_aead_ivsize(aead) ? |
84 | PTR_ALIGN((u8 *)tmp, crypto_aead_alignmask(aead) + 1) : tmp; | 93 | PTR_ALIGN((u8 *)tmp + seqhilen, |
94 | crypto_aead_alignmask(aead) + 1) : tmp + seqhilen; | ||
85 | } | 95 | } |
86 | 96 | ||
87 | static inline struct aead_givcrypt_request *esp_tmp_givreq( | 97 | static inline struct aead_givcrypt_request *esp_tmp_givreq( |
@@ -145,8 +155,12 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
145 | int plen; | 155 | int plen; |
146 | int tfclen; | 156 | int tfclen; |
147 | int nfrags; | 157 | int nfrags; |
158 | int assoclen; | ||
159 | int sglists; | ||
160 | int seqhilen; | ||
148 | u8 *iv; | 161 | u8 *iv; |
149 | u8 *tail; | 162 | u8 *tail; |
163 | __be32 *seqhi; | ||
150 | struct esp_data *esp = x->data; | 164 | struct esp_data *esp = x->data; |
151 | 165 | ||
152 | /* skb is pure payload to encrypt */ | 166 | /* skb is pure payload to encrypt */ |
@@ -175,14 +189,25 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
175 | goto error; | 189 | goto error; |
176 | nfrags = err; | 190 | nfrags = err; |
177 | 191 | ||
178 | tmp = esp_alloc_tmp(aead, nfrags + 1); | 192 | assoclen = sizeof(*esph); |
193 | sglists = 1; | ||
194 | seqhilen = 0; | ||
195 | |||
196 | if (x->props.flags & XFRM_STATE_ESN) { | ||
197 | sglists += 2; | ||
198 | seqhilen += sizeof(__be32); | ||
199 | assoclen += seqhilen; | ||
200 | } | ||
201 | |||
202 | tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen); | ||
179 | if (!tmp) | 203 | if (!tmp) |
180 | goto error; | 204 | goto error; |
181 | 205 | ||
182 | iv = esp_tmp_iv(aead, tmp); | 206 | seqhi = esp_tmp_seqhi(tmp); |
207 | iv = esp_tmp_iv(aead, tmp, seqhilen); | ||
183 | req = esp_tmp_givreq(aead, iv); | 208 | req = esp_tmp_givreq(aead, iv); |
184 | asg = esp_givreq_sg(aead, req); | 209 | asg = esp_givreq_sg(aead, req); |
185 | sg = asg + 1; | 210 | sg = asg + sglists; |
186 | 211 | ||
187 | /* Fill padding... */ | 212 | /* Fill padding... */ |
188 | tail = skb_tail_pointer(trailer); | 213 | tail = skb_tail_pointer(trailer); |
@@ -204,19 +229,27 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
204 | *skb_mac_header(skb) = IPPROTO_ESP; | 229 | *skb_mac_header(skb) = IPPROTO_ESP; |
205 | 230 | ||
206 | esph->spi = x->id.spi; | 231 | esph->spi = x->id.spi; |
207 | esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output); | 232 | esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); |
208 | 233 | ||
209 | sg_init_table(sg, nfrags); | 234 | sg_init_table(sg, nfrags); |
210 | skb_to_sgvec(skb, sg, | 235 | skb_to_sgvec(skb, sg, |
211 | esph->enc_data + crypto_aead_ivsize(aead) - skb->data, | 236 | esph->enc_data + crypto_aead_ivsize(aead) - skb->data, |
212 | clen + alen); | 237 | clen + alen); |
213 | sg_init_one(asg, esph, sizeof(*esph)); | 238 | |
239 | if ((x->props.flags & XFRM_STATE_ESN)) { | ||
240 | sg_init_table(asg, 3); | ||
241 | sg_set_buf(asg, &esph->spi, sizeof(__be32)); | ||
242 | *seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi); | ||
243 | sg_set_buf(asg + 1, seqhi, seqhilen); | ||
244 | sg_set_buf(asg + 2, &esph->seq_no, sizeof(__be32)); | ||
245 | } else | ||
246 | sg_init_one(asg, esph, sizeof(*esph)); | ||
214 | 247 | ||
215 | aead_givcrypt_set_callback(req, 0, esp_output_done, skb); | 248 | aead_givcrypt_set_callback(req, 0, esp_output_done, skb); |
216 | aead_givcrypt_set_crypt(req, sg, sg, clen, iv); | 249 | aead_givcrypt_set_crypt(req, sg, sg, clen, iv); |
217 | aead_givcrypt_set_assoc(req, asg, sizeof(*esph)); | 250 | aead_givcrypt_set_assoc(req, asg, assoclen); |
218 | aead_givcrypt_set_giv(req, esph->enc_data, | 251 | aead_givcrypt_set_giv(req, esph->enc_data, |
219 | XFRM_SKB_CB(skb)->seq.output); | 252 | XFRM_SKB_CB(skb)->seq.output.low); |
220 | 253 | ||
221 | ESP_SKB_CB(skb)->tmp = tmp; | 254 | ESP_SKB_CB(skb)->tmp = tmp; |
222 | err = crypto_aead_givencrypt(req); | 255 | err = crypto_aead_givencrypt(req); |
@@ -292,8 +325,12 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
292 | struct sk_buff *trailer; | 325 | struct sk_buff *trailer; |
293 | int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead); | 326 | int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead); |
294 | int nfrags; | 327 | int nfrags; |
328 | int assoclen; | ||
329 | int sglists; | ||
330 | int seqhilen; | ||
295 | int ret = 0; | 331 | int ret = 0; |
296 | void *tmp; | 332 | void *tmp; |
333 | __be32 *seqhi; | ||
297 | u8 *iv; | 334 | u8 *iv; |
298 | struct scatterlist *sg; | 335 | struct scatterlist *sg; |
299 | struct scatterlist *asg; | 336 | struct scatterlist *asg; |
@@ -314,12 +351,24 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
314 | } | 351 | } |
315 | 352 | ||
316 | ret = -ENOMEM; | 353 | ret = -ENOMEM; |
317 | tmp = esp_alloc_tmp(aead, nfrags + 1); | 354 | |
355 | assoclen = sizeof(*esph); | ||
356 | sglists = 1; | ||
357 | seqhilen = 0; | ||
358 | |||
359 | if (x->props.flags & XFRM_STATE_ESN) { | ||
360 | sglists += 2; | ||
361 | seqhilen += sizeof(__be32); | ||
362 | assoclen += seqhilen; | ||
363 | } | ||
364 | |||
365 | tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen); | ||
318 | if (!tmp) | 366 | if (!tmp) |
319 | goto out; | 367 | goto out; |
320 | 368 | ||
321 | ESP_SKB_CB(skb)->tmp = tmp; | 369 | ESP_SKB_CB(skb)->tmp = tmp; |
322 | iv = esp_tmp_iv(aead, tmp); | 370 | seqhi = esp_tmp_seqhi(tmp); |
371 | iv = esp_tmp_iv(aead, tmp, seqhilen); | ||
323 | req = esp_tmp_req(aead, iv); | 372 | req = esp_tmp_req(aead, iv); |
324 | asg = esp_req_sg(aead, req); | 373 | asg = esp_req_sg(aead, req); |
325 | sg = asg + 1; | 374 | sg = asg + 1; |
@@ -333,11 +382,19 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
333 | 382 | ||
334 | sg_init_table(sg, nfrags); | 383 | sg_init_table(sg, nfrags); |
335 | skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen); | 384 | skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen); |
336 | sg_init_one(asg, esph, sizeof(*esph)); | 385 | |
386 | if ((x->props.flags & XFRM_STATE_ESN)) { | ||
387 | sg_init_table(asg, 3); | ||
388 | sg_set_buf(asg, &esph->spi, sizeof(__be32)); | ||
389 | *seqhi = XFRM_SKB_CB(skb)->seq.input.hi; | ||
390 | sg_set_buf(asg + 1, seqhi, seqhilen); | ||
391 | sg_set_buf(asg + 2, &esph->seq_no, sizeof(__be32)); | ||
392 | } else | ||
393 | sg_init_one(asg, esph, sizeof(*esph)); | ||
337 | 394 | ||
338 | aead_request_set_callback(req, 0, esp_input_done, skb); | 395 | aead_request_set_callback(req, 0, esp_input_done, skb); |
339 | aead_request_set_crypt(req, sg, sg, elen, iv); | 396 | aead_request_set_crypt(req, sg, sg, elen, iv); |
340 | aead_request_set_assoc(req, asg, sizeof(*esph)); | 397 | aead_request_set_assoc(req, asg, assoclen); |
341 | 398 | ||
342 | ret = crypto_aead_decrypt(req); | 399 | ret = crypto_aead_decrypt(req); |
343 | if (ret == -EINPROGRESS) | 400 | if (ret == -EINPROGRESS) |
@@ -443,10 +500,20 @@ static int esp_init_authenc(struct xfrm_state *x) | |||
443 | goto error; | 500 | goto error; |
444 | 501 | ||
445 | err = -ENAMETOOLONG; | 502 | err = -ENAMETOOLONG; |
446 | if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)", | 503 | |
447 | x->aalg ? x->aalg->alg_name : "digest_null", | 504 | if ((x->props.flags & XFRM_STATE_ESN)) { |
448 | x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME) | 505 | if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, |
449 | goto error; | 506 | "authencesn(%s,%s)", |
507 | x->aalg ? x->aalg->alg_name : "digest_null", | ||
508 | x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME) | ||
509 | goto error; | ||
510 | } else { | ||
511 | if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, | ||
512 | "authenc(%s,%s)", | ||
513 | x->aalg ? x->aalg->alg_name : "digest_null", | ||
514 | x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME) | ||
515 | goto error; | ||
516 | } | ||
450 | 517 | ||
451 | aead = crypto_alloc_aead(authenc_name, 0, 0); | 518 | aead = crypto_alloc_aead(authenc_name, 0, 0); |
452 | err = PTR_ERR(aead); | 519 | err = PTR_ERR(aead); |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 262f105d23b9..79a485e8a700 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -876,22 +876,22 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space, | |||
876 | * fl6_update_dst - update flowi destination address with info given | 876 | * fl6_update_dst - update flowi destination address with info given |
877 | * by srcrt option, if any. | 877 | * by srcrt option, if any. |
878 | * | 878 | * |
879 | * @fl: flowi for which fl6_dst is to be updated | 879 | * @fl6: flowi6 for which daddr is to be updated |
880 | * @opt: struct ipv6_txoptions in which to look for srcrt opt | 880 | * @opt: struct ipv6_txoptions in which to look for srcrt opt |
881 | * @orig: copy of original fl6_dst address if modified | 881 | * @orig: copy of original daddr address if modified |
882 | * | 882 | * |
883 | * Returns NULL if no txoptions or no srcrt, otherwise returns orig | 883 | * Returns NULL if no txoptions or no srcrt, otherwise returns orig |
884 | * and initial value of fl->fl6_dst set in orig | 884 | * and initial value of fl6->daddr set in orig |
885 | */ | 885 | */ |
886 | struct in6_addr *fl6_update_dst(struct flowi *fl, | 886 | struct in6_addr *fl6_update_dst(struct flowi6 *fl6, |
887 | const struct ipv6_txoptions *opt, | 887 | const struct ipv6_txoptions *opt, |
888 | struct in6_addr *orig) | 888 | struct in6_addr *orig) |
889 | { | 889 | { |
890 | if (!opt || !opt->srcrt) | 890 | if (!opt || !opt->srcrt) |
891 | return NULL; | 891 | return NULL; |
892 | 892 | ||
893 | ipv6_addr_copy(orig, &fl->fl6_dst); | 893 | ipv6_addr_copy(orig, &fl6->daddr); |
894 | ipv6_addr_copy(&fl->fl6_dst, ((struct rt0_hdr *)opt->srcrt)->addr); | 894 | ipv6_addr_copy(&fl6->daddr, ((struct rt0_hdr *)opt->srcrt)->addr); |
895 | return orig; | 895 | return orig; |
896 | } | 896 | } |
897 | 897 | ||
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index d829874d8946..34d244df907d 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -29,7 +29,7 @@ struct fib6_rule | |||
29 | u8 tclass; | 29 | u8 tclass; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, | 32 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, |
33 | int flags, pol_lookup_t lookup) | 33 | int flags, pol_lookup_t lookup) |
34 | { | 34 | { |
35 | struct fib_lookup_arg arg = { | 35 | struct fib_lookup_arg arg = { |
@@ -37,7 +37,8 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, | |||
37 | .flags = FIB_LOOKUP_NOREF, | 37 | .flags = FIB_LOOKUP_NOREF, |
38 | }; | 38 | }; |
39 | 39 | ||
40 | fib_rules_lookup(net->ipv6.fib6_rules_ops, fl, flags, &arg); | 40 | fib_rules_lookup(net->ipv6.fib6_rules_ops, |
41 | flowi6_to_flowi(fl6), flags, &arg); | ||
41 | 42 | ||
42 | if (arg.result) | 43 | if (arg.result) |
43 | return arg.result; | 44 | return arg.result; |
@@ -49,6 +50,7 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, | |||
49 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | 50 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, |
50 | int flags, struct fib_lookup_arg *arg) | 51 | int flags, struct fib_lookup_arg *arg) |
51 | { | 52 | { |
53 | struct flowi6 *flp6 = &flp->u.ip6; | ||
52 | struct rt6_info *rt = NULL; | 54 | struct rt6_info *rt = NULL; |
53 | struct fib6_table *table; | 55 | struct fib6_table *table; |
54 | struct net *net = rule->fr_net; | 56 | struct net *net = rule->fr_net; |
@@ -71,7 +73,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
71 | 73 | ||
72 | table = fib6_get_table(net, rule->table); | 74 | table = fib6_get_table(net, rule->table); |
73 | if (table) | 75 | if (table) |
74 | rt = lookup(net, table, flp, flags); | 76 | rt = lookup(net, table, flp6, flags); |
75 | 77 | ||
76 | if (rt != net->ipv6.ip6_null_entry) { | 78 | if (rt != net->ipv6.ip6_null_entry) { |
77 | struct fib6_rule *r = (struct fib6_rule *)rule; | 79 | struct fib6_rule *r = (struct fib6_rule *)rule; |
@@ -86,14 +88,14 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
86 | 88 | ||
87 | if (ipv6_dev_get_saddr(net, | 89 | if (ipv6_dev_get_saddr(net, |
88 | ip6_dst_idev(&rt->dst)->dev, | 90 | ip6_dst_idev(&rt->dst)->dev, |
89 | &flp->fl6_dst, | 91 | &flp6->daddr, |
90 | rt6_flags2srcprefs(flags), | 92 | rt6_flags2srcprefs(flags), |
91 | &saddr)) | 93 | &saddr)) |
92 | goto again; | 94 | goto again; |
93 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, | 95 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, |
94 | r->src.plen)) | 96 | r->src.plen)) |
95 | goto again; | 97 | goto again; |
96 | ipv6_addr_copy(&flp->fl6_src, &saddr); | 98 | ipv6_addr_copy(&flp6->saddr, &saddr); |
97 | } | 99 | } |
98 | goto out; | 100 | goto out; |
99 | } | 101 | } |
@@ -113,9 +115,10 @@ out: | |||
113 | static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | 115 | static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) |
114 | { | 116 | { |
115 | struct fib6_rule *r = (struct fib6_rule *) rule; | 117 | struct fib6_rule *r = (struct fib6_rule *) rule; |
118 | struct flowi6 *fl6 = &fl->u.ip6; | ||
116 | 119 | ||
117 | if (r->dst.plen && | 120 | if (r->dst.plen && |
118 | !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen)) | 121 | !ipv6_prefix_equal(&fl6->daddr, &r->dst.addr, r->dst.plen)) |
119 | return 0; | 122 | return 0; |
120 | 123 | ||
121 | /* | 124 | /* |
@@ -125,14 +128,14 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | |||
125 | */ | 128 | */ |
126 | if (r->src.plen) { | 129 | if (r->src.plen) { |
127 | if (flags & RT6_LOOKUP_F_HAS_SADDR) { | 130 | if (flags & RT6_LOOKUP_F_HAS_SADDR) { |
128 | if (!ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, | 131 | if (!ipv6_prefix_equal(&fl6->saddr, &r->src.addr, |
129 | r->src.plen)) | 132 | r->src.plen)) |
130 | return 0; | 133 | return 0; |
131 | } else if (!(r->common.flags & FIB_RULE_FIND_SADDR)) | 134 | } else if (!(r->common.flags & FIB_RULE_FIND_SADDR)) |
132 | return 0; | 135 | return 0; |
133 | } | 136 | } |
134 | 137 | ||
135 | if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) | 138 | if (r->tclass && r->tclass != ((ntohl(fl6->flowlabel) >> 20) & 0xff)) |
136 | return 0; | 139 | return 0; |
137 | 140 | ||
138 | return 1; | 141 | return 1; |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 03e62f94ff8e..83cb4f9add81 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -157,32 +157,32 @@ static int is_ineligible(struct sk_buff *skb) | |||
157 | /* | 157 | /* |
158 | * Check the ICMP output rate limit | 158 | * Check the ICMP output rate limit |
159 | */ | 159 | */ |
160 | static inline int icmpv6_xrlim_allow(struct sock *sk, u8 type, | 160 | static inline bool icmpv6_xrlim_allow(struct sock *sk, u8 type, |
161 | struct flowi *fl) | 161 | struct flowi6 *fl6) |
162 | { | 162 | { |
163 | struct dst_entry *dst; | 163 | struct dst_entry *dst; |
164 | struct net *net = sock_net(sk); | 164 | struct net *net = sock_net(sk); |
165 | int res = 0; | 165 | bool res = false; |
166 | 166 | ||
167 | /* Informational messages are not limited. */ | 167 | /* Informational messages are not limited. */ |
168 | if (type & ICMPV6_INFOMSG_MASK) | 168 | if (type & ICMPV6_INFOMSG_MASK) |
169 | return 1; | 169 | return true; |
170 | 170 | ||
171 | /* Do not limit pmtu discovery, it would break it. */ | 171 | /* Do not limit pmtu discovery, it would break it. */ |
172 | if (type == ICMPV6_PKT_TOOBIG) | 172 | if (type == ICMPV6_PKT_TOOBIG) |
173 | return 1; | 173 | return true; |
174 | 174 | ||
175 | /* | 175 | /* |
176 | * Look up the output route. | 176 | * Look up the output route. |
177 | * XXX: perhaps the expire for routing entries cloned by | 177 | * XXX: perhaps the expire for routing entries cloned by |
178 | * this lookup should be more aggressive (not longer than timeout). | 178 | * this lookup should be more aggressive (not longer than timeout). |
179 | */ | 179 | */ |
180 | dst = ip6_route_output(net, sk, fl); | 180 | dst = ip6_route_output(net, sk, fl6); |
181 | if (dst->error) { | 181 | if (dst->error) { |
182 | IP6_INC_STATS(net, ip6_dst_idev(dst), | 182 | IP6_INC_STATS(net, ip6_dst_idev(dst), |
183 | IPSTATS_MIB_OUTNOROUTES); | 183 | IPSTATS_MIB_OUTNOROUTES); |
184 | } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { | 184 | } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { |
185 | res = 1; | 185 | res = true; |
186 | } else { | 186 | } else { |
187 | struct rt6_info *rt = (struct rt6_info *)dst; | 187 | struct rt6_info *rt = (struct rt6_info *)dst; |
188 | int tmo = net->ipv6.sysctl.icmpv6_time; | 188 | int tmo = net->ipv6.sysctl.icmpv6_time; |
@@ -191,7 +191,9 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, u8 type, | |||
191 | if (rt->rt6i_dst.plen < 128) | 191 | if (rt->rt6i_dst.plen < 128) |
192 | tmo >>= ((128 - rt->rt6i_dst.plen)>>5); | 192 | tmo >>= ((128 - rt->rt6i_dst.plen)>>5); |
193 | 193 | ||
194 | res = xrlim_allow(dst, tmo); | 194 | if (!rt->rt6i_peer) |
195 | rt6_bind_peer(rt, 1); | ||
196 | res = inet_peer_xrlim_allow(rt->rt6i_peer, tmo); | ||
195 | } | 197 | } |
196 | dst_release(dst); | 198 | dst_release(dst); |
197 | return res; | 199 | return res; |
@@ -215,7 +217,7 @@ static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset) | |||
215 | return (*op & 0xC0) == 0x80; | 217 | return (*op & 0xC0) == 0x80; |
216 | } | 218 | } |
217 | 219 | ||
218 | static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hdr *thdr, int len) | 220 | static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len) |
219 | { | 221 | { |
220 | struct sk_buff *skb; | 222 | struct sk_buff *skb; |
221 | struct icmp6hdr *icmp6h; | 223 | struct icmp6hdr *icmp6h; |
@@ -231,9 +233,9 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct | |||
231 | if (skb_queue_len(&sk->sk_write_queue) == 1) { | 233 | if (skb_queue_len(&sk->sk_write_queue) == 1) { |
232 | skb->csum = csum_partial(icmp6h, | 234 | skb->csum = csum_partial(icmp6h, |
233 | sizeof(struct icmp6hdr), skb->csum); | 235 | sizeof(struct icmp6hdr), skb->csum); |
234 | icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src, | 236 | icmp6h->icmp6_cksum = csum_ipv6_magic(&fl6->saddr, |
235 | &fl->fl6_dst, | 237 | &fl6->daddr, |
236 | len, fl->proto, | 238 | len, fl6->flowi6_proto, |
237 | skb->csum); | 239 | skb->csum); |
238 | } else { | 240 | } else { |
239 | __wsum tmp_csum = 0; | 241 | __wsum tmp_csum = 0; |
@@ -244,9 +246,9 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct | |||
244 | 246 | ||
245 | tmp_csum = csum_partial(icmp6h, | 247 | tmp_csum = csum_partial(icmp6h, |
246 | sizeof(struct icmp6hdr), tmp_csum); | 248 | sizeof(struct icmp6hdr), tmp_csum); |
247 | icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src, | 249 | icmp6h->icmp6_cksum = csum_ipv6_magic(&fl6->saddr, |
248 | &fl->fl6_dst, | 250 | &fl6->daddr, |
249 | len, fl->proto, | 251 | len, fl6->flowi6_proto, |
250 | tmp_csum); | 252 | tmp_csum); |
251 | } | 253 | } |
252 | ip6_push_pending_frames(sk); | 254 | ip6_push_pending_frames(sk); |
@@ -298,6 +300,68 @@ static void mip6_addr_swap(struct sk_buff *skb) | |||
298 | static inline void mip6_addr_swap(struct sk_buff *skb) {} | 300 | static inline void mip6_addr_swap(struct sk_buff *skb) {} |
299 | #endif | 301 | #endif |
300 | 302 | ||
303 | static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, | ||
304 | struct sock *sk, struct flowi6 *fl6) | ||
305 | { | ||
306 | struct dst_entry *dst, *dst2; | ||
307 | struct flowi6 fl2; | ||
308 | int err; | ||
309 | |||
310 | err = ip6_dst_lookup(sk, &dst, fl6); | ||
311 | if (err) | ||
312 | return ERR_PTR(err); | ||
313 | |||
314 | /* | ||
315 | * We won't send icmp if the destination is known | ||
316 | * anycast. | ||
317 | */ | ||
318 | if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) { | ||
319 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n"); | ||
320 | dst_release(dst); | ||
321 | return ERR_PTR(-EINVAL); | ||
322 | } | ||
323 | |||
324 | /* No need to clone since we're just using its address. */ | ||
325 | dst2 = dst; | ||
326 | |||
327 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), sk, 0); | ||
328 | if (!IS_ERR(dst)) { | ||
329 | if (dst != dst2) | ||
330 | return dst; | ||
331 | } else { | ||
332 | if (PTR_ERR(dst) == -EPERM) | ||
333 | dst = NULL; | ||
334 | else | ||
335 | return dst; | ||
336 | } | ||
337 | |||
338 | err = xfrm_decode_session_reverse(skb, flowi6_to_flowi(&fl2), AF_INET6); | ||
339 | if (err) | ||
340 | goto relookup_failed; | ||
341 | |||
342 | err = ip6_dst_lookup(sk, &dst2, &fl2); | ||
343 | if (err) | ||
344 | goto relookup_failed; | ||
345 | |||
346 | dst2 = xfrm_lookup(net, dst2, flowi6_to_flowi(&fl2), sk, XFRM_LOOKUP_ICMP); | ||
347 | if (!IS_ERR(dst2)) { | ||
348 | dst_release(dst); | ||
349 | dst = dst2; | ||
350 | } else { | ||
351 | err = PTR_ERR(dst2); | ||
352 | if (err == -EPERM) { | ||
353 | dst_release(dst); | ||
354 | return dst2; | ||
355 | } else | ||
356 | goto relookup_failed; | ||
357 | } | ||
358 | |||
359 | relookup_failed: | ||
360 | if (dst) | ||
361 | return dst; | ||
362 | return ERR_PTR(err); | ||
363 | } | ||
364 | |||
301 | /* | 365 | /* |
302 | * Send an ICMP message in response to a packet in error | 366 | * Send an ICMP message in response to a packet in error |
303 | */ | 367 | */ |
@@ -310,10 +374,8 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
310 | struct ipv6_pinfo *np; | 374 | struct ipv6_pinfo *np; |
311 | struct in6_addr *saddr = NULL; | 375 | struct in6_addr *saddr = NULL; |
312 | struct dst_entry *dst; | 376 | struct dst_entry *dst; |
313 | struct dst_entry *dst2; | ||
314 | struct icmp6hdr tmp_hdr; | 377 | struct icmp6hdr tmp_hdr; |
315 | struct flowi fl; | 378 | struct flowi6 fl6; |
316 | struct flowi fl2; | ||
317 | struct icmpv6_msg msg; | 379 | struct icmpv6_msg msg; |
318 | int iif = 0; | 380 | int iif = 0; |
319 | int addr_type = 0; | 381 | int addr_type = 0; |
@@ -380,22 +442,22 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
380 | 442 | ||
381 | mip6_addr_swap(skb); | 443 | mip6_addr_swap(skb); |
382 | 444 | ||
383 | memset(&fl, 0, sizeof(fl)); | 445 | memset(&fl6, 0, sizeof(fl6)); |
384 | fl.proto = IPPROTO_ICMPV6; | 446 | fl6.flowi6_proto = IPPROTO_ICMPV6; |
385 | ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr); | 447 | ipv6_addr_copy(&fl6.daddr, &hdr->saddr); |
386 | if (saddr) | 448 | if (saddr) |
387 | ipv6_addr_copy(&fl.fl6_src, saddr); | 449 | ipv6_addr_copy(&fl6.saddr, saddr); |
388 | fl.oif = iif; | 450 | fl6.flowi6_oif = iif; |
389 | fl.fl_icmp_type = type; | 451 | fl6.fl6_icmp_type = type; |
390 | fl.fl_icmp_code = code; | 452 | fl6.fl6_icmp_code = code; |
391 | security_skb_classify_flow(skb, &fl); | 453 | security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); |
392 | 454 | ||
393 | sk = icmpv6_xmit_lock(net); | 455 | sk = icmpv6_xmit_lock(net); |
394 | if (sk == NULL) | 456 | if (sk == NULL) |
395 | return; | 457 | return; |
396 | np = inet6_sk(sk); | 458 | np = inet6_sk(sk); |
397 | 459 | ||
398 | if (!icmpv6_xrlim_allow(sk, type, &fl)) | 460 | if (!icmpv6_xrlim_allow(sk, type, &fl6)) |
399 | goto out; | 461 | goto out; |
400 | 462 | ||
401 | tmp_hdr.icmp6_type = type; | 463 | tmp_hdr.icmp6_type = type; |
@@ -403,61 +465,14 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
403 | tmp_hdr.icmp6_cksum = 0; | 465 | tmp_hdr.icmp6_cksum = 0; |
404 | tmp_hdr.icmp6_pointer = htonl(info); | 466 | tmp_hdr.icmp6_pointer = htonl(info); |
405 | 467 | ||
406 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 468 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) |
407 | fl.oif = np->mcast_oif; | 469 | fl6.flowi6_oif = np->mcast_oif; |
408 | 470 | ||
409 | err = ip6_dst_lookup(sk, &dst, &fl); | 471 | dst = icmpv6_route_lookup(net, skb, sk, &fl6); |
410 | if (err) | 472 | if (IS_ERR(dst)) |
411 | goto out; | 473 | goto out; |
412 | 474 | ||
413 | /* | 475 | if (ipv6_addr_is_multicast(&fl6.daddr)) |
414 | * We won't send icmp if the destination is known | ||
415 | * anycast. | ||
416 | */ | ||
417 | if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) { | ||
418 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n"); | ||
419 | goto out_dst_release; | ||
420 | } | ||
421 | |||
422 | /* No need to clone since we're just using its address. */ | ||
423 | dst2 = dst; | ||
424 | |||
425 | err = xfrm_lookup(net, &dst, &fl, sk, 0); | ||
426 | switch (err) { | ||
427 | case 0: | ||
428 | if (dst != dst2) | ||
429 | goto route_done; | ||
430 | break; | ||
431 | case -EPERM: | ||
432 | dst = NULL; | ||
433 | break; | ||
434 | default: | ||
435 | goto out; | ||
436 | } | ||
437 | |||
438 | if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6)) | ||
439 | goto relookup_failed; | ||
440 | |||
441 | if (ip6_dst_lookup(sk, &dst2, &fl2)) | ||
442 | goto relookup_failed; | ||
443 | |||
444 | err = xfrm_lookup(net, &dst2, &fl2, sk, XFRM_LOOKUP_ICMP); | ||
445 | switch (err) { | ||
446 | case 0: | ||
447 | dst_release(dst); | ||
448 | dst = dst2; | ||
449 | break; | ||
450 | case -EPERM: | ||
451 | goto out_dst_release; | ||
452 | default: | ||
453 | relookup_failed: | ||
454 | if (!dst) | ||
455 | goto out; | ||
456 | break; | ||
457 | } | ||
458 | |||
459 | route_done: | ||
460 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | ||
461 | hlimit = np->mcast_hops; | 476 | hlimit = np->mcast_hops; |
462 | else | 477 | else |
463 | hlimit = np->hop_limit; | 478 | hlimit = np->hop_limit; |
@@ -480,14 +495,14 @@ route_done: | |||
480 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, | 495 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, |
481 | len + sizeof(struct icmp6hdr), | 496 | len + sizeof(struct icmp6hdr), |
482 | sizeof(struct icmp6hdr), hlimit, | 497 | sizeof(struct icmp6hdr), hlimit, |
483 | np->tclass, NULL, &fl, (struct rt6_info*)dst, | 498 | np->tclass, NULL, &fl6, (struct rt6_info*)dst, |
484 | MSG_DONTWAIT, np->dontfrag); | 499 | MSG_DONTWAIT, np->dontfrag); |
485 | if (err) { | 500 | if (err) { |
486 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); | 501 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); |
487 | ip6_flush_pending_frames(sk); | 502 | ip6_flush_pending_frames(sk); |
488 | goto out_put; | 503 | goto out_put; |
489 | } | 504 | } |
490 | err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr)); | 505 | err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, len + sizeof(struct icmp6hdr)); |
491 | 506 | ||
492 | out_put: | 507 | out_put: |
493 | if (likely(idev != NULL)) | 508 | if (likely(idev != NULL)) |
@@ -509,7 +524,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
509 | struct in6_addr *saddr = NULL; | 524 | struct in6_addr *saddr = NULL; |
510 | struct icmp6hdr *icmph = icmp6_hdr(skb); | 525 | struct icmp6hdr *icmph = icmp6_hdr(skb); |
511 | struct icmp6hdr tmp_hdr; | 526 | struct icmp6hdr tmp_hdr; |
512 | struct flowi fl; | 527 | struct flowi6 fl6; |
513 | struct icmpv6_msg msg; | 528 | struct icmpv6_msg msg; |
514 | struct dst_entry *dst; | 529 | struct dst_entry *dst; |
515 | int err = 0; | 530 | int err = 0; |
@@ -523,30 +538,31 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
523 | memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr)); | 538 | memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr)); |
524 | tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY; | 539 | tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY; |
525 | 540 | ||
526 | memset(&fl, 0, sizeof(fl)); | 541 | memset(&fl6, 0, sizeof(fl6)); |
527 | fl.proto = IPPROTO_ICMPV6; | 542 | fl6.flowi6_proto = IPPROTO_ICMPV6; |
528 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); | 543 | ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->saddr); |
529 | if (saddr) | 544 | if (saddr) |
530 | ipv6_addr_copy(&fl.fl6_src, saddr); | 545 | ipv6_addr_copy(&fl6.saddr, saddr); |
531 | fl.oif = skb->dev->ifindex; | 546 | fl6.flowi6_oif = skb->dev->ifindex; |
532 | fl.fl_icmp_type = ICMPV6_ECHO_REPLY; | 547 | fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY; |
533 | security_skb_classify_flow(skb, &fl); | 548 | security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); |
534 | 549 | ||
535 | sk = icmpv6_xmit_lock(net); | 550 | sk = icmpv6_xmit_lock(net); |
536 | if (sk == NULL) | 551 | if (sk == NULL) |
537 | return; | 552 | return; |
538 | np = inet6_sk(sk); | 553 | np = inet6_sk(sk); |
539 | 554 | ||
540 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 555 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) |
541 | fl.oif = np->mcast_oif; | 556 | fl6.flowi6_oif = np->mcast_oif; |
542 | 557 | ||
543 | err = ip6_dst_lookup(sk, &dst, &fl); | 558 | err = ip6_dst_lookup(sk, &dst, &fl6); |
544 | if (err) | 559 | if (err) |
545 | goto out; | 560 | goto out; |
546 | if ((err = xfrm_lookup(net, &dst, &fl, sk, 0)) < 0) | 561 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), sk, 0); |
562 | if (IS_ERR(dst)) | ||
547 | goto out; | 563 | goto out; |
548 | 564 | ||
549 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 565 | if (ipv6_addr_is_multicast(&fl6.daddr)) |
550 | hlimit = np->mcast_hops; | 566 | hlimit = np->mcast_hops; |
551 | else | 567 | else |
552 | hlimit = np->hop_limit; | 568 | hlimit = np->hop_limit; |
@@ -560,7 +576,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
560 | msg.type = ICMPV6_ECHO_REPLY; | 576 | msg.type = ICMPV6_ECHO_REPLY; |
561 | 577 | ||
562 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), | 578 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), |
563 | sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl, | 579 | sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl6, |
564 | (struct rt6_info*)dst, MSG_DONTWAIT, | 580 | (struct rt6_info*)dst, MSG_DONTWAIT, |
565 | np->dontfrag); | 581 | np->dontfrag); |
566 | 582 | ||
@@ -569,7 +585,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
569 | ip6_flush_pending_frames(sk); | 585 | ip6_flush_pending_frames(sk); |
570 | goto out_put; | 586 | goto out_put; |
571 | } | 587 | } |
572 | err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr)); | 588 | err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, skb->len + sizeof(struct icmp6hdr)); |
573 | 589 | ||
574 | out_put: | 590 | out_put: |
575 | if (likely(idev != NULL)) | 591 | if (likely(idev != NULL)) |
@@ -768,20 +784,20 @@ drop_no_count: | |||
768 | return 0; | 784 | return 0; |
769 | } | 785 | } |
770 | 786 | ||
771 | void icmpv6_flow_init(struct sock *sk, struct flowi *fl, | 787 | void icmpv6_flow_init(struct sock *sk, struct flowi6 *fl6, |
772 | u8 type, | 788 | u8 type, |
773 | const struct in6_addr *saddr, | 789 | const struct in6_addr *saddr, |
774 | const struct in6_addr *daddr, | 790 | const struct in6_addr *daddr, |
775 | int oif) | 791 | int oif) |
776 | { | 792 | { |
777 | memset(fl, 0, sizeof(*fl)); | 793 | memset(fl6, 0, sizeof(*fl6)); |
778 | ipv6_addr_copy(&fl->fl6_src, saddr); | 794 | ipv6_addr_copy(&fl6->saddr, saddr); |
779 | ipv6_addr_copy(&fl->fl6_dst, daddr); | 795 | ipv6_addr_copy(&fl6->daddr, daddr); |
780 | fl->proto = IPPROTO_ICMPV6; | 796 | fl6->flowi6_proto = IPPROTO_ICMPV6; |
781 | fl->fl_icmp_type = type; | 797 | fl6->fl6_icmp_type = type; |
782 | fl->fl_icmp_code = 0; | 798 | fl6->fl6_icmp_code = 0; |
783 | fl->oif = oif; | 799 | fl6->flowi6_oif = oif; |
784 | security_sk_classify_flow(sk, fl); | 800 | security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); |
785 | } | 801 | } |
786 | 802 | ||
787 | /* | 803 | /* |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index d144e629d2b4..166054650466 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -61,26 +61,21 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk, | |||
61 | struct ipv6_pinfo *np = inet6_sk(sk); | 61 | struct ipv6_pinfo *np = inet6_sk(sk); |
62 | struct in6_addr *final_p, final; | 62 | struct in6_addr *final_p, final; |
63 | struct dst_entry *dst; | 63 | struct dst_entry *dst; |
64 | struct flowi fl; | 64 | struct flowi6 fl6; |
65 | 65 | ||
66 | memset(&fl, 0, sizeof(fl)); | 66 | memset(&fl6, 0, sizeof(fl6)); |
67 | fl.proto = IPPROTO_TCP; | 67 | fl6.flowi6_proto = IPPROTO_TCP; |
68 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | 68 | ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr); |
69 | final_p = fl6_update_dst(&fl, np->opt, &final); | 69 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
70 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); | 70 | ipv6_addr_copy(&fl6.saddr, &treq->loc_addr); |
71 | fl.oif = sk->sk_bound_dev_if; | 71 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
72 | fl.mark = sk->sk_mark; | 72 | fl6.flowi6_mark = sk->sk_mark; |
73 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; | 73 | fl6.fl6_dport = inet_rsk(req)->rmt_port; |
74 | fl.fl_ip_sport = inet_rsk(req)->loc_port; | 74 | fl6.fl6_sport = inet_rsk(req)->loc_port; |
75 | security_req_classify_flow(req, &fl); | 75 | security_req_classify_flow(req, flowi6_to_flowi(&fl6)); |
76 | 76 | ||
77 | if (ip6_dst_lookup(sk, &dst, &fl)) | 77 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); |
78 | return NULL; | 78 | if (IS_ERR(dst)) |
79 | |||
80 | if (final_p) | ||
81 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
82 | |||
83 | if ((xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) | ||
84 | return NULL; | 79 | return NULL; |
85 | 80 | ||
86 | return dst; | 81 | return dst; |
@@ -213,42 +208,34 @@ int inet6_csk_xmit(struct sk_buff *skb) | |||
213 | struct sock *sk = skb->sk; | 208 | struct sock *sk = skb->sk; |
214 | struct inet_sock *inet = inet_sk(sk); | 209 | struct inet_sock *inet = inet_sk(sk); |
215 | struct ipv6_pinfo *np = inet6_sk(sk); | 210 | struct ipv6_pinfo *np = inet6_sk(sk); |
216 | struct flowi fl; | 211 | struct flowi6 fl6; |
217 | struct dst_entry *dst; | 212 | struct dst_entry *dst; |
218 | struct in6_addr *final_p, final; | 213 | struct in6_addr *final_p, final; |
219 | 214 | ||
220 | memset(&fl, 0, sizeof(fl)); | 215 | memset(&fl6, 0, sizeof(fl6)); |
221 | fl.proto = sk->sk_protocol; | 216 | fl6.flowi6_proto = sk->sk_protocol; |
222 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 217 | ipv6_addr_copy(&fl6.daddr, &np->daddr); |
223 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 218 | ipv6_addr_copy(&fl6.saddr, &np->saddr); |
224 | fl.fl6_flowlabel = np->flow_label; | 219 | fl6.flowlabel = np->flow_label; |
225 | IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel); | 220 | IP6_ECN_flow_xmit(sk, fl6.flowlabel); |
226 | fl.oif = sk->sk_bound_dev_if; | 221 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
227 | fl.mark = sk->sk_mark; | 222 | fl6.flowi6_mark = sk->sk_mark; |
228 | fl.fl_ip_sport = inet->inet_sport; | 223 | fl6.fl6_sport = inet->inet_sport; |
229 | fl.fl_ip_dport = inet->inet_dport; | 224 | fl6.fl6_dport = inet->inet_dport; |
230 | security_sk_classify_flow(sk, &fl); | 225 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
231 | 226 | ||
232 | final_p = fl6_update_dst(&fl, np->opt, &final); | 227 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
233 | 228 | ||
234 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); | 229 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); |
235 | 230 | ||
236 | if (dst == NULL) { | 231 | if (dst == NULL) { |
237 | int err = ip6_dst_lookup(sk, &dst, &fl); | 232 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); |
238 | |||
239 | if (err) { | ||
240 | sk->sk_err_soft = -err; | ||
241 | kfree_skb(skb); | ||
242 | return err; | ||
243 | } | ||
244 | |||
245 | if (final_p) | ||
246 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
247 | 233 | ||
248 | if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) { | 234 | if (IS_ERR(dst)) { |
235 | sk->sk_err_soft = -PTR_ERR(dst); | ||
249 | sk->sk_route_caps = 0; | 236 | sk->sk_route_caps = 0; |
250 | kfree_skb(skb); | 237 | kfree_skb(skb); |
251 | return err; | 238 | return PTR_ERR(dst); |
252 | } | 239 | } |
253 | 240 | ||
254 | __inet6_csk_dst_store(sk, dst, NULL, NULL); | 241 | __inet6_csk_dst_store(sk, dst, NULL, NULL); |
@@ -257,9 +244,9 @@ int inet6_csk_xmit(struct sk_buff *skb) | |||
257 | skb_dst_set(skb, dst_clone(dst)); | 244 | skb_dst_set(skb, dst_clone(dst)); |
258 | 245 | ||
259 | /* Restore final destination back after routing done */ | 246 | /* Restore final destination back after routing done */ |
260 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 247 | ipv6_addr_copy(&fl6.daddr, &np->daddr); |
261 | 248 | ||
262 | return ip6_xmit(sk, skb, &fl, np->opt); | 249 | return ip6_xmit(sk, skb, &fl6, np->opt); |
263 | } | 250 | } |
264 | 251 | ||
265 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); | 252 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index de382114609b..7548905e79e1 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -260,10 +260,10 @@ struct fib6_table *fib6_get_table(struct net *net, u32 id) | |||
260 | return net->ipv6.fib6_main_tbl; | 260 | return net->ipv6.fib6_main_tbl; |
261 | } | 261 | } |
262 | 262 | ||
263 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, | 263 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, |
264 | int flags, pol_lookup_t lookup) | 264 | int flags, pol_lookup_t lookup) |
265 | { | 265 | { |
266 | return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl, flags); | 266 | return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl6, flags); |
267 | } | 267 | } |
268 | 268 | ||
269 | static void __net_init fib6_tables_init(struct net *net) | 269 | static void __net_init fib6_tables_init(struct net *net) |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 13654686aeab..f3caf1b8d572 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -342,7 +342,7 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | |||
342 | 342 | ||
343 | if (olen > 0) { | 343 | if (olen > 0) { |
344 | struct msghdr msg; | 344 | struct msghdr msg; |
345 | struct flowi flowi; | 345 | struct flowi6 flowi6; |
346 | int junk; | 346 | int junk; |
347 | 347 | ||
348 | err = -ENOMEM; | 348 | err = -ENOMEM; |
@@ -358,9 +358,9 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | |||
358 | 358 | ||
359 | msg.msg_controllen = olen; | 359 | msg.msg_controllen = olen; |
360 | msg.msg_control = (void*)(fl->opt+1); | 360 | msg.msg_control = (void*)(fl->opt+1); |
361 | flowi.oif = 0; | 361 | memset(&flowi6, 0, sizeof(flowi6)); |
362 | 362 | ||
363 | err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk, | 363 | err = datagram_send_ctl(net, &msg, &flowi6, fl->opt, &junk, |
364 | &junk, &junk); | 364 | &junk, &junk); |
365 | if (err) | 365 | if (err) |
366 | goto done; | 366 | goto done; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 94b5bf132b2e..18208876aa8a 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -174,15 +174,15 @@ int ip6_output(struct sk_buff *skb) | |||
174 | * xmit an sk_buff (used by TCP, SCTP and DCCP) | 174 | * xmit an sk_buff (used by TCP, SCTP and DCCP) |
175 | */ | 175 | */ |
176 | 176 | ||
177 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | 177 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, |
178 | struct ipv6_txoptions *opt) | 178 | struct ipv6_txoptions *opt) |
179 | { | 179 | { |
180 | struct net *net = sock_net(sk); | 180 | struct net *net = sock_net(sk); |
181 | struct ipv6_pinfo *np = inet6_sk(sk); | 181 | struct ipv6_pinfo *np = inet6_sk(sk); |
182 | struct in6_addr *first_hop = &fl->fl6_dst; | 182 | struct in6_addr *first_hop = &fl6->daddr; |
183 | struct dst_entry *dst = skb_dst(skb); | 183 | struct dst_entry *dst = skb_dst(skb); |
184 | struct ipv6hdr *hdr; | 184 | struct ipv6hdr *hdr; |
185 | u8 proto = fl->proto; | 185 | u8 proto = fl6->flowi6_proto; |
186 | int seg_len = skb->len; | 186 | int seg_len = skb->len; |
187 | int hlimit = -1; | 187 | int hlimit = -1; |
188 | int tclass = 0; | 188 | int tclass = 0; |
@@ -230,13 +230,13 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
230 | if (hlimit < 0) | 230 | if (hlimit < 0) |
231 | hlimit = ip6_dst_hoplimit(dst); | 231 | hlimit = ip6_dst_hoplimit(dst); |
232 | 232 | ||
233 | *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; | 233 | *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl6->flowlabel; |
234 | 234 | ||
235 | hdr->payload_len = htons(seg_len); | 235 | hdr->payload_len = htons(seg_len); |
236 | hdr->nexthdr = proto; | 236 | hdr->nexthdr = proto; |
237 | hdr->hop_limit = hlimit; | 237 | hdr->hop_limit = hlimit; |
238 | 238 | ||
239 | ipv6_addr_copy(&hdr->saddr, &fl->fl6_src); | 239 | ipv6_addr_copy(&hdr->saddr, &fl6->saddr); |
240 | ipv6_addr_copy(&hdr->daddr, first_hop); | 240 | ipv6_addr_copy(&hdr->daddr, first_hop); |
241 | 241 | ||
242 | skb->priority = sk->sk_priority; | 242 | skb->priority = sk->sk_priority; |
@@ -274,13 +274,10 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, | |||
274 | { | 274 | { |
275 | struct ipv6_pinfo *np = inet6_sk(sk); | 275 | struct ipv6_pinfo *np = inet6_sk(sk); |
276 | struct ipv6hdr *hdr; | 276 | struct ipv6hdr *hdr; |
277 | int totlen; | ||
278 | 277 | ||
279 | skb->protocol = htons(ETH_P_IPV6); | 278 | skb->protocol = htons(ETH_P_IPV6); |
280 | skb->dev = dev; | 279 | skb->dev = dev; |
281 | 280 | ||
282 | totlen = len + sizeof(struct ipv6hdr); | ||
283 | |||
284 | skb_reset_network_header(skb); | 281 | skb_reset_network_header(skb); |
285 | skb_put(skb, sizeof(struct ipv6hdr)); | 282 | skb_put(skb, sizeof(struct ipv6hdr)); |
286 | hdr = ipv6_hdr(skb); | 283 | hdr = ipv6_hdr(skb); |
@@ -401,6 +398,9 @@ int ip6_forward(struct sk_buff *skb) | |||
401 | goto drop; | 398 | goto drop; |
402 | } | 399 | } |
403 | 400 | ||
401 | if (skb->pkt_type != PACKET_HOST) | ||
402 | goto drop; | ||
403 | |||
404 | skb_forward_csum(skb); | 404 | skb_forward_csum(skb); |
405 | 405 | ||
406 | /* | 406 | /* |
@@ -476,10 +476,13 @@ int ip6_forward(struct sk_buff *skb) | |||
476 | else | 476 | else |
477 | target = &hdr->daddr; | 477 | target = &hdr->daddr; |
478 | 478 | ||
479 | if (!rt->rt6i_peer) | ||
480 | rt6_bind_peer(rt, 1); | ||
481 | |||
479 | /* Limit redirects both by destination (here) | 482 | /* Limit redirects both by destination (here) |
480 | and by source (inside ndisc_send_redirect) | 483 | and by source (inside ndisc_send_redirect) |
481 | */ | 484 | */ |
482 | if (xrlim_allow(dst, 1*HZ)) | 485 | if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) |
483 | ndisc_send_redirect(skb, n, target); | 486 | ndisc_send_redirect(skb, n, target); |
484 | } else { | 487 | } else { |
485 | int addrtype = ipv6_addr_type(&hdr->saddr); | 488 | int addrtype = ipv6_addr_type(&hdr->saddr); |
@@ -876,7 +879,7 @@ static inline int ip6_rt_check(struct rt6key *rt_key, | |||
876 | 879 | ||
877 | static struct dst_entry *ip6_sk_dst_check(struct sock *sk, | 880 | static struct dst_entry *ip6_sk_dst_check(struct sock *sk, |
878 | struct dst_entry *dst, | 881 | struct dst_entry *dst, |
879 | struct flowi *fl) | 882 | struct flowi6 *fl6) |
880 | { | 883 | { |
881 | struct ipv6_pinfo *np = inet6_sk(sk); | 884 | struct ipv6_pinfo *np = inet6_sk(sk); |
882 | struct rt6_info *rt = (struct rt6_info *)dst; | 885 | struct rt6_info *rt = (struct rt6_info *)dst; |
@@ -901,11 +904,11 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk, | |||
901 | * sockets. | 904 | * sockets. |
902 | * 2. oif also should be the same. | 905 | * 2. oif also should be the same. |
903 | */ | 906 | */ |
904 | if (ip6_rt_check(&rt->rt6i_dst, &fl->fl6_dst, np->daddr_cache) || | 907 | if (ip6_rt_check(&rt->rt6i_dst, &fl6->daddr, np->daddr_cache) || |
905 | #ifdef CONFIG_IPV6_SUBTREES | 908 | #ifdef CONFIG_IPV6_SUBTREES |
906 | ip6_rt_check(&rt->rt6i_src, &fl->fl6_src, np->saddr_cache) || | 909 | ip6_rt_check(&rt->rt6i_src, &fl6->saddr, np->saddr_cache) || |
907 | #endif | 910 | #endif |
908 | (fl->oif && fl->oif != dst->dev->ifindex)) { | 911 | (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex)) { |
909 | dst_release(dst); | 912 | dst_release(dst); |
910 | dst = NULL; | 913 | dst = NULL; |
911 | } | 914 | } |
@@ -915,22 +918,22 @@ out: | |||
915 | } | 918 | } |
916 | 919 | ||
917 | static int ip6_dst_lookup_tail(struct sock *sk, | 920 | static int ip6_dst_lookup_tail(struct sock *sk, |
918 | struct dst_entry **dst, struct flowi *fl) | 921 | struct dst_entry **dst, struct flowi6 *fl6) |
919 | { | 922 | { |
920 | int err; | 923 | int err; |
921 | struct net *net = sock_net(sk); | 924 | struct net *net = sock_net(sk); |
922 | 925 | ||
923 | if (*dst == NULL) | 926 | if (*dst == NULL) |
924 | *dst = ip6_route_output(net, sk, fl); | 927 | *dst = ip6_route_output(net, sk, fl6); |
925 | 928 | ||
926 | if ((err = (*dst)->error)) | 929 | if ((err = (*dst)->error)) |
927 | goto out_err_release; | 930 | goto out_err_release; |
928 | 931 | ||
929 | if (ipv6_addr_any(&fl->fl6_src)) { | 932 | if (ipv6_addr_any(&fl6->saddr)) { |
930 | err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev, | 933 | err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev, |
931 | &fl->fl6_dst, | 934 | &fl6->daddr, |
932 | sk ? inet6_sk(sk)->srcprefs : 0, | 935 | sk ? inet6_sk(sk)->srcprefs : 0, |
933 | &fl->fl6_src); | 936 | &fl6->saddr); |
934 | if (err) | 937 | if (err) |
935 | goto out_err_release; | 938 | goto out_err_release; |
936 | } | 939 | } |
@@ -946,10 +949,10 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
946 | */ | 949 | */ |
947 | if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) { | 950 | if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) { |
948 | struct inet6_ifaddr *ifp; | 951 | struct inet6_ifaddr *ifp; |
949 | struct flowi fl_gw; | 952 | struct flowi6 fl_gw6; |
950 | int redirect; | 953 | int redirect; |
951 | 954 | ||
952 | ifp = ipv6_get_ifaddr(net, &fl->fl6_src, | 955 | ifp = ipv6_get_ifaddr(net, &fl6->saddr, |
953 | (*dst)->dev, 1); | 956 | (*dst)->dev, 1); |
954 | 957 | ||
955 | redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); | 958 | redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); |
@@ -962,9 +965,9 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
962 | * default router instead | 965 | * default router instead |
963 | */ | 966 | */ |
964 | dst_release(*dst); | 967 | dst_release(*dst); |
965 | memcpy(&fl_gw, fl, sizeof(struct flowi)); | 968 | memcpy(&fl_gw6, fl6, sizeof(struct flowi6)); |
966 | memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); | 969 | memset(&fl_gw6.daddr, 0, sizeof(struct in6_addr)); |
967 | *dst = ip6_route_output(net, sk, &fl_gw); | 970 | *dst = ip6_route_output(net, sk, &fl_gw6); |
968 | if ((err = (*dst)->error)) | 971 | if ((err = (*dst)->error)) |
969 | goto out_err_release; | 972 | goto out_err_release; |
970 | } | 973 | } |
@@ -985,43 +988,85 @@ out_err_release: | |||
985 | * ip6_dst_lookup - perform route lookup on flow | 988 | * ip6_dst_lookup - perform route lookup on flow |
986 | * @sk: socket which provides route info | 989 | * @sk: socket which provides route info |
987 | * @dst: pointer to dst_entry * for result | 990 | * @dst: pointer to dst_entry * for result |
988 | * @fl: flow to lookup | 991 | * @fl6: flow to lookup |
989 | * | 992 | * |
990 | * This function performs a route lookup on the given flow. | 993 | * This function performs a route lookup on the given flow. |
991 | * | 994 | * |
992 | * It returns zero on success, or a standard errno code on error. | 995 | * It returns zero on success, or a standard errno code on error. |
993 | */ | 996 | */ |
994 | int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | 997 | int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi6 *fl6) |
995 | { | 998 | { |
996 | *dst = NULL; | 999 | *dst = NULL; |
997 | return ip6_dst_lookup_tail(sk, dst, fl); | 1000 | return ip6_dst_lookup_tail(sk, dst, fl6); |
998 | } | 1001 | } |
999 | EXPORT_SYMBOL_GPL(ip6_dst_lookup); | 1002 | EXPORT_SYMBOL_GPL(ip6_dst_lookup); |
1000 | 1003 | ||
1001 | /** | 1004 | /** |
1002 | * ip6_sk_dst_lookup - perform socket cached route lookup on flow | 1005 | * ip6_dst_lookup_flow - perform route lookup on flow with ipsec |
1006 | * @sk: socket which provides route info | ||
1007 | * @fl6: flow to lookup | ||
1008 | * @final_dst: final destination address for ipsec lookup | ||
1009 | * @can_sleep: we are in a sleepable context | ||
1010 | * | ||
1011 | * This function performs a route lookup on the given flow. | ||
1012 | * | ||
1013 | * It returns a valid dst pointer on success, or a pointer encoded | ||
1014 | * error code. | ||
1015 | */ | ||
1016 | struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, | ||
1017 | const struct in6_addr *final_dst, | ||
1018 | bool can_sleep) | ||
1019 | { | ||
1020 | struct dst_entry *dst = NULL; | ||
1021 | int err; | ||
1022 | |||
1023 | err = ip6_dst_lookup_tail(sk, &dst, fl6); | ||
1024 | if (err) | ||
1025 | return ERR_PTR(err); | ||
1026 | if (final_dst) | ||
1027 | ipv6_addr_copy(&fl6->daddr, final_dst); | ||
1028 | if (can_sleep) | ||
1029 | fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP; | ||
1030 | |||
1031 | return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); | ||
1032 | } | ||
1033 | EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); | ||
1034 | |||
1035 | /** | ||
1036 | * ip6_sk_dst_lookup_flow - perform socket cached route lookup on flow | ||
1003 | * @sk: socket which provides the dst cache and route info | 1037 | * @sk: socket which provides the dst cache and route info |
1004 | * @dst: pointer to dst_entry * for result | 1038 | * @fl6: flow to lookup |
1005 | * @fl: flow to lookup | 1039 | * @final_dst: final destination address for ipsec lookup |
1040 | * @can_sleep: we are in a sleepable context | ||
1006 | * | 1041 | * |
1007 | * This function performs a route lookup on the given flow with the | 1042 | * This function performs a route lookup on the given flow with the |
1008 | * possibility of using the cached route in the socket if it is valid. | 1043 | * possibility of using the cached route in the socket if it is valid. |
1009 | * It will take the socket dst lock when operating on the dst cache. | 1044 | * It will take the socket dst lock when operating on the dst cache. |
1010 | * As a result, this function can only be used in process context. | 1045 | * As a result, this function can only be used in process context. |
1011 | * | 1046 | * |
1012 | * It returns zero on success, or a standard errno code on error. | 1047 | * It returns a valid dst pointer on success, or a pointer encoded |
1048 | * error code. | ||
1013 | */ | 1049 | */ |
1014 | int ip6_sk_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | 1050 | struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, |
1051 | const struct in6_addr *final_dst, | ||
1052 | bool can_sleep) | ||
1015 | { | 1053 | { |
1016 | *dst = NULL; | 1054 | struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); |
1017 | if (sk) { | 1055 | int err; |
1018 | *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); | 1056 | |
1019 | *dst = ip6_sk_dst_check(sk, *dst, fl); | 1057 | dst = ip6_sk_dst_check(sk, dst, fl6); |
1020 | } | 1058 | |
1059 | err = ip6_dst_lookup_tail(sk, &dst, fl6); | ||
1060 | if (err) | ||
1061 | return ERR_PTR(err); | ||
1062 | if (final_dst) | ||
1063 | ipv6_addr_copy(&fl6->daddr, final_dst); | ||
1064 | if (can_sleep) | ||
1065 | fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP; | ||
1021 | 1066 | ||
1022 | return ip6_dst_lookup_tail(sk, dst, fl); | 1067 | return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); |
1023 | } | 1068 | } |
1024 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup); | 1069 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); |
1025 | 1070 | ||
1026 | static inline int ip6_ufo_append_data(struct sock *sk, | 1071 | static inline int ip6_ufo_append_data(struct sock *sk, |
1027 | int getfrag(void *from, char *to, int offset, int len, | 1072 | int getfrag(void *from, char *to, int offset, int len, |
@@ -1058,7 +1103,6 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
1058 | 1103 | ||
1059 | skb->ip_summed = CHECKSUM_PARTIAL; | 1104 | skb->ip_summed = CHECKSUM_PARTIAL; |
1060 | skb->csum = 0; | 1105 | skb->csum = 0; |
1061 | sk->sk_sndmsg_off = 0; | ||
1062 | } | 1106 | } |
1063 | 1107 | ||
1064 | err = skb_append_datato_frags(sk,skb, getfrag, from, | 1108 | err = skb_append_datato_frags(sk,skb, getfrag, from, |
@@ -1101,7 +1145,7 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, | |||
1101 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | 1145 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, |
1102 | int offset, int len, int odd, struct sk_buff *skb), | 1146 | int offset, int len, int odd, struct sk_buff *skb), |
1103 | void *from, int length, int transhdrlen, | 1147 | void *from, int length, int transhdrlen, |
1104 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, | 1148 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6, |
1105 | struct rt6_info *rt, unsigned int flags, int dontfrag) | 1149 | struct rt6_info *rt, unsigned int flags, int dontfrag) |
1106 | { | 1150 | { |
1107 | struct inet_sock *inet = inet_sk(sk); | 1151 | struct inet_sock *inet = inet_sk(sk); |
@@ -1115,6 +1159,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1115 | int err; | 1159 | int err; |
1116 | int offset = 0; | 1160 | int offset = 0; |
1117 | int csummode = CHECKSUM_NONE; | 1161 | int csummode = CHECKSUM_NONE; |
1162 | __u8 tx_flags = 0; | ||
1118 | 1163 | ||
1119 | if (flags&MSG_PROBE) | 1164 | if (flags&MSG_PROBE) |
1120 | return 0; | 1165 | return 0; |
@@ -1158,7 +1203,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1158 | } | 1203 | } |
1159 | dst_hold(&rt->dst); | 1204 | dst_hold(&rt->dst); |
1160 | inet->cork.dst = &rt->dst; | 1205 | inet->cork.dst = &rt->dst; |
1161 | inet->cork.fl = *fl; | 1206 | inet->cork.fl.u.ip6 = *fl6; |
1162 | np->cork.hop_limit = hlimit; | 1207 | np->cork.hop_limit = hlimit; |
1163 | np->cork.tclass = tclass; | 1208 | np->cork.tclass = tclass; |
1164 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? | 1209 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? |
@@ -1179,7 +1224,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1179 | transhdrlen += exthdrlen; | 1224 | transhdrlen += exthdrlen; |
1180 | } else { | 1225 | } else { |
1181 | rt = (struct rt6_info *)inet->cork.dst; | 1226 | rt = (struct rt6_info *)inet->cork.dst; |
1182 | fl = &inet->cork.fl; | 1227 | fl6 = &inet->cork.fl.u.ip6; |
1183 | opt = np->cork.opt; | 1228 | opt = np->cork.opt; |
1184 | transhdrlen = 0; | 1229 | transhdrlen = 0; |
1185 | exthdrlen = 0; | 1230 | exthdrlen = 0; |
@@ -1194,11 +1239,18 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1194 | 1239 | ||
1195 | if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { | 1240 | if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { |
1196 | if (inet->cork.length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { | 1241 | if (inet->cork.length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { |
1197 | ipv6_local_error(sk, EMSGSIZE, fl, mtu-exthdrlen); | 1242 | ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen); |
1198 | return -EMSGSIZE; | 1243 | return -EMSGSIZE; |
1199 | } | 1244 | } |
1200 | } | 1245 | } |
1201 | 1246 | ||
1247 | /* For UDP, check if TX timestamp is enabled */ | ||
1248 | if (sk->sk_type == SOCK_DGRAM) { | ||
1249 | err = sock_tx_timestamp(sk, &tx_flags); | ||
1250 | if (err) | ||
1251 | goto error; | ||
1252 | } | ||
1253 | |||
1202 | /* | 1254 | /* |
1203 | * Let's try using as much space as possible. | 1255 | * Let's try using as much space as possible. |
1204 | * Use MTU if total length of the message fits into the MTU. | 1256 | * Use MTU if total length of the message fits into the MTU. |
@@ -1219,7 +1271,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1219 | if (length > mtu) { | 1271 | if (length > mtu) { |
1220 | int proto = sk->sk_protocol; | 1272 | int proto = sk->sk_protocol; |
1221 | if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ | 1273 | if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ |
1222 | ipv6_local_rxpmtu(sk, fl, mtu-exthdrlen); | 1274 | ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); |
1223 | return -EMSGSIZE; | 1275 | return -EMSGSIZE; |
1224 | } | 1276 | } |
1225 | 1277 | ||
@@ -1303,6 +1355,12 @@ alloc_new_skb: | |||
1303 | sk->sk_allocation); | 1355 | sk->sk_allocation); |
1304 | if (unlikely(skb == NULL)) | 1356 | if (unlikely(skb == NULL)) |
1305 | err = -ENOBUFS; | 1357 | err = -ENOBUFS; |
1358 | else { | ||
1359 | /* Only the initial fragment | ||
1360 | * is time stamped. | ||
1361 | */ | ||
1362 | tx_flags = 0; | ||
1363 | } | ||
1306 | } | 1364 | } |
1307 | if (skb == NULL) | 1365 | if (skb == NULL) |
1308 | goto error; | 1366 | goto error; |
@@ -1314,6 +1372,9 @@ alloc_new_skb: | |||
1314 | /* reserve for fragmentation */ | 1372 | /* reserve for fragmentation */ |
1315 | skb_reserve(skb, hh_len+sizeof(struct frag_hdr)); | 1373 | skb_reserve(skb, hh_len+sizeof(struct frag_hdr)); |
1316 | 1374 | ||
1375 | if (sk->sk_type == SOCK_DGRAM) | ||
1376 | skb_shinfo(skb)->tx_flags = tx_flags; | ||
1377 | |||
1317 | /* | 1378 | /* |
1318 | * Find where to start putting bytes | 1379 | * Find where to start putting bytes |
1319 | */ | 1380 | */ |
@@ -1455,8 +1516,8 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1455 | struct ipv6hdr *hdr; | 1516 | struct ipv6hdr *hdr; |
1456 | struct ipv6_txoptions *opt = np->cork.opt; | 1517 | struct ipv6_txoptions *opt = np->cork.opt; |
1457 | struct rt6_info *rt = (struct rt6_info *)inet->cork.dst; | 1518 | struct rt6_info *rt = (struct rt6_info *)inet->cork.dst; |
1458 | struct flowi *fl = &inet->cork.fl; | 1519 | struct flowi6 *fl6 = &inet->cork.fl.u.ip6; |
1459 | unsigned char proto = fl->proto; | 1520 | unsigned char proto = fl6->flowi6_proto; |
1460 | int err = 0; | 1521 | int err = 0; |
1461 | 1522 | ||
1462 | if ((skb = __skb_dequeue(&sk->sk_write_queue)) == NULL) | 1523 | if ((skb = __skb_dequeue(&sk->sk_write_queue)) == NULL) |
@@ -1481,7 +1542,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1481 | if (np->pmtudisc < IPV6_PMTUDISC_DO) | 1542 | if (np->pmtudisc < IPV6_PMTUDISC_DO) |
1482 | skb->local_df = 1; | 1543 | skb->local_df = 1; |
1483 | 1544 | ||
1484 | ipv6_addr_copy(final_dst, &fl->fl6_dst); | 1545 | ipv6_addr_copy(final_dst, &fl6->daddr); |
1485 | __skb_pull(skb, skb_network_header_len(skb)); | 1546 | __skb_pull(skb, skb_network_header_len(skb)); |
1486 | if (opt && opt->opt_flen) | 1547 | if (opt && opt->opt_flen) |
1487 | ipv6_push_frag_opts(skb, opt, &proto); | 1548 | ipv6_push_frag_opts(skb, opt, &proto); |
@@ -1492,12 +1553,12 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1492 | skb_reset_network_header(skb); | 1553 | skb_reset_network_header(skb); |
1493 | hdr = ipv6_hdr(skb); | 1554 | hdr = ipv6_hdr(skb); |
1494 | 1555 | ||
1495 | *(__be32*)hdr = fl->fl6_flowlabel | | 1556 | *(__be32*)hdr = fl6->flowlabel | |
1496 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); | 1557 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); |
1497 | 1558 | ||
1498 | hdr->hop_limit = np->cork.hop_limit; | 1559 | hdr->hop_limit = np->cork.hop_limit; |
1499 | hdr->nexthdr = proto; | 1560 | hdr->nexthdr = proto; |
1500 | ipv6_addr_copy(&hdr->saddr, &fl->fl6_src); | 1561 | ipv6_addr_copy(&hdr->saddr, &fl6->saddr); |
1501 | ipv6_addr_copy(&hdr->daddr, final_dst); | 1562 | ipv6_addr_copy(&hdr->daddr, final_dst); |
1502 | 1563 | ||
1503 | skb->priority = sk->sk_priority; | 1564 | skb->priority = sk->sk_priority; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 4f4483e697bd..c1b1bd312df2 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -57,6 +57,7 @@ | |||
57 | MODULE_AUTHOR("Ville Nuorvala"); | 57 | MODULE_AUTHOR("Ville Nuorvala"); |
58 | MODULE_DESCRIPTION("IPv6 tunneling device"); | 58 | MODULE_DESCRIPTION("IPv6 tunneling device"); |
59 | MODULE_LICENSE("GPL"); | 59 | MODULE_LICENSE("GPL"); |
60 | MODULE_ALIAS_NETDEV("ip6tnl0"); | ||
60 | 61 | ||
61 | #ifdef IP6_TNL_DEBUG | 62 | #ifdef IP6_TNL_DEBUG |
62 | #define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __func__) | 63 | #define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __func__) |
@@ -535,7 +536,6 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
535 | int err; | 536 | int err; |
536 | struct sk_buff *skb2; | 537 | struct sk_buff *skb2; |
537 | struct iphdr *eiph; | 538 | struct iphdr *eiph; |
538 | struct flowi fl; | ||
539 | struct rtable *rt; | 539 | struct rtable *rt; |
540 | 540 | ||
541 | err = ip6_tnl_err(skb, IPPROTO_IPIP, opt, &rel_type, &rel_code, | 541 | err = ip6_tnl_err(skb, IPPROTO_IPIP, opt, &rel_type, &rel_code, |
@@ -577,11 +577,11 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
577 | eiph = ip_hdr(skb2); | 577 | eiph = ip_hdr(skb2); |
578 | 578 | ||
579 | /* Try to guess incoming interface */ | 579 | /* Try to guess incoming interface */ |
580 | memset(&fl, 0, sizeof(fl)); | 580 | rt = ip_route_output_ports(dev_net(skb->dev), NULL, |
581 | fl.fl4_dst = eiph->saddr; | 581 | eiph->saddr, 0, |
582 | fl.fl4_tos = RT_TOS(eiph->tos); | 582 | 0, 0, |
583 | fl.proto = IPPROTO_IPIP; | 583 | IPPROTO_IPIP, RT_TOS(eiph->tos), 0); |
584 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl)) | 584 | if (IS_ERR(rt)) |
585 | goto out; | 585 | goto out; |
586 | 586 | ||
587 | skb2->dev = rt->dst.dev; | 587 | skb2->dev = rt->dst.dev; |
@@ -590,15 +590,18 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
590 | if (rt->rt_flags & RTCF_LOCAL) { | 590 | if (rt->rt_flags & RTCF_LOCAL) { |
591 | ip_rt_put(rt); | 591 | ip_rt_put(rt); |
592 | rt = NULL; | 592 | rt = NULL; |
593 | fl.fl4_dst = eiph->daddr; | 593 | rt = ip_route_output_ports(dev_net(skb->dev), NULL, |
594 | fl.fl4_src = eiph->saddr; | 594 | eiph->daddr, eiph->saddr, |
595 | fl.fl4_tos = eiph->tos; | 595 | 0, 0, |
596 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) || | 596 | IPPROTO_IPIP, |
597 | RT_TOS(eiph->tos), 0); | ||
598 | if (IS_ERR(rt) || | ||
597 | rt->dst.dev->type != ARPHRD_TUNNEL) { | 599 | rt->dst.dev->type != ARPHRD_TUNNEL) { |
598 | ip_rt_put(rt); | 600 | if (!IS_ERR(rt)) |
601 | ip_rt_put(rt); | ||
599 | goto out; | 602 | goto out; |
600 | } | 603 | } |
601 | skb_dst_set(skb2, (struct dst_entry *)rt); | 604 | skb_dst_set(skb2, &rt->dst); |
602 | } else { | 605 | } else { |
603 | ip_rt_put(rt); | 606 | ip_rt_put(rt); |
604 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, | 607 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, |
@@ -881,7 +884,7 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t) | |||
881 | static int ip6_tnl_xmit2(struct sk_buff *skb, | 884 | static int ip6_tnl_xmit2(struct sk_buff *skb, |
882 | struct net_device *dev, | 885 | struct net_device *dev, |
883 | __u8 dsfield, | 886 | __u8 dsfield, |
884 | struct flowi *fl, | 887 | struct flowi6 *fl6, |
885 | int encap_limit, | 888 | int encap_limit, |
886 | __u32 *pmtu) | 889 | __u32 *pmtu) |
887 | { | 890 | { |
@@ -901,10 +904,16 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
901 | if ((dst = ip6_tnl_dst_check(t)) != NULL) | 904 | if ((dst = ip6_tnl_dst_check(t)) != NULL) |
902 | dst_hold(dst); | 905 | dst_hold(dst); |
903 | else { | 906 | else { |
904 | dst = ip6_route_output(net, NULL, fl); | 907 | dst = ip6_route_output(net, NULL, fl6); |
905 | 908 | ||
906 | if (dst->error || xfrm_lookup(net, &dst, fl, NULL, 0) < 0) | 909 | if (dst->error) |
907 | goto tx_err_link_failure; | 910 | goto tx_err_link_failure; |
911 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), NULL, 0); | ||
912 | if (IS_ERR(dst)) { | ||
913 | err = PTR_ERR(dst); | ||
914 | dst = NULL; | ||
915 | goto tx_err_link_failure; | ||
916 | } | ||
908 | } | 917 | } |
909 | 918 | ||
910 | tdev = dst->dev; | 919 | tdev = dst->dev; |
@@ -954,7 +963,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
954 | 963 | ||
955 | skb->transport_header = skb->network_header; | 964 | skb->transport_header = skb->network_header; |
956 | 965 | ||
957 | proto = fl->proto; | 966 | proto = fl6->flowi6_proto; |
958 | if (encap_limit >= 0) { | 967 | if (encap_limit >= 0) { |
959 | init_tel_txopt(&opt, encap_limit); | 968 | init_tel_txopt(&opt, encap_limit); |
960 | ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL); | 969 | ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL); |
@@ -962,13 +971,13 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
962 | skb_push(skb, sizeof(struct ipv6hdr)); | 971 | skb_push(skb, sizeof(struct ipv6hdr)); |
963 | skb_reset_network_header(skb); | 972 | skb_reset_network_header(skb); |
964 | ipv6h = ipv6_hdr(skb); | 973 | ipv6h = ipv6_hdr(skb); |
965 | *(__be32*)ipv6h = fl->fl6_flowlabel | htonl(0x60000000); | 974 | *(__be32*)ipv6h = fl6->flowlabel | htonl(0x60000000); |
966 | dsfield = INET_ECN_encapsulate(0, dsfield); | 975 | dsfield = INET_ECN_encapsulate(0, dsfield); |
967 | ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); | 976 | ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); |
968 | ipv6h->hop_limit = t->parms.hop_limit; | 977 | ipv6h->hop_limit = t->parms.hop_limit; |
969 | ipv6h->nexthdr = proto; | 978 | ipv6h->nexthdr = proto; |
970 | ipv6_addr_copy(&ipv6h->saddr, &fl->fl6_src); | 979 | ipv6_addr_copy(&ipv6h->saddr, &fl6->saddr); |
971 | ipv6_addr_copy(&ipv6h->daddr, &fl->fl6_dst); | 980 | ipv6_addr_copy(&ipv6h->daddr, &fl6->daddr); |
972 | nf_reset(skb); | 981 | nf_reset(skb); |
973 | pkt_len = skb->len; | 982 | pkt_len = skb->len; |
974 | err = ip6_local_out(skb); | 983 | err = ip6_local_out(skb); |
@@ -998,7 +1007,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
998 | struct ip6_tnl *t = netdev_priv(dev); | 1007 | struct ip6_tnl *t = netdev_priv(dev); |
999 | struct iphdr *iph = ip_hdr(skb); | 1008 | struct iphdr *iph = ip_hdr(skb); |
1000 | int encap_limit = -1; | 1009 | int encap_limit = -1; |
1001 | struct flowi fl; | 1010 | struct flowi6 fl6; |
1002 | __u8 dsfield; | 1011 | __u8 dsfield; |
1003 | __u32 mtu; | 1012 | __u32 mtu; |
1004 | int err; | 1013 | int err; |
@@ -1010,16 +1019,16 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1010 | if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | 1019 | if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) |
1011 | encap_limit = t->parms.encap_limit; | 1020 | encap_limit = t->parms.encap_limit; |
1012 | 1021 | ||
1013 | memcpy(&fl, &t->fl, sizeof (fl)); | 1022 | memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6)); |
1014 | fl.proto = IPPROTO_IPIP; | 1023 | fl6.flowi6_proto = IPPROTO_IPIP; |
1015 | 1024 | ||
1016 | dsfield = ipv4_get_dsfield(iph); | 1025 | dsfield = ipv4_get_dsfield(iph); |
1017 | 1026 | ||
1018 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) | 1027 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) |
1019 | fl.fl6_flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) | 1028 | fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) |
1020 | & IPV6_TCLASS_MASK; | 1029 | & IPV6_TCLASS_MASK; |
1021 | 1030 | ||
1022 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl, encap_limit, &mtu); | 1031 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); |
1023 | if (err != 0) { | 1032 | if (err != 0) { |
1024 | /* XXX: send ICMP error even if DF is not set. */ | 1033 | /* XXX: send ICMP error even if DF is not set. */ |
1025 | if (err == -EMSGSIZE) | 1034 | if (err == -EMSGSIZE) |
@@ -1038,7 +1047,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1038 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 1047 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
1039 | int encap_limit = -1; | 1048 | int encap_limit = -1; |
1040 | __u16 offset; | 1049 | __u16 offset; |
1041 | struct flowi fl; | 1050 | struct flowi6 fl6; |
1042 | __u8 dsfield; | 1051 | __u8 dsfield; |
1043 | __u32 mtu; | 1052 | __u32 mtu; |
1044 | int err; | 1053 | int err; |
@@ -1060,16 +1069,16 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1060 | } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | 1069 | } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) |
1061 | encap_limit = t->parms.encap_limit; | 1070 | encap_limit = t->parms.encap_limit; |
1062 | 1071 | ||
1063 | memcpy(&fl, &t->fl, sizeof (fl)); | 1072 | memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6)); |
1064 | fl.proto = IPPROTO_IPV6; | 1073 | fl6.flowi6_proto = IPPROTO_IPV6; |
1065 | 1074 | ||
1066 | dsfield = ipv6_get_dsfield(ipv6h); | 1075 | dsfield = ipv6_get_dsfield(ipv6h); |
1067 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) | 1076 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) |
1068 | fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); | 1077 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); |
1069 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) | 1078 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) |
1070 | fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); | 1079 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); |
1071 | 1080 | ||
1072 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl, encap_limit, &mtu); | 1081 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); |
1073 | if (err != 0) { | 1082 | if (err != 0) { |
1074 | if (err == -EMSGSIZE) | 1083 | if (err == -EMSGSIZE) |
1075 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 1084 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
@@ -1132,21 +1141,21 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) | |||
1132 | { | 1141 | { |
1133 | struct net_device *dev = t->dev; | 1142 | struct net_device *dev = t->dev; |
1134 | struct ip6_tnl_parm *p = &t->parms; | 1143 | struct ip6_tnl_parm *p = &t->parms; |
1135 | struct flowi *fl = &t->fl; | 1144 | struct flowi6 *fl6 = &t->fl.u.ip6; |
1136 | 1145 | ||
1137 | memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); | 1146 | memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); |
1138 | memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); | 1147 | memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); |
1139 | 1148 | ||
1140 | /* Set up flowi template */ | 1149 | /* Set up flowi template */ |
1141 | ipv6_addr_copy(&fl->fl6_src, &p->laddr); | 1150 | ipv6_addr_copy(&fl6->saddr, &p->laddr); |
1142 | ipv6_addr_copy(&fl->fl6_dst, &p->raddr); | 1151 | ipv6_addr_copy(&fl6->daddr, &p->raddr); |
1143 | fl->oif = p->link; | 1152 | fl6->flowi6_oif = p->link; |
1144 | fl->fl6_flowlabel = 0; | 1153 | fl6->flowlabel = 0; |
1145 | 1154 | ||
1146 | if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS)) | 1155 | if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS)) |
1147 | fl->fl6_flowlabel |= IPV6_TCLASS_MASK & p->flowinfo; | 1156 | fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo; |
1148 | if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL)) | 1157 | if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL)) |
1149 | fl->fl6_flowlabel |= IPV6_FLOWLABEL_MASK & p->flowinfo; | 1158 | fl6->flowlabel |= IPV6_FLOWLABEL_MASK & p->flowinfo; |
1150 | 1159 | ||
1151 | ip6_tnl_set_cap(t); | 1160 | ip6_tnl_set_cap(t); |
1152 | 1161 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 9fab274019c0..7ff0343e05c7 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/compat.h> | ||
37 | #include <net/protocol.h> | 38 | #include <net/protocol.h> |
38 | #include <linux/skbuff.h> | 39 | #include <linux/skbuff.h> |
39 | #include <net/sock.h> | 40 | #include <net/sock.h> |
@@ -134,14 +135,15 @@ static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) | |||
134 | return NULL; | 135 | return NULL; |
135 | } | 136 | } |
136 | 137 | ||
137 | static int ip6mr_fib_lookup(struct net *net, struct flowi *flp, | 138 | static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6, |
138 | struct mr6_table **mrt) | 139 | struct mr6_table **mrt) |
139 | { | 140 | { |
140 | struct ip6mr_result res; | 141 | struct ip6mr_result res; |
141 | struct fib_lookup_arg arg = { .result = &res, }; | 142 | struct fib_lookup_arg arg = { .result = &res, }; |
142 | int err; | 143 | int err; |
143 | 144 | ||
144 | err = fib_rules_lookup(net->ipv6.mr6_rules_ops, flp, 0, &arg); | 145 | err = fib_rules_lookup(net->ipv6.mr6_rules_ops, |
146 | flowi6_to_flowi(flp6), 0, &arg); | ||
145 | if (err < 0) | 147 | if (err < 0) |
146 | return err; | 148 | return err; |
147 | *mrt = res.mrt; | 149 | *mrt = res.mrt; |
@@ -269,7 +271,7 @@ static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) | |||
269 | return net->ipv6.mrt6; | 271 | return net->ipv6.mrt6; |
270 | } | 272 | } |
271 | 273 | ||
272 | static int ip6mr_fib_lookup(struct net *net, struct flowi *flp, | 274 | static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6, |
273 | struct mr6_table **mrt) | 275 | struct mr6_table **mrt) |
274 | { | 276 | { |
275 | *mrt = net->ipv6.mrt6; | 277 | *mrt = net->ipv6.mrt6; |
@@ -616,9 +618,9 @@ static int pim6_rcv(struct sk_buff *skb) | |||
616 | struct net_device *reg_dev = NULL; | 618 | struct net_device *reg_dev = NULL; |
617 | struct net *net = dev_net(skb->dev); | 619 | struct net *net = dev_net(skb->dev); |
618 | struct mr6_table *mrt; | 620 | struct mr6_table *mrt; |
619 | struct flowi fl = { | 621 | struct flowi6 fl6 = { |
620 | .iif = skb->dev->ifindex, | 622 | .flowi6_iif = skb->dev->ifindex, |
621 | .mark = skb->mark, | 623 | .flowi6_mark = skb->mark, |
622 | }; | 624 | }; |
623 | int reg_vif_num; | 625 | int reg_vif_num; |
624 | 626 | ||
@@ -643,7 +645,7 @@ static int pim6_rcv(struct sk_buff *skb) | |||
643 | ntohs(encap->payload_len) + sizeof(*pim) > skb->len) | 645 | ntohs(encap->payload_len) + sizeof(*pim) > skb->len) |
644 | goto drop; | 646 | goto drop; |
645 | 647 | ||
646 | if (ip6mr_fib_lookup(net, &fl, &mrt) < 0) | 648 | if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0) |
647 | goto drop; | 649 | goto drop; |
648 | reg_vif_num = mrt->mroute_reg_vif_num; | 650 | reg_vif_num = mrt->mroute_reg_vif_num; |
649 | 651 | ||
@@ -686,14 +688,14 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, | |||
686 | { | 688 | { |
687 | struct net *net = dev_net(dev); | 689 | struct net *net = dev_net(dev); |
688 | struct mr6_table *mrt; | 690 | struct mr6_table *mrt; |
689 | struct flowi fl = { | 691 | struct flowi6 fl6 = { |
690 | .oif = dev->ifindex, | 692 | .flowi6_oif = dev->ifindex, |
691 | .iif = skb->skb_iif, | 693 | .flowi6_iif = skb->skb_iif, |
692 | .mark = skb->mark, | 694 | .flowi6_mark = skb->mark, |
693 | }; | 695 | }; |
694 | int err; | 696 | int err; |
695 | 697 | ||
696 | err = ip6mr_fib_lookup(net, &fl, &mrt); | 698 | err = ip6mr_fib_lookup(net, &fl6, &mrt); |
697 | if (err < 0) | 699 | if (err < 0) |
698 | return err; | 700 | return err; |
699 | 701 | ||
@@ -1038,7 +1040,6 @@ static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt, | |||
1038 | 1040 | ||
1039 | while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { | 1041 | while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) { |
1040 | if (ipv6_hdr(skb)->version == 0) { | 1042 | if (ipv6_hdr(skb)->version == 0) { |
1041 | int err; | ||
1042 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); | 1043 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); |
1043 | 1044 | ||
1044 | if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { | 1045 | if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { |
@@ -1049,7 +1050,7 @@ static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt, | |||
1049 | skb_trim(skb, nlh->nlmsg_len); | 1050 | skb_trim(skb, nlh->nlmsg_len); |
1050 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; | 1051 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; |
1051 | } | 1052 | } |
1052 | err = rtnl_unicast(skb, net, NETLINK_CB(skb).pid); | 1053 | rtnl_unicast(skb, net, NETLINK_CB(skb).pid); |
1053 | } else | 1054 | } else |
1054 | ip6_mr_forward(net, mrt, skb, c); | 1055 | ip6_mr_forward(net, mrt, skb, c); |
1055 | } | 1056 | } |
@@ -1547,13 +1548,13 @@ int ip6mr_sk_done(struct sock *sk) | |||
1547 | struct sock *mroute6_socket(struct net *net, struct sk_buff *skb) | 1548 | struct sock *mroute6_socket(struct net *net, struct sk_buff *skb) |
1548 | { | 1549 | { |
1549 | struct mr6_table *mrt; | 1550 | struct mr6_table *mrt; |
1550 | struct flowi fl = { | 1551 | struct flowi6 fl6 = { |
1551 | .iif = skb->skb_iif, | 1552 | .flowi6_iif = skb->skb_iif, |
1552 | .oif = skb->dev->ifindex, | 1553 | .flowi6_oif = skb->dev->ifindex, |
1553 | .mark = skb->mark, | 1554 | .flowi6_mark = skb->mark, |
1554 | }; | 1555 | }; |
1555 | 1556 | ||
1556 | if (ip6mr_fib_lookup(net, &fl, &mrt) < 0) | 1557 | if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0) |
1557 | return NULL; | 1558 | return NULL; |
1558 | 1559 | ||
1559 | return mrt->mroute6_sk; | 1560 | return mrt->mroute6_sk; |
@@ -1804,6 +1805,80 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1804 | } | 1805 | } |
1805 | } | 1806 | } |
1806 | 1807 | ||
1808 | #ifdef CONFIG_COMPAT | ||
1809 | struct compat_sioc_sg_req6 { | ||
1810 | struct sockaddr_in6 src; | ||
1811 | struct sockaddr_in6 grp; | ||
1812 | compat_ulong_t pktcnt; | ||
1813 | compat_ulong_t bytecnt; | ||
1814 | compat_ulong_t wrong_if; | ||
1815 | }; | ||
1816 | |||
1817 | struct compat_sioc_mif_req6 { | ||
1818 | mifi_t mifi; | ||
1819 | compat_ulong_t icount; | ||
1820 | compat_ulong_t ocount; | ||
1821 | compat_ulong_t ibytes; | ||
1822 | compat_ulong_t obytes; | ||
1823 | }; | ||
1824 | |||
1825 | int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) | ||
1826 | { | ||
1827 | struct compat_sioc_sg_req6 sr; | ||
1828 | struct compat_sioc_mif_req6 vr; | ||
1829 | struct mif_device *vif; | ||
1830 | struct mfc6_cache *c; | ||
1831 | struct net *net = sock_net(sk); | ||
1832 | struct mr6_table *mrt; | ||
1833 | |||
1834 | mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); | ||
1835 | if (mrt == NULL) | ||
1836 | return -ENOENT; | ||
1837 | |||
1838 | switch (cmd) { | ||
1839 | case SIOCGETMIFCNT_IN6: | ||
1840 | if (copy_from_user(&vr, arg, sizeof(vr))) | ||
1841 | return -EFAULT; | ||
1842 | if (vr.mifi >= mrt->maxvif) | ||
1843 | return -EINVAL; | ||
1844 | read_lock(&mrt_lock); | ||
1845 | vif = &mrt->vif6_table[vr.mifi]; | ||
1846 | if (MIF_EXISTS(mrt, vr.mifi)) { | ||
1847 | vr.icount = vif->pkt_in; | ||
1848 | vr.ocount = vif->pkt_out; | ||
1849 | vr.ibytes = vif->bytes_in; | ||
1850 | vr.obytes = vif->bytes_out; | ||
1851 | read_unlock(&mrt_lock); | ||
1852 | |||
1853 | if (copy_to_user(arg, &vr, sizeof(vr))) | ||
1854 | return -EFAULT; | ||
1855 | return 0; | ||
1856 | } | ||
1857 | read_unlock(&mrt_lock); | ||
1858 | return -EADDRNOTAVAIL; | ||
1859 | case SIOCGETSGCNT_IN6: | ||
1860 | if (copy_from_user(&sr, arg, sizeof(sr))) | ||
1861 | return -EFAULT; | ||
1862 | |||
1863 | read_lock(&mrt_lock); | ||
1864 | c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr); | ||
1865 | if (c) { | ||
1866 | sr.pktcnt = c->mfc_un.res.pkt; | ||
1867 | sr.bytecnt = c->mfc_un.res.bytes; | ||
1868 | sr.wrong_if = c->mfc_un.res.wrong_if; | ||
1869 | read_unlock(&mrt_lock); | ||
1870 | |||
1871 | if (copy_to_user(arg, &sr, sizeof(sr))) | ||
1872 | return -EFAULT; | ||
1873 | return 0; | ||
1874 | } | ||
1875 | read_unlock(&mrt_lock); | ||
1876 | return -EADDRNOTAVAIL; | ||
1877 | default: | ||
1878 | return -ENOIOCTLCMD; | ||
1879 | } | ||
1880 | } | ||
1881 | #endif | ||
1807 | 1882 | ||
1808 | static inline int ip6mr_forward2_finish(struct sk_buff *skb) | 1883 | static inline int ip6mr_forward2_finish(struct sk_buff *skb) |
1809 | { | 1884 | { |
@@ -1823,7 +1898,7 @@ static int ip6mr_forward2(struct net *net, struct mr6_table *mrt, | |||
1823 | struct mif_device *vif = &mrt->vif6_table[vifi]; | 1898 | struct mif_device *vif = &mrt->vif6_table[vifi]; |
1824 | struct net_device *dev; | 1899 | struct net_device *dev; |
1825 | struct dst_entry *dst; | 1900 | struct dst_entry *dst; |
1826 | struct flowi fl; | 1901 | struct flowi6 fl6; |
1827 | 1902 | ||
1828 | if (vif->dev == NULL) | 1903 | if (vif->dev == NULL) |
1829 | goto out_free; | 1904 | goto out_free; |
@@ -1841,12 +1916,12 @@ static int ip6mr_forward2(struct net *net, struct mr6_table *mrt, | |||
1841 | 1916 | ||
1842 | ipv6h = ipv6_hdr(skb); | 1917 | ipv6h = ipv6_hdr(skb); |
1843 | 1918 | ||
1844 | fl = (struct flowi) { | 1919 | fl6 = (struct flowi6) { |
1845 | .oif = vif->link, | 1920 | .flowi6_oif = vif->link, |
1846 | .fl6_dst = ipv6h->daddr, | 1921 | .daddr = ipv6h->daddr, |
1847 | }; | 1922 | }; |
1848 | 1923 | ||
1849 | dst = ip6_route_output(net, NULL, &fl); | 1924 | dst = ip6_route_output(net, NULL, &fl6); |
1850 | if (!dst) | 1925 | if (!dst) |
1851 | goto out_free; | 1926 | goto out_free; |
1852 | 1927 | ||
@@ -1969,13 +2044,13 @@ int ip6_mr_input(struct sk_buff *skb) | |||
1969 | struct mfc6_cache *cache; | 2044 | struct mfc6_cache *cache; |
1970 | struct net *net = dev_net(skb->dev); | 2045 | struct net *net = dev_net(skb->dev); |
1971 | struct mr6_table *mrt; | 2046 | struct mr6_table *mrt; |
1972 | struct flowi fl = { | 2047 | struct flowi6 fl6 = { |
1973 | .iif = skb->dev->ifindex, | 2048 | .flowi6_iif = skb->dev->ifindex, |
1974 | .mark = skb->mark, | 2049 | .flowi6_mark = skb->mark, |
1975 | }; | 2050 | }; |
1976 | int err; | 2051 | int err; |
1977 | 2052 | ||
1978 | err = ip6mr_fib_lookup(net, &fl, &mrt); | 2053 | err = ip6mr_fib_lookup(net, &fl6, &mrt); |
1979 | if (err < 0) | 2054 | if (err < 0) |
1980 | return err; | 2055 | return err; |
1981 | 2056 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index d1770e061c08..9cb191ecaba8 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -444,12 +444,12 @@ sticky_done: | |||
444 | { | 444 | { |
445 | struct ipv6_txoptions *opt = NULL; | 445 | struct ipv6_txoptions *opt = NULL; |
446 | struct msghdr msg; | 446 | struct msghdr msg; |
447 | struct flowi fl; | 447 | struct flowi6 fl6; |
448 | int junk; | 448 | int junk; |
449 | 449 | ||
450 | fl.fl6_flowlabel = 0; | 450 | memset(&fl6, 0, sizeof(fl6)); |
451 | fl.oif = sk->sk_bound_dev_if; | 451 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
452 | fl.mark = sk->sk_mark; | 452 | fl6.flowi6_mark = sk->sk_mark; |
453 | 453 | ||
454 | if (optlen == 0) | 454 | if (optlen == 0) |
455 | goto update; | 455 | goto update; |
@@ -475,7 +475,7 @@ sticky_done: | |||
475 | msg.msg_controllen = optlen; | 475 | msg.msg_controllen = optlen; |
476 | msg.msg_control = (void*)(opt+1); | 476 | msg.msg_control = (void*)(opt+1); |
477 | 477 | ||
478 | retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk, | 478 | retv = datagram_send_ctl(net, &msg, &fl6, opt, &junk, &junk, |
479 | &junk); | 479 | &junk); |
480 | if (retv) | 480 | if (retv) |
481 | goto done; | 481 | goto done; |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 49f986d626a0..76b893771e6e 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -319,7 +319,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
319 | { | 319 | { |
320 | struct in6_addr *source, *group; | 320 | struct in6_addr *source, *group; |
321 | struct ipv6_mc_socklist *pmc; | 321 | struct ipv6_mc_socklist *pmc; |
322 | struct net_device *dev; | ||
323 | struct inet6_dev *idev; | 322 | struct inet6_dev *idev; |
324 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 323 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
325 | struct ip6_sf_socklist *psl; | 324 | struct ip6_sf_socklist *psl; |
@@ -341,7 +340,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk, | |||
341 | rcu_read_unlock(); | 340 | rcu_read_unlock(); |
342 | return -ENODEV; | 341 | return -ENODEV; |
343 | } | 342 | } |
344 | dev = idev->dev; | ||
345 | 343 | ||
346 | err = -EADDRNOTAVAIL; | 344 | err = -EADDRNOTAVAIL; |
347 | 345 | ||
@@ -455,7 +453,6 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
455 | { | 453 | { |
456 | struct in6_addr *group; | 454 | struct in6_addr *group; |
457 | struct ipv6_mc_socklist *pmc; | 455 | struct ipv6_mc_socklist *pmc; |
458 | struct net_device *dev; | ||
459 | struct inet6_dev *idev; | 456 | struct inet6_dev *idev; |
460 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 457 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
461 | struct ip6_sf_socklist *newpsl, *psl; | 458 | struct ip6_sf_socklist *newpsl, *psl; |
@@ -478,7 +475,6 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
478 | rcu_read_unlock(); | 475 | rcu_read_unlock(); |
479 | return -ENODEV; | 476 | return -ENODEV; |
480 | } | 477 | } |
481 | dev = idev->dev; | ||
482 | 478 | ||
483 | err = 0; | 479 | err = 0; |
484 | 480 | ||
@@ -549,7 +545,6 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
549 | struct in6_addr *group; | 545 | struct in6_addr *group; |
550 | struct ipv6_mc_socklist *pmc; | 546 | struct ipv6_mc_socklist *pmc; |
551 | struct inet6_dev *idev; | 547 | struct inet6_dev *idev; |
552 | struct net_device *dev; | ||
553 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 548 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
554 | struct ip6_sf_socklist *psl; | 549 | struct ip6_sf_socklist *psl; |
555 | struct net *net = sock_net(sk); | 550 | struct net *net = sock_net(sk); |
@@ -566,7 +561,6 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
566 | rcu_read_unlock(); | 561 | rcu_read_unlock(); |
567 | return -ENODEV; | 562 | return -ENODEV; |
568 | } | 563 | } |
569 | dev = idev->dev; | ||
570 | 564 | ||
571 | err = -EADDRNOTAVAIL; | 565 | err = -EADDRNOTAVAIL; |
572 | /* | 566 | /* |
@@ -1402,7 +1396,7 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1402 | struct inet6_dev *idev; | 1396 | struct inet6_dev *idev; |
1403 | struct net *net = dev_net(skb->dev); | 1397 | struct net *net = dev_net(skb->dev); |
1404 | int err; | 1398 | int err; |
1405 | struct flowi fl; | 1399 | struct flowi6 fl6; |
1406 | struct dst_entry *dst; | 1400 | struct dst_entry *dst; |
1407 | 1401 | ||
1408 | rcu_read_lock(); | 1402 | rcu_read_lock(); |
@@ -1425,11 +1419,16 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1425 | goto err_out; | 1419 | goto err_out; |
1426 | } | 1420 | } |
1427 | 1421 | ||
1428 | icmpv6_flow_init(net->ipv6.igmp_sk, &fl, ICMPV6_MLD2_REPORT, | 1422 | icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT, |
1429 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, | 1423 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, |
1430 | skb->dev->ifindex); | 1424 | skb->dev->ifindex); |
1431 | 1425 | ||
1432 | err = xfrm_lookup(net, &dst, &fl, NULL, 0); | 1426 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); |
1427 | err = 0; | ||
1428 | if (IS_ERR(dst)) { | ||
1429 | err = PTR_ERR(dst); | ||
1430 | dst = NULL; | ||
1431 | } | ||
1433 | skb_dst_set(skb, dst); | 1432 | skb_dst_set(skb, dst); |
1434 | if (err) | 1433 | if (err) |
1435 | goto err_out; | 1434 | goto err_out; |
@@ -1732,7 +1731,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1732 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1731 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
1733 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1732 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
1734 | IPV6_TLV_PADN, 0 }; | 1733 | IPV6_TLV_PADN, 0 }; |
1735 | struct flowi fl; | 1734 | struct flowi6 fl6; |
1736 | struct dst_entry *dst; | 1735 | struct dst_entry *dst; |
1737 | 1736 | ||
1738 | if (type == ICMPV6_MGM_REDUCTION) | 1737 | if (type == ICMPV6_MGM_REDUCTION) |
@@ -1792,13 +1791,15 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1792 | goto err_out; | 1791 | goto err_out; |
1793 | } | 1792 | } |
1794 | 1793 | ||
1795 | icmpv6_flow_init(sk, &fl, type, | 1794 | icmpv6_flow_init(sk, &fl6, type, |
1796 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, | 1795 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, |
1797 | skb->dev->ifindex); | 1796 | skb->dev->ifindex); |
1798 | 1797 | ||
1799 | err = xfrm_lookup(net, &dst, &fl, NULL, 0); | 1798 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); |
1800 | if (err) | 1799 | if (IS_ERR(dst)) { |
1800 | err = PTR_ERR(dst); | ||
1801 | goto err_out; | 1801 | goto err_out; |
1802 | } | ||
1802 | 1803 | ||
1803 | skb_dst_set(skb, dst); | 1804 | skb_dst_set(skb, dst); |
1804 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, | 1805 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index d6e9599d0705..9b210482fb05 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -203,18 +203,20 @@ static inline int mip6_report_rl_allow(struct timeval *stamp, | |||
203 | return allow; | 203 | return allow; |
204 | } | 204 | } |
205 | 205 | ||
206 | static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct flowi *fl) | 206 | static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, |
207 | const struct flowi *fl) | ||
207 | { | 208 | { |
208 | struct net *net = xs_net(x); | 209 | struct net *net = xs_net(x); |
209 | struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; | 210 | struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; |
211 | const struct flowi6 *fl6 = &fl->u.ip6; | ||
210 | struct ipv6_destopt_hao *hao = NULL; | 212 | struct ipv6_destopt_hao *hao = NULL; |
211 | struct xfrm_selector sel; | 213 | struct xfrm_selector sel; |
212 | int offset; | 214 | int offset; |
213 | struct timeval stamp; | 215 | struct timeval stamp; |
214 | int err = 0; | 216 | int err = 0; |
215 | 217 | ||
216 | if (unlikely(fl->proto == IPPROTO_MH && | 218 | if (unlikely(fl6->flowi6_proto == IPPROTO_MH && |
217 | fl->fl_mh_type <= IP6_MH_TYPE_MAX)) | 219 | fl6->fl6_mh_type <= IP6_MH_TYPE_MAX)) |
218 | goto out; | 220 | goto out; |
219 | 221 | ||
220 | if (likely(opt->dsthao)) { | 222 | if (likely(opt->dsthao)) { |
@@ -239,14 +241,14 @@ static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct | |||
239 | sizeof(sel.saddr)); | 241 | sizeof(sel.saddr)); |
240 | sel.prefixlen_s = 128; | 242 | sel.prefixlen_s = 128; |
241 | sel.family = AF_INET6; | 243 | sel.family = AF_INET6; |
242 | sel.proto = fl->proto; | 244 | sel.proto = fl6->flowi6_proto; |
243 | sel.dport = xfrm_flowi_dport(fl); | 245 | sel.dport = xfrm_flowi_dport(fl, &fl6->uli); |
244 | if (sel.dport) | 246 | if (sel.dport) |
245 | sel.dport_mask = htons(~0); | 247 | sel.dport_mask = htons(~0); |
246 | sel.sport = xfrm_flowi_sport(fl); | 248 | sel.sport = xfrm_flowi_sport(fl, &fl6->uli); |
247 | if (sel.sport) | 249 | if (sel.sport) |
248 | sel.sport_mask = htons(~0); | 250 | sel.sport_mask = htons(~0); |
249 | sel.ifindex = fl->oif; | 251 | sel.ifindex = fl6->flowi6_oif; |
250 | 252 | ||
251 | err = km_report(net, IPPROTO_DSTOPTS, &sel, | 253 | err = km_report(net, IPPROTO_DSTOPTS, &sel, |
252 | (hao ? (xfrm_address_t *)&hao->addr : NULL)); | 254 | (hao ? (xfrm_address_t *)&hao->addr : NULL)); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 2342545a5ee9..0e49c9db3c98 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -511,7 +511,7 @@ void ndisc_send_skb(struct sk_buff *skb, | |||
511 | const struct in6_addr *saddr, | 511 | const struct in6_addr *saddr, |
512 | struct icmp6hdr *icmp6h) | 512 | struct icmp6hdr *icmp6h) |
513 | { | 513 | { |
514 | struct flowi fl; | 514 | struct flowi6 fl6; |
515 | struct dst_entry *dst; | 515 | struct dst_entry *dst; |
516 | struct net *net = dev_net(dev); | 516 | struct net *net = dev_net(dev); |
517 | struct sock *sk = net->ipv6.ndisc_sk; | 517 | struct sock *sk = net->ipv6.ndisc_sk; |
@@ -521,7 +521,7 @@ void ndisc_send_skb(struct sk_buff *skb, | |||
521 | 521 | ||
522 | type = icmp6h->icmp6_type; | 522 | type = icmp6h->icmp6_type; |
523 | 523 | ||
524 | icmpv6_flow_init(sk, &fl, type, saddr, daddr, dev->ifindex); | 524 | icmpv6_flow_init(sk, &fl6, type, saddr, daddr, dev->ifindex); |
525 | 525 | ||
526 | dst = icmp6_dst_alloc(dev, neigh, daddr); | 526 | dst = icmp6_dst_alloc(dev, neigh, daddr); |
527 | if (!dst) { | 527 | if (!dst) { |
@@ -529,8 +529,8 @@ void ndisc_send_skb(struct sk_buff *skb, | |||
529 | return; | 529 | return; |
530 | } | 530 | } |
531 | 531 | ||
532 | err = xfrm_lookup(net, &dst, &fl, NULL, 0); | 532 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); |
533 | if (err < 0) { | 533 | if (IS_ERR(dst)) { |
534 | kfree_skb(skb); | 534 | kfree_skb(skb); |
535 | return; | 535 | return; |
536 | } | 536 | } |
@@ -1515,7 +1515,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1515 | struct rt6_info *rt; | 1515 | struct rt6_info *rt; |
1516 | struct dst_entry *dst; | 1516 | struct dst_entry *dst; |
1517 | struct inet6_dev *idev; | 1517 | struct inet6_dev *idev; |
1518 | struct flowi fl; | 1518 | struct flowi6 fl6; |
1519 | u8 *opt; | 1519 | u8 *opt; |
1520 | int rd_len; | 1520 | int rd_len; |
1521 | int err; | 1521 | int err; |
@@ -1535,15 +1535,15 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1535 | return; | 1535 | return; |
1536 | } | 1536 | } |
1537 | 1537 | ||
1538 | icmpv6_flow_init(sk, &fl, NDISC_REDIRECT, | 1538 | icmpv6_flow_init(sk, &fl6, NDISC_REDIRECT, |
1539 | &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex); | 1539 | &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex); |
1540 | 1540 | ||
1541 | dst = ip6_route_output(net, NULL, &fl); | 1541 | dst = ip6_route_output(net, NULL, &fl6); |
1542 | if (dst == NULL) | 1542 | if (dst == NULL) |
1543 | return; | 1543 | return; |
1544 | 1544 | ||
1545 | err = xfrm_lookup(net, &dst, &fl, NULL, 0); | 1545 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); |
1546 | if (err) | 1546 | if (IS_ERR(dst)) |
1547 | return; | 1547 | return; |
1548 | 1548 | ||
1549 | rt = (struct rt6_info *) dst; | 1549 | rt = (struct rt6_info *) dst; |
@@ -1553,7 +1553,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1553 | "ICMPv6 Redirect: destination is not a neighbour.\n"); | 1553 | "ICMPv6 Redirect: destination is not a neighbour.\n"); |
1554 | goto release; | 1554 | goto release; |
1555 | } | 1555 | } |
1556 | if (!xrlim_allow(dst, 1*HZ)) | 1556 | if (!rt->rt6i_peer) |
1557 | rt6_bind_peer(rt, 1); | ||
1558 | if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) | ||
1557 | goto release; | 1559 | goto release; |
1558 | 1560 | ||
1559 | if (dev->addr_len) { | 1561 | if (dev->addr_len) { |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 35915e8617f0..39aaca2b4fd2 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -15,14 +15,14 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
15 | struct net *net = dev_net(skb_dst(skb)->dev); | 15 | struct net *net = dev_net(skb_dst(skb)->dev); |
16 | struct ipv6hdr *iph = ipv6_hdr(skb); | 16 | struct ipv6hdr *iph = ipv6_hdr(skb); |
17 | struct dst_entry *dst; | 17 | struct dst_entry *dst; |
18 | struct flowi fl = { | 18 | struct flowi6 fl6 = { |
19 | .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, | 19 | .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, |
20 | .mark = skb->mark, | 20 | .flowi6_mark = skb->mark, |
21 | .fl6_dst = iph->daddr, | 21 | .daddr = iph->daddr, |
22 | .fl6_src = iph->saddr, | 22 | .saddr = iph->saddr, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | dst = ip6_route_output(net, skb->sk, &fl); | 25 | dst = ip6_route_output(net, skb->sk, &fl6); |
26 | if (dst->error) { | 26 | if (dst->error) { |
27 | IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | 27 | IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
28 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); | 28 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); |
@@ -37,9 +37,10 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
37 | 37 | ||
38 | #ifdef CONFIG_XFRM | 38 | #ifdef CONFIG_XFRM |
39 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | 39 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && |
40 | xfrm_decode_session(skb, &fl, AF_INET6) == 0) { | 40 | xfrm_decode_session(skb, flowi6_to_flowi(&fl6), AF_INET6) == 0) { |
41 | skb_dst_set(skb, NULL); | 41 | skb_dst_set(skb, NULL); |
42 | if (xfrm_lookup(net, &dst, &fl, skb->sk, 0)) | 42 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), skb->sk, 0); |
43 | if (IS_ERR(dst)) | ||
43 | return -1; | 44 | return -1; |
44 | skb_dst_set(skb, dst); | 45 | skb_dst_set(skb, dst); |
45 | } | 46 | } |
@@ -91,7 +92,7 @@ static int nf_ip6_reroute(struct sk_buff *skb, | |||
91 | 92 | ||
92 | static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl) | 93 | static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl) |
93 | { | 94 | { |
94 | *dst = ip6_route_output(&init_net, NULL, fl); | 95 | *dst = ip6_route_output(&init_net, NULL, &fl->u.ip6); |
95 | return (*dst)->error; | 96 | return (*dst)->error; |
96 | } | 97 | } |
97 | 98 | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 7d227c644f72..c9598a9067d7 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -1076,6 +1076,7 @@ static int compat_table_info(const struct xt_table_info *info, | |||
1076 | memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); | 1076 | memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); |
1077 | newinfo->initial_entries = 0; | 1077 | newinfo->initial_entries = 0; |
1078 | loc_cpu_entry = info->entries[raw_smp_processor_id()]; | 1078 | loc_cpu_entry = info->entries[raw_smp_processor_id()]; |
1079 | xt_compat_init_offsets(AF_INET6, info->number); | ||
1079 | xt_entry_foreach(iter, loc_cpu_entry, info->size) { | 1080 | xt_entry_foreach(iter, loc_cpu_entry, info->size) { |
1080 | ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); | 1081 | ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); |
1081 | if (ret != 0) | 1082 | if (ret != 0) |
@@ -1274,6 +1275,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len) | |||
1274 | /* overflow check */ | 1275 | /* overflow check */ |
1275 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1276 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
1276 | return -ENOMEM; | 1277 | return -ENOMEM; |
1278 | tmp.name[sizeof(tmp.name)-1] = 0; | ||
1277 | 1279 | ||
1278 | newinfo = xt_alloc_table_info(tmp.size); | 1280 | newinfo = xt_alloc_table_info(tmp.size); |
1279 | if (!newinfo) | 1281 | if (!newinfo) |
@@ -1679,6 +1681,7 @@ translate_compat_table(struct net *net, | |||
1679 | duprintf("translate_compat_table: size %u\n", info->size); | 1681 | duprintf("translate_compat_table: size %u\n", info->size); |
1680 | j = 0; | 1682 | j = 0; |
1681 | xt_compat_lock(AF_INET6); | 1683 | xt_compat_lock(AF_INET6); |
1684 | xt_compat_init_offsets(AF_INET6, number); | ||
1682 | /* Walk through entries, checking offsets. */ | 1685 | /* Walk through entries, checking offsets. */ |
1683 | xt_entry_foreach(iter0, entry0, total_size) { | 1686 | xt_entry_foreach(iter0, entry0, total_size) { |
1684 | ret = check_compat_entry_size_and_hooks(iter0, info, &size, | 1687 | ret = check_compat_entry_size_and_hooks(iter0, info, &size, |
@@ -1820,6 +1823,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) | |||
1820 | return -ENOMEM; | 1823 | return -ENOMEM; |
1821 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) | 1824 | if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) |
1822 | return -ENOMEM; | 1825 | return -ENOMEM; |
1826 | tmp.name[sizeof(tmp.name)-1] = 0; | ||
1823 | 1827 | ||
1824 | newinfo = xt_alloc_table_info(tmp.size); | 1828 | newinfo = xt_alloc_table_info(tmp.size); |
1825 | if (!newinfo) | 1829 | if (!newinfo) |
@@ -2049,6 +2053,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2049 | ret = -EFAULT; | 2053 | ret = -EFAULT; |
2050 | break; | 2054 | break; |
2051 | } | 2055 | } |
2056 | rev.name[sizeof(rev.name)-1] = 0; | ||
2052 | 2057 | ||
2053 | if (cmd == IP6T_SO_GET_REVISION_TARGET) | 2058 | if (cmd == IP6T_SO_GET_REVISION_TARGET) |
2054 | target = 1; | 2059 | target = 1; |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 09c88891a753..e6af8d72f26b 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -410,7 +410,7 @@ fallback: | |||
410 | if (p != NULL) { | 410 | if (p != NULL) { |
411 | sb_add(m, "%02x", *p++); | 411 | sb_add(m, "%02x", *p++); |
412 | for (i = 1; i < len; i++) | 412 | for (i = 1; i < len; i++) |
413 | sb_add(m, ":%02x", p[i]); | 413 | sb_add(m, ":%02x", *p++); |
414 | } | 414 | } |
415 | sb_add(m, " "); | 415 | sb_add(m, " "); |
416 | 416 | ||
@@ -452,8 +452,7 @@ ip6t_log_packet(u_int8_t pf, | |||
452 | in ? in->name : "", | 452 | in ? in->name : "", |
453 | out ? out->name : ""); | 453 | out ? out->name : ""); |
454 | 454 | ||
455 | /* MAC logging for input path only. */ | 455 | if (in != NULL) |
456 | if (in && !out) | ||
457 | dump_mac_header(m, loginfo, skb); | 456 | dump_mac_header(m, loginfo, skb); |
458 | 457 | ||
459 | dump_packet(m, loginfo, skb, skb_network_offset(skb), 1); | 458 | dump_packet(m, loginfo, skb, skb_network_offset(skb), 1); |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index bf998feac14e..28e74488a329 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -47,7 +47,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
47 | struct ipv6hdr *ip6h; | 47 | struct ipv6hdr *ip6h; |
48 | struct dst_entry *dst = NULL; | 48 | struct dst_entry *dst = NULL; |
49 | u8 proto; | 49 | u8 proto; |
50 | struct flowi fl; | 50 | struct flowi6 fl6; |
51 | 51 | ||
52 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | 52 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || |
53 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { | 53 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { |
@@ -89,19 +89,20 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
89 | return; | 89 | return; |
90 | } | 90 | } |
91 | 91 | ||
92 | memset(&fl, 0, sizeof(fl)); | 92 | memset(&fl6, 0, sizeof(fl6)); |
93 | fl.proto = IPPROTO_TCP; | 93 | fl6.flowi6_proto = IPPROTO_TCP; |
94 | ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr); | 94 | ipv6_addr_copy(&fl6.saddr, &oip6h->daddr); |
95 | ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr); | 95 | ipv6_addr_copy(&fl6.daddr, &oip6h->saddr); |
96 | fl.fl_ip_sport = otcph.dest; | 96 | fl6.fl6_sport = otcph.dest; |
97 | fl.fl_ip_dport = otcph.source; | 97 | fl6.fl6_dport = otcph.source; |
98 | security_skb_classify_flow(oldskb, &fl); | 98 | security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); |
99 | dst = ip6_route_output(net, NULL, &fl); | 99 | dst = ip6_route_output(net, NULL, &fl6); |
100 | if (dst == NULL || dst->error) { | 100 | if (dst == NULL || dst->error) { |
101 | dst_release(dst); | 101 | dst_release(dst); |
102 | return; | 102 | return; |
103 | } | 103 | } |
104 | if (xfrm_lookup(net, &dst, &fl, NULL, 0)) | 104 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); |
105 | if (IS_ERR(dst)) | ||
105 | return; | 106 | return; |
106 | 107 | ||
107 | hh_len = (dst->dev->hard_header_len + 15)&~15; | 108 | hh_len = (dst->dev->hard_header_len + 15)&~15; |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 79d43aa8fa8d..085727263812 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/netfilter_ipv6.h> | 45 | #include <linux/netfilter_ipv6.h> |
46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
48 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> | ||
48 | 49 | ||
49 | 50 | ||
50 | struct nf_ct_frag6_skb_cb | 51 | struct nf_ct_frag6_skb_cb |
@@ -73,7 +74,7 @@ static struct inet_frags nf_frags; | |||
73 | static struct netns_frags nf_init_frags; | 74 | static struct netns_frags nf_init_frags; |
74 | 75 | ||
75 | #ifdef CONFIG_SYSCTL | 76 | #ifdef CONFIG_SYSCTL |
76 | struct ctl_table nf_ct_frag6_sysctl_table[] = { | 77 | static struct ctl_table nf_ct_frag6_sysctl_table[] = { |
77 | { | 78 | { |
78 | .procname = "nf_conntrack_frag6_timeout", | 79 | .procname = "nf_conntrack_frag6_timeout", |
79 | .data = &nf_init_frags.timeout, | 80 | .data = &nf_init_frags.timeout, |
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c index 99abfb53bab9..97c5b21b9674 100644 --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | |||
@@ -19,13 +19,15 @@ | |||
19 | 19 | ||
20 | #include <linux/netfilter_ipv6.h> | 20 | #include <linux/netfilter_ipv6.h> |
21 | #include <linux/netfilter_bridge.h> | 21 | #include <linux/netfilter_bridge.h> |
22 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
22 | #include <net/netfilter/nf_conntrack.h> | 23 | #include <net/netfilter/nf_conntrack.h> |
23 | #include <net/netfilter/nf_conntrack_helper.h> | 24 | #include <net/netfilter/nf_conntrack_helper.h> |
24 | #include <net/netfilter/nf_conntrack_l4proto.h> | 25 | #include <net/netfilter/nf_conntrack_l4proto.h> |
25 | #include <net/netfilter/nf_conntrack_l3proto.h> | 26 | #include <net/netfilter/nf_conntrack_l3proto.h> |
26 | #include <net/netfilter/nf_conntrack_core.h> | 27 | #include <net/netfilter/nf_conntrack_core.h> |
27 | #include <net/netfilter/nf_conntrack_zones.h> | ||
28 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> | 28 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> |
29 | #endif | ||
30 | #include <net/netfilter/nf_conntrack_zones.h> | ||
29 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> | 31 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> |
30 | 32 | ||
31 | static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, | 33 | static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, |
@@ -33,8 +35,10 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, | |||
33 | { | 35 | { |
34 | u16 zone = NF_CT_DEFAULT_ZONE; | 36 | u16 zone = NF_CT_DEFAULT_ZONE; |
35 | 37 | ||
38 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
36 | if (skb->nfct) | 39 | if (skb->nfct) |
37 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); | 40 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); |
41 | #endif | ||
38 | 42 | ||
39 | #ifdef CONFIG_BRIDGE_NETFILTER | 43 | #ifdef CONFIG_BRIDGE_NETFILTER |
40 | if (skb->nf_bridge && | 44 | if (skb->nf_bridge && |
@@ -56,9 +60,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum, | |||
56 | { | 60 | { |
57 | struct sk_buff *reasm; | 61 | struct sk_buff *reasm; |
58 | 62 | ||
63 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
59 | /* Previously seen (loopback)? */ | 64 | /* Previously seen (loopback)? */ |
60 | if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct)) | 65 | if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct)) |
61 | return NF_ACCEPT; | 66 | return NF_ACCEPT; |
67 | #endif | ||
62 | 68 | ||
63 | reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb)); | 69 | reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb)); |
64 | /* queued */ | 70 | /* queued */ |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 86c39526ba5e..4a1c3b46c56b 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/netfilter.h> | 31 | #include <linux/netfilter.h> |
32 | #include <linux/netfilter_ipv6.h> | 32 | #include <linux/netfilter_ipv6.h> |
33 | #include <linux/skbuff.h> | 33 | #include <linux/skbuff.h> |
34 | #include <linux/compat.h> | ||
34 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
35 | #include <asm/ioctls.h> | 36 | #include <asm/ioctls.h> |
36 | 37 | ||
@@ -123,18 +124,18 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) | |||
123 | } | 124 | } |
124 | 125 | ||
125 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 126 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
126 | static int (*mh_filter)(struct sock *sock, struct sk_buff *skb); | 127 | typedef int mh_filter_t(struct sock *sock, struct sk_buff *skb); |
127 | 128 | ||
128 | int rawv6_mh_filter_register(int (*filter)(struct sock *sock, | 129 | static mh_filter_t __rcu *mh_filter __read_mostly; |
129 | struct sk_buff *skb)) | 130 | |
131 | int rawv6_mh_filter_register(mh_filter_t filter) | ||
130 | { | 132 | { |
131 | rcu_assign_pointer(mh_filter, filter); | 133 | rcu_assign_pointer(mh_filter, filter); |
132 | return 0; | 134 | return 0; |
133 | } | 135 | } |
134 | EXPORT_SYMBOL(rawv6_mh_filter_register); | 136 | EXPORT_SYMBOL(rawv6_mh_filter_register); |
135 | 137 | ||
136 | int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock, | 138 | int rawv6_mh_filter_unregister(mh_filter_t filter) |
137 | struct sk_buff *skb)) | ||
138 | { | 139 | { |
139 | rcu_assign_pointer(mh_filter, NULL); | 140 | rcu_assign_pointer(mh_filter, NULL); |
140 | synchronize_rcu(); | 141 | synchronize_rcu(); |
@@ -192,10 +193,10 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
192 | * policy is placed in rawv6_rcv() because it is | 193 | * policy is placed in rawv6_rcv() because it is |
193 | * required for each socket. | 194 | * required for each socket. |
194 | */ | 195 | */ |
195 | int (*filter)(struct sock *sock, struct sk_buff *skb); | 196 | mh_filter_t *filter; |
196 | 197 | ||
197 | filter = rcu_dereference(mh_filter); | 198 | filter = rcu_dereference(mh_filter); |
198 | filtered = filter ? filter(sk, skb) : 0; | 199 | filtered = filter ? (*filter)(sk, skb) : 0; |
199 | break; | 200 | break; |
200 | } | 201 | } |
201 | #endif | 202 | #endif |
@@ -523,7 +524,7 @@ csum_copy_err: | |||
523 | goto out; | 524 | goto out; |
524 | } | 525 | } |
525 | 526 | ||
526 | static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, | 527 | static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, |
527 | struct raw6_sock *rp) | 528 | struct raw6_sock *rp) |
528 | { | 529 | { |
529 | struct sk_buff *skb; | 530 | struct sk_buff *skb; |
@@ -585,11 +586,10 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, | |||
585 | if (unlikely(csum)) | 586 | if (unlikely(csum)) |
586 | tmp_csum = csum_sub(tmp_csum, csum_unfold(csum)); | 587 | tmp_csum = csum_sub(tmp_csum, csum_unfold(csum)); |
587 | 588 | ||
588 | csum = csum_ipv6_magic(&fl->fl6_src, | 589 | csum = csum_ipv6_magic(&fl6->saddr, &fl6->daddr, |
589 | &fl->fl6_dst, | 590 | total_len, fl6->flowi6_proto, tmp_csum); |
590 | total_len, fl->proto, tmp_csum); | ||
591 | 591 | ||
592 | if (csum == 0 && fl->proto == IPPROTO_UDP) | 592 | if (csum == 0 && fl6->flowi6_proto == IPPROTO_UDP) |
593 | csum = CSUM_MANGLED_0; | 593 | csum = CSUM_MANGLED_0; |
594 | 594 | ||
595 | if (skb_store_bits(skb, offset, &csum, 2)) | 595 | if (skb_store_bits(skb, offset, &csum, 2)) |
@@ -602,7 +602,7 @@ out: | |||
602 | } | 602 | } |
603 | 603 | ||
604 | static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | 604 | static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, |
605 | struct flowi *fl, struct dst_entry **dstp, | 605 | struct flowi6 *fl6, struct dst_entry **dstp, |
606 | unsigned int flags) | 606 | unsigned int flags) |
607 | { | 607 | { |
608 | struct ipv6_pinfo *np = inet6_sk(sk); | 608 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -612,7 +612,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
612 | struct rt6_info *rt = (struct rt6_info *)*dstp; | 612 | struct rt6_info *rt = (struct rt6_info *)*dstp; |
613 | 613 | ||
614 | if (length > rt->dst.dev->mtu) { | 614 | if (length > rt->dst.dev->mtu) { |
615 | ipv6_local_error(sk, EMSGSIZE, fl, rt->dst.dev->mtu); | 615 | ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu); |
616 | return -EMSGSIZE; | 616 | return -EMSGSIZE; |
617 | } | 617 | } |
618 | if (flags&MSG_PROBE) | 618 | if (flags&MSG_PROBE) |
@@ -661,7 +661,7 @@ error: | |||
661 | return err; | 661 | return err; |
662 | } | 662 | } |
663 | 663 | ||
664 | static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | 664 | static int rawv6_probe_proto_opt(struct flowi6 *fl6, struct msghdr *msg) |
665 | { | 665 | { |
666 | struct iovec *iov; | 666 | struct iovec *iov; |
667 | u8 __user *type = NULL; | 667 | u8 __user *type = NULL; |
@@ -678,7 +678,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
678 | if (!iov) | 678 | if (!iov) |
679 | continue; | 679 | continue; |
680 | 680 | ||
681 | switch (fl->proto) { | 681 | switch (fl6->flowi6_proto) { |
682 | case IPPROTO_ICMPV6: | 682 | case IPPROTO_ICMPV6: |
683 | /* check if one-byte field is readable or not. */ | 683 | /* check if one-byte field is readable or not. */ |
684 | if (iov->iov_base && iov->iov_len < 1) | 684 | if (iov->iov_base && iov->iov_len < 1) |
@@ -693,8 +693,8 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
693 | code = iov->iov_base; | 693 | code = iov->iov_base; |
694 | 694 | ||
695 | if (type && code) { | 695 | if (type && code) { |
696 | if (get_user(fl->fl_icmp_type, type) || | 696 | if (get_user(fl6->fl6_icmp_type, type) || |
697 | get_user(fl->fl_icmp_code, code)) | 697 | get_user(fl6->fl6_icmp_code, code)) |
698 | return -EFAULT; | 698 | return -EFAULT; |
699 | probed = 1; | 699 | probed = 1; |
700 | } | 700 | } |
@@ -705,7 +705,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
705 | /* check if type field is readable or not. */ | 705 | /* check if type field is readable or not. */ |
706 | if (iov->iov_len > 2 - len) { | 706 | if (iov->iov_len > 2 - len) { |
707 | u8 __user *p = iov->iov_base; | 707 | u8 __user *p = iov->iov_base; |
708 | if (get_user(fl->fl_mh_type, &p[2 - len])) | 708 | if (get_user(fl6->fl6_mh_type, &p[2 - len])) |
709 | return -EFAULT; | 709 | return -EFAULT; |
710 | probed = 1; | 710 | probed = 1; |
711 | } else | 711 | } else |
@@ -734,7 +734,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
734 | struct ipv6_txoptions *opt = NULL; | 734 | struct ipv6_txoptions *opt = NULL; |
735 | struct ip6_flowlabel *flowlabel = NULL; | 735 | struct ip6_flowlabel *flowlabel = NULL; |
736 | struct dst_entry *dst = NULL; | 736 | struct dst_entry *dst = NULL; |
737 | struct flowi fl; | 737 | struct flowi6 fl6; |
738 | int addr_len = msg->msg_namelen; | 738 | int addr_len = msg->msg_namelen; |
739 | int hlimit = -1; | 739 | int hlimit = -1; |
740 | int tclass = -1; | 740 | int tclass = -1; |
@@ -755,9 +755,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
755 | /* | 755 | /* |
756 | * Get and verify the address. | 756 | * Get and verify the address. |
757 | */ | 757 | */ |
758 | memset(&fl, 0, sizeof(fl)); | 758 | memset(&fl6, 0, sizeof(fl6)); |
759 | 759 | ||
760 | fl.mark = sk->sk_mark; | 760 | fl6.flowi6_mark = sk->sk_mark; |
761 | 761 | ||
762 | if (sin6) { | 762 | if (sin6) { |
763 | if (addr_len < SIN6_LEN_RFC2133) | 763 | if (addr_len < SIN6_LEN_RFC2133) |
@@ -779,9 +779,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
779 | 779 | ||
780 | daddr = &sin6->sin6_addr; | 780 | daddr = &sin6->sin6_addr; |
781 | if (np->sndflow) { | 781 | if (np->sndflow) { |
782 | fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; | 782 | fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; |
783 | if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { | 783 | if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { |
784 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); | 784 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
785 | if (flowlabel == NULL) | 785 | if (flowlabel == NULL) |
786 | return -EINVAL; | 786 | return -EINVAL; |
787 | daddr = &flowlabel->dst; | 787 | daddr = &flowlabel->dst; |
@@ -799,32 +799,32 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
799 | if (addr_len >= sizeof(struct sockaddr_in6) && | 799 | if (addr_len >= sizeof(struct sockaddr_in6) && |
800 | sin6->sin6_scope_id && | 800 | sin6->sin6_scope_id && |
801 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) | 801 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) |
802 | fl.oif = sin6->sin6_scope_id; | 802 | fl6.flowi6_oif = sin6->sin6_scope_id; |
803 | } else { | 803 | } else { |
804 | if (sk->sk_state != TCP_ESTABLISHED) | 804 | if (sk->sk_state != TCP_ESTABLISHED) |
805 | return -EDESTADDRREQ; | 805 | return -EDESTADDRREQ; |
806 | 806 | ||
807 | proto = inet->inet_num; | 807 | proto = inet->inet_num; |
808 | daddr = &np->daddr; | 808 | daddr = &np->daddr; |
809 | fl.fl6_flowlabel = np->flow_label; | 809 | fl6.flowlabel = np->flow_label; |
810 | } | 810 | } |
811 | 811 | ||
812 | if (fl.oif == 0) | 812 | if (fl6.flowi6_oif == 0) |
813 | fl.oif = sk->sk_bound_dev_if; | 813 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
814 | 814 | ||
815 | if (msg->msg_controllen) { | 815 | if (msg->msg_controllen) { |
816 | opt = &opt_space; | 816 | opt = &opt_space; |
817 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 817 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
818 | opt->tot_len = sizeof(struct ipv6_txoptions); | 818 | opt->tot_len = sizeof(struct ipv6_txoptions); |
819 | 819 | ||
820 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, | 820 | err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit, |
821 | &tclass, &dontfrag); | 821 | &tclass, &dontfrag); |
822 | if (err < 0) { | 822 | if (err < 0) { |
823 | fl6_sock_release(flowlabel); | 823 | fl6_sock_release(flowlabel); |
824 | return err; | 824 | return err; |
825 | } | 825 | } |
826 | if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { | 826 | if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { |
827 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); | 827 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
828 | if (flowlabel == NULL) | 828 | if (flowlabel == NULL) |
829 | return -EINVAL; | 829 | return -EINVAL; |
830 | } | 830 | } |
@@ -837,40 +837,31 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
837 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | 837 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
838 | opt = ipv6_fixup_options(&opt_space, opt); | 838 | opt = ipv6_fixup_options(&opt_space, opt); |
839 | 839 | ||
840 | fl.proto = proto; | 840 | fl6.flowi6_proto = proto; |
841 | err = rawv6_probe_proto_opt(&fl, msg); | 841 | err = rawv6_probe_proto_opt(&fl6, msg); |
842 | if (err) | 842 | if (err) |
843 | goto out; | 843 | goto out; |
844 | 844 | ||
845 | if (!ipv6_addr_any(daddr)) | 845 | if (!ipv6_addr_any(daddr)) |
846 | ipv6_addr_copy(&fl.fl6_dst, daddr); | 846 | ipv6_addr_copy(&fl6.daddr, daddr); |
847 | else | 847 | else |
848 | fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | 848 | fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ |
849 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 849 | if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) |
850 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 850 | ipv6_addr_copy(&fl6.saddr, &np->saddr); |
851 | 851 | ||
852 | final_p = fl6_update_dst(&fl, opt, &final); | 852 | final_p = fl6_update_dst(&fl6, opt, &final); |
853 | 853 | ||
854 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 854 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) |
855 | fl.oif = np->mcast_oif; | 855 | fl6.flowi6_oif = np->mcast_oif; |
856 | security_sk_classify_flow(sk, &fl); | 856 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
857 | 857 | ||
858 | err = ip6_dst_lookup(sk, &dst, &fl); | 858 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); |
859 | if (err) | 859 | if (IS_ERR(dst)) { |
860 | err = PTR_ERR(dst); | ||
860 | goto out; | 861 | goto out; |
861 | if (final_p) | ||
862 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
863 | |||
864 | err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT); | ||
865 | if (err < 0) { | ||
866 | if (err == -EREMOTE) | ||
867 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
868 | if (err < 0) | ||
869 | goto out; | ||
870 | } | 862 | } |
871 | |||
872 | if (hlimit < 0) { | 863 | if (hlimit < 0) { |
873 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 864 | if (ipv6_addr_is_multicast(&fl6.daddr)) |
874 | hlimit = np->mcast_hops; | 865 | hlimit = np->mcast_hops; |
875 | else | 866 | else |
876 | hlimit = np->hop_limit; | 867 | hlimit = np->hop_limit; |
@@ -889,17 +880,17 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
889 | 880 | ||
890 | back_from_confirm: | 881 | back_from_confirm: |
891 | if (inet->hdrincl) | 882 | if (inet->hdrincl) |
892 | err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, &dst, msg->msg_flags); | 883 | err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl6, &dst, msg->msg_flags); |
893 | else { | 884 | else { |
894 | lock_sock(sk); | 885 | lock_sock(sk); |
895 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, | 886 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, |
896 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, | 887 | len, 0, hlimit, tclass, opt, &fl6, (struct rt6_info*)dst, |
897 | msg->msg_flags, dontfrag); | 888 | msg->msg_flags, dontfrag); |
898 | 889 | ||
899 | if (err) | 890 | if (err) |
900 | ip6_flush_pending_frames(sk); | 891 | ip6_flush_pending_frames(sk); |
901 | else if (!(msg->msg_flags & MSG_MORE)) | 892 | else if (!(msg->msg_flags & MSG_MORE)) |
902 | err = rawv6_push_pending_frames(sk, &fl, rp); | 893 | err = rawv6_push_pending_frames(sk, &fl6, rp); |
903 | release_sock(sk); | 894 | release_sock(sk); |
904 | } | 895 | } |
905 | done: | 896 | done: |
@@ -1157,6 +1148,23 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
1157 | } | 1148 | } |
1158 | } | 1149 | } |
1159 | 1150 | ||
1151 | #ifdef CONFIG_COMPAT | ||
1152 | static int compat_rawv6_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg) | ||
1153 | { | ||
1154 | switch (cmd) { | ||
1155 | case SIOCOUTQ: | ||
1156 | case SIOCINQ: | ||
1157 | return -ENOIOCTLCMD; | ||
1158 | default: | ||
1159 | #ifdef CONFIG_IPV6_MROUTE | ||
1160 | return ip6mr_compat_ioctl(sk, cmd, compat_ptr(arg)); | ||
1161 | #else | ||
1162 | return -ENOIOCTLCMD; | ||
1163 | #endif | ||
1164 | } | ||
1165 | } | ||
1166 | #endif | ||
1167 | |||
1160 | static void rawv6_close(struct sock *sk, long timeout) | 1168 | static void rawv6_close(struct sock *sk, long timeout) |
1161 | { | 1169 | { |
1162 | if (inet_sk(sk)->inet_num == IPPROTO_RAW) | 1170 | if (inet_sk(sk)->inet_num == IPPROTO_RAW) |
@@ -1215,6 +1223,7 @@ struct proto rawv6_prot = { | |||
1215 | #ifdef CONFIG_COMPAT | 1223 | #ifdef CONFIG_COMPAT |
1216 | .compat_setsockopt = compat_rawv6_setsockopt, | 1224 | .compat_setsockopt = compat_rawv6_setsockopt, |
1217 | .compat_getsockopt = compat_rawv6_getsockopt, | 1225 | .compat_getsockopt = compat_rawv6_getsockopt, |
1226 | .compat_ioctl = compat_rawv6_ioctl, | ||
1218 | #endif | 1227 | #endif |
1219 | }; | 1228 | }; |
1220 | 1229 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 373bd0416f69..6814c8722fa7 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -72,8 +72,6 @@ | |||
72 | #define RT6_TRACE(x...) do { ; } while (0) | 72 | #define RT6_TRACE(x...) do { ; } while (0) |
73 | #endif | 73 | #endif |
74 | 74 | ||
75 | #define CLONE_OFFLINK_ROUTE 0 | ||
76 | |||
77 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); | 75 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); |
78 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); | 76 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); |
79 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); | 77 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); |
@@ -99,6 +97,36 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
99 | struct in6_addr *gwaddr, int ifindex); | 97 | struct in6_addr *gwaddr, int ifindex); |
100 | #endif | 98 | #endif |
101 | 99 | ||
100 | static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | ||
101 | { | ||
102 | struct rt6_info *rt = (struct rt6_info *) dst; | ||
103 | struct inet_peer *peer; | ||
104 | u32 *p = NULL; | ||
105 | |||
106 | if (!rt->rt6i_peer) | ||
107 | rt6_bind_peer(rt, 1); | ||
108 | |||
109 | peer = rt->rt6i_peer; | ||
110 | if (peer) { | ||
111 | u32 *old_p = __DST_METRICS_PTR(old); | ||
112 | unsigned long prev, new; | ||
113 | |||
114 | p = peer->metrics; | ||
115 | if (inet_metrics_new(peer)) | ||
116 | memcpy(p, old_p, sizeof(u32) * RTAX_MAX); | ||
117 | |||
118 | new = (unsigned long) p; | ||
119 | prev = cmpxchg(&dst->_metrics, old, new); | ||
120 | |||
121 | if (prev != old) { | ||
122 | p = __DST_METRICS_PTR(prev); | ||
123 | if (prev & DST_METRICS_READ_ONLY) | ||
124 | p = NULL; | ||
125 | } | ||
126 | } | ||
127 | return p; | ||
128 | } | ||
129 | |||
102 | static struct dst_ops ip6_dst_ops_template = { | 130 | static struct dst_ops ip6_dst_ops_template = { |
103 | .family = AF_INET6, | 131 | .family = AF_INET6, |
104 | .protocol = cpu_to_be16(ETH_P_IPV6), | 132 | .protocol = cpu_to_be16(ETH_P_IPV6), |
@@ -107,6 +135,7 @@ static struct dst_ops ip6_dst_ops_template = { | |||
107 | .check = ip6_dst_check, | 135 | .check = ip6_dst_check, |
108 | .default_advmss = ip6_default_advmss, | 136 | .default_advmss = ip6_default_advmss, |
109 | .default_mtu = ip6_default_mtu, | 137 | .default_mtu = ip6_default_mtu, |
138 | .cow_metrics = ipv6_cow_metrics, | ||
110 | .destroy = ip6_dst_destroy, | 139 | .destroy = ip6_dst_destroy, |
111 | .ifdown = ip6_dst_ifdown, | 140 | .ifdown = ip6_dst_ifdown, |
112 | .negative_advice = ip6_negative_advice, | 141 | .negative_advice = ip6_negative_advice, |
@@ -115,6 +144,11 @@ static struct dst_ops ip6_dst_ops_template = { | |||
115 | .local_out = __ip6_local_out, | 144 | .local_out = __ip6_local_out, |
116 | }; | 145 | }; |
117 | 146 | ||
147 | static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst) | ||
148 | { | ||
149 | return 0; | ||
150 | } | ||
151 | |||
118 | static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | 152 | static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) |
119 | { | 153 | { |
120 | } | 154 | } |
@@ -124,9 +158,15 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
124 | .protocol = cpu_to_be16(ETH_P_IPV6), | 158 | .protocol = cpu_to_be16(ETH_P_IPV6), |
125 | .destroy = ip6_dst_destroy, | 159 | .destroy = ip6_dst_destroy, |
126 | .check = ip6_dst_check, | 160 | .check = ip6_dst_check, |
161 | .default_mtu = ip6_blackhole_default_mtu, | ||
162 | .default_advmss = ip6_default_advmss, | ||
127 | .update_pmtu = ip6_rt_blackhole_update_pmtu, | 163 | .update_pmtu = ip6_rt_blackhole_update_pmtu, |
128 | }; | 164 | }; |
129 | 165 | ||
166 | static const u32 ip6_template_metrics[RTAX_MAX] = { | ||
167 | [RTAX_HOPLIMIT - 1] = 255, | ||
168 | }; | ||
169 | |||
130 | static struct rt6_info ip6_null_entry_template = { | 170 | static struct rt6_info ip6_null_entry_template = { |
131 | .dst = { | 171 | .dst = { |
132 | .__refcnt = ATOMIC_INIT(1), | 172 | .__refcnt = ATOMIC_INIT(1), |
@@ -182,7 +222,7 @@ static struct rt6_info ip6_blk_hole_entry_template = { | |||
182 | /* allocate dst with ip6_dst_ops */ | 222 | /* allocate dst with ip6_dst_ops */ |
183 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) | 223 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) |
184 | { | 224 | { |
185 | return (struct rt6_info *)dst_alloc(ops); | 225 | return (struct rt6_info *)dst_alloc(ops, 0); |
186 | } | 226 | } |
187 | 227 | ||
188 | static void ip6_dst_destroy(struct dst_entry *dst) | 228 | static void ip6_dst_destroy(struct dst_entry *dst) |
@@ -196,22 +236,27 @@ static void ip6_dst_destroy(struct dst_entry *dst) | |||
196 | in6_dev_put(idev); | 236 | in6_dev_put(idev); |
197 | } | 237 | } |
198 | if (peer) { | 238 | if (peer) { |
199 | BUG_ON(!(rt->rt6i_flags & RTF_CACHE)); | ||
200 | rt->rt6i_peer = NULL; | 239 | rt->rt6i_peer = NULL; |
201 | inet_putpeer(peer); | 240 | inet_putpeer(peer); |
202 | } | 241 | } |
203 | } | 242 | } |
204 | 243 | ||
244 | static atomic_t __rt6_peer_genid = ATOMIC_INIT(0); | ||
245 | |||
246 | static u32 rt6_peer_genid(void) | ||
247 | { | ||
248 | return atomic_read(&__rt6_peer_genid); | ||
249 | } | ||
250 | |||
205 | void rt6_bind_peer(struct rt6_info *rt, int create) | 251 | void rt6_bind_peer(struct rt6_info *rt, int create) |
206 | { | 252 | { |
207 | struct inet_peer *peer; | 253 | struct inet_peer *peer; |
208 | 254 | ||
209 | if (WARN_ON(!(rt->rt6i_flags & RTF_CACHE))) | ||
210 | return; | ||
211 | |||
212 | peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create); | 255 | peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create); |
213 | if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL) | 256 | if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL) |
214 | inet_putpeer(peer); | 257 | inet_putpeer(peer); |
258 | else | ||
259 | rt->rt6i_peer_genid = rt6_peer_genid(); | ||
215 | } | 260 | } |
216 | 261 | ||
217 | static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | 262 | static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, |
@@ -554,17 +599,17 @@ do { \ | |||
554 | 599 | ||
555 | static struct rt6_info *ip6_pol_route_lookup(struct net *net, | 600 | static struct rt6_info *ip6_pol_route_lookup(struct net *net, |
556 | struct fib6_table *table, | 601 | struct fib6_table *table, |
557 | struct flowi *fl, int flags) | 602 | struct flowi6 *fl6, int flags) |
558 | { | 603 | { |
559 | struct fib6_node *fn; | 604 | struct fib6_node *fn; |
560 | struct rt6_info *rt; | 605 | struct rt6_info *rt; |
561 | 606 | ||
562 | read_lock_bh(&table->tb6_lock); | 607 | read_lock_bh(&table->tb6_lock); |
563 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 608 | fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); |
564 | restart: | 609 | restart: |
565 | rt = fn->leaf; | 610 | rt = fn->leaf; |
566 | rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags); | 611 | rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags); |
567 | BACKTRACK(net, &fl->fl6_src); | 612 | BACKTRACK(net, &fl6->saddr); |
568 | out: | 613 | out: |
569 | dst_use(&rt->dst, jiffies); | 614 | dst_use(&rt->dst, jiffies); |
570 | read_unlock_bh(&table->tb6_lock); | 615 | read_unlock_bh(&table->tb6_lock); |
@@ -575,19 +620,19 @@ out: | |||
575 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, | 620 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, |
576 | const struct in6_addr *saddr, int oif, int strict) | 621 | const struct in6_addr *saddr, int oif, int strict) |
577 | { | 622 | { |
578 | struct flowi fl = { | 623 | struct flowi6 fl6 = { |
579 | .oif = oif, | 624 | .flowi6_oif = oif, |
580 | .fl6_dst = *daddr, | 625 | .daddr = *daddr, |
581 | }; | 626 | }; |
582 | struct dst_entry *dst; | 627 | struct dst_entry *dst; |
583 | int flags = strict ? RT6_LOOKUP_F_IFACE : 0; | 628 | int flags = strict ? RT6_LOOKUP_F_IFACE : 0; |
584 | 629 | ||
585 | if (saddr) { | 630 | if (saddr) { |
586 | memcpy(&fl.fl6_src, saddr, sizeof(*saddr)); | 631 | memcpy(&fl6.saddr, saddr, sizeof(*saddr)); |
587 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 632 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
588 | } | 633 | } |
589 | 634 | ||
590 | dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_lookup); | 635 | dst = fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_lookup); |
591 | if (dst->error == 0) | 636 | if (dst->error == 0) |
592 | return (struct rt6_info *) dst; | 637 | return (struct rt6_info *) dst; |
593 | 638 | ||
@@ -708,7 +753,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d | |||
708 | } | 753 | } |
709 | 754 | ||
710 | static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif, | 755 | static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif, |
711 | struct flowi *fl, int flags) | 756 | struct flowi6 *fl6, int flags) |
712 | { | 757 | { |
713 | struct fib6_node *fn; | 758 | struct fib6_node *fn; |
714 | struct rt6_info *rt, *nrt; | 759 | struct rt6_info *rt, *nrt; |
@@ -723,12 +768,12 @@ relookup: | |||
723 | read_lock_bh(&table->tb6_lock); | 768 | read_lock_bh(&table->tb6_lock); |
724 | 769 | ||
725 | restart_2: | 770 | restart_2: |
726 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 771 | fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); |
727 | 772 | ||
728 | restart: | 773 | restart: |
729 | rt = rt6_select(fn, oif, strict | reachable); | 774 | rt = rt6_select(fn, oif, strict | reachable); |
730 | 775 | ||
731 | BACKTRACK(net, &fl->fl6_src); | 776 | BACKTRACK(net, &fl6->saddr); |
732 | if (rt == net->ipv6.ip6_null_entry || | 777 | if (rt == net->ipv6.ip6_null_entry || |
733 | rt->rt6i_flags & RTF_CACHE) | 778 | rt->rt6i_flags & RTF_CACHE) |
734 | goto out; | 779 | goto out; |
@@ -737,14 +782,11 @@ restart: | |||
737 | read_unlock_bh(&table->tb6_lock); | 782 | read_unlock_bh(&table->tb6_lock); |
738 | 783 | ||
739 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 784 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
740 | nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); | 785 | nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); |
741 | else { | 786 | else if (!(rt->dst.flags & DST_HOST)) |
742 | #if CLONE_OFFLINK_ROUTE | 787 | nrt = rt6_alloc_clone(rt, &fl6->daddr); |
743 | nrt = rt6_alloc_clone(rt, &fl->fl6_dst); | 788 | else |
744 | #else | ||
745 | goto out2; | 789 | goto out2; |
746 | #endif | ||
747 | } | ||
748 | 790 | ||
749 | dst_release(&rt->dst); | 791 | dst_release(&rt->dst); |
750 | rt = nrt ? : net->ipv6.ip6_null_entry; | 792 | rt = nrt ? : net->ipv6.ip6_null_entry; |
@@ -781,9 +823,9 @@ out2: | |||
781 | } | 823 | } |
782 | 824 | ||
783 | static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table, | 825 | static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table, |
784 | struct flowi *fl, int flags) | 826 | struct flowi6 *fl6, int flags) |
785 | { | 827 | { |
786 | return ip6_pol_route(net, table, fl->iif, fl, flags); | 828 | return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags); |
787 | } | 829 | } |
788 | 830 | ||
789 | void ip6_route_input(struct sk_buff *skb) | 831 | void ip6_route_input(struct sk_buff *skb) |
@@ -791,56 +833,54 @@ void ip6_route_input(struct sk_buff *skb) | |||
791 | struct ipv6hdr *iph = ipv6_hdr(skb); | 833 | struct ipv6hdr *iph = ipv6_hdr(skb); |
792 | struct net *net = dev_net(skb->dev); | 834 | struct net *net = dev_net(skb->dev); |
793 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 835 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
794 | struct flowi fl = { | 836 | struct flowi6 fl6 = { |
795 | .iif = skb->dev->ifindex, | 837 | .flowi6_iif = skb->dev->ifindex, |
796 | .fl6_dst = iph->daddr, | 838 | .daddr = iph->daddr, |
797 | .fl6_src = iph->saddr, | 839 | .saddr = iph->saddr, |
798 | .fl6_flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, | 840 | .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, |
799 | .mark = skb->mark, | 841 | .flowi6_mark = skb->mark, |
800 | .proto = iph->nexthdr, | 842 | .flowi6_proto = iph->nexthdr, |
801 | }; | 843 | }; |
802 | 844 | ||
803 | if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG) | 845 | if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG) |
804 | flags |= RT6_LOOKUP_F_IFACE; | 846 | flags |= RT6_LOOKUP_F_IFACE; |
805 | 847 | ||
806 | skb_dst_set(skb, fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input)); | 848 | skb_dst_set(skb, fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_input)); |
807 | } | 849 | } |
808 | 850 | ||
809 | static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, | 851 | static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, |
810 | struct flowi *fl, int flags) | 852 | struct flowi6 *fl6, int flags) |
811 | { | 853 | { |
812 | return ip6_pol_route(net, table, fl->oif, fl, flags); | 854 | return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags); |
813 | } | 855 | } |
814 | 856 | ||
815 | struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, | 857 | struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, |
816 | struct flowi *fl) | 858 | struct flowi6 *fl6) |
817 | { | 859 | { |
818 | int flags = 0; | 860 | int flags = 0; |
819 | 861 | ||
820 | if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl->fl6_dst)) | 862 | if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr)) |
821 | flags |= RT6_LOOKUP_F_IFACE; | 863 | flags |= RT6_LOOKUP_F_IFACE; |
822 | 864 | ||
823 | if (!ipv6_addr_any(&fl->fl6_src)) | 865 | if (!ipv6_addr_any(&fl6->saddr)) |
824 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 866 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
825 | else if (sk) | 867 | else if (sk) |
826 | flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); | 868 | flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); |
827 | 869 | ||
828 | return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); | 870 | return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output); |
829 | } | 871 | } |
830 | 872 | ||
831 | EXPORT_SYMBOL(ip6_route_output); | 873 | EXPORT_SYMBOL(ip6_route_output); |
832 | 874 | ||
833 | int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl) | 875 | struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig) |
834 | { | 876 | { |
835 | struct rt6_info *ort = (struct rt6_info *) *dstp; | 877 | struct rt6_info *rt = dst_alloc(&ip6_dst_blackhole_ops, 1); |
836 | struct rt6_info *rt = (struct rt6_info *) | 878 | struct rt6_info *ort = (struct rt6_info *) dst_orig; |
837 | dst_alloc(&ip6_dst_blackhole_ops); | ||
838 | struct dst_entry *new = NULL; | 879 | struct dst_entry *new = NULL; |
839 | 880 | ||
840 | if (rt) { | 881 | if (rt) { |
841 | new = &rt->dst; | 882 | new = &rt->dst; |
842 | 883 | ||
843 | atomic_set(&new->__refcnt, 1); | ||
844 | new->__use = 1; | 884 | new->__use = 1; |
845 | new->input = dst_discard; | 885 | new->input = dst_discard; |
846 | new->output = dst_discard; | 886 | new->output = dst_discard; |
@@ -866,11 +906,9 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl | |||
866 | dst_free(new); | 906 | dst_free(new); |
867 | } | 907 | } |
868 | 908 | ||
869 | dst_release(*dstp); | 909 | dst_release(dst_orig); |
870 | *dstp = new; | 910 | return new ? new : ERR_PTR(-ENOMEM); |
871 | return new ? 0 : -ENOMEM; | ||
872 | } | 911 | } |
873 | EXPORT_SYMBOL_GPL(ip6_dst_blackhole); | ||
874 | 912 | ||
875 | /* | 913 | /* |
876 | * Destination cache support functions | 914 | * Destination cache support functions |
@@ -882,9 +920,14 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) | |||
882 | 920 | ||
883 | rt = (struct rt6_info *) dst; | 921 | rt = (struct rt6_info *) dst; |
884 | 922 | ||
885 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) | 923 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { |
924 | if (rt->rt6i_peer_genid != rt6_peer_genid()) { | ||
925 | if (!rt->rt6i_peer) | ||
926 | rt6_bind_peer(rt, 0); | ||
927 | rt->rt6i_peer_genid = rt6_peer_genid(); | ||
928 | } | ||
886 | return dst; | 929 | return dst; |
887 | 930 | } | |
888 | return NULL; | 931 | return NULL; |
889 | } | 932 | } |
890 | 933 | ||
@@ -935,7 +978,6 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
935 | dst_metric_set(dst, RTAX_FEATURES, features); | 978 | dst_metric_set(dst, RTAX_FEATURES, features); |
936 | } | 979 | } |
937 | dst_metric_set(dst, RTAX_MTU, mtu); | 980 | dst_metric_set(dst, RTAX_MTU, mtu); |
938 | call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); | ||
939 | } | 981 | } |
940 | } | 982 | } |
941 | 983 | ||
@@ -1032,11 +1074,9 @@ out: | |||
1032 | 1074 | ||
1033 | int icmp6_dst_gc(void) | 1075 | int icmp6_dst_gc(void) |
1034 | { | 1076 | { |
1035 | struct dst_entry *dst, *next, **pprev; | 1077 | struct dst_entry *dst, **pprev; |
1036 | int more = 0; | 1078 | int more = 0; |
1037 | 1079 | ||
1038 | next = NULL; | ||
1039 | |||
1040 | spin_lock_bh(&icmp6_dst_lock); | 1080 | spin_lock_bh(&icmp6_dst_lock); |
1041 | pprev = &icmp6_dst_gc_list; | 1081 | pprev = &icmp6_dst_gc_list; |
1042 | 1082 | ||
@@ -1404,16 +1444,16 @@ static int ip6_route_del(struct fib6_config *cfg) | |||
1404 | * Handle redirects | 1444 | * Handle redirects |
1405 | */ | 1445 | */ |
1406 | struct ip6rd_flowi { | 1446 | struct ip6rd_flowi { |
1407 | struct flowi fl; | 1447 | struct flowi6 fl6; |
1408 | struct in6_addr gateway; | 1448 | struct in6_addr gateway; |
1409 | }; | 1449 | }; |
1410 | 1450 | ||
1411 | static struct rt6_info *__ip6_route_redirect(struct net *net, | 1451 | static struct rt6_info *__ip6_route_redirect(struct net *net, |
1412 | struct fib6_table *table, | 1452 | struct fib6_table *table, |
1413 | struct flowi *fl, | 1453 | struct flowi6 *fl6, |
1414 | int flags) | 1454 | int flags) |
1415 | { | 1455 | { |
1416 | struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl; | 1456 | struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6; |
1417 | struct rt6_info *rt; | 1457 | struct rt6_info *rt; |
1418 | struct fib6_node *fn; | 1458 | struct fib6_node *fn; |
1419 | 1459 | ||
@@ -1429,7 +1469,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, | |||
1429 | */ | 1469 | */ |
1430 | 1470 | ||
1431 | read_lock_bh(&table->tb6_lock); | 1471 | read_lock_bh(&table->tb6_lock); |
1432 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); | 1472 | fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); |
1433 | restart: | 1473 | restart: |
1434 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { | 1474 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { |
1435 | /* | 1475 | /* |
@@ -1444,7 +1484,7 @@ restart: | |||
1444 | continue; | 1484 | continue; |
1445 | if (!(rt->rt6i_flags & RTF_GATEWAY)) | 1485 | if (!(rt->rt6i_flags & RTF_GATEWAY)) |
1446 | continue; | 1486 | continue; |
1447 | if (fl->oif != rt->rt6i_dev->ifindex) | 1487 | if (fl6->flowi6_oif != rt->rt6i_dev->ifindex) |
1448 | continue; | 1488 | continue; |
1449 | if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) | 1489 | if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) |
1450 | continue; | 1490 | continue; |
@@ -1453,7 +1493,7 @@ restart: | |||
1453 | 1493 | ||
1454 | if (!rt) | 1494 | if (!rt) |
1455 | rt = net->ipv6.ip6_null_entry; | 1495 | rt = net->ipv6.ip6_null_entry; |
1456 | BACKTRACK(net, &fl->fl6_src); | 1496 | BACKTRACK(net, &fl6->saddr); |
1457 | out: | 1497 | out: |
1458 | dst_hold(&rt->dst); | 1498 | dst_hold(&rt->dst); |
1459 | 1499 | ||
@@ -1470,10 +1510,10 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1470 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 1510 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
1471 | struct net *net = dev_net(dev); | 1511 | struct net *net = dev_net(dev); |
1472 | struct ip6rd_flowi rdfl = { | 1512 | struct ip6rd_flowi rdfl = { |
1473 | .fl = { | 1513 | .fl6 = { |
1474 | .oif = dev->ifindex, | 1514 | .flowi6_oif = dev->ifindex, |
1475 | .fl6_dst = *dest, | 1515 | .daddr = *dest, |
1476 | .fl6_src = *src, | 1516 | .saddr = *src, |
1477 | }, | 1517 | }, |
1478 | }; | 1518 | }; |
1479 | 1519 | ||
@@ -1482,7 +1522,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1482 | if (rt6_need_strict(dest)) | 1522 | if (rt6_need_strict(dest)) |
1483 | flags |= RT6_LOOKUP_F_IFACE; | 1523 | flags |= RT6_LOOKUP_F_IFACE; |
1484 | 1524 | ||
1485 | return (struct rt6_info *)fib6_rule_lookup(net, (struct flowi *)&rdfl, | 1525 | return (struct rt6_info *)fib6_rule_lookup(net, &rdfl.fl6, |
1486 | flags, __ip6_route_redirect); | 1526 | flags, __ip6_route_redirect); |
1487 | } | 1527 | } |
1488 | 1528 | ||
@@ -1984,12 +2024,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1984 | if (IS_ERR(neigh)) { | 2024 | if (IS_ERR(neigh)) { |
1985 | dst_free(&rt->dst); | 2025 | dst_free(&rt->dst); |
1986 | 2026 | ||
1987 | /* We are casting this because that is the return | 2027 | return ERR_CAST(neigh); |
1988 | * value type. But an errno encoded pointer is the | ||
1989 | * same regardless of the underlying pointer type, | ||
1990 | * and that's what we are returning. So this is OK. | ||
1991 | */ | ||
1992 | return (struct rt6_info *) neigh; | ||
1993 | } | 2028 | } |
1994 | rt->rt6i_nexthop = neigh; | 2029 | rt->rt6i_nexthop = neigh; |
1995 | 2030 | ||
@@ -2350,7 +2385,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2350 | struct rt6_info *rt; | 2385 | struct rt6_info *rt; |
2351 | struct sk_buff *skb; | 2386 | struct sk_buff *skb; |
2352 | struct rtmsg *rtm; | 2387 | struct rtmsg *rtm; |
2353 | struct flowi fl; | 2388 | struct flowi6 fl6; |
2354 | int err, iif = 0; | 2389 | int err, iif = 0; |
2355 | 2390 | ||
2356 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); | 2391 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); |
@@ -2358,27 +2393,27 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2358 | goto errout; | 2393 | goto errout; |
2359 | 2394 | ||
2360 | err = -EINVAL; | 2395 | err = -EINVAL; |
2361 | memset(&fl, 0, sizeof(fl)); | 2396 | memset(&fl6, 0, sizeof(fl6)); |
2362 | 2397 | ||
2363 | if (tb[RTA_SRC]) { | 2398 | if (tb[RTA_SRC]) { |
2364 | if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) | 2399 | if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) |
2365 | goto errout; | 2400 | goto errout; |
2366 | 2401 | ||
2367 | ipv6_addr_copy(&fl.fl6_src, nla_data(tb[RTA_SRC])); | 2402 | ipv6_addr_copy(&fl6.saddr, nla_data(tb[RTA_SRC])); |
2368 | } | 2403 | } |
2369 | 2404 | ||
2370 | if (tb[RTA_DST]) { | 2405 | if (tb[RTA_DST]) { |
2371 | if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr)) | 2406 | if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr)) |
2372 | goto errout; | 2407 | goto errout; |
2373 | 2408 | ||
2374 | ipv6_addr_copy(&fl.fl6_dst, nla_data(tb[RTA_DST])); | 2409 | ipv6_addr_copy(&fl6.daddr, nla_data(tb[RTA_DST])); |
2375 | } | 2410 | } |
2376 | 2411 | ||
2377 | if (tb[RTA_IIF]) | 2412 | if (tb[RTA_IIF]) |
2378 | iif = nla_get_u32(tb[RTA_IIF]); | 2413 | iif = nla_get_u32(tb[RTA_IIF]); |
2379 | 2414 | ||
2380 | if (tb[RTA_OIF]) | 2415 | if (tb[RTA_OIF]) |
2381 | fl.oif = nla_get_u32(tb[RTA_OIF]); | 2416 | fl6.flowi6_oif = nla_get_u32(tb[RTA_OIF]); |
2382 | 2417 | ||
2383 | if (iif) { | 2418 | if (iif) { |
2384 | struct net_device *dev; | 2419 | struct net_device *dev; |
@@ -2401,10 +2436,10 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2401 | skb_reset_mac_header(skb); | 2436 | skb_reset_mac_header(skb); |
2402 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); | 2437 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); |
2403 | 2438 | ||
2404 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl); | 2439 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl6); |
2405 | skb_dst_set(skb, &rt->dst); | 2440 | skb_dst_set(skb, &rt->dst); |
2406 | 2441 | ||
2407 | err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, | 2442 | err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif, |
2408 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, | 2443 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, |
2409 | nlh->nlmsg_seq, 0, 0, 0); | 2444 | nlh->nlmsg_seq, 0, 0, 0); |
2410 | if (err < 0) { | 2445 | if (err < 0) { |
@@ -2561,14 +2596,16 @@ static | |||
2561 | int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, | 2596 | int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, |
2562 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2597 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2563 | { | 2598 | { |
2564 | struct net *net = current->nsproxy->net_ns; | 2599 | struct net *net; |
2565 | int delay = net->ipv6.sysctl.flush_delay; | 2600 | int delay; |
2566 | if (write) { | 2601 | if (!write) |
2567 | proc_dointvec(ctl, write, buffer, lenp, ppos); | ||
2568 | fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net); | ||
2569 | return 0; | ||
2570 | } else | ||
2571 | return -EINVAL; | 2602 | return -EINVAL; |
2603 | |||
2604 | net = (struct net *)ctl->extra1; | ||
2605 | delay = net->ipv6.sysctl.flush_delay; | ||
2606 | proc_dointvec(ctl, write, buffer, lenp, ppos); | ||
2607 | fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net); | ||
2608 | return 0; | ||
2572 | } | 2609 | } |
2573 | 2610 | ||
2574 | ctl_table ipv6_route_table_template[] = { | 2611 | ctl_table ipv6_route_table_template[] = { |
@@ -2655,6 +2692,7 @@ struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net) | |||
2655 | 2692 | ||
2656 | if (table) { | 2693 | if (table) { |
2657 | table[0].data = &net->ipv6.sysctl.flush_delay; | 2694 | table[0].data = &net->ipv6.sysctl.flush_delay; |
2695 | table[0].extra1 = net; | ||
2658 | table[1].data = &net->ipv6.ip6_dst_ops.gc_thresh; | 2696 | table[1].data = &net->ipv6.ip6_dst_ops.gc_thresh; |
2659 | table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; | 2697 | table[2].data = &net->ipv6.sysctl.ip6_rt_max_size; |
2660 | table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; | 2698 | table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; |
@@ -2688,7 +2726,8 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2688 | net->ipv6.ip6_null_entry->dst.path = | 2726 | net->ipv6.ip6_null_entry->dst.path = |
2689 | (struct dst_entry *)net->ipv6.ip6_null_entry; | 2727 | (struct dst_entry *)net->ipv6.ip6_null_entry; |
2690 | net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2728 | net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2691 | dst_metric_set(&net->ipv6.ip6_null_entry->dst, RTAX_HOPLIMIT, 255); | 2729 | dst_init_metrics(&net->ipv6.ip6_null_entry->dst, |
2730 | ip6_template_metrics, true); | ||
2692 | 2731 | ||
2693 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2732 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
2694 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | 2733 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, |
@@ -2699,7 +2738,8 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2699 | net->ipv6.ip6_prohibit_entry->dst.path = | 2738 | net->ipv6.ip6_prohibit_entry->dst.path = |
2700 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | 2739 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; |
2701 | net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2740 | net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2702 | dst_metric_set(&net->ipv6.ip6_prohibit_entry->dst, RTAX_HOPLIMIT, 255); | 2741 | dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst, |
2742 | ip6_template_metrics, true); | ||
2703 | 2743 | ||
2704 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | 2744 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, |
2705 | sizeof(*net->ipv6.ip6_blk_hole_entry), | 2745 | sizeof(*net->ipv6.ip6_blk_hole_entry), |
@@ -2709,7 +2749,8 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2709 | net->ipv6.ip6_blk_hole_entry->dst.path = | 2749 | net->ipv6.ip6_blk_hole_entry->dst.path = |
2710 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | 2750 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; |
2711 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2751 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2712 | dst_metric_set(&net->ipv6.ip6_blk_hole_entry->dst, RTAX_HOPLIMIT, 255); | 2752 | dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, |
2753 | ip6_template_metrics, true); | ||
2713 | #endif | 2754 | #endif |
2714 | 2755 | ||
2715 | net->ipv6.sysctl.flush_delay = 0; | 2756 | net->ipv6.sysctl.flush_delay = 0; |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 8ce38f10a547..43b33373adb2 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -412,7 +412,7 @@ static void prl_list_destroy_rcu(struct rcu_head *head) | |||
412 | 412 | ||
413 | p = container_of(head, struct ip_tunnel_prl_entry, rcu_head); | 413 | p = container_of(head, struct ip_tunnel_prl_entry, rcu_head); |
414 | do { | 414 | do { |
415 | n = p->next; | 415 | n = rcu_dereference_protected(p->next, 1); |
416 | kfree(p); | 416 | kfree(p); |
417 | p = n; | 417 | p = n; |
418 | } while (p); | 418 | } while (p); |
@@ -421,15 +421,17 @@ static void prl_list_destroy_rcu(struct rcu_head *head) | |||
421 | static int | 421 | static int |
422 | ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | 422 | ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) |
423 | { | 423 | { |
424 | struct ip_tunnel_prl_entry *x, **p; | 424 | struct ip_tunnel_prl_entry *x; |
425 | struct ip_tunnel_prl_entry __rcu **p; | ||
425 | int err = 0; | 426 | int err = 0; |
426 | 427 | ||
427 | ASSERT_RTNL(); | 428 | ASSERT_RTNL(); |
428 | 429 | ||
429 | if (a && a->addr != htonl(INADDR_ANY)) { | 430 | if (a && a->addr != htonl(INADDR_ANY)) { |
430 | for (p = &t->prl; *p; p = &(*p)->next) { | 431 | for (p = &t->prl; |
431 | if ((*p)->addr == a->addr) { | 432 | (x = rtnl_dereference(*p)) != NULL; |
432 | x = *p; | 433 | p = &x->next) { |
434 | if (x->addr == a->addr) { | ||
433 | *p = x->next; | 435 | *p = x->next; |
434 | call_rcu(&x->rcu_head, prl_entry_destroy_rcu); | 436 | call_rcu(&x->rcu_head, prl_entry_destroy_rcu); |
435 | t->prl_count--; | 437 | t->prl_count--; |
@@ -438,9 +440,9 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | |||
438 | } | 440 | } |
439 | err = -ENXIO; | 441 | err = -ENXIO; |
440 | } else { | 442 | } else { |
441 | if (t->prl) { | 443 | x = rtnl_dereference(t->prl); |
444 | if (x) { | ||
442 | t->prl_count = 0; | 445 | t->prl_count = 0; |
443 | x = t->prl; | ||
444 | call_rcu(&x->rcu_head, prl_list_destroy_rcu); | 446 | call_rcu(&x->rcu_head, prl_list_destroy_rcu); |
445 | t->prl = NULL; | 447 | t->prl = NULL; |
446 | } | 448 | } |
@@ -730,16 +732,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
730 | dst = addr6->s6_addr32[3]; | 732 | dst = addr6->s6_addr32[3]; |
731 | } | 733 | } |
732 | 734 | ||
733 | { | 735 | rt = ip_route_output_ports(dev_net(dev), NULL, |
734 | struct flowi fl = { .fl4_dst = dst, | 736 | dst, tiph->saddr, |
735 | .fl4_src = tiph->saddr, | 737 | 0, 0, |
736 | .fl4_tos = RT_TOS(tos), | 738 | IPPROTO_IPV6, RT_TOS(tos), |
737 | .oif = tunnel->parms.link, | 739 | tunnel->parms.link); |
738 | .proto = IPPROTO_IPV6 }; | 740 | if (IS_ERR(rt)) { |
739 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { | 741 | dev->stats.tx_carrier_errors++; |
740 | dev->stats.tx_carrier_errors++; | 742 | goto tx_error_icmp; |
741 | goto tx_error_icmp; | ||
742 | } | ||
743 | } | 743 | } |
744 | if (rt->rt_type != RTN_UNICAST) { | 744 | if (rt->rt_type != RTN_UNICAST) { |
745 | ip_rt_put(rt); | 745 | ip_rt_put(rt); |
@@ -855,13 +855,14 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
855 | iph = &tunnel->parms.iph; | 855 | iph = &tunnel->parms.iph; |
856 | 856 | ||
857 | if (iph->daddr) { | 857 | if (iph->daddr) { |
858 | struct flowi fl = { .fl4_dst = iph->daddr, | 858 | struct rtable *rt = ip_route_output_ports(dev_net(dev), NULL, |
859 | .fl4_src = iph->saddr, | 859 | iph->daddr, iph->saddr, |
860 | .fl4_tos = RT_TOS(iph->tos), | 860 | 0, 0, |
861 | .oif = tunnel->parms.link, | 861 | IPPROTO_IPV6, |
862 | .proto = IPPROTO_IPV6 }; | 862 | RT_TOS(iph->tos), |
863 | struct rtable *rt; | 863 | tunnel->parms.link); |
864 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { | 864 | |
865 | if (!IS_ERR(rt)) { | ||
865 | tdev = rt->dst.dev; | 866 | tdev = rt->dst.dev; |
866 | ip_rt_put(rt); | 867 | ip_rt_put(rt); |
867 | } | 868 | } |
@@ -1179,7 +1180,7 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
1179 | if (!dev->tstats) | 1180 | if (!dev->tstats) |
1180 | return -ENOMEM; | 1181 | return -ENOMEM; |
1181 | dev_hold(dev); | 1182 | dev_hold(dev); |
1182 | sitn->tunnels_wc[0] = tunnel; | 1183 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); |
1183 | return 0; | 1184 | return 0; |
1184 | } | 1185 | } |
1185 | 1186 | ||
@@ -1196,11 +1197,12 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea | |||
1196 | for (prio = 1; prio < 4; prio++) { | 1197 | for (prio = 1; prio < 4; prio++) { |
1197 | int h; | 1198 | int h; |
1198 | for (h = 0; h < HASH_SIZE; h++) { | 1199 | for (h = 0; h < HASH_SIZE; h++) { |
1199 | struct ip_tunnel *t = sitn->tunnels[prio][h]; | 1200 | struct ip_tunnel *t; |
1200 | 1201 | ||
1202 | t = rtnl_dereference(sitn->tunnels[prio][h]); | ||
1201 | while (t != NULL) { | 1203 | while (t != NULL) { |
1202 | unregister_netdevice_queue(t->dev, head); | 1204 | unregister_netdevice_queue(t->dev, head); |
1203 | t = t->next; | 1205 | t = rtnl_dereference(t->next); |
1204 | } | 1206 | } |
1205 | } | 1207 | } |
1206 | } | 1208 | } |
@@ -1290,4 +1292,4 @@ static int __init sit_init(void) | |||
1290 | module_init(sit_init); | 1292 | module_init(sit_init); |
1291 | module_exit(sit_cleanup); | 1293 | module_exit(sit_cleanup); |
1292 | MODULE_LICENSE("GPL"); | 1294 | MODULE_LICENSE("GPL"); |
1293 | MODULE_ALIAS("sit0"); | 1295 | MODULE_ALIAS_NETDEV("sit0"); |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 09fd34f0dbf2..352c26081f5d 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -232,23 +232,20 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
232 | */ | 232 | */ |
233 | { | 233 | { |
234 | struct in6_addr *final_p, final; | 234 | struct in6_addr *final_p, final; |
235 | struct flowi fl; | 235 | struct flowi6 fl6; |
236 | memset(&fl, 0, sizeof(fl)); | 236 | memset(&fl6, 0, sizeof(fl6)); |
237 | fl.proto = IPPROTO_TCP; | 237 | fl6.flowi6_proto = IPPROTO_TCP; |
238 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); | 238 | ipv6_addr_copy(&fl6.daddr, &ireq6->rmt_addr); |
239 | final_p = fl6_update_dst(&fl, np->opt, &final); | 239 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
240 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); | 240 | ipv6_addr_copy(&fl6.saddr, &ireq6->loc_addr); |
241 | fl.oif = sk->sk_bound_dev_if; | 241 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
242 | fl.mark = sk->sk_mark; | 242 | fl6.flowi6_mark = sk->sk_mark; |
243 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; | 243 | fl6.fl6_dport = inet_rsk(req)->rmt_port; |
244 | fl.fl_ip_sport = inet_sk(sk)->inet_sport; | 244 | fl6.fl6_sport = inet_sk(sk)->inet_sport; |
245 | security_req_classify_flow(req, &fl); | 245 | security_req_classify_flow(req, flowi6_to_flowi(&fl6)); |
246 | if (ip6_dst_lookup(sk, &dst, &fl)) | 246 | |
247 | goto out_free; | 247 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); |
248 | 248 | if (IS_ERR(dst)) | |
249 | if (final_p) | ||
250 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
251 | if ((xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) | ||
252 | goto out_free; | 249 | goto out_free; |
253 | } | 250 | } |
254 | 251 | ||
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index fa1d8f4e0051..7cb65ef79f9c 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <net/addrconf.h> | 15 | #include <net/addrconf.h> |
16 | #include <net/inet_frag.h> | 16 | #include <net/inet_frag.h> |
17 | 17 | ||
18 | static struct ctl_table empty[1]; | ||
19 | |||
18 | static ctl_table ipv6_table_template[] = { | 20 | static ctl_table ipv6_table_template[] = { |
19 | { | 21 | { |
20 | .procname = "route", | 22 | .procname = "route", |
@@ -35,6 +37,12 @@ static ctl_table ipv6_table_template[] = { | |||
35 | .mode = 0644, | 37 | .mode = 0644, |
36 | .proc_handler = proc_dointvec | 38 | .proc_handler = proc_dointvec |
37 | }, | 39 | }, |
40 | { | ||
41 | .procname = "neigh", | ||
42 | .maxlen = 0, | ||
43 | .mode = 0555, | ||
44 | .child = empty, | ||
45 | }, | ||
38 | { } | 46 | { } |
39 | }; | 47 | }; |
40 | 48 | ||
@@ -152,7 +160,6 @@ static struct ctl_table_header *ip6_base; | |||
152 | 160 | ||
153 | int ipv6_static_sysctl_register(void) | 161 | int ipv6_static_sysctl_register(void) |
154 | { | 162 | { |
155 | static struct ctl_table empty[1]; | ||
156 | ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty); | 163 | ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty); |
157 | if (ip6_base == NULL) | 164 | if (ip6_base == NULL) |
158 | return -ENOMEM; | 165 | return -ENOMEM; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 20aa95e37359..2b0c186862c8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -131,7 +131,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
131 | struct tcp_sock *tp = tcp_sk(sk); | 131 | struct tcp_sock *tp = tcp_sk(sk); |
132 | struct in6_addr *saddr = NULL, *final_p, final; | 132 | struct in6_addr *saddr = NULL, *final_p, final; |
133 | struct rt6_info *rt; | 133 | struct rt6_info *rt; |
134 | struct flowi fl; | 134 | struct flowi6 fl6; |
135 | struct dst_entry *dst; | 135 | struct dst_entry *dst; |
136 | int addr_type; | 136 | int addr_type; |
137 | int err; | 137 | int err; |
@@ -142,14 +142,14 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
142 | if (usin->sin6_family != AF_INET6) | 142 | if (usin->sin6_family != AF_INET6) |
143 | return -EAFNOSUPPORT; | 143 | return -EAFNOSUPPORT; |
144 | 144 | ||
145 | memset(&fl, 0, sizeof(fl)); | 145 | memset(&fl6, 0, sizeof(fl6)); |
146 | 146 | ||
147 | if (np->sndflow) { | 147 | if (np->sndflow) { |
148 | fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; | 148 | fl6.flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; |
149 | IP6_ECN_flow_init(fl.fl6_flowlabel); | 149 | IP6_ECN_flow_init(fl6.flowlabel); |
150 | if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { | 150 | if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { |
151 | struct ip6_flowlabel *flowlabel; | 151 | struct ip6_flowlabel *flowlabel; |
152 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); | 152 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
153 | if (flowlabel == NULL) | 153 | if (flowlabel == NULL) |
154 | return -EINVAL; | 154 | return -EINVAL; |
155 | ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); | 155 | ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst); |
@@ -195,7 +195,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
195 | } | 195 | } |
196 | 196 | ||
197 | ipv6_addr_copy(&np->daddr, &usin->sin6_addr); | 197 | ipv6_addr_copy(&np->daddr, &usin->sin6_addr); |
198 | np->flow_label = fl.fl6_flowlabel; | 198 | np->flow_label = fl6.flowlabel; |
199 | 199 | ||
200 | /* | 200 | /* |
201 | * TCP over IPv4 | 201 | * TCP over IPv4 |
@@ -242,35 +242,27 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
242 | if (!ipv6_addr_any(&np->rcv_saddr)) | 242 | if (!ipv6_addr_any(&np->rcv_saddr)) |
243 | saddr = &np->rcv_saddr; | 243 | saddr = &np->rcv_saddr; |
244 | 244 | ||
245 | fl.proto = IPPROTO_TCP; | 245 | fl6.flowi6_proto = IPPROTO_TCP; |
246 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 246 | ipv6_addr_copy(&fl6.daddr, &np->daddr); |
247 | ipv6_addr_copy(&fl.fl6_src, | 247 | ipv6_addr_copy(&fl6.saddr, |
248 | (saddr ? saddr : &np->saddr)); | 248 | (saddr ? saddr : &np->saddr)); |
249 | fl.oif = sk->sk_bound_dev_if; | 249 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
250 | fl.mark = sk->sk_mark; | 250 | fl6.flowi6_mark = sk->sk_mark; |
251 | fl.fl_ip_dport = usin->sin6_port; | 251 | fl6.fl6_dport = usin->sin6_port; |
252 | fl.fl_ip_sport = inet->inet_sport; | 252 | fl6.fl6_sport = inet->inet_sport; |
253 | 253 | ||
254 | final_p = fl6_update_dst(&fl, np->opt, &final); | 254 | final_p = fl6_update_dst(&fl6, np->opt, &final); |
255 | 255 | ||
256 | security_sk_classify_flow(sk, &fl); | 256 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
257 | 257 | ||
258 | err = ip6_dst_lookup(sk, &dst, &fl); | 258 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); |
259 | if (err) | 259 | if (IS_ERR(dst)) { |
260 | err = PTR_ERR(dst); | ||
260 | goto failure; | 261 | goto failure; |
261 | if (final_p) | ||
262 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
263 | |||
264 | err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT); | ||
265 | if (err < 0) { | ||
266 | if (err == -EREMOTE) | ||
267 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
268 | if (err < 0) | ||
269 | goto failure; | ||
270 | } | 262 | } |
271 | 263 | ||
272 | if (saddr == NULL) { | 264 | if (saddr == NULL) { |
273 | saddr = &fl.fl6_src; | 265 | saddr = &fl6.saddr; |
274 | ipv6_addr_copy(&np->rcv_saddr, saddr); | 266 | ipv6_addr_copy(&np->rcv_saddr, saddr); |
275 | } | 267 | } |
276 | 268 | ||
@@ -385,7 +377,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
385 | np = inet6_sk(sk); | 377 | np = inet6_sk(sk); |
386 | 378 | ||
387 | if (type == ICMPV6_PKT_TOOBIG) { | 379 | if (type == ICMPV6_PKT_TOOBIG) { |
388 | struct dst_entry *dst = NULL; | 380 | struct dst_entry *dst; |
389 | 381 | ||
390 | if (sock_owned_by_user(sk)) | 382 | if (sock_owned_by_user(sk)) |
391 | goto out; | 383 | goto out; |
@@ -397,29 +389,25 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
397 | 389 | ||
398 | if (dst == NULL) { | 390 | if (dst == NULL) { |
399 | struct inet_sock *inet = inet_sk(sk); | 391 | struct inet_sock *inet = inet_sk(sk); |
400 | struct flowi fl; | 392 | struct flowi6 fl6; |
401 | 393 | ||
402 | /* BUGGG_FUTURE: Again, it is not clear how | 394 | /* BUGGG_FUTURE: Again, it is not clear how |
403 | to handle rthdr case. Ignore this complexity | 395 | to handle rthdr case. Ignore this complexity |
404 | for now. | 396 | for now. |
405 | */ | 397 | */ |
406 | memset(&fl, 0, sizeof(fl)); | 398 | memset(&fl6, 0, sizeof(fl6)); |
407 | fl.proto = IPPROTO_TCP; | 399 | fl6.flowi6_proto = IPPROTO_TCP; |
408 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 400 | ipv6_addr_copy(&fl6.daddr, &np->daddr); |
409 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 401 | ipv6_addr_copy(&fl6.saddr, &np->saddr); |
410 | fl.oif = sk->sk_bound_dev_if; | 402 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
411 | fl.mark = sk->sk_mark; | 403 | fl6.flowi6_mark = sk->sk_mark; |
412 | fl.fl_ip_dport = inet->inet_dport; | 404 | fl6.fl6_dport = inet->inet_dport; |
413 | fl.fl_ip_sport = inet->inet_sport; | 405 | fl6.fl6_sport = inet->inet_sport; |
414 | security_skb_classify_flow(skb, &fl); | 406 | security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); |
415 | 407 | ||
416 | if ((err = ip6_dst_lookup(sk, &dst, &fl))) { | 408 | dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false); |
417 | sk->sk_err_soft = -err; | 409 | if (IS_ERR(dst)) { |
418 | goto out; | 410 | sk->sk_err_soft = -PTR_ERR(dst); |
419 | } | ||
420 | |||
421 | if ((err = xfrm_lookup(net, &dst, &fl, sk, 0)) < 0) { | ||
422 | sk->sk_err_soft = -err; | ||
423 | goto out; | 411 | goto out; |
424 | } | 412 | } |
425 | 413 | ||
@@ -494,38 +482,36 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
494 | struct sk_buff * skb; | 482 | struct sk_buff * skb; |
495 | struct ipv6_txoptions *opt = NULL; | 483 | struct ipv6_txoptions *opt = NULL; |
496 | struct in6_addr * final_p, final; | 484 | struct in6_addr * final_p, final; |
497 | struct flowi fl; | 485 | struct flowi6 fl6; |
498 | struct dst_entry *dst; | 486 | struct dst_entry *dst; |
499 | int err = -1; | 487 | int err; |
500 | 488 | ||
501 | memset(&fl, 0, sizeof(fl)); | 489 | memset(&fl6, 0, sizeof(fl6)); |
502 | fl.proto = IPPROTO_TCP; | 490 | fl6.flowi6_proto = IPPROTO_TCP; |
503 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | 491 | ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr); |
504 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); | 492 | ipv6_addr_copy(&fl6.saddr, &treq->loc_addr); |
505 | fl.fl6_flowlabel = 0; | 493 | fl6.flowlabel = 0; |
506 | fl.oif = treq->iif; | 494 | fl6.flowi6_oif = treq->iif; |
507 | fl.mark = sk->sk_mark; | 495 | fl6.flowi6_mark = sk->sk_mark; |
508 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; | 496 | fl6.fl6_dport = inet_rsk(req)->rmt_port; |
509 | fl.fl_ip_sport = inet_rsk(req)->loc_port; | 497 | fl6.fl6_sport = inet_rsk(req)->loc_port; |
510 | security_req_classify_flow(req, &fl); | 498 | security_req_classify_flow(req, flowi6_to_flowi(&fl6)); |
511 | 499 | ||
512 | opt = np->opt; | 500 | opt = np->opt; |
513 | final_p = fl6_update_dst(&fl, opt, &final); | 501 | final_p = fl6_update_dst(&fl6, opt, &final); |
514 | 502 | ||
515 | err = ip6_dst_lookup(sk, &dst, &fl); | 503 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); |
516 | if (err) | 504 | if (IS_ERR(dst)) { |
517 | goto done; | 505 | err = PTR_ERR(dst); |
518 | if (final_p) | ||
519 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
520 | if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) | ||
521 | goto done; | 506 | goto done; |
522 | 507 | } | |
523 | skb = tcp_make_synack(sk, dst, req, rvp); | 508 | skb = tcp_make_synack(sk, dst, req, rvp); |
509 | err = -ENOMEM; | ||
524 | if (skb) { | 510 | if (skb) { |
525 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); | 511 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); |
526 | 512 | ||
527 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | 513 | ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr); |
528 | err = ip6_xmit(sk, skb, &fl, opt); | 514 | err = ip6_xmit(sk, skb, &fl6, opt); |
529 | err = net_xmit_eval(err); | 515 | err = net_xmit_eval(err); |
530 | } | 516 | } |
531 | 517 | ||
@@ -1006,7 +992,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1006 | { | 992 | { |
1007 | struct tcphdr *th = tcp_hdr(skb), *t1; | 993 | struct tcphdr *th = tcp_hdr(skb), *t1; |
1008 | struct sk_buff *buff; | 994 | struct sk_buff *buff; |
1009 | struct flowi fl; | 995 | struct flowi6 fl6; |
1010 | struct net *net = dev_net(skb_dst(skb)->dev); | 996 | struct net *net = dev_net(skb_dst(skb)->dev); |
1011 | struct sock *ctl_sk = net->ipv6.tcp_sk; | 997 | struct sock *ctl_sk = net->ipv6.tcp_sk; |
1012 | unsigned int tot_len = sizeof(struct tcphdr); | 998 | unsigned int tot_len = sizeof(struct tcphdr); |
@@ -1060,34 +1046,33 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1060 | } | 1046 | } |
1061 | #endif | 1047 | #endif |
1062 | 1048 | ||
1063 | memset(&fl, 0, sizeof(fl)); | 1049 | memset(&fl6, 0, sizeof(fl6)); |
1064 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); | 1050 | ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->saddr); |
1065 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); | 1051 | ipv6_addr_copy(&fl6.saddr, &ipv6_hdr(skb)->daddr); |
1066 | 1052 | ||
1067 | buff->ip_summed = CHECKSUM_PARTIAL; | 1053 | buff->ip_summed = CHECKSUM_PARTIAL; |
1068 | buff->csum = 0; | 1054 | buff->csum = 0; |
1069 | 1055 | ||
1070 | __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst); | 1056 | __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr); |
1071 | 1057 | ||
1072 | fl.proto = IPPROTO_TCP; | 1058 | fl6.flowi6_proto = IPPROTO_TCP; |
1073 | fl.oif = inet6_iif(skb); | 1059 | fl6.flowi6_oif = inet6_iif(skb); |
1074 | fl.fl_ip_dport = t1->dest; | 1060 | fl6.fl6_dport = t1->dest; |
1075 | fl.fl_ip_sport = t1->source; | 1061 | fl6.fl6_sport = t1->source; |
1076 | security_skb_classify_flow(skb, &fl); | 1062 | security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); |
1077 | 1063 | ||
1078 | /* Pass a socket to ip6_dst_lookup either it is for RST | 1064 | /* Pass a socket to ip6_dst_lookup either it is for RST |
1079 | * Underlying function will use this to retrieve the network | 1065 | * Underlying function will use this to retrieve the network |
1080 | * namespace | 1066 | * namespace |
1081 | */ | 1067 | */ |
1082 | if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { | 1068 | dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false); |
1083 | if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { | 1069 | if (!IS_ERR(dst)) { |
1084 | skb_dst_set(buff, dst); | 1070 | skb_dst_set(buff, dst); |
1085 | ip6_xmit(ctl_sk, buff, &fl, NULL); | 1071 | ip6_xmit(ctl_sk, buff, &fl6, NULL); |
1086 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 1072 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
1087 | if (rst) | 1073 | if (rst) |
1088 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); | 1074 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); |
1089 | return; | 1075 | return; |
1090 | } | ||
1091 | } | 1076 | } |
1092 | 1077 | ||
1093 | kfree_skb(buff); | 1078 | kfree_skb(buff); |
@@ -1323,7 +1308,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1323 | tcp_death_row.sysctl_tw_recycle && | 1308 | tcp_death_row.sysctl_tw_recycle && |
1324 | (dst = inet6_csk_route_req(sk, req)) != NULL && | 1309 | (dst = inet6_csk_route_req(sk, req)) != NULL && |
1325 | (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL && | 1310 | (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL && |
1326 | ipv6_addr_equal((struct in6_addr *)peer->daddr.a6, | 1311 | ipv6_addr_equal((struct in6_addr *)peer->daddr.addr.a6, |
1327 | &treq->rmt_addr)) { | 1312 | &treq->rmt_addr)) { |
1328 | inet_peer_refcheck(peer); | 1313 | inet_peer_refcheck(peer); |
1329 | if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL && | 1314 | if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL && |
@@ -1636,10 +1621,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1636 | opt_skb = skb_clone(skb, GFP_ATOMIC); | 1621 | opt_skb = skb_clone(skb, GFP_ATOMIC); |
1637 | 1622 | ||
1638 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1623 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1639 | TCP_CHECK_TIMER(sk); | ||
1640 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) | 1624 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) |
1641 | goto reset; | 1625 | goto reset; |
1642 | TCP_CHECK_TIMER(sk); | ||
1643 | if (opt_skb) | 1626 | if (opt_skb) |
1644 | goto ipv6_pktoptions; | 1627 | goto ipv6_pktoptions; |
1645 | return 0; | 1628 | return 0; |
@@ -1667,10 +1650,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1667 | } | 1650 | } |
1668 | } | 1651 | } |
1669 | 1652 | ||
1670 | TCP_CHECK_TIMER(sk); | ||
1671 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) | 1653 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) |
1672 | goto reset; | 1654 | goto reset; |
1673 | TCP_CHECK_TIMER(sk); | ||
1674 | if (opt_skb) | 1655 | if (opt_skb) |
1675 | goto ipv6_pktoptions; | 1656 | goto ipv6_pktoptions; |
1676 | return 0; | 1657 | return 0; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9a009c66c8a3..d7037c006e13 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -886,7 +886,7 @@ static int udp_v6_push_pending_frames(struct sock *sk) | |||
886 | struct udphdr *uh; | 886 | struct udphdr *uh; |
887 | struct udp_sock *up = udp_sk(sk); | 887 | struct udp_sock *up = udp_sk(sk); |
888 | struct inet_sock *inet = inet_sk(sk); | 888 | struct inet_sock *inet = inet_sk(sk); |
889 | struct flowi *fl = &inet->cork.fl; | 889 | struct flowi6 *fl6 = &inet->cork.fl.u.ip6; |
890 | int err = 0; | 890 | int err = 0; |
891 | int is_udplite = IS_UDPLITE(sk); | 891 | int is_udplite = IS_UDPLITE(sk); |
892 | __wsum csum = 0; | 892 | __wsum csum = 0; |
@@ -899,23 +899,23 @@ static int udp_v6_push_pending_frames(struct sock *sk) | |||
899 | * Create a UDP header | 899 | * Create a UDP header |
900 | */ | 900 | */ |
901 | uh = udp_hdr(skb); | 901 | uh = udp_hdr(skb); |
902 | uh->source = fl->fl_ip_sport; | 902 | uh->source = fl6->fl6_sport; |
903 | uh->dest = fl->fl_ip_dport; | 903 | uh->dest = fl6->fl6_dport; |
904 | uh->len = htons(up->len); | 904 | uh->len = htons(up->len); |
905 | uh->check = 0; | 905 | uh->check = 0; |
906 | 906 | ||
907 | if (is_udplite) | 907 | if (is_udplite) |
908 | csum = udplite_csum_outgoing(sk, skb); | 908 | csum = udplite_csum_outgoing(sk, skb); |
909 | else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ | 909 | else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ |
910 | udp6_hwcsum_outgoing(sk, skb, &fl->fl6_src, &fl->fl6_dst, | 910 | udp6_hwcsum_outgoing(sk, skb, &fl6->saddr, &fl6->daddr, |
911 | up->len); | 911 | up->len); |
912 | goto send; | 912 | goto send; |
913 | } else | 913 | } else |
914 | csum = udp_csum_outgoing(sk, skb); | 914 | csum = udp_csum_outgoing(sk, skb); |
915 | 915 | ||
916 | /* add protocol-dependent pseudo-header */ | 916 | /* add protocol-dependent pseudo-header */ |
917 | uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst, | 917 | uh->check = csum_ipv6_magic(&fl6->saddr, &fl6->daddr, |
918 | up->len, fl->proto, csum ); | 918 | up->len, fl6->flowi6_proto, csum); |
919 | if (uh->check == 0) | 919 | if (uh->check == 0) |
920 | uh->check = CSUM_MANGLED_0; | 920 | uh->check = CSUM_MANGLED_0; |
921 | 921 | ||
@@ -947,7 +947,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
947 | struct in6_addr *daddr, *final_p, final; | 947 | struct in6_addr *daddr, *final_p, final; |
948 | struct ipv6_txoptions *opt = NULL; | 948 | struct ipv6_txoptions *opt = NULL; |
949 | struct ip6_flowlabel *flowlabel = NULL; | 949 | struct ip6_flowlabel *flowlabel = NULL; |
950 | struct flowi fl; | 950 | struct flowi6 fl6; |
951 | struct dst_entry *dst; | 951 | struct dst_entry *dst; |
952 | int addr_len = msg->msg_namelen; | 952 | int addr_len = msg->msg_namelen; |
953 | int ulen = len; | 953 | int ulen = len; |
@@ -1030,19 +1030,19 @@ do_udp_sendmsg: | |||
1030 | } | 1030 | } |
1031 | ulen += sizeof(struct udphdr); | 1031 | ulen += sizeof(struct udphdr); |
1032 | 1032 | ||
1033 | memset(&fl, 0, sizeof(fl)); | 1033 | memset(&fl6, 0, sizeof(fl6)); |
1034 | 1034 | ||
1035 | if (sin6) { | 1035 | if (sin6) { |
1036 | if (sin6->sin6_port == 0) | 1036 | if (sin6->sin6_port == 0) |
1037 | return -EINVAL; | 1037 | return -EINVAL; |
1038 | 1038 | ||
1039 | fl.fl_ip_dport = sin6->sin6_port; | 1039 | fl6.fl6_dport = sin6->sin6_port; |
1040 | daddr = &sin6->sin6_addr; | 1040 | daddr = &sin6->sin6_addr; |
1041 | 1041 | ||
1042 | if (np->sndflow) { | 1042 | if (np->sndflow) { |
1043 | fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; | 1043 | fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; |
1044 | if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { | 1044 | if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { |
1045 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); | 1045 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
1046 | if (flowlabel == NULL) | 1046 | if (flowlabel == NULL) |
1047 | return -EINVAL; | 1047 | return -EINVAL; |
1048 | daddr = &flowlabel->dst; | 1048 | daddr = &flowlabel->dst; |
@@ -1060,38 +1060,38 @@ do_udp_sendmsg: | |||
1060 | if (addr_len >= sizeof(struct sockaddr_in6) && | 1060 | if (addr_len >= sizeof(struct sockaddr_in6) && |
1061 | sin6->sin6_scope_id && | 1061 | sin6->sin6_scope_id && |
1062 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) | 1062 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) |
1063 | fl.oif = sin6->sin6_scope_id; | 1063 | fl6.flowi6_oif = sin6->sin6_scope_id; |
1064 | } else { | 1064 | } else { |
1065 | if (sk->sk_state != TCP_ESTABLISHED) | 1065 | if (sk->sk_state != TCP_ESTABLISHED) |
1066 | return -EDESTADDRREQ; | 1066 | return -EDESTADDRREQ; |
1067 | 1067 | ||
1068 | fl.fl_ip_dport = inet->inet_dport; | 1068 | fl6.fl6_dport = inet->inet_dport; |
1069 | daddr = &np->daddr; | 1069 | daddr = &np->daddr; |
1070 | fl.fl6_flowlabel = np->flow_label; | 1070 | fl6.flowlabel = np->flow_label; |
1071 | connected = 1; | 1071 | connected = 1; |
1072 | } | 1072 | } |
1073 | 1073 | ||
1074 | if (!fl.oif) | 1074 | if (!fl6.flowi6_oif) |
1075 | fl.oif = sk->sk_bound_dev_if; | 1075 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
1076 | 1076 | ||
1077 | if (!fl.oif) | 1077 | if (!fl6.flowi6_oif) |
1078 | fl.oif = np->sticky_pktinfo.ipi6_ifindex; | 1078 | fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; |
1079 | 1079 | ||
1080 | fl.mark = sk->sk_mark; | 1080 | fl6.flowi6_mark = sk->sk_mark; |
1081 | 1081 | ||
1082 | if (msg->msg_controllen) { | 1082 | if (msg->msg_controllen) { |
1083 | opt = &opt_space; | 1083 | opt = &opt_space; |
1084 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 1084 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
1085 | opt->tot_len = sizeof(*opt); | 1085 | opt->tot_len = sizeof(*opt); |
1086 | 1086 | ||
1087 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, | 1087 | err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit, |
1088 | &tclass, &dontfrag); | 1088 | &tclass, &dontfrag); |
1089 | if (err < 0) { | 1089 | if (err < 0) { |
1090 | fl6_sock_release(flowlabel); | 1090 | fl6_sock_release(flowlabel); |
1091 | return err; | 1091 | return err; |
1092 | } | 1092 | } |
1093 | if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { | 1093 | if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { |
1094 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); | 1094 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
1095 | if (flowlabel == NULL) | 1095 | if (flowlabel == NULL) |
1096 | return -EINVAL; | 1096 | return -EINVAL; |
1097 | } | 1097 | } |
@@ -1105,42 +1105,35 @@ do_udp_sendmsg: | |||
1105 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | 1105 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
1106 | opt = ipv6_fixup_options(&opt_space, opt); | 1106 | opt = ipv6_fixup_options(&opt_space, opt); |
1107 | 1107 | ||
1108 | fl.proto = sk->sk_protocol; | 1108 | fl6.flowi6_proto = sk->sk_protocol; |
1109 | if (!ipv6_addr_any(daddr)) | 1109 | if (!ipv6_addr_any(daddr)) |
1110 | ipv6_addr_copy(&fl.fl6_dst, daddr); | 1110 | ipv6_addr_copy(&fl6.daddr, daddr); |
1111 | else | 1111 | else |
1112 | fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | 1112 | fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ |
1113 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 1113 | if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) |
1114 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 1114 | ipv6_addr_copy(&fl6.saddr, &np->saddr); |
1115 | fl.fl_ip_sport = inet->inet_sport; | 1115 | fl6.fl6_sport = inet->inet_sport; |
1116 | 1116 | ||
1117 | final_p = fl6_update_dst(&fl, opt, &final); | 1117 | final_p = fl6_update_dst(&fl6, opt, &final); |
1118 | if (final_p) | 1118 | if (final_p) |
1119 | connected = 0; | 1119 | connected = 0; |
1120 | 1120 | ||
1121 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { | 1121 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) { |
1122 | fl.oif = np->mcast_oif; | 1122 | fl6.flowi6_oif = np->mcast_oif; |
1123 | connected = 0; | 1123 | connected = 0; |
1124 | } | 1124 | } |
1125 | 1125 | ||
1126 | security_sk_classify_flow(sk, &fl); | 1126 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
1127 | 1127 | ||
1128 | err = ip6_sk_dst_lookup(sk, &dst, &fl); | 1128 | dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p, true); |
1129 | if (err) | 1129 | if (IS_ERR(dst)) { |
1130 | err = PTR_ERR(dst); | ||
1131 | dst = NULL; | ||
1130 | goto out; | 1132 | goto out; |
1131 | if (final_p) | ||
1132 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
1133 | |||
1134 | err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT); | ||
1135 | if (err < 0) { | ||
1136 | if (err == -EREMOTE) | ||
1137 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
1138 | if (err < 0) | ||
1139 | goto out; | ||
1140 | } | 1133 | } |
1141 | 1134 | ||
1142 | if (hlimit < 0) { | 1135 | if (hlimit < 0) { |
1143 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 1136 | if (ipv6_addr_is_multicast(&fl6.daddr)) |
1144 | hlimit = np->mcast_hops; | 1137 | hlimit = np->mcast_hops; |
1145 | else | 1138 | else |
1146 | hlimit = np->hop_limit; | 1139 | hlimit = np->hop_limit; |
@@ -1175,7 +1168,7 @@ do_append_data: | |||
1175 | up->len += ulen; | 1168 | up->len += ulen; |
1176 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; | 1169 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; |
1177 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, | 1170 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, |
1178 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, | 1171 | sizeof(struct udphdr), hlimit, tclass, opt, &fl6, |
1179 | (struct rt6_info*)dst, | 1172 | (struct rt6_info*)dst, |
1180 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); | 1173 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); |
1181 | if (err) | 1174 | if (err) |
@@ -1188,10 +1181,10 @@ do_append_data: | |||
1188 | if (dst) { | 1181 | if (dst) { |
1189 | if (connected) { | 1182 | if (connected) { |
1190 | ip6_dst_store(sk, dst, | 1183 | ip6_dst_store(sk, dst, |
1191 | ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ? | 1184 | ipv6_addr_equal(&fl6.daddr, &np->daddr) ? |
1192 | &np->daddr : NULL, | 1185 | &np->daddr : NULL, |
1193 | #ifdef CONFIG_IPV6_SUBTREES | 1186 | #ifdef CONFIG_IPV6_SUBTREES |
1194 | ipv6_addr_equal(&fl.fl6_src, &np->saddr) ? | 1187 | ipv6_addr_equal(&fl6.saddr, &np->saddr) ? |
1195 | &np->saddr : | 1188 | &np->saddr : |
1196 | #endif | 1189 | #endif |
1197 | NULL); | 1190 | NULL); |
@@ -1299,7 +1292,7 @@ static int udp6_ufo_send_check(struct sk_buff *skb) | |||
1299 | return 0; | 1292 | return 0; |
1300 | } | 1293 | } |
1301 | 1294 | ||
1302 | static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features) | 1295 | static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) |
1303 | { | 1296 | { |
1304 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 1297 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
1305 | unsigned int mss; | 1298 | unsigned int mss; |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 7e74023ea6e4..05e34c8ec913 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -27,18 +27,19 @@ | |||
27 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; | 27 | static struct xfrm_policy_afinfo xfrm6_policy_afinfo; |
28 | 28 | ||
29 | static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, | 29 | static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, |
30 | xfrm_address_t *saddr, | 30 | const xfrm_address_t *saddr, |
31 | xfrm_address_t *daddr) | 31 | const xfrm_address_t *daddr) |
32 | { | 32 | { |
33 | struct flowi fl = {}; | 33 | struct flowi6 fl6; |
34 | struct dst_entry *dst; | 34 | struct dst_entry *dst; |
35 | int err; | 35 | int err; |
36 | 36 | ||
37 | memcpy(&fl.fl6_dst, daddr, sizeof(fl.fl6_dst)); | 37 | memset(&fl6, 0, sizeof(fl6)); |
38 | memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr)); | ||
38 | if (saddr) | 39 | if (saddr) |
39 | memcpy(&fl.fl6_src, saddr, sizeof(fl.fl6_src)); | 40 | memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr)); |
40 | 41 | ||
41 | dst = ip6_route_output(net, NULL, &fl); | 42 | dst = ip6_route_output(net, NULL, &fl6); |
42 | 43 | ||
43 | err = dst->error; | 44 | err = dst->error; |
44 | if (dst->error) { | 45 | if (dst->error) { |
@@ -67,7 +68,7 @@ static int xfrm6_get_saddr(struct net *net, | |||
67 | return 0; | 68 | return 0; |
68 | } | 69 | } |
69 | 70 | ||
70 | static int xfrm6_get_tos(struct flowi *fl) | 71 | static int xfrm6_get_tos(const struct flowi *fl) |
71 | { | 72 | { |
72 | return 0; | 73 | return 0; |
73 | } | 74 | } |
@@ -87,7 +88,7 @@ static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, | |||
87 | } | 88 | } |
88 | 89 | ||
89 | static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | 90 | static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, |
90 | struct flowi *fl) | 91 | const struct flowi *fl) |
91 | { | 92 | { |
92 | struct rt6_info *rt = (struct rt6_info*)xdst->route; | 93 | struct rt6_info *rt = (struct rt6_info*)xdst->route; |
93 | 94 | ||
@@ -98,6 +99,10 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
98 | if (!xdst->u.rt6.rt6i_idev) | 99 | if (!xdst->u.rt6.rt6i_idev) |
99 | return -ENODEV; | 100 | return -ENODEV; |
100 | 101 | ||
102 | xdst->u.rt6.rt6i_peer = rt->rt6i_peer; | ||
103 | if (rt->rt6i_peer) | ||
104 | atomic_inc(&rt->rt6i_peer->refcnt); | ||
105 | |||
101 | /* Sheit... I remember I did this right. Apparently, | 106 | /* Sheit... I remember I did this right. Apparently, |
102 | * it was magically lost, so this code needs audit */ | 107 | * it was magically lost, so this code needs audit */ |
103 | xdst->u.rt6.rt6i_flags = rt->rt6i_flags & (RTF_ANYCAST | | 108 | xdst->u.rt6.rt6i_flags = rt->rt6i_flags & (RTF_ANYCAST | |
@@ -116,6 +121,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
116 | static inline void | 121 | static inline void |
117 | _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | 122 | _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) |
118 | { | 123 | { |
124 | struct flowi6 *fl6 = &fl->u.ip6; | ||
119 | int onlyproto = 0; | 125 | int onlyproto = 0; |
120 | u16 offset = skb_network_header_len(skb); | 126 | u16 offset = skb_network_header_len(skb); |
121 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 127 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
@@ -123,11 +129,11 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
123 | const unsigned char *nh = skb_network_header(skb); | 129 | const unsigned char *nh = skb_network_header(skb); |
124 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; | 130 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; |
125 | 131 | ||
126 | memset(fl, 0, sizeof(struct flowi)); | 132 | memset(fl6, 0, sizeof(struct flowi6)); |
127 | fl->mark = skb->mark; | 133 | fl6->flowi6_mark = skb->mark; |
128 | 134 | ||
129 | ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr); | 135 | ipv6_addr_copy(&fl6->daddr, reverse ? &hdr->saddr : &hdr->daddr); |
130 | ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr); | 136 | ipv6_addr_copy(&fl6->saddr, reverse ? &hdr->daddr : &hdr->saddr); |
131 | 137 | ||
132 | while (nh + offset + 1 < skb->data || | 138 | while (nh + offset + 1 < skb->data || |
133 | pskb_may_pull(skb, nh + offset + 1 - skb->data)) { | 139 | pskb_may_pull(skb, nh + offset + 1 - skb->data)) { |
@@ -154,20 +160,20 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
154 | pskb_may_pull(skb, nh + offset + 4 - skb->data))) { | 160 | pskb_may_pull(skb, nh + offset + 4 - skb->data))) { |
155 | __be16 *ports = (__be16 *)exthdr; | 161 | __be16 *ports = (__be16 *)exthdr; |
156 | 162 | ||
157 | fl->fl_ip_sport = ports[!!reverse]; | 163 | fl6->fl6_sport = ports[!!reverse]; |
158 | fl->fl_ip_dport = ports[!reverse]; | 164 | fl6->fl6_dport = ports[!reverse]; |
159 | } | 165 | } |
160 | fl->proto = nexthdr; | 166 | fl6->flowi6_proto = nexthdr; |
161 | return; | 167 | return; |
162 | 168 | ||
163 | case IPPROTO_ICMPV6: | 169 | case IPPROTO_ICMPV6: |
164 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) { | 170 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) { |
165 | u8 *icmp = (u8 *)exthdr; | 171 | u8 *icmp = (u8 *)exthdr; |
166 | 172 | ||
167 | fl->fl_icmp_type = icmp[0]; | 173 | fl6->fl6_icmp_type = icmp[0]; |
168 | fl->fl_icmp_code = icmp[1]; | 174 | fl6->fl6_icmp_code = icmp[1]; |
169 | } | 175 | } |
170 | fl->proto = nexthdr; | 176 | fl6->flowi6_proto = nexthdr; |
171 | return; | 177 | return; |
172 | 178 | ||
173 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 179 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
@@ -176,9 +182,9 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
176 | struct ip6_mh *mh; | 182 | struct ip6_mh *mh; |
177 | mh = (struct ip6_mh *)exthdr; | 183 | mh = (struct ip6_mh *)exthdr; |
178 | 184 | ||
179 | fl->fl_mh_type = mh->ip6mh_type; | 185 | fl6->fl6_mh_type = mh->ip6mh_type; |
180 | } | 186 | } |
181 | fl->proto = nexthdr; | 187 | fl6->flowi6_proto = nexthdr; |
182 | return; | 188 | return; |
183 | #endif | 189 | #endif |
184 | 190 | ||
@@ -187,8 +193,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
187 | case IPPROTO_ESP: | 193 | case IPPROTO_ESP: |
188 | case IPPROTO_COMP: | 194 | case IPPROTO_COMP: |
189 | default: | 195 | default: |
190 | fl->fl_ipsec_spi = 0; | 196 | fl6->fl6_ipsec_spi = 0; |
191 | fl->proto = nexthdr; | 197 | fl6->flowi6_proto = nexthdr; |
192 | return; | 198 | return; |
193 | } | 199 | } |
194 | } | 200 | } |
@@ -216,6 +222,9 @@ static void xfrm6_dst_destroy(struct dst_entry *dst) | |||
216 | 222 | ||
217 | if (likely(xdst->u.rt6.rt6i_idev)) | 223 | if (likely(xdst->u.rt6.rt6i_idev)) |
218 | in6_dev_put(xdst->u.rt6.rt6i_idev); | 224 | in6_dev_put(xdst->u.rt6.rt6i_idev); |
225 | dst_destroy_metrics_generic(dst); | ||
226 | if (likely(xdst->u.rt6.rt6i_peer)) | ||
227 | inet_putpeer(xdst->u.rt6.rt6i_peer); | ||
219 | xfrm_dst_destroy(xdst); | 228 | xfrm_dst_destroy(xdst); |
220 | } | 229 | } |
221 | 230 | ||
@@ -251,6 +260,7 @@ static struct dst_ops xfrm6_dst_ops = { | |||
251 | .protocol = cpu_to_be16(ETH_P_IPV6), | 260 | .protocol = cpu_to_be16(ETH_P_IPV6), |
252 | .gc = xfrm6_garbage_collect, | 261 | .gc = xfrm6_garbage_collect, |
253 | .update_pmtu = xfrm6_update_pmtu, | 262 | .update_pmtu = xfrm6_update_pmtu, |
263 | .cow_metrics = dst_cow_metrics_generic, | ||
254 | .destroy = xfrm6_dst_destroy, | 264 | .destroy = xfrm6_dst_destroy, |
255 | .ifdown = xfrm6_dst_ifdown, | 265 | .ifdown = xfrm6_dst_ifdown, |
256 | .local_out = __ip6_local_out, | 266 | .local_out = __ip6_local_out, |
@@ -266,6 +276,7 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { | |||
266 | .get_tos = xfrm6_get_tos, | 276 | .get_tos = xfrm6_get_tos, |
267 | .init_path = xfrm6_init_path, | 277 | .init_path = xfrm6_init_path, |
268 | .fill_dst = xfrm6_fill_dst, | 278 | .fill_dst = xfrm6_fill_dst, |
279 | .blackhole_route = ip6_blackhole_route, | ||
269 | }; | 280 | }; |
270 | 281 | ||
271 | static int __init xfrm6_policy_init(void) | 282 | static int __init xfrm6_policy_init(void) |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index a67575d472a3..afe941e9415c 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -20,26 +20,28 @@ | |||
20 | #include <net/addrconf.h> | 20 | #include <net/addrconf.h> |
21 | 21 | ||
22 | static void | 22 | static void |
23 | __xfrm6_init_tempsel(struct xfrm_selector *sel, struct flowi *fl) | 23 | __xfrm6_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl) |
24 | { | 24 | { |
25 | const struct flowi6 *fl6 = &fl->u.ip6; | ||
26 | |||
25 | /* Initialize temporary selector matching only | 27 | /* Initialize temporary selector matching only |
26 | * to current session. */ | 28 | * to current session. */ |
27 | ipv6_addr_copy((struct in6_addr *)&sel->daddr, &fl->fl6_dst); | 29 | ipv6_addr_copy((struct in6_addr *)&sel->daddr, &fl6->daddr); |
28 | ipv6_addr_copy((struct in6_addr *)&sel->saddr, &fl->fl6_src); | 30 | ipv6_addr_copy((struct in6_addr *)&sel->saddr, &fl6->saddr); |
29 | sel->dport = xfrm_flowi_dport(fl); | 31 | sel->dport = xfrm_flowi_dport(fl, &fl6->uli); |
30 | sel->dport_mask = htons(0xffff); | 32 | sel->dport_mask = htons(0xffff); |
31 | sel->sport = xfrm_flowi_sport(fl); | 33 | sel->sport = xfrm_flowi_sport(fl, &fl6->uli); |
32 | sel->sport_mask = htons(0xffff); | 34 | sel->sport_mask = htons(0xffff); |
33 | sel->family = AF_INET6; | 35 | sel->family = AF_INET6; |
34 | sel->prefixlen_d = 128; | 36 | sel->prefixlen_d = 128; |
35 | sel->prefixlen_s = 128; | 37 | sel->prefixlen_s = 128; |
36 | sel->proto = fl->proto; | 38 | sel->proto = fl6->flowi6_proto; |
37 | sel->ifindex = fl->oif; | 39 | sel->ifindex = fl6->flowi6_oif; |
38 | } | 40 | } |
39 | 41 | ||
40 | static void | 42 | static void |
41 | xfrm6_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl, | 43 | xfrm6_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl, |
42 | xfrm_address_t *daddr, xfrm_address_t *saddr) | 44 | const xfrm_address_t *daddr, const xfrm_address_t *saddr) |
43 | { | 45 | { |
44 | x->id = tmpl->id; | 46 | x->id = tmpl->id; |
45 | if (ipv6_addr_any((struct in6_addr*)&x->id.daddr)) | 47 | if (ipv6_addr_any((struct in6_addr*)&x->id.daddr)) |