@@ -129,7 +129,7 @@ static void udp_v6_rehash(struct sock *sk)
129
129
static int compute_score (struct sock * sk , struct net * net ,
130
130
const struct in6_addr * saddr , __be16 sport ,
131
131
const struct in6_addr * daddr , unsigned short hnum ,
132
- int dif , bool exact_dif )
132
+ int dif , int sdif , bool exact_dif )
133
133
{
134
134
int score ;
135
135
struct inet_sock * inet ;
@@ -161,9 +161,13 @@ static int compute_score(struct sock *sk, struct net *net,
161
161
}
162
162
163
163
if (sk -> sk_bound_dev_if || exact_dif ) {
164
- if (sk -> sk_bound_dev_if != dif )
164
+ bool dev_match = (sk -> sk_bound_dev_if == dif ||
165
+ sk -> sk_bound_dev_if == sdif );
166
+
167
+ if (exact_dif && !dev_match )
165
168
return -1 ;
166
- score ++ ;
169
+ if (sk -> sk_bound_dev_if && dev_match )
170
+ score ++ ;
167
171
}
168
172
169
173
if (sk -> sk_incoming_cpu == raw_smp_processor_id ())
@@ -175,9 +179,9 @@ static int compute_score(struct sock *sk, struct net *net,
175
179
/* called with rcu_read_lock() */
176
180
static struct sock * udp6_lib_lookup2 (struct net * net ,
177
181
const struct in6_addr * saddr , __be16 sport ,
178
- const struct in6_addr * daddr , unsigned int hnum , int dif ,
179
- bool exact_dif , struct udp_hslot * hslot2 ,
180
- struct sk_buff * skb )
182
+ const struct in6_addr * daddr , unsigned int hnum ,
183
+ int dif , int sdif , bool exact_dif ,
184
+ struct udp_hslot * hslot2 , struct sk_buff * skb )
181
185
{
182
186
struct sock * sk , * result ;
183
187
int score , badness , matches = 0 , reuseport = 0 ;
@@ -187,7 +191,7 @@ static struct sock *udp6_lib_lookup2(struct net *net,
187
191
badness = -1 ;
188
192
udp_portaddr_for_each_entry_rcu (sk , & hslot2 -> head ) {
189
193
score = compute_score (sk , net , saddr , sport ,
190
- daddr , hnum , dif , exact_dif );
194
+ daddr , hnum , dif , sdif , exact_dif );
191
195
if (score > badness ) {
192
196
reuseport = sk -> sk_reuseport ;
193
197
if (reuseport ) {
@@ -214,10 +218,10 @@ static struct sock *udp6_lib_lookup2(struct net *net,
214
218
215
219
/* rcu_read_lock() must be held */
216
220
struct sock * __udp6_lib_lookup (struct net * net ,
217
- const struct in6_addr * saddr , __be16 sport ,
218
- const struct in6_addr * daddr , __be16 dport ,
219
- int dif , struct udp_table * udptable ,
220
- struct sk_buff * skb )
221
+ const struct in6_addr * saddr , __be16 sport ,
222
+ const struct in6_addr * daddr , __be16 dport ,
223
+ int dif , int sdif , struct udp_table * udptable ,
224
+ struct sk_buff * skb )
221
225
{
222
226
struct sock * sk , * result ;
223
227
unsigned short hnum = ntohs (dport );
@@ -235,7 +239,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
235
239
goto begin ;
236
240
237
241
result = udp6_lib_lookup2 (net , saddr , sport ,
238
- daddr , hnum , dif , exact_dif ,
242
+ daddr , hnum , dif , sdif , exact_dif ,
239
243
hslot2 , skb );
240
244
if (!result ) {
241
245
unsigned int old_slot2 = slot2 ;
@@ -250,7 +254,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
250
254
goto begin ;
251
255
252
256
result = udp6_lib_lookup2 (net , saddr , sport ,
253
- daddr , hnum , dif ,
257
+ daddr , hnum , dif , sdif ,
254
258
exact_dif , hslot2 ,
255
259
skb );
256
260
}
@@ -261,7 +265,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
261
265
badness = -1 ;
262
266
sk_for_each_rcu (sk , & hslot -> head ) {
263
267
score = compute_score (sk , net , saddr , sport , daddr , hnum , dif ,
264
- exact_dif );
268
+ sdif , exact_dif );
265
269
if (score > badness ) {
266
270
reuseport = sk -> sk_reuseport ;
267
271
if (reuseport ) {
@@ -294,7 +298,7 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
294
298
295
299
return __udp6_lib_lookup (dev_net (skb -> dev ), & iph -> saddr , sport ,
296
300
& iph -> daddr , dport , inet6_iif (skb ),
297
- udptable , skb );
301
+ inet6_sdif ( skb ), udptable , skb );
298
302
}
299
303
300
304
struct sock * udp6_lib_lookup_skb (struct sk_buff * skb ,
@@ -304,7 +308,7 @@ struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
304
308
305
309
return __udp6_lib_lookup (dev_net (skb -> dev ), & iph -> saddr , sport ,
306
310
& iph -> daddr , dport , inet6_iif (skb ),
307
- & udp_table , skb );
311
+ inet6_sdif ( skb ), & udp_table , skb );
308
312
}
309
313
EXPORT_SYMBOL_GPL (udp6_lib_lookup_skb );
310
314
@@ -320,7 +324,7 @@ struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be
320
324
struct sock * sk ;
321
325
322
326
sk = __udp6_lib_lookup (net , saddr , sport , daddr , dport ,
323
- dif , & udp_table , NULL );
327
+ dif , 0 , & udp_table , NULL );
324
328
if (sk && !refcount_inc_not_zero (& sk -> sk_refcnt ))
325
329
sk = NULL ;
326
330
return sk ;
@@ -501,7 +505,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
501
505
struct net * net = dev_net (skb -> dev );
502
506
503
507
sk = __udp6_lib_lookup (net , daddr , uh -> dest , saddr , uh -> source ,
504
- inet6_iif (skb ), udptable , skb );
508
+ inet6_iif (skb ), 0 , udptable , skb );
505
509
if (!sk ) {
506
510
__ICMP6_INC_STATS (net , __in6_dev_get (skb -> dev ),
507
511
ICMP6_MIB_INERRORS );
0 commit comments