@@ -64,16 +64,65 @@ static void ip6_datagram_flow_key_init(struct flowi6 *fl6, struct sock *sk)
64
64
security_sk_classify_flow (sk , flowi6_to_flowi (fl6 ));
65
65
}
66
66
67
+ static int ip6_datagram_dst_update (struct sock * sk )
68
+ {
69
+ struct ip6_flowlabel * flowlabel = NULL ;
70
+ struct in6_addr * final_p , final ;
71
+ struct ipv6_txoptions * opt ;
72
+ struct dst_entry * dst ;
73
+ struct inet_sock * inet = inet_sk (sk );
74
+ struct ipv6_pinfo * np = inet6_sk (sk );
75
+ struct flowi6 fl6 ;
76
+ int err = 0 ;
77
+
78
+ if (np -> sndflow && (np -> flow_label & IPV6_FLOWLABEL_MASK )) {
79
+ flowlabel = fl6_sock_lookup (sk , np -> flow_label );
80
+ if (!flowlabel )
81
+ return - EINVAL ;
82
+ }
83
+ ip6_datagram_flow_key_init (& fl6 , sk );
84
+
85
+ rcu_read_lock ();
86
+ opt = flowlabel ? flowlabel -> opt : rcu_dereference (np -> opt );
87
+ final_p = fl6_update_dst (& fl6 , opt , & final );
88
+ rcu_read_unlock ();
89
+
90
+ dst = ip6_dst_lookup_flow (sk , & fl6 , final_p );
91
+ if (IS_ERR (dst )) {
92
+ err = PTR_ERR (dst );
93
+ goto out ;
94
+ }
95
+
96
+ if (ipv6_addr_any (& np -> saddr ))
97
+ np -> saddr = fl6 .saddr ;
98
+
99
+ if (ipv6_addr_any (& sk -> sk_v6_rcv_saddr )) {
100
+ sk -> sk_v6_rcv_saddr = fl6 .saddr ;
101
+ inet -> inet_rcv_saddr = LOOPBACK4_IPV6 ;
102
+ if (sk -> sk_prot -> rehash )
103
+ sk -> sk_prot -> rehash (sk );
104
+ }
105
+
106
+ ip6_dst_store (sk , dst ,
107
+ ipv6_addr_equal (& fl6 .daddr , & sk -> sk_v6_daddr ) ?
108
+ & sk -> sk_v6_daddr : NULL ,
109
+ #ifdef CONFIG_IPV6_SUBTREES
110
+ ipv6_addr_equal (& fl6 .saddr , & np -> saddr ) ?
111
+ & np -> saddr :
112
+ #endif
113
+ NULL );
114
+
115
+ out :
116
+ fl6_sock_release (flowlabel );
117
+ return err ;
118
+ }
119
+
67
120
static int __ip6_datagram_connect (struct sock * sk , struct sockaddr * uaddr , int addr_len )
68
121
{
69
122
struct sockaddr_in6 * usin = (struct sockaddr_in6 * ) uaddr ;
70
123
struct inet_sock * inet = inet_sk (sk );
71
124
struct ipv6_pinfo * np = inet6_sk (sk );
72
- struct in6_addr * daddr , * final_p , final ;
73
- struct dst_entry * dst ;
74
- struct flowi6 fl6 ;
75
- struct ip6_flowlabel * flowlabel = NULL ;
76
- struct ipv6_txoptions * opt ;
125
+ struct in6_addr * daddr ;
77
126
int addr_type ;
78
127
int err ;
79
128
__be32 fl6_flowlabel = 0 ;
@@ -91,14 +140,8 @@ static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int a
91
140
if (usin -> sin6_family != AF_INET6 )
92
141
return - EAFNOSUPPORT ;
93
142
94
- if (np -> sndflow ) {
143
+ if (np -> sndflow )
95
144
fl6_flowlabel = usin -> sin6_flowinfo & IPV6_FLOWINFO_MASK ;
96
- if (fl6_flowlabel & IPV6_FLOWLABEL_MASK ) {
97
- flowlabel = fl6_sock_lookup (sk , fl6_flowlabel );
98
- if (!flowlabel )
99
- return - EINVAL ;
100
- }
101
- }
102
145
103
146
addr_type = ipv6_addr_type (& usin -> sin6_addr );
104
147
@@ -178,45 +221,13 @@ static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int a
178
221
* destination cache for it.
179
222
*/
180
223
181
- ip6_datagram_flow_key_init (& fl6 , sk );
182
-
183
- rcu_read_lock ();
184
- opt = flowlabel ? flowlabel -> opt : rcu_dereference (np -> opt );
185
- final_p = fl6_update_dst (& fl6 , opt , & final );
186
- rcu_read_unlock ();
187
-
188
- dst = ip6_dst_lookup_flow (sk , & fl6 , final_p );
189
- err = 0 ;
190
- if (IS_ERR (dst )) {
191
- err = PTR_ERR (dst );
224
+ err = ip6_datagram_dst_update (sk );
225
+ if (err )
192
226
goto out ;
193
- }
194
-
195
- /* source address lookup done in ip6_dst_lookup */
196
-
197
- if (ipv6_addr_any (& np -> saddr ))
198
- np -> saddr = fl6 .saddr ;
199
-
200
- if (ipv6_addr_any (& sk -> sk_v6_rcv_saddr )) {
201
- sk -> sk_v6_rcv_saddr = fl6 .saddr ;
202
- inet -> inet_rcv_saddr = LOOPBACK4_IPV6 ;
203
- if (sk -> sk_prot -> rehash )
204
- sk -> sk_prot -> rehash (sk );
205
- }
206
-
207
- ip6_dst_store (sk , dst ,
208
- ipv6_addr_equal (& fl6 .daddr , & sk -> sk_v6_daddr ) ?
209
- & sk -> sk_v6_daddr : NULL ,
210
- #ifdef CONFIG_IPV6_SUBTREES
211
- ipv6_addr_equal (& fl6 .saddr , & np -> saddr ) ?
212
- & np -> saddr :
213
- #endif
214
- NULL );
215
227
216
228
sk -> sk_state = TCP_ESTABLISHED ;
217
229
sk_set_txhash (sk );
218
230
out :
219
- fl6_sock_release (flowlabel );
220
231
return err ;
221
232
}
222
233
0 commit comments