diff options
Diffstat (limited to 'net/ipv6/datagram.c')
-rw-r--r-- | net/ipv6/datagram.c | 88 |
1 files changed, 41 insertions, 47 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 320bdb877ee..16560336eb7 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: |