+
+void
+sweep_sleepwake(void)
+{
+ ike_session_t *session = NULL;
+ ike_session_t *next_session = NULL;
+ phase2_handle_t *iph2 = NULL;
+ phase2_handle_t *next_iph2 = NULL;
+ phase1_handle_t *iph1 = NULL;
+ phase1_handle_t *next_iph1 = NULL;
+
+ LIST_FOREACH_SAFE(session, &ike_session_tree, chain, next_session) {
+ // do the ph1s.
+ LIST_FOREACH_SAFE(iph1, &session->ph1tree, ph1ofsession_chain, next_iph1) {
+ if (iph1->parent_session && iph1->parent_session->is_asserted) {
+ plog(ASL_LEVEL_NOTICE, "Skipping sweep of Phase 1 %s because it's been asserted.\n",
+ isakmp_pindex(&iph1->index, 0));
+ continue;
+ }
+ if (iph1->is_dying || FSM_STATE_IS_EXPIRED(iph1->status)) {
+ plog(ASL_LEVEL_NOTICE, "Skipping sweep of Phase 1 %s because it's already expired.\n",
+ isakmp_pindex(&iph1->index, 0));
+ continue;
+ }
+ if (iph1->sce) {
+ time_t xtime;
+ if (sched_get_time(iph1->sce, &xtime)) {
+ if (xtime <= swept_at) {
+ SCHED_KILL(iph1->sce);
+ SCHED_KILL(iph1->sce_rekey);
+ iph1->is_dying = 1;
+ fsm_set_state(&iph1->status, IKEV1_STATE_PHASE1_EXPIRED);
+ ike_session_update_ph1_ph2tree(iph1); // move unbind/rebind ph2s to from current ph1
+ iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
+ plog(ASL_LEVEL_NOTICE, "Phase 1 %s expired while sleeping: quick deletion.\n",
+ isakmp_pindex(&iph1->index, 0));
+ }
+ }
+ }
+ if (iph1->sce_rekey) {
+ time_t xtime;
+ if (sched_get_time(iph1->sce_rekey, &xtime)) {
+ if (FSM_STATE_IS_EXPIRED(iph1->status) || xtime <= swept_at) {
+ SCHED_KILL(iph1->sce_rekey);
+ }
+ }
+ }
+ if (iph1->scr) {
+ time_t xtime;
+ if (sched_get_time(iph1->scr, &xtime)) {
+ if (FSM_STATE_IS_EXPIRED(iph1->status) || xtime <= swept_at) {
+ SCHED_KILL(iph1->scr);
+ }
+ }
+ }
+ #ifdef ENABLE_DPD
+ if (iph1->dpd_r_u) {
+ time_t xtime;
+ if (sched_get_time(iph1->dpd_r_u, &xtime)) {
+ if (FSM_STATE_IS_EXPIRED(iph1->status) || xtime <= swept_at) {
+ SCHED_KILL(iph1->dpd_r_u);
+ }
+ }
+ }
+ #endif
+ }
+
+ // do ph2's next
+ LIST_FOREACH_SAFE(iph2, &session->ph2tree, ph2ofsession_chain, next_iph2) {
+ if (iph2->parent_session && iph2->parent_session->is_asserted) {
+ plog(ASL_LEVEL_NOTICE, "Skipping sweep of Phase 2 because it's been asserted.\n");
+ continue;
+ }
+ if (iph2->is_dying || FSM_STATE_IS_EXPIRED(iph2->status)) {
+ plog(ASL_LEVEL_NOTICE, "Skipping sweep of Phase 2 because it's already expired.\n");
+ continue;
+ }
+ if (iph2->sce) {
+ time_t xtime;
+ if (sched_get_time(iph2->sce, &xtime)) {
+ if (xtime <= swept_at) {
+ fsm_set_state(&iph2->status, IKEV1_STATE_PHASE2_EXPIRED);
+ iph2->is_dying = 1;
+ isakmp_ph2expire(iph2); // iph2 will go down 1 second later.
+ ike_session_stopped_by_controller(iph2->parent_session,
+ ike_session_stopped_by_sleepwake);
+ plog(ASL_LEVEL_NOTICE, "Phase 2 expired while sleeping: quick deletion.\n");
+ }
+ }
+ }
+ if (iph2->scr) {
+ time_t xtime;
+ if (sched_get_time(iph2->scr, &xtime)) {
+ if (FSM_STATE_IS_EXPIRED(iph2->status) || xtime <= swept_at) {
+ SCHED_KILL(iph2->scr);
+ }
+ }
+ }
+ }
+ }
+ //%%%%%%%%%%%%%%% fix this
+ // do the ike_session last
+ ike_session_sweep_sleepwake();
+}
+
+uint32_t
+iph1_get_remote_v4_address(phase1_handle_t *iph1)
+{
+ uint32_t address = 0;
+ if (iph1->remote->ss_family == AF_INET) {
+ address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr;
+ } else if (iph1->remote->ss_family == AF_INET6 &&
+ iph1->nat64_prefix.length) {
+ if (!nw_nat64_extract_v4(&iph1->nat64_prefix, &((struct sockaddr_in6 *)iph1->remote)->sin6_addr, (struct in_addr *)&address)) {
+ plog(ASL_LEVEL_ERR, "Failed to extract IPv4 from Phase 1 IPv6 address.\n");
+ }
+ } else {
+ plog(ASL_LEVEL_ERR, "Failed to get IPv4 address for Phase 1 (family=%u, NAT64Prefix=%u)\n",
+ iph1->remote->ss_family,
+ iph1->nat64_prefix.length);
+ }
+ return address;
+}
+
+uint32_t
+iph2_get_remote_v4_address(phase2_handle_t *iph2)
+{
+ uint32_t address = 0;
+ if (iph2->dst->ss_family == AF_INET) {
+ address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr;
+ } else if (iph2->dst->ss_family == AF_INET6 &&
+ iph2->nat64_prefix.length) {
+ if (!nw_nat64_extract_v4(&iph2->nat64_prefix, &((struct sockaddr_in6 *)iph2->dst)->sin6_addr, (struct in_addr *)&address)) {
+ plog(ASL_LEVEL_ERR, "Failed to extract IPv4 from Phase 2 IPv6 address.\n");
+ }
+ } else {
+ plog(ASL_LEVEL_ERR, "Failed to get IPv4 address for Phase 2 (family=%u, NAT64Prefix=%u)\n",
+ iph2->dst->ss_family,
+ iph2->nat64_prefix.length);
+ }
+ return address;
+}