Esempio n. 1
0
stf_status dpd_init(struct state *st)
{
	/**
	 * Used to store the 1st state
	 */
#ifdef HAVE_LABELED_IPSEC
	if (st->st_connection->loopback) {
		libreswan_log(
			"dpd is not required for ipsec connections over loopback");
		return STF_OK;
	}
#endif
	struct state *p1st;

	/* find the related Phase 1 state */
	p1st = find_state_ikev1(st->st_icookie, st->st_rcookie, 0);

	if (p1st == NULL) {
		loglog(RC_LOG_SERIOUS, "could not find phase 1 state for DPD");

		/*
		 * if the phase 1 state has gone away, it really should have
		 * deleted all of its children.
		 * Why would this happen? because a quick mode SA can take
		 * some time to create (DNS lookups for instance), and the phase 1
		 * might have been taken down for some reason in the meantime.
		 * We really can not do anything here --- attempting to invoke
		 * the DPD action would be a good idea, but we really should
		 * do that outside this function.
		 */
		return STF_FAIL;
	}

	/* if it was enabled, and we haven't turned it on already */
	if (p1st->hidden_variables.st_dpd) {
		time_t n = now();
		libreswan_log("Dead Peer Detection (RFC 3706): enabled");

		if (st->st_dpd_event == NULL ||
		    (st->st_connection->dpd_delay + n) <
		    st->st_dpd_event->ev_time) {
			if (st->st_dpd_event != NULL)
				delete_dpd_event(st);
			event_schedule(EVENT_DPD, st->st_connection->dpd_delay,
				       st);
		}
	} else {
		libreswan_log(
			"Dead Peer Detection (RFC 3706): not enabled because peer did not advertise it");
	}

	if (p1st != st) {
		/* st was not a phase 1 SA, so kill the DPD_EVENT on the phase 1 */
		if (p1st->st_dpd_event != NULL &&
		    p1st->st_dpd_event->ev_type == EVENT_DPD)
			delete_dpd_event(p1st);
	}
	return STF_OK;
}
Esempio n. 2
0
stf_status dpd_init(struct state *st)
{
	/**
	 * Used to store the 1st state
	 */
	struct state *p1st;

	/* find the related Phase 1 state */
	p1st = find_state_ikev1(st->st_icookie, st->st_rcookie, 0);

	if (p1st == NULL) {
		loglog(RC_LOG_SERIOUS, "could not find phase 1 state for DPD");

		/*
		 * if the phase 1 state has gone away, it really should have
		 * deleted all of its children.
		 * Why would this happen? because a quick mode SA can take
		 * some time to create (DNS lookups for instance), and the phase 1
		 * might have been taken down for some reason in the meantime.
		 * We really cannot do anything here --- attempting to invoke
		 * the DPD action would be a good idea, but we really should
		 * do that outside this function.
		 */
		return STF_FAIL;
	}

	/* if it was enabled, and we haven't turned it on already */
	if (p1st->hidden_variables.st_peer_supports_dpd) {
		DBG(DBG_DPD, DBG_log("Dead Peer Detection (RFC 3706): enabled"));
		if (st->st_dpd_event == NULL || ev_before(st->st_dpd_event,
					st->st_connection->dpd_delay)){
			if (st->st_dpd_event != NULL)
				delete_dpd_event(st);
			event_schedule(EVENT_DPD,
					deltasecs(st->st_connection->dpd_delay),
					st);
		}
	} else {
		loglog(RC_LOG_SERIOUS,
			"Configured DPD (RFC 3706) support not enabled because remote peer did not advertise DPD support");
	}

	if (p1st != st) {
		/* st was not a phase 1 SA, so kill the DPD_EVENT on the phase 1 */
		if (p1st->st_dpd_event != NULL &&
		    p1st->st_dpd_event->ev_type == EVENT_DPD)
			delete_dpd_event(p1st);
	}
	return STF_OK;
}
Esempio n. 3
0
/*
 * Only schedule a new timeout if there isn't one currently,
 * or if it would be sooner than the current timeout.
 */
static void dpd_sched_timeout(struct state *p1st, monotime_t nw, deltatime_t timeout)
{
	passert(deltasecs(timeout) > 0);
	if (p1st->st_dpd_event == NULL ||
	    monobefore(monotimesum(nw, timeout), p1st->st_dpd_event->ev_time)) {
		DBG(DBG_DPD, DBG_log("DPD: scheduling timeout to %ld",
				     (long)deltasecs(timeout)));
		if (p1st->st_dpd_event != NULL)
			delete_dpd_event(p1st);
		event_schedule(EVENT_DPD_TIMEOUT, deltasecs(timeout), p1st);
	}
}
Esempio n. 4
0
/*
 * Only schedule a new timeout if there isn't one currently,
 * or if it would be sooner than the current timeout.
 */
static void dpd_sched_timeout(struct state *p1st, time_t tm, time_t timeout)
{
	passert(timeout > 0);
	if (p1st->st_dpd_event == NULL ||
	    p1st->st_dpd_event->ev_time > tm + timeout) {
		DBG(DBG_DPD, DBG_log("DPD: scheduling timeout to %lu",
				     (unsigned long)timeout));
		if (p1st->st_dpd_event != NULL)
			delete_dpd_event(p1st);
		event_schedule(EVENT_DPD_TIMEOUT, timeout, p1st);
	}
}
Esempio n. 5
0
/**
 * DPD Out Initiator
 *
 * @param p2st A state struct that is already in phase2
 * @return void
 */
static void dpd_outI(struct state *p1st, struct state *st, bool eroute_care,
		     deltatime_t delay, deltatime_t timeout)
{
	monotime_t nw;
	monotime_t last;
	deltatime_t nextdelay;
	u_int32_t seqno;

	DBG(DBG_DPD,
	    DBG_log("DPD: processing for state #%lu (\"%s\")",
		    st->st_serialno,
		    st->st_connection->name));

	/* If no DPD, then get out of here */
	if (!st->hidden_variables.st_peer_supports_dpd) {
		DBG(DBG_DPD,
		    DBG_log("DPD: peer does not support dpd"));
		return;
	}

	/* If there is no state, there can be no DPD */
	if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state)) {
		DBG(DBG_DPD,
		    DBG_log("DPD: no phase1 state, so no DPD"));
		return;
	}

	/* find out when now is */
	nw = mononow();

	/*
	 * pick least recent activity value, since with multiple phase 2s,
	 * it may well be that one phase 2 is very active, while the other
	 * for some reason, gets stomped upon by some network screw up.
	 *
	 * (this would only happen if the network was sensitive to different
	 *  SPI#, since for NAT-T, all traffic should be on the same UDP port.
	 *  At worst, this means that we send a bit more traffic then we need
	 *  to when there are multiple SAs and one is much less active.
	 *
	 * ??? the code actually picks the most recent.  So much for comments.
	 */
	last = !monobefore(p1st->st_last_dpd, st->st_last_dpd) ?
		p1st->st_last_dpd : st->st_last_dpd;

	nextdelay = monotimediff(monotimesum(last, delay), nw);

	/* has there been enough activity of late? */
	if (deltasecs(nextdelay) > 0) {
		/* Yes, just reschedule "phase 2" */
		DBG(DBG_DPD,
		    DBG_log("DPD: not yet time for dpd event: %ld < %ld",
			    (long)nw.mono_secs,
			    (long)(last.mono_secs + deltasecs(delay))));
		event_schedule(EVENT_DPD, deltasecs(nextdelay), st);
		return;
	}

	/* now plan next check time */
	/* ??? this test is nuts: it will always succeed! */
	if (deltasecs(nextdelay) < 1)
		nextdelay = delay;

	/*
	 * check the phase 2, if we are supposed to,
	 * and return if it is active recently
	 */
	if (eroute_care && st->hidden_variables.st_nat_traversal == LEMPTY &&
			!was_eroute_idle(st, delay)) {
		DBG(DBG_DPD,
		    DBG_log("DPD: out event not sent, phase 2 active"));

		/* update phase 2 time stamp only */
		st->st_last_dpd = nw;

		/*
		 * Since there was activity, kill any EVENT_DPD_TIMEOUT that might
		 * be waiting. This can happen when a R_U_THERE_ACK is lost, and
		 * subsequently traffic started flowing over the SA again, and no
		 * more DPD packets are sent to cancel the outstanding DPD timer.
		 */
		if (p1st->st_dpd_event != NULL &&
		    p1st->st_dpd_event->ev_type == EVENT_DPD_TIMEOUT) {
			DBG(DBG_DPD,
			    DBG_log("DPD: deleting p1st DPD event"));
			delete_dpd_event(p1st);
		}

		event_schedule(EVENT_DPD, deltasecs(nextdelay), st);
		return;
	}

	if (st != p1st) {
		/*
		 * reschedule next event, since we cannot do it from the activity
		 * routine.
		 */
		event_schedule(EVENT_DPD, deltasecs(nextdelay), st);
	}

	if (p1st->st_dpd_seqno == 0) {
		/* Get a non-zero random value that has room to grow */
		get_rnd_bytes((u_char *)&p1st->st_dpd_seqno,
			      sizeof(p1st->st_dpd_seqno));
		p1st->st_dpd_seqno &= 0x7fff;
		p1st->st_dpd_seqno++;
	}
	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, nw, timeout);

	DBG(DBG_DPD, {
		ipstr_buf b;
		DBG_log("DPD: sending R_U_THERE %u to %s:%d (state #%lu)",
			 p1st->st_dpd_seqno,
			 ipstr(&p1st->st_remoteaddr, &b),
			 p1st->st_remoteport,
			 p1st->st_serialno);
	});
Esempio n. 6
0
/* 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);
}
Esempio n. 7
0
/**
 * 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
 */
void
dpd_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
	    || action == DPD_ACTION_RESTART_BY_PEER
	    );
        
    /** delete the state, which is probably in phase 2 */
    set_cur_connection(c);

    openswan_log("DPD: 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: 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: Clearing Connection");
	delete_states_by_connection(c, TRUE);
	DBG(DBG_DPD, DBG_log("unrouting connection"));
        unroute_connection(c);        /* --unroute */
	break;

    case DPD_ACTION_RESTART:
	/** dpdaction=restart - immediate renegotiate the connection. */
        openswan_log("DPD: Restarting Connection");

	/*
	 * unlike the other kinds, we do not delete any states,
	 * but rather, we arrange to replace all SAs involved.
	 */
	rekey_p2states_by_connection(c);

	if (c->kind == CK_INSTANCE) {
		/* If this is a template (eg: right=%any) we won't be able to
		 * reinitiate, the peer has probably changed IP addresses,
		 * or isn't available anymore.  So remove the routes too */
	        unroute_connection(c);        /* --unroute */
	}

	/* we schedule the replace of the SA so that we do it
	 * in a rational place and do it at a negative future time,
	 * so it will occur before any of the phase 2 replacements.
	 */
	delete_event(st);
	delete_dpd_event(st);
	event_schedule(EVENT_SA_REPLACE, 0, st);

	case DPD_ACTION_RESTART_BY_PEER:
	/* dpdaction=restart_by_peer - immediately renegotiate connections to the same peer. */
	openswan_log("DPD: Restarting all connections that share this peer");
	restart_connections_by_peer(c);
	break;

	break;
    }
    reset_cur_connection();
}
Esempio n. 8
0
/**
 * 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_status
dpd_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, "recevied 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, "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, "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, "R_U_THERE_ACK has invalid rcookie (tolerated)");
    }
    pbs->cur += COOKIE_SIZE;
    
    if (pbs_left(pbs) != sizeof(seqno))
    {
        loglog(RC_LOG_SERIOUS, "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("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, "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;
}       
Esempio n. 9
0
/**
 * 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_status
dpd_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 Error: 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 (broken Cisco?)");
    }
    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 (broken Cisco?)");      
    }
    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 Info: received old or duplicate R_U_THERE");
        return STF_IGNORE;
    }
     
    DBG(DBG_DPD, DBG_log("received R_U_THERE seq:%u time:%lu (state=#%lu name=\"%s\")"
			 , seqno
			 , (unsigned long)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 Info: 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;
}
Esempio n. 10
0
stf_status
dpd_init(struct state *st)
{
    /**
     * Used to store the 1st state 
     */
    struct state *p1st;

#ifdef CONSOLE_DEBUG
    time_start = time(NULL);
#endif

    /* find the related Phase 1 state */
    p1st = find_state(st->st_icookie, st->st_rcookie,
		      &st->st_connection->that.host_addr, 0);

    if (p1st == NULL) {
        loglog(RC_LOG_SERIOUS, "could not find phase 1 state for DPD");

	/*
	 * if the phase 1 state has gone away, it really should have
	 * deleted all of its children.
	 * Why would this happen? because a quick mode SA can take
	 * some time to create (DNS lookups for instance), and the phase 1
	 * might have been taken down for some reason in the meantime.
	 * We really can not do anything here --- attempting to invoke
	 * the DPD action would be a good idea, but we really should
	 * do that outside this function.
	 */
	return STF_FAIL;
    }

    /* if it was enabled, and we haven't turned it on already */
    if (p1st->hidden_variables.st_dpd) {
	time_t n = now();
	log("Dead Peer Detection (RFC 3706): enabled");

	/* If st is a phase 2 state, so turn its DPD on. This is needed, because
	 * DPD support is negotiated during phase 1.
	 */
	if (p1st != st)
	    st->hidden_variables.st_dpd = p1st->hidden_variables.st_dpd;

	if(st->st_dpd_event == NULL
	   || (st->st_connection->dpd_idle_timeout + n) <
	   st->st_dpd_event->ev_time) {
	    delete_dpd_event(st);
	    event_schedule(EVENT_DPD, st->st_connection->dpd_idle_timeout, st);
	}

    } else {
      log("Dead Peer Detection (RFC 3706): not enabled because peer did not advertise it");
    }

    if(p1st != st) {
	/* st was not a phase 1 SA, so kill the DPD_EVENT on the phase 1 */
	if(p1st->st_dpd_event != NULL
	   && p1st->st_dpd_event->ev_type == EVENT_DPD) {
	    delete_dpd_event(p1st);
	}
    }
    return STF_OK;
}
Esempio n. 11
0
/**
 * DPD Out Initiator
 *
 * @param p2st A state struct that is already in phase2
 * @return void
 */
static void dpd_outI(struct state *p1st, struct state *st, bool eroute_care,
		     time_t delay, time_t timeout)
{
	time_t tm;
	time_t last;
	u_int32_t seqno;
	bool eroute_idle;
	time_t nextdelay;

	DBG(DBG_DPD,
	    DBG_log("DPD: processing for state #%lu (\"%s\")",
		    st->st_serialno,
		    st->st_connection->name));

	/* If no DPD, then get out of here */
	if (!st->hidden_variables.st_dpd)
		return;

	/* If there is no state, there can be no DPD */
	if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state))
		return;

	/* find out when now is */
	tm = now();

	/*
	 * pick least recent activity value, since with multiple phase 2s,
	 * it may well be that one phase 2 is very active, while the other
	 * for some reason, gets stomped upon by some network screw up.
	 *
	 * (this would only happen if the network was sensitive to different
	 *  SPI#, since for NAT-T, all traffic should be on the same UDP port.
	 *  At worst, this means that we send a bit more traffic then we need
	 *  to when there are multiple SAs and one is much less active.
	 *
	 */
	last = (p1st->st_last_dpd < st->st_last_dpd ?
		st->st_last_dpd : p1st->st_last_dpd );

	nextdelay = last + delay - tm;

	/* has there been enough activity of late? */
	if (nextdelay > 0) {
		/* Yes, just reschedule "phase 2" */
		DBG(DBG_DPD,
		    DBG_log("DPD: not yet time for dpd event: %lu < %lu",
			    (unsigned long)tm,
			    (unsigned long)(last + delay)));
		event_schedule(EVENT_DPD, nextdelay, st);
		return;
	}

	/* now plan next check time */
	if (nextdelay < 1)
		nextdelay = delay;

	/*
	 * check the phase 2, if we are supposed to,
	 * and return if it is active recently
	 */
	if (eroute_care && !st->hidden_variables.st_nat_traversal) {

		eroute_idle = was_eroute_idle(st, delay);
		if (!eroute_idle) {
			DBG(DBG_DPD,
			    DBG_log("DPD: out event not sent, phase 2 active"));

			/* update phase 2 time stamp only */
			st->st_last_dpd = tm;

			/*
			 * Since there was activity, kill any EVENT_DPD_TIMEOUT that might
			 * be waiting. This can happen when a R_U_THERE_ACK is lost, and
			 * subsequently traffic started flowing over the SA again, and no
			 * more DPD packets are sent to cancel the outstanding DPD timer.
			 */
			if (p1st->st_dpd_event != NULL &&
			    p1st->st_dpd_event->ev_type == EVENT_DPD_TIMEOUT)
				delete_dpd_event(p1st);

			event_schedule(EVENT_DPD, nextdelay, st);
			return;
		}
	}

	if (st != p1st) {
		/*
		 * reschedule next event, since we can not do it from the activity
		 * routine.
		 */
		event_schedule(EVENT_DPD, nextdelay, st);
	}

	if (!p1st->st_dpd_seqno) {
		/* Get a non-zero random value that has room to grow */
		get_rnd_bytes((u_char *)&p1st->st_dpd_seqno,
			      sizeof(p1st->st_dpd_seqno));
		p1st->st_dpd_seqno &= 0x7fff;
		p1st->st_dpd_seqno++;
	}
	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: sending R_U_THERE %u to %s:%d (state #%lu)",
			     p1st->st_dpd_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: 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++;

}