dpd.c
来自「ipsec vpn」· C语言 代码 · 共 581 行 · 第 1/2 页
C
581 行
} seqno = htonl(p1st->st_dpd_seqno); /* make sure that the timeout occurs. We do this before the send, * because the send may fail due to network issues, etc, and * the timeout has to occur anyway */ dpd_sched_timeout(p1st, tm, timeout); DBG(DBG_DPD, DBG_log("DPD: Debug: sending R_U_THERE %u to %s:%d (state #%lu)" , seqno , ip_str(&p1st->st_remoteaddr) , p1st->st_remoteport , p1st->st_serialno)); if (send_isakmp_notification(p1st, R_U_THERE , &seqno, sizeof(seqno)) != STF_IGNORE) { loglog(RC_LOG_SERIOUS, "DPD: Serious: could not send R_U_THERE"); return; } st->st_last_dpd = tm; p1st->st_last_dpd = tm; p1st->st_dpd_expectseqno = p1st->st_dpd_seqno++;}voidp1_dpd_outI1(struct state *p1st){ time_t delay = p1st->st_connection->dpd_delay; time_t timeout = p1st->st_connection->dpd_timeout; dpd_outI(p1st, p1st, FALSE, delay, timeout);}voidp2_dpd_outI1(struct state *p2st){ struct state *st; time_t delay = p2st->st_connection->dpd_delay; time_t timeout = p2st->st_connection->dpd_timeout; /* find the related Phase 1 state */ st = find_phase1_state(p2st->st_connection, ISAKMP_SA_ESTABLISHED_STATES); if (st == NULL) { loglog(RC_LOG_SERIOUS, "DPD: Serious: could not find newest phase 1 state"); return; } dpd_outI(st, p2st, TRUE, delay, timeout);}voiddpd_event(struct state *st){ if(st==NULL) return; if(IS_PHASE1(st->st_state)) { p1_dpd_outI1(st); } else { p2_dpd_outI1(st); }}/** * DPD in Initiator, out Responder * * @param st A state structure (the phase 1 state) * @param n A notification (isakmp_notification) * @param pbs A PB Stream * @return stf_status */stf_statusdpd_inI_outR(struct state *p1st , struct isakmp_notification *const n , pb_stream *pbs){ time_t tm = now(); u_int32_t seqno; if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state)) { loglog(RC_LOG_SERIOUS, "DPD: Warning: received R_U_THERE for unestablished ISKAMP SA"); return STF_IGNORE; } if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2) { loglog(RC_LOG_SERIOUS, "DPD: Error: R_U_THERE has invalid SPI length (%d)", n->isan_spisize); return STF_FAIL + PAYLOAD_MALFORMED; } if (memcmp(pbs->cur, p1st->st_icookie, COOKIE_SIZE) != 0) { /* RFC states we *SHOULD* check cookies, not MUST. So invalid cookies are technically valid, as per Geoffrey Huang */ loglog(RC_LOG_SERIOUS, "DPD: Warning: R_U_THERE has invalid icookie"); } pbs->cur += COOKIE_SIZE; if (memcmp(pbs->cur, p1st->st_rcookie, COOKIE_SIZE) != 0) { loglog(RC_LOG_SERIOUS, "DPD: Warning: R_U_THERE has invalid rcookie"); } pbs->cur += COOKIE_SIZE; if (pbs_left(pbs) != sizeof(seqno)) { loglog(RC_LOG_SERIOUS, "DPD: Error: R_U_THERE has invalid data length (%d)", (int) pbs_left(pbs)); return STF_FAIL + PAYLOAD_MALFORMED; } seqno = ntohl(*(u_int32_t *)pbs->cur); if (p1st->st_dpd_peerseqno && seqno <= p1st->st_dpd_peerseqno) { loglog(RC_LOG_SERIOUS, "DPD Warning: received old or duplicate R_U_THERE"); return STF_IGNORE; } DBG(DBG_DPD, DBG_log("DPD: Debug: received R_U_THERE seq:%u time:%lu (state=#%lu name=\"%s\")" , seqno, tm, p1st->st_serialno, p1st->st_connection->name)); p1st->st_dpd_peerseqno = seqno; if (send_isakmp_notification(p1st, R_U_THERE_ACK , pbs->cur, pbs_left(pbs)) != STF_IGNORE) { loglog(RC_LOG_SERIOUS, "DPD: Warning: could not send R_U_THERE_ACK"); return STF_IGNORE; } /* update the time stamp */ p1st->st_last_dpd = tm; /* * since there was activity, kill any EVENT_DPD_TIMEOUT that might * be waiting. */ if(p1st->st_dpd_event != NULL && p1st->st_dpd_event->ev_type == EVENT_DPD_TIMEOUT) { delete_dpd_event(p1st); } return STF_IGNORE;}/** * DPD out Responder * * @param st A state structure (phase 1) * @param n A notification (isakmp_notification) * @param pbs A PB Stream * @return stf_status */stf_statusdpd_inR(struct state *p1st , struct isakmp_notification *const n , pb_stream *pbs){ time_t tm = now(); u_int32_t seqno; if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state)) { loglog(RC_LOG_SERIOUS, "DPD: Warning: recieved R_U_THERE_ACK for unestablished ISKAMP SA"); return STF_FAIL; } if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2) { loglog(RC_LOG_SERIOUS, "DPD: Error: R_U_THERE_ACK has invalid SPI length (%d)", n->isan_spisize); return STF_FAIL + PAYLOAD_MALFORMED; } if (memcmp(pbs->cur, p1st->st_icookie, COOKIE_SIZE) != 0) { /* RFC states we *SHOULD* check cookies, not MUST. So invalid cookies are technically valid, as per Geoffrey Huang */ loglog(RC_LOG_SERIOUS, "DPD: Warning: R_U_THERE_ACK has invalid icookie"); } pbs->cur += COOKIE_SIZE; if (memcmp(pbs->cur, p1st->st_rcookie, COOKIE_SIZE) != 0) { /* RFC states we *SHOULD* check cookies, not MUST. So invalid cookies are technically valid, as per Geoffrey Huang */ loglog(RC_LOG_SERIOUS, "DPD: Warning: R_U_THERE_ACK has invalid rcookie "); } pbs->cur += COOKIE_SIZE; if (pbs_left(pbs) != sizeof(seqno)) { loglog(RC_LOG_SERIOUS, "DPD: Error: R_U_THERE_ACK has invalid data length (%d)", (int) pbs_left(pbs)); return STF_FAIL + PAYLOAD_MALFORMED; } seqno = ntohl(*(u_int32_t *)pbs->cur); DBG(DBG_DPD, DBG_log("DPD: Debug: R_U_THERE_ACK, seqno received: %u expected: %u (state=#%lu)", seqno, p1st->st_dpd_expectseqno, p1st->st_serialno)); if (!p1st->st_dpd_expectseqno && seqno != p1st->st_dpd_expectseqno) { loglog(RC_LOG_SERIOUS, "DPD: Error: R_U_THERE_ACK has unexpected sequence number (expected: %u got: %u", seqno, p1st->st_dpd_expectseqno); p1st->st_dpd_expectseqno = 0; /* do not update time stamp, so we'll send a new one sooner */ } else { /* update the time stamp */ p1st->st_last_dpd = tm; } p1st->st_dpd_expectseqno = 0; /* * since there was activity, kill any EVENT_DPD_TIMEOUT that might * be waiting. */ if(p1st->st_dpd_event != NULL && p1st->st_dpd_event->ev_type == EVENT_DPD_TIMEOUT) { delete_dpd_event(p1st); } return STF_IGNORE;} /** * DPD Timeout Function * * This function is called when a timeout DPD_EVENT occurs. We set clear/trap * both the SA and the eroutes, depending on what the connection definition * tells us (either 'hold' or 'clear') * * @param st A state structure that is fully negotiated * @return void */voiddpd_timeout(struct state *st){ int action; struct connection *c = st->st_connection; action = st->st_connection->dpd_action; /* probably wrong thing to assert here */ passert(action == DPD_ACTION_HOLD || action == DPD_ACTION_CLEAR || action == DPD_ACTION_RESTART); /** delete the state, which is probably in phase 2 */ set_cur_connection(c); openswan_log("DPD: Info: No response from peer - declaring peer dead"); switch(action) { case DPD_ACTION_HOLD: /** dpdaction=hold - Wipe the SA's but %trap the eroute so we don't leak traffic. Also, being in %trap means new packets will force an initiation of the conn again. */ openswan_log("DPD: Info: Putting connection into %%trap"); delete_states_by_connection(c, TRUE); break; case DPD_ACTION_CLEAR: /** dpdaction=clear - Wipe the SA & eroute - everything */ openswan_log("DPD: Info: Clearing Connection"); delete_states_by_connection(c, TRUE); DBG(DBG_DPD, DBG_log("DPD: Debug: issuing unroute_connection()")); unroute_connection(c); /* --unroute */ break; case DPD_ACTION_RESTART: /** dpdaction=restart - immediate renegotiate the connection. */ openswan_log("DPD: Info: Restarting Connection"); /* we replace the SA so that we do it in a rational place */ delete_event(st); event_schedule(EVENT_SA_REPLACE, 0, st); break; } reset_cur_connection();}/* * Local Variables: * c-basic-offset:4 * c-style: pluto * End: */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?