示例#1
0
文件: dpd.c 项目: millken/zhuxianB30
/*****************************************************************************************   
 函数名称: dpd_timeout
 功能描述: dpd超时处理,删除连接
 输入参数: st
 输出参数: 无
 返 回 值: 无
-------------------------------------------------------------------------------------------    
 最近一次修改记录 :    
 修改作者: 王之云  
 修改目的: 超时处理  
 修改日期: 2012年3月20日
********************************************************************************************/  	 
void dpd_timeout(struct state *st)
{
    int action;
    struct ike_conn *c = st->st_connection;
    action = st->st_connection->dpd_action;
	so_serial_t newest = c->newest_isakmp_sa ;
	char buf_remoteip[20] = {0};
	st->st_dpd_timeout_flag = 1;
	addrtot(&st->st_remoteaddr, 0, buf_remoteip, sizeof(buf_remoteip));
	passert(IS_ISAKMP_SA_ESTABLISHED(st->st_state));
	
    passert(action == DPD_ACTION_HOLD
		    || action == DPD_ACTION_CLEAR
		    || action == DPD_ACTION_RESTART
		    || action == DPD_ACTION_RESTART_BY_PEER);

	
	if (newest != st->st_serialno && newest != SOS_NOBODY)
	{
		IPSEC_log(IPSEC_LOGLEVEL_WARNING, 
				  "Connection < %s > < %s > old state DPD TIMEOUT, "
				  "We will delete state depend on it.!", 
				  st->st_connection->name, buf_remoteip); 
		
		ipsec_release_state_by_parent(st);
		
		delete_state(st); 
		return;
	}

   {
       IPSEC_log(IPSEC_LOGLEVEL_WARNING, 
	   	         "Connection < %s > < %s > DPD TIMEOUT, we will %s connection!", 
	   	         st->st_connection->name, buf_remoteip, action == DPD_ACTION_CLEAR ? "clear":"restart");	
   }

    switch(action) 
	{
	    case DPD_ACTION_CLEAR:
			release_connection(&c);
		break;
		
	    case DPD_ACTION_RESTART:
			release_connection(&c);
			if(NULL != c)
			{
				start_initiate_connnection(c);
			}
		break;
		
	    case DPD_ACTION_HOLD:
		case DPD_ACTION_RESTART_BY_PEER:
			/*未用到此两种情况*/
		break;
		
		default :
			break;
    }
}
示例#2
0
文件: log.c 项目: mcr/Openswan
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;
		}
	}
}
示例#3
0
/*
 * delete all states that were created for a given connection,
 * additionally delete any states for which func(st, arg)
 * returns true.
 */
static void
foreach_states_by_connection_func(struct connection *c
				  , bool (*comparefunc)(struct state *st, struct connection *c, void *arg, int pass)
				 , void (*successfunc)(struct state *st, struct connection *c, void *arg)
				 , void *arg)
{
    int pass;
    /* this kludge avoids an n^2 algorithm */

    /* We take two passes so that we delete any ISAKMP SAs last.
     * This allows Delete Notifications to be sent.
     * ?? We could probably double the performance by caching any
     * ISAKMP SA states found in the first pass, avoiding a second.
     */
    for (pass = 0; pass != 2; pass++)
    {
	int i;

	/* For each hash chain... */
	for (i = 0; i < STATE_TABLE_SIZE; i++)
	{
	    struct state *st;

	    /* For each state in the hash chain... */
	    for (st = statetable[i]; st != NULL; )
	    {
		struct state *this = st;

		st = st->st_hashchain_next;	/* before this is deleted */

		/* on pass 2, ignore phase2 states */
 		if(pass == 1 && IS_ISAKMP_SA_ESTABLISHED(this->st_state)) {
		    continue;
		}

		/* call comparison function */
                if ((*comparefunc)(this, c, arg, pass))
                {
		    struct state *old_cur_state
			= cur_state == this? NULL : cur_state;
#ifdef DEBUG
		    lset_t old_cur_debugging = cur_debugging;
#endif

    set_cur_state(this);
		    (*successfunc)(this, c, arg);

		    cur_state = old_cur_state;
#ifdef DEBUG
		    set_debugging(old_cur_debugging);
#endif
		}
	    }
	}
    }
}
示例#4
0
文件: ikev1_dpd.c 项目: mkj/libreswan
/**
 * 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);
	});
示例#5
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);
}
示例#6
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;
}       
示例#7
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;
}
示例#8
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("processing dpd 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 = p1st->st_last_dpd + delay - tm;

    /* has there been enough activity of late? */
    if(nextdelay > 0) {
	/* Yes, just reschedule "phase 2" */
	DBG(DBG_DPD, DBG_log("not yet time for dpd event: %lu < %lu"
			     , (unsigned long)tm
			     , (unsigned long)(p1st->st_last_dpd + 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;
	    
	    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("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 Error: 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++;

}
示例#9
0
文件: dpd.c 项目: millken/zhuxianB30
/*****************************************************************************************   
 函数名称: dpd_outI
 功能描述: dpd 处理事件,当dpd第一次触发时添加一个超时事件,
 	          如果是重传的dpd处理,不添加超时事件。
 输入参数: p1st
 输出参数: 无
 返 回 值: 无
-------------------------------------------------------------------------------------------    
 最近一次修改记录 :    
 修改作者: 王之云    
 修改目的: dpd_outI处理  
 修改日期: 2012年3月20日
********************************************************************************************/  	 
static void dpd_outI(struct state *p1st)
{
    time_t tm;
    u_int32_t seqno;
	time_t timeout = p1st->st_connection->dpd_timeout;
    EV_ADD  ev_arg;
    
	
    DBG(DBG_DPD, DBG_log("processing dpd for state #%lu (\"%s\")"
			 , p1st->st_serialno
			 , p1st->st_connection->name));

    /* If no DPD, then get out of here */
    if (!p1st->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();

    
    if (!p1st->st_dpd_seqno)
    {   
        p1st->st_dpd_seqno = dpd_seqno++;
    }    
    seqno = htonl(p1st->st_dpd_seqno);

	/* 如果dpd事件为空,添加dpd事件 */
	if(p1st->st_dpd_event == NULL)
	{
	    ev_arg.u.st = p1st;
		event_schedule(EVENT_DPD, p1st->st_connection->dpd_delay, &ev_arg);
	}

	/* 如果dpd超时事件为空,添加dpd超时事件 */
    if(p1st->st_dpd_timeout_event == NULL)
	{
		passert(timeout > 0);     
		ev_arg.u.st = p1st;
		event_schedule(EVENT_DPD_TIMEOUT, timeout, &ev_arg);   		
	}
	DBG(DBG_DPD, DBG_log("sending R_U_THERE %u to %s:%d (state #%lu)"
			 , seqno
			 , ip_str(&p1st->st_remoteaddr)
			 , p1st->st_remoteport
			 , p1st->st_serialno));

	if(p1st->hidden_variables.st_is_dp_dev && p1st->st_connection->modecfg_quick_dpd )
	{
		if (send_quick_isakmp_notification(p1st, R_U_THERE, &seqno, sizeof(seqno)) != STF_IGNORE)
		{   
       		IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, 
					"QUICK DPD Error: connection(%s) send R_U_THERE error\n", p1st->st_connection->name);
       	 	return;	
    	}
	}
	else
	{
		if (send_isakmp_notification(p1st, R_U_THERE, &seqno, sizeof(seqno)) != STF_IGNORE)
		{	
			IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, 
					"DPD Error: connection(%s) send R_U_THERE error\n", p1st->st_connection->name);
			return; 
		}
	}

  	p1st->st_dpd_expectseqno = p1st->st_dpd_seqno++;
}
示例#10
0
文件: dpd.c 项目: millken/zhuxianB30
/*****************************************************************************************   
 函数名称: dpd_inR
 功能描述: 处理R_U_THERE_ACK 报文,判断报文长度是否正确以及通过序列号判断
 		   报文是否是自己想要的
 输入参数: p1st,n,pbs
 输出参数: 无
 返 回 值: stf_status
-------------------------------------------------------------------------------------------    
 最近一次修改记录 :    
 修改作者: 王之云    
 修改目的: ACk处理   
 修改日期: 2012年3月20日
********************************************************************************************/ 
stf_status dpd_inR(struct state *p1st, struct isakmp_notification *const n, pb_stream *pbs)
{

    EV_ADD ev_arg;     
    
    
	if(!p1st->hidden_variables.st_is_dp_dev)
	{
	    time_t tm = now();
	    u_int32_t seqno;
        

	    char buf_remoteip[20] = {0};
		addrtot(&p1st->st_remoteaddr, 0, buf_remoteip, sizeof(buf_remoteip));

	    if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state))
	    {
	        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "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)
	    {
	       IPSEC_log(IPSEC_LOGLEVEL_ERROR, 
		   	            "<%s> < %s > R_U_THERE_ACK has invalid SPI length (%d)",
		   	            p1st->st_connection->name, buf_remoteip, n->isan_spisize);
	        return STF_FAIL + PAYLOAD_MALFORMED;
	    }
	     
	    if (memcmp(pbs->cur, p1st->st_icookie, COOKIE_SIZE) != 0)
	    {
	        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "R_U_THERE_ACK has invalid icookie");
	    }
		
	    pbs->cur += COOKIE_SIZE;
	    
	    if (memcmp(pbs->cur, p1st->st_rcookie, COOKIE_SIZE) != 0)
	    {
	        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "R_U_THERE_ACK has invalid rcookie (tolerated)");
	    }
		
	    pbs->cur += COOKIE_SIZE;
	    
	    if (pbs_left(pbs) != sizeof(seqno))
	    {
	        IPSEC_log(IPSEC_LOGLEVEL_ERROR, 
				"<%s> < %s > R_U_THERE_ACK has invalid data length (%d)",
				p1st->st_connection->name, buf_remoteip, (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 (seqno != p1st->st_dpd_expectseqno) 
		{
		    IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "R_U_THERE_ACK has unexpected sequence number (expected: %u got: %u", seqno, p1st->st_dpd_expectseqno);
			return STF_IGNORE;
		}
		else 
	    {
	        p1st->st_last_dpd = tm;
	    }

	}
	
    if(p1st->st_dpd_timeout_event != NULL)
	{
	    ev_arg.u.st = p1st;  
		disable_event(EVENT_DPD_TIMEOUT, &ev_arg);
    }
	
    return STF_IGNORE;
}       
示例#11
0
文件: dpd.c 项目: millken/zhuxianB30
 /*****************************************************************************************   
 函数名称: dpd_inI_outR
 功能描述: 处理R_U_THERE报文,判断R_U_THERE报文长度是否正确以及
 			通过序列号判断自己想要的报文
 输入参数: p1st,n,pbs
 输出参数: stf_status
 返 回 值: 无
-------------------------------------------------------------------------------------------    
 最近一次修改记录 :    
 修改作者: 王之云    
 修改目的: dpd_outI处理  
 修改日期: 2012年3月20日
********************************************************************************************/  	 
stf_status dpd_inI_outR(struct state *p1st, 
                        struct isakmp_notification *const n, pb_stream *pbs)
{
    time_t tm = now();
    u_int32_t seqno;
    char buf_remoteip[20] = {0};
    EV_ADD ev_arg;


    
	addrtot(&p1st->st_remoteaddr, 0, buf_remoteip, sizeof(buf_remoteip));
	
    if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state))
    {   
        return STF_IGNORE;
    }
    if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2)
    {
        IPSEC_log(IPSEC_LOGLEVEL_ERROR, 
			"<%s> < %s > DPD Error: R_U_THERE has invalid SPI length (%d)", 
			p1st->st_connection->name, buf_remoteip, n->isan_spisize);
        return STF_FAIL + PAYLOAD_MALFORMED;
    }
        
    if (memcmp(pbs->cur, p1st->st_icookie, COOKIE_SIZE) != 0)
    {
        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, 
			"DPD Warning: R_U_THERE has invalid icookie (broken Cisco?)");
    }
    pbs->cur += COOKIE_SIZE;
    
    if (memcmp(pbs->cur, p1st->st_rcookie, COOKIE_SIZE) != 0)
    {
        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, 
			"DPD Warning: R_U_THERE has invalid rcookie (broken Cisco?)");      
    }
    pbs->cur += COOKIE_SIZE;

    if (pbs_left(pbs) != sizeof(seqno))
    {
       IPSEC_log(IPSEC_LOGLEVEL_ERROR, 
	   	            "<%s> < %s > DPD Error: R_U_THERE has invalid data length (%d)", 
	   	            p1st->st_connection->name, buf_remoteip, (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) 
	{
        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, 
			"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)
    {
        IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, 
			"DPD Info: could not send R_U_THERE_ACK"); 
        return STF_IGNORE;
    }

    p1st->st_last_dpd = tm;

    if(p1st->st_dpd_timeout_event != NULL) 
	{
	    ev_arg.u.st = p1st;
		disable_event(EVENT_DPD_TIMEOUT, &ev_arg);
    }

    return STF_IGNORE;
}