コード例 #1
0
ファイル: dpd.c プロジェクト: qianguozheng/Openswan
/**
 * 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;
}
コード例 #2
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++;
}
コード例 #3
0
ファイル: dpd.c プロジェクト: qianguozheng/Openswan
/**
 * 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++;

}
コード例 #4
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;
}