diff options
-rw-r--r-- | include/net/ipv6.h | 4 | ||||
-rw-r--r-- | net/dccp/ipv6.c | 30 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 9 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 18 | ||||
-rw-r--r-- | net/ipv6/exthdrs.c | 24 | ||||
-rw-r--r-- | net/ipv6/inet6_connection_sock.c | 9 | ||||
-rw-r--r-- | net/ipv6/raw.c | 10 | ||||
-rw-r--r-- | net/ipv6/syncookies.c | 9 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 27 | ||||
-rw-r--r-- | net/ipv6/udp.c | 11 |
10 files changed, 55 insertions, 96 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 2600b69757b8..f5808d596aab 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -551,6 +551,10 @@ extern int ipv6_ext_hdr(u8 nexthdr); | |||
551 | 551 | ||
552 | extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type); | 552 | extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type); |
553 | 553 | ||
554 | extern struct in6_addr *fl6_update_dst(struct flowi *fl, | ||
555 | const struct ipv6_txoptions *opt, | ||
556 | struct in6_addr *orig); | ||
557 | |||
554 | /* | 558 | /* |
555 | * socket options (ipv6_sockglue.c) | 559 | * socket options (ipv6_sockglue.c) |
556 | */ | 560 | */ |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 091698899594..6e3f32575df7 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -248,7 +248,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, | |||
248 | struct ipv6_pinfo *np = inet6_sk(sk); | 248 | struct ipv6_pinfo *np = inet6_sk(sk); |
249 | struct sk_buff *skb; | 249 | struct sk_buff *skb; |
250 | struct ipv6_txoptions *opt = NULL; | 250 | struct ipv6_txoptions *opt = NULL; |
251 | struct in6_addr *final_p = NULL, final; | 251 | struct in6_addr *final_p, final; |
252 | struct flowi fl; | 252 | struct flowi fl; |
253 | int err = -1; | 253 | int err = -1; |
254 | struct dst_entry *dst; | 254 | struct dst_entry *dst; |
@@ -265,13 +265,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, | |||
265 | 265 | ||
266 | opt = np->opt; | 266 | opt = np->opt; |
267 | 267 | ||
268 | if (opt != NULL && opt->srcrt != NULL) { | 268 | final_p = fl6_update_dst(&fl, opt, &final); |
269 | const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; | ||
270 | |||
271 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
272 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
273 | final_p = &final; | ||
274 | } | ||
275 | 269 | ||
276 | err = ip6_dst_lookup(sk, &dst, &fl); | 270 | err = ip6_dst_lookup(sk, &dst, &fl); |
277 | if (err) | 271 | if (err) |
@@ -545,19 +539,13 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, | |||
545 | goto out_overflow; | 539 | goto out_overflow; |
546 | 540 | ||
547 | if (dst == NULL) { | 541 | if (dst == NULL) { |
548 | struct in6_addr *final_p = NULL, final; | 542 | struct in6_addr *final_p, final; |
549 | struct flowi fl; | 543 | struct flowi fl; |
550 | 544 | ||
551 | memset(&fl, 0, sizeof(fl)); | 545 | memset(&fl, 0, sizeof(fl)); |
552 | fl.proto = IPPROTO_DCCP; | 546 | fl.proto = IPPROTO_DCCP; |
553 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); | 547 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); |
554 | if (opt != NULL && opt->srcrt != NULL) { | 548 | final_p = fl6_update_dst(&fl, opt, &final); |
555 | const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt; | ||
556 | |||
557 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
558 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
559 | final_p = &final; | ||
560 | } | ||
561 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); | 549 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); |
562 | fl.oif = sk->sk_bound_dev_if; | 550 | fl.oif = sk->sk_bound_dev_if; |
563 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; | 551 | fl.fl_ip_dport = inet_rsk(req)->rmt_port; |
@@ -885,7 +873,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
885 | struct inet_sock *inet = inet_sk(sk); | 873 | struct inet_sock *inet = inet_sk(sk); |
886 | struct ipv6_pinfo *np = inet6_sk(sk); | 874 | struct ipv6_pinfo *np = inet6_sk(sk); |
887 | struct dccp_sock *dp = dccp_sk(sk); | 875 | struct dccp_sock *dp = dccp_sk(sk); |
888 | struct in6_addr *saddr = NULL, *final_p = NULL, final; | 876 | struct in6_addr *saddr = NULL, *final_p, final; |
889 | struct flowi fl; | 877 | struct flowi fl; |
890 | struct dst_entry *dst; | 878 | struct dst_entry *dst; |
891 | int addr_type; | 879 | int addr_type; |
@@ -988,13 +976,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
988 | fl.fl_ip_sport = inet->inet_sport; | 976 | fl.fl_ip_sport = inet->inet_sport; |
989 | security_sk_classify_flow(sk, &fl); | 977 | security_sk_classify_flow(sk, &fl); |
990 | 978 | ||
991 | if (np->opt != NULL && np->opt->srcrt != NULL) { | 979 | final_p = fl6_update_dst(&fl, np->opt, &final); |
992 | const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; | ||
993 | |||
994 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
995 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
996 | final_p = &final; | ||
997 | } | ||
998 | 980 | ||
999 | err = ip6_dst_lookup(sk, &dst, &fl); | 981 | err = ip6_dst_lookup(sk, &dst, &fl); |
1000 | if (err) | 982 | if (err) |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e733942dafe1..94b1b9c954bf 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -651,7 +651,7 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
651 | 651 | ||
652 | if (dst == NULL) { | 652 | if (dst == NULL) { |
653 | struct inet_sock *inet = inet_sk(sk); | 653 | struct inet_sock *inet = inet_sk(sk); |
654 | struct in6_addr *final_p = NULL, final; | 654 | struct in6_addr *final_p, final; |
655 | struct flowi fl; | 655 | struct flowi fl; |
656 | 656 | ||
657 | memset(&fl, 0, sizeof(fl)); | 657 | memset(&fl, 0, sizeof(fl)); |
@@ -665,12 +665,7 @@ int inet6_sk_rebuild_header(struct sock *sk) | |||
665 | fl.fl_ip_sport = inet->inet_sport; | 665 | fl.fl_ip_sport = inet->inet_sport; |
666 | security_sk_classify_flow(sk, &fl); | 666 | security_sk_classify_flow(sk, &fl); |
667 | 667 | ||
668 | if (np->opt && np->opt->srcrt) { | 668 | final_p = fl6_update_dst(&fl, np->opt, &final); |
669 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; | ||
670 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
671 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
672 | final_p = &final; | ||
673 | } | ||
674 | 669 | ||
675 | err = ip6_dst_lookup(sk, &dst, &fl); | 670 | err = ip6_dst_lookup(sk, &dst, &fl); |
676 | if (err) { | 671 | if (err) { |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 712684687c9a..7d929a22cbc2 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -38,10 +38,11 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
38 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; | 38 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; |
39 | struct inet_sock *inet = inet_sk(sk); | 39 | struct inet_sock *inet = inet_sk(sk); |
40 | struct ipv6_pinfo *np = inet6_sk(sk); | 40 | struct ipv6_pinfo *np = inet6_sk(sk); |
41 | struct in6_addr *daddr, *final_p = NULL, final; | 41 | struct in6_addr *daddr, *final_p, final; |
42 | struct dst_entry *dst; | 42 | struct dst_entry *dst; |
43 | struct flowi fl; | 43 | struct flowi fl; |
44 | struct ip6_flowlabel *flowlabel = NULL; | 44 | struct ip6_flowlabel *flowlabel = NULL; |
45 | struct ipv6_txoptions *opt; | ||
45 | int addr_type; | 46 | int addr_type; |
46 | int err; | 47 | int err; |
47 | 48 | ||
@@ -155,19 +156,8 @@ ipv4_connected: | |||
155 | 156 | ||
156 | security_sk_classify_flow(sk, &fl); | 157 | security_sk_classify_flow(sk, &fl); |
157 | 158 | ||
158 | if (flowlabel) { | 159 | opt = flowlabel ? flowlabel->opt : np->opt; |
159 | if (flowlabel->opt && flowlabel->opt->srcrt) { | 160 | final_p = fl6_update_dst(&fl, opt, &final); |
160 | struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; | ||
161 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
162 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
163 | final_p = &final; | ||
164 | } | ||
165 | } else if (np->opt && np->opt->srcrt) { | ||
166 | struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; | ||
167 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
168 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
169 | final_p = &final; | ||
170 | } | ||
171 | 161 | ||
172 | err = ip6_dst_lookup(sk, &dst, &fl); | 162 | err = ip6_dst_lookup(sk, &dst, &fl); |
173 | if (err) | 163 | if (err) |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 8a659f92d17a..853a633a94d4 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -874,3 +874,27 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space, | |||
874 | return opt; | 874 | return opt; |
875 | } | 875 | } |
876 | 876 | ||
877 | /** | ||
878 | * fl6_update_dst - update flowi destination address with info given | ||
879 | * by srcrt option, if any. | ||
880 | * | ||
881 | * @fl: flowi for which fl6_dst is to be updated | ||
882 | * @opt: struct ipv6_txoptions in which to look for srcrt opt | ||
883 | * @orig: copy of original fl6_dst address if modified | ||
884 | * | ||
885 | * Returns NULL if no txoptions or no srcrt, otherwise returns orig | ||
886 | * and initial value of fl->fl6_dst set in orig | ||
887 | */ | ||
888 | struct in6_addr *fl6_update_dst(struct flowi *fl, | ||
889 | const struct ipv6_txoptions *opt, | ||
890 | struct in6_addr *orig) | ||
891 | { | ||
892 | if (!opt || !opt->srcrt) | ||
893 | return NULL; | ||
894 | |||
895 | ipv6_addr_copy(orig, &fl->fl6_dst); | ||
896 | ipv6_addr_copy(&fl->fl6_dst, ((struct rt0_hdr *)opt->srcrt)->addr); | ||
897 | return orig; | ||
898 | } | ||
899 | |||
900 | EXPORT_SYMBOL_GPL(fl6_update_dst); | ||
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 0c5e3c3b7fd5..8a1628023bd1 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -185,7 +185,7 @@ int inet6_csk_xmit(struct sk_buff *skb) | |||
185 | struct ipv6_pinfo *np = inet6_sk(sk); | 185 | struct ipv6_pinfo *np = inet6_sk(sk); |
186 | struct flowi fl; | 186 | struct flowi fl; |
187 | struct dst_entry *dst; | 187 | struct dst_entry *dst; |
188 | struct in6_addr *final_p = NULL, final; | 188 | struct in6_addr *final_p, final; |
189 | 189 | ||
190 | memset(&fl, 0, sizeof(fl)); | 190 | memset(&fl, 0, sizeof(fl)); |
191 | fl.proto = sk->sk_protocol; | 191 | fl.proto = sk->sk_protocol; |
@@ -199,12 +199,7 @@ int inet6_csk_xmit(struct sk_buff *skb) | |||
199 | fl.fl_ip_dport = inet->inet_dport; | 199 | fl.fl_ip_dport = inet->inet_dport; |
200 | security_sk_classify_flow(sk, &fl); | 200 | security_sk_classify_flow(sk, &fl); |
201 | 201 | ||
202 | if (np->opt && np->opt->srcrt) { | 202 | final_p = fl6_update_dst(&fl, np->opt, &final); |
203 | struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; | ||
204 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
205 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
206 | final_p = &final; | ||
207 | } | ||
208 | 203 | ||
209 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); | 204 | dst = __inet6_csk_dst_check(sk, np->dst_cookie); |
210 | 205 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 4a4dcbe4f8b2..864eb8e03b1b 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -725,7 +725,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
725 | { | 725 | { |
726 | struct ipv6_txoptions opt_space; | 726 | struct ipv6_txoptions opt_space; |
727 | struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; | 727 | struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; |
728 | struct in6_addr *daddr, *final_p = NULL, final; | 728 | struct in6_addr *daddr, *final_p, final; |
729 | struct inet_sock *inet = inet_sk(sk); | 729 | struct inet_sock *inet = inet_sk(sk); |
730 | struct ipv6_pinfo *np = inet6_sk(sk); | 730 | struct ipv6_pinfo *np = inet6_sk(sk); |
731 | struct raw6_sock *rp = raw6_sk(sk); | 731 | struct raw6_sock *rp = raw6_sk(sk); |
@@ -847,13 +847,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
847 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 847 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
848 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 848 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
849 | 849 | ||
850 | /* merge ip6_build_xmit from ip6_output */ | 850 | final_p = fl6_update_dst(&fl, opt, &final); |
851 | if (opt && opt->srcrt) { | ||
852 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
853 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
854 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
855 | final_p = &final; | ||
856 | } | ||
857 | 851 | ||
858 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 852 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) |
859 | fl.oif = np->mcast_oif; | 853 | fl.oif = np->mcast_oif; |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 34d1f0690d7e..12383705dbad 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -240,17 +240,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
240 | * me if there is a preferred way. | 240 | * me if there is a preferred way. |
241 | */ | 241 | */ |
242 | { | 242 | { |
243 | struct in6_addr *final_p = NULL, final; | 243 | struct in6_addr *final_p, final; |
244 | struct flowi fl; | 244 | struct flowi fl; |
245 | memset(&fl, 0, sizeof(fl)); | 245 | memset(&fl, 0, sizeof(fl)); |
246 | fl.proto = IPPROTO_TCP; | 246 | fl.proto = IPPROTO_TCP; |
247 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); | 247 | ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); |
248 | if (np->opt && np->opt->srcrt) { | 248 | final_p = fl6_update_dst(&fl, np->opt, &final); |
249 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; | ||
250 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
251 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
252 | final_p = &final; | ||
253 | } | ||
254 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); | 249 | ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr); |
255 | fl.oif = sk->sk_bound_dev_if; | 250 | fl.oif = sk->sk_bound_dev_if; |
256 | fl.mark = sk->sk_mark; | 251 | fl.mark = sk->sk_mark; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 2b7c3a100e2c..e487080d02db 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -129,7 +129,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
129 | struct inet_connection_sock *icsk = inet_csk(sk); | 129 | struct inet_connection_sock *icsk = inet_csk(sk); |
130 | struct ipv6_pinfo *np = inet6_sk(sk); | 130 | struct ipv6_pinfo *np = inet6_sk(sk); |
131 | struct tcp_sock *tp = tcp_sk(sk); | 131 | struct tcp_sock *tp = tcp_sk(sk); |
132 | struct in6_addr *saddr = NULL, *final_p = NULL, final; | 132 | struct in6_addr *saddr = NULL, *final_p, final; |
133 | struct flowi fl; | 133 | struct flowi fl; |
134 | struct dst_entry *dst; | 134 | struct dst_entry *dst; |
135 | int addr_type; | 135 | int addr_type; |
@@ -250,12 +250,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
250 | fl.fl_ip_dport = usin->sin6_port; | 250 | fl.fl_ip_dport = usin->sin6_port; |
251 | fl.fl_ip_sport = inet->inet_sport; | 251 | fl.fl_ip_sport = inet->inet_sport; |
252 | 252 | ||
253 | if (np->opt && np->opt->srcrt) { | 253 | final_p = fl6_update_dst(&fl, np->opt, &final); |
254 | struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; | ||
255 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
256 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
257 | final_p = &final; | ||
258 | } | ||
259 | 254 | ||
260 | security_sk_classify_flow(sk, &fl); | 255 | security_sk_classify_flow(sk, &fl); |
261 | 256 | ||
@@ -477,7 +472,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
477 | struct ipv6_pinfo *np = inet6_sk(sk); | 472 | struct ipv6_pinfo *np = inet6_sk(sk); |
478 | struct sk_buff * skb; | 473 | struct sk_buff * skb; |
479 | struct ipv6_txoptions *opt = NULL; | 474 | struct ipv6_txoptions *opt = NULL; |
480 | struct in6_addr * final_p = NULL, final; | 475 | struct in6_addr * final_p, final; |
481 | struct flowi fl; | 476 | struct flowi fl; |
482 | struct dst_entry *dst; | 477 | struct dst_entry *dst; |
483 | int err = -1; | 478 | int err = -1; |
@@ -494,12 +489,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
494 | security_req_classify_flow(req, &fl); | 489 | security_req_classify_flow(req, &fl); |
495 | 490 | ||
496 | opt = np->opt; | 491 | opt = np->opt; |
497 | if (opt && opt->srcrt) { | 492 | final_p = fl6_update_dst(&fl, opt, &final); |
498 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
499 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
500 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
501 | final_p = &final; | ||
502 | } | ||
503 | 493 | ||
504 | err = ip6_dst_lookup(sk, &dst, &fl); | 494 | err = ip6_dst_lookup(sk, &dst, &fl); |
505 | if (err) | 495 | if (err) |
@@ -1392,18 +1382,13 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1392 | goto out_overflow; | 1382 | goto out_overflow; |
1393 | 1383 | ||
1394 | if (dst == NULL) { | 1384 | if (dst == NULL) { |
1395 | struct in6_addr *final_p = NULL, final; | 1385 | struct in6_addr *final_p, final; |
1396 | struct flowi fl; | 1386 | struct flowi fl; |
1397 | 1387 | ||
1398 | memset(&fl, 0, sizeof(fl)); | 1388 | memset(&fl, 0, sizeof(fl)); |
1399 | fl.proto = IPPROTO_TCP; | 1389 | fl.proto = IPPROTO_TCP; |
1400 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | 1390 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); |
1401 | if (opt && opt->srcrt) { | 1391 | final_p = fl6_update_dst(&fl, opt, &final); |
1402 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
1403 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
1404 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
1405 | final_p = &final; | ||
1406 | } | ||
1407 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); | 1392 | ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr); |
1408 | fl.oif = sk->sk_bound_dev_if; | 1393 | fl.oif = sk->sk_bound_dev_if; |
1409 | fl.mark = sk->sk_mark; | 1394 | fl.mark = sk->sk_mark; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 3048f906c042..4aea57dec75f 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -929,7 +929,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
929 | struct inet_sock *inet = inet_sk(sk); | 929 | struct inet_sock *inet = inet_sk(sk); |
930 | struct ipv6_pinfo *np = inet6_sk(sk); | 930 | struct ipv6_pinfo *np = inet6_sk(sk); |
931 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; | 931 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; |
932 | struct in6_addr *daddr, *final_p = NULL, final; | 932 | struct in6_addr *daddr, *final_p, final; |
933 | struct ipv6_txoptions *opt = NULL; | 933 | struct ipv6_txoptions *opt = NULL; |
934 | struct ip6_flowlabel *flowlabel = NULL; | 934 | struct ip6_flowlabel *flowlabel = NULL; |
935 | struct flowi fl; | 935 | struct flowi fl; |
@@ -1099,14 +1099,9 @@ do_udp_sendmsg: | |||
1099 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 1099 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
1100 | fl.fl_ip_sport = inet->inet_sport; | 1100 | fl.fl_ip_sport = inet->inet_sport; |
1101 | 1101 | ||
1102 | /* merge ip6_build_xmit from ip6_output */ | 1102 | final_p = fl6_update_dst(&fl, opt, &final); |
1103 | if (opt && opt->srcrt) { | 1103 | if (final_p) |
1104 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
1105 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
1106 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
1107 | final_p = &final; | ||
1108 | connected = 0; | 1104 | connected = 0; |
1109 | } | ||
1110 | 1105 | ||
1111 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { | 1106 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { |
1112 | fl.oif = np->mcast_oif; | 1107 | fl.oif = np->mcast_oif; |