| 4409 | } |
| 4410 | |
| 4411 | static void |
| 4412 | key_flush_spd(time_t now) |
| 4413 | { |
| 4414 | SPTREE_RLOCK_TRACKER; |
| 4415 | struct secpolicy_list drainq; |
| 4416 | struct secpolicy *sp, *nextsp; |
| 4417 | u_int dir; |
| 4418 | |
| 4419 | LIST_INIT(&drainq); |
| 4420 | SPTREE_RLOCK(); |
| 4421 | for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { |
| 4422 | TAILQ_FOREACH(sp, &V_sptree[dir], chain) { |
| 4423 | if (sp->lifetime == 0 && sp->validtime == 0) |
| 4424 | continue; |
| 4425 | if ((sp->lifetime && |
| 4426 | now - sp->created > sp->lifetime) || |
| 4427 | (sp->validtime && |
| 4428 | now - sp->lastused > sp->validtime)) { |
| 4429 | /* Hold extra reference to send SPDEXPIRE */ |
| 4430 | SP_ADDREF(sp); |
| 4431 | LIST_INSERT_HEAD(&drainq, sp, drainq); |
| 4432 | } |
| 4433 | } |
| 4434 | } |
| 4435 | SPTREE_RUNLOCK(); |
| 4436 | if (LIST_EMPTY(&drainq)) |
| 4437 | return; |
| 4438 | |
| 4439 | SPTREE_WLOCK(); |
| 4440 | sp = LIST_FIRST(&drainq); |
| 4441 | while (sp != NULL) { |
| 4442 | nextsp = LIST_NEXT(sp, drainq); |
| 4443 | /* Check that SP is still linked */ |
| 4444 | if (sp->state != IPSEC_SPSTATE_ALIVE) { |
| 4445 | LIST_REMOVE(sp, drainq); |
| 4446 | key_freesp(&sp); /* release extra reference */ |
| 4447 | sp = nextsp; |
| 4448 | continue; |
| 4449 | } |
| 4450 | TAILQ_REMOVE(&V_sptree[sp->spidx.dir], sp, chain); |
| 4451 | V_spd_size--; |
| 4452 | LIST_REMOVE(sp, idhash); |
| 4453 | sp->state = IPSEC_SPSTATE_DEAD; |
| 4454 | sp = nextsp; |
| 4455 | } |
| 4456 | V_sp_genid++; |
| 4457 | SPTREE_WUNLOCK(); |
| 4458 | if (SPDCACHE_ENABLED()) |
| 4459 | spdcache_clear(); |
| 4460 | |
| 4461 | sp = LIST_FIRST(&drainq); |
| 4462 | while (sp != NULL) { |
| 4463 | nextsp = LIST_NEXT(sp, drainq); |
| 4464 | key_spdexpire(sp); |
| 4465 | key_freesp(&sp); /* release extra reference */ |
| 4466 | key_freesp(&sp); /* release last reference */ |
| 4467 | sp = nextsp; |
| 4468 | } |
no test coverage detected