@@ -1252,13 +1252,10 @@ static void xfrm_hash_rebuild(struct work_struct *work)
1252
1252
{
1253
1253
struct net * net = container_of (work , struct net ,
1254
1254
xfrm .policy_hthresh .work );
1255
- unsigned int hmask ;
1256
1255
struct xfrm_policy * pol ;
1257
1256
struct xfrm_policy * policy ;
1258
1257
struct hlist_head * chain ;
1259
- struct hlist_head * odst ;
1260
1258
struct hlist_node * newpos ;
1261
- int i ;
1262
1259
int dir ;
1263
1260
unsigned seq ;
1264
1261
u8 lbits4 , rbits4 , lbits6 , rbits6 ;
@@ -1322,23 +1319,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
1322
1319
goto out_unlock ;
1323
1320
}
1324
1321
1325
- /* reset the bydst and inexact table in all directions */
1326
1322
for (dir = 0 ; dir < XFRM_POLICY_MAX ; dir ++ ) {
1327
- struct hlist_node * n ;
1328
-
1329
- hlist_for_each_entry_safe (policy , n ,
1330
- & net -> xfrm .policy_inexact [dir ],
1331
- bydst_inexact_list ) {
1332
- hlist_del_rcu (& policy -> bydst );
1333
- hlist_del_init (& policy -> bydst_inexact_list );
1334
- }
1335
-
1336
- hmask = net -> xfrm .policy_bydst [dir ].hmask ;
1337
- odst = net -> xfrm .policy_bydst [dir ].table ;
1338
- for (i = hmask ; i >= 0 ; i -- ) {
1339
- hlist_for_each_entry_safe (policy , n , odst + i , bydst )
1340
- hlist_del_rcu (& policy -> bydst );
1341
- }
1342
1323
if ((dir & XFRM_POLICY_MASK ) == XFRM_POLICY_OUT ) {
1343
1324
/* dir out => dst = remote, src = local */
1344
1325
net -> xfrm .policy_bydst [dir ].dbits4 = rbits4 ;
@@ -1363,6 +1344,10 @@ static void xfrm_hash_rebuild(struct work_struct *work)
1363
1344
/* skip socket policies */
1364
1345
continue ;
1365
1346
}
1347
+
1348
+ hlist_del_rcu (& policy -> bydst );
1349
+ hlist_del_init (& policy -> bydst_inexact_list );
1350
+
1366
1351
newpos = NULL ;
1367
1352
chain = policy_hash_bysel (net , & policy -> selector ,
1368
1353
policy -> family , dir );
@@ -4484,63 +4469,50 @@ EXPORT_SYMBOL_GPL(xfrm_audit_policy_delete);
4484
4469
#endif
4485
4470
4486
4471
#ifdef CONFIG_XFRM_MIGRATE
4487
- static bool xfrm_migrate_selector_match (const struct xfrm_selector * sel_cmp ,
4488
- const struct xfrm_selector * sel_tgt )
4489
- {
4490
- if (sel_cmp -> proto == IPSEC_ULPROTO_ANY ) {
4491
- if (sel_tgt -> family == sel_cmp -> family &&
4492
- xfrm_addr_equal (& sel_tgt -> daddr , & sel_cmp -> daddr ,
4493
- sel_cmp -> family ) &&
4494
- xfrm_addr_equal (& sel_tgt -> saddr , & sel_cmp -> saddr ,
4495
- sel_cmp -> family ) &&
4496
- sel_tgt -> prefixlen_d == sel_cmp -> prefixlen_d &&
4497
- sel_tgt -> prefixlen_s == sel_cmp -> prefixlen_s ) {
4498
- return true;
4499
- }
4500
- } else {
4501
- if (memcmp (sel_tgt , sel_cmp , sizeof (* sel_tgt )) == 0 ) {
4502
- return true;
4503
- }
4504
- }
4505
- return false;
4506
- }
4507
-
4508
4472
static struct xfrm_policy * xfrm_migrate_policy_find (const struct xfrm_selector * sel ,
4509
4473
u8 dir , u8 type , struct net * net , u32 if_id )
4510
4474
{
4511
4475
struct xfrm_policy * pol , * ret = NULL ;
4512
- struct hlist_head * chain ;
4513
- u32 priority = ~0U ;
4476
+ struct flowi fl ;
4514
4477
4515
- spin_lock_bh (& net -> xfrm .xfrm_policy_lock );
4516
- chain = policy_hash_direct (net , & sel -> daddr , & sel -> saddr , sel -> family , dir );
4517
- hlist_for_each_entry (pol , chain , bydst ) {
4518
- if ((if_id == 0 || pol -> if_id == if_id ) &&
4519
- xfrm_migrate_selector_match (sel , & pol -> selector ) &&
4520
- pol -> type == type ) {
4521
- ret = pol ;
4522
- priority = ret -> priority ;
4523
- break ;
4524
- }
4525
- }
4526
- chain = & net -> xfrm .policy_inexact [dir ];
4527
- hlist_for_each_entry (pol , chain , bydst_inexact_list ) {
4528
- if ((pol -> priority >= priority ) && ret )
4529
- break ;
4478
+ memset (& fl , 0 , sizeof (fl ));
4530
4479
4531
- if ((if_id == 0 || pol -> if_id == if_id ) &&
4532
- xfrm_migrate_selector_match (sel , & pol -> selector ) &&
4533
- pol -> type == type ) {
4534
- ret = pol ;
4480
+ fl .flowi_proto = sel -> proto ;
4481
+
4482
+ switch (sel -> family ) {
4483
+ case AF_INET :
4484
+ fl .u .ip4 .saddr = sel -> saddr .a4 ;
4485
+ fl .u .ip4 .daddr = sel -> daddr .a4 ;
4486
+ if (sel -> proto == IPSEC_ULPROTO_ANY )
4535
4487
break ;
4536
- }
4488
+ fl .u .flowi4_oif = sel -> ifindex ;
4489
+ fl .u .ip4 .fl4_sport = sel -> sport ;
4490
+ fl .u .ip4 .fl4_dport = sel -> dport ;
4491
+ break ;
4492
+ case AF_INET6 :
4493
+ fl .u .ip6 .saddr = sel -> saddr .in6 ;
4494
+ fl .u .ip6 .daddr = sel -> daddr .in6 ;
4495
+ if (sel -> proto == IPSEC_ULPROTO_ANY )
4496
+ break ;
4497
+ fl .u .flowi6_oif = sel -> ifindex ;
4498
+ fl .u .ip6 .fl4_sport = sel -> sport ;
4499
+ fl .u .ip6 .fl4_dport = sel -> dport ;
4500
+ break ;
4501
+ default :
4502
+ return ERR_PTR (- EAFNOSUPPORT );
4537
4503
}
4538
4504
4539
- xfrm_pol_hold ( ret );
4505
+ rcu_read_lock ( );
4540
4506
4541
- spin_unlock_bh (& net -> xfrm .xfrm_policy_lock );
4507
+ pol = xfrm_policy_lookup_bytype (net , type , & fl , sel -> family , dir , if_id );
4508
+ if (IS_ERR_OR_NULL (pol ))
4509
+ goto out_unlock ;
4542
4510
4543
- return ret ;
4511
+ if (!xfrm_pol_hold_rcu (ret ))
4512
+ pol = NULL ;
4513
+ out_unlock :
4514
+ rcu_read_unlock ();
4515
+ return pol ;
4544
4516
}
4545
4517
4546
4518
static int migrate_tmpl_match (const struct xfrm_migrate * m , const struct xfrm_tmpl * t )
@@ -4677,9 +4649,9 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
4677
4649
4678
4650
/* Stage 1 - find policy */
4679
4651
pol = xfrm_migrate_policy_find (sel , dir , type , net , if_id );
4680
- if (! pol ) {
4652
+ if (IS_ERR_OR_NULL ( pol ) ) {
4681
4653
NL_SET_ERR_MSG (extack , "Target policy not found" );
4682
- err = - ENOENT ;
4654
+ err = IS_ERR ( pol ) ? PTR_ERR ( pol ) : - ENOENT ;
4683
4655
goto out ;
4684
4656
}
4685
4657
0 commit comments