static void connection_state(struct state *st, void *data) { struct log_conn_info *lc = data; if (!st || st == lc->ignore || !st->st_connection || !lc->conn) return; if (st->st_connection != lc->conn) { if (lc->conn->IPhost_pair != st->st_connection->IPhost_pair || !same_peer_ids(lc->conn, st->st_connection, NULL)) return; /* phase1 is shared with another connnection */ } /* ignore undefined states (ie., just deleted) */ if (st->st_state == STATE_UNDEFINED) return; if (IS_PHASE1(st->st_state)) { if (lc->tunnel < tun_phase1) lc->tunnel = tun_phase1; if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)) { if (lc->tunnel < tun_phase1up) lc->tunnel = tun_phase1up; lc->phase1 = p1_up; } else { if (lc->phase1 < p1_init) lc->phase1 = p1_init; if (IS_ISAKMP_ENCRYPTED(st->st_state) && lc->phase1 < p1_encrypt) lc->phase1 = p1_encrypt; if (IS_ISAKMP_AUTHENTICATED(st->st_state) && lc->phase1 < p1_auth) lc->phase1 = p1_auth; } } else lc->phase1 = p1_down; /* only phase one shares across connections, so we can quit now */ if (st->st_connection != lc->conn) return; if (IS_PHASE15(st->st_state)) { if (lc->tunnel < tun_phase15) lc->tunnel = tun_phase15; } if (IS_QUICK(st->st_state)) { if (lc->tunnel < tun_phase2) lc->tunnel = tun_phase2; if (IS_IPSEC_SA_ESTABLISHED(st->st_state)) { if (lc->tunnel < tun_up) lc->tunnel = tun_up; lc->phase2 = p2_up; } else { if (lc->phase2 < p2_neg) lc->phase2 = p2_neg; } } }
/* delete a state object */ void delete_state(struct state *st) { struct connection *const c = st->st_connection; struct state *old_cur_state = cur_state == st? NULL : cur_state; openswan_log("deleting state #%lu (%s)", st->st_serialno, enum_show(&state_names, st->st_state)); /* * for most IKEv2 things, we may have further things to do after marking the state deleted, * so we do not actually free it here at all, but back in the main loop when all the work is done. */ if(st->st_ikev2) { /* child sa*/ if(st->st_clonedfrom != 0) { DBG(DBG_CONTROL, DBG_log("received request to delete child state")); if(st->st_state == STATE_CHILDSA_DEL) { DBG(DBG_CONTROL, DBG_log("now deleting the child state")); } else { /* Only send request if child sa is established * otherwise continue with deletion */ if(IS_CHILD_SA_ESTABLISHED(st)) { DBG(DBG_CONTROL, DBG_log("sending Child SA delete equest")); send_delete(st); change_state(st, STATE_CHILDSA_DEL); /* actual deletion when we receive peer response*/ return; } } } else { DBG(DBG_CONTROL, DBG_log("considering request to delete IKE parent state")); /* parent sa */ if(st->st_state == STATE_IKESA_DEL) { DBG(DBG_CONTROL, DBG_log("now deleting the IKE (or parent) state")); } else { /* Another check to verify if a secured * INFORMATIONAL exchange can be sent or not */ if(st->st_skey_ei.ptr && st->st_skey_ai.ptr && st->st_skey_er.ptr && st->st_skey_ar.ptr) { DBG(DBG_CONTROL, DBG_log("sending IKE SA delete request")); send_delete(st); change_state(st, STATE_IKESA_DEL); /* actual deletion when we receive peer response*/ return; } } } } /* If DPD is enabled on this state object, clear any pending events */ if(st->st_dpd_event != NULL) delete_dpd_event(st); /* if there is a suspended state transition, disconnect us */ if (st->st_suspended_md != NULL) { passert(st->st_suspended_md->st == st); DBG(DBG_CONTROL, DBG_log("disconnecting state #%lu from md", st->st_serialno)); st->st_suspended_md->st = NULL; } /* tell the other side of any IPSEC SAs that are going down */ if (IS_IPSEC_SA_ESTABLISHED(st->st_state) || IS_ISAKMP_SA_ESTABLISHED(st->st_state)) send_delete(st); delete_event(st); /* delete any pending timer event */ /* Ditch anything pending on ISAKMP SA being established. * Note: this must be done before the unhash_state to prevent * flush_pending_by_state inadvertently and prematurely * deleting our connection. */ flush_pending_by_state(st); /* if there is anything in the cryptographic queue, then remove this * state from it. */ delete_cryptographic_continuation(st); /* effectively, this deletes any ISAKMP SA that this state represents */ unhash_state(st); /* tell kernel to delete any IPSEC SA * ??? we ought to tell peer to delete IPSEC SAs */ if (IS_IPSEC_SA_ESTABLISHED(st->st_state) || IS_CHILD_SA_ESTABLISHED(st)) delete_ipsec_sa(st, FALSE); else if (IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(st->st_state)) delete_ipsec_sa(st, TRUE); if (c->newest_ipsec_sa == st->st_serialno) c->newest_ipsec_sa = SOS_NOBODY; if (c->newest_isakmp_sa == st->st_serialno) c->newest_isakmp_sa = SOS_NOBODY; /* * fake a state change here while we are still associated with a * connection. Without this the state logging (when enabled) cannot * work out what happened. */ fake_state(st, STATE_UNDEFINED); st->st_connection = NULL; /* we might be about to free it */ cur_state = old_cur_state; /* without st_connection, st isn't complete */ connection_discard(c); change_state(st, STATE_UNDEFINED); release_whack(st); change_state(st, STATE_CHILDSA_DEL); }