⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timer.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 2 页
字号:
/* timer event handling * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2001  D. Hugh Redelmeier. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * for more details. * * RCSID $Id: timer.c,v 1.96 2004/11/30 16:11:04 mcr Exp $ */#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <time.h>#include <unistd.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/queue.h>#include <openswan.h>#include "constants.h"#include "defs.h"#include "id.h"#include "x509.h"#include "pgp.h"#include "certs.h"#include "smartcard.h"#ifdef XAUTH_USEPAM#include <security/pam_appl.h>#endif#include "connections.h"	/* needs id.h */#include "state.h"#include "packet.h"#include "demux.h"  /* needs packet.h */#include "ipsec_doi.h"	/* needs demux.h and state.h */#include "kernel.h"	/* needs connections.h */#include "server.h"#include "log.h"#include "rnd.h"#include "timer.h"#include "whack.h"#include "dpd.h"#ifdef NAT_TRAVERSAL#include "nat_traversal.h"#endif/* monotonic version of time(3) */time_tnow(void){    static time_t delta = 0	, last_time = 0;    time_t n = time((time_t)NULL);    passert(n != (time_t)-1);    if (last_time > n)    {	openswan_log("time moved backwards %ld seconds", (long)(last_time - n));	delta += last_time - n;    }    last_time = n;    return n + delta;}/* This file has the event handling routines. Events are * kept as a linked list of event structures. These structures * have information like event type, expiration time and a pointer * to event specific data (for example, to a state structure). */static struct event *evlist = (struct event *) NULL;/* * This routine places an event in the event list. */voidevent_schedule(enum event_type type, time_t tm, struct state *st){    struct event *ev = alloc_thing(struct event, "struct event in event_schedule()");    passert(tm >= 0);    ev->ev_type = type;    ev->ev_time = tm + now();    ev->ev_state = st;    /* If the event is associated with a state, put a backpointer to the     * event in the state object, so we can find and delete the event     * if we need to (for example, if we receive a reply).     */    if (st != NULL)    {            if(type == EVENT_DPD || type == EVENT_DPD_TIMEOUT)            {                    passert(st->st_dpd_event == NULL);                    st->st_dpd_event = ev;            } else {        passert(st->st_event == NULL);        st->st_event = ev;    }    }    DBG(DBG_CONTROL,	if (st == NULL)	    DBG_log("inserting event %s, timeout in %lu seconds"		, enum_show(&timer_event_names, type), (unsigned long)tm);	else	    DBG_log("inserting event %s, timeout in %lu seconds for #%lu"		, enum_show(&timer_event_names, type), (unsigned long)tm		, ev->ev_state->st_serialno));    if (evlist == (struct event *) NULL    || evlist->ev_time >= ev->ev_time)    {	ev->ev_next = evlist;	evlist = ev;    }    else    {	struct event *evt;	for (evt = evlist; evt->ev_next != NULL; evt = evt->ev_next)	    if (evt->ev_next->ev_time >= ev->ev_time)		break;#ifdef NEVER	/* this seems to be overkill */	DBG(DBG_CONTROL,	    if (evt->ev_state == NULL)		DBG_log("event added after event %s"		    , enum_show(&timer_event_names, evt->ev_type));	    else		DBG_log("event added after event %s for #%lu"		    , enum_show(&timer_event_names, evt->ev_type)		    , evt->ev_state->st_serialno));#endif /* NEVER */	ev->ev_next = evt->ev_next;	evt->ev_next = ev;    }}/* * Handle the first event on the list. */voidhandle_timer_event(void){    time_t tm;    struct event *ev = evlist;    int type;    struct state *st;    struct connection *c;    ip_address peer;    if (ev == (struct event *) NULL)    /* Just paranoid */    {	DBG(DBG_CONTROL, DBG_log("empty event list, yet we're called"));	return;    }    type = ev->ev_type;    st = ev->ev_state;    tm = now();    if (tm < ev->ev_time)    {	DBG(DBG_CONTROL, DBG_log("called while no event expired (%lu/%lu, %s)"	    , (unsigned long)tm, (unsigned long)ev->ev_time	    , enum_show(&timer_event_names, type)));	/* This will happen if the most close-to-expire event was	 * a retransmission or cleanup, and we received a packet	 * at the same time as the event expired. Due to the processing	 * order in call_server(), the packet processing will happen first,	 * and the event will be removed.	 */	return;    }    evlist = evlist->ev_next;		/* Ok, we'll handle this event */    DBG(DBG_CONTROL, DBG_log("handling event %s"			     , enum_show(&timer_event_names, type)));    if(DBGP(DBG_CONTROL)) {	if (evlist != (struct event *) NULL) {	    DBG_log("event after this is %s in %ld seconds"		    , enum_show(&timer_event_names, evlist->ev_type)		    , (long) (evlist->ev_time - tm));	}	else {	    DBG_log("no more events are scheduled");	}	        }    /* for state-associated events, pick up the state pointer     * and remove the backpointer from the state object.     * We'll eventually either schedule a new event, or delete the state.     */    passert(GLOBALS_ARE_RESET());    if (st != NULL)    {	c = st->st_connection;        if( type  == EVENT_DPD || type == EVENT_DPD_TIMEOUT)        {                passert(st->st_dpd_event == ev);                st->st_dpd_event = NULL;        } else {	    passert(st->st_event == ev);	    st->st_event = NULL;        }	peer = c->spd.that.host_addr;	set_cur_state(st);    }    switch (type)    {	case EVENT_REINIT_SECRET:	    passert(st == NULL);	    DBG(DBG_CONTROL, DBG_log("event EVENT_REINIT_SECRET handled"));	    init_secret();	    break;#ifdef KLIPS	case EVENT_SHUNT_SCAN:	    passert(st == NULL);	    scan_proc_shunts();	    break;#endif	case EVENT_LOG_DAILY:	    daily_log_event();	    break;	case EVENT_RETRANSMIT:	    /* Time to retransmit, or give up.	     *	     * Generally, we'll only try to send the message	     * MAXIMUM_RETRANSMISSIONS times.  Each time we double	     * our patience.	     *	     * As a special case, if this is the first initiating message	     * of a Main Mode exchange, and we have been directed to try	     * forever, we'll extend the number of retransmissions to	     * MAXIMUM_RETRANSMISSIONS_INITIAL times, with all these	     * extended attempts having the same patience.  The intention	     * is to reduce the bother when nobody is home.	     *	     * Since IKEv1 is not reliable for the Quick Mode responder,	     * we'll extend the number of retransmissions as well to	     * improve the reliability.	     */	    {		time_t delay = 0;		DBG(DBG_CONTROL, DBG_log(		    "handling event EVENT_RETRANSMIT for %s \"%s\" #%lu"		    , ip_str(&peer), c->name, st->st_serialno));		if (st->st_retransmit < MAXIMUM_RETRANSMISSIONS)		    delay = EVENT_RETRANSMIT_DELAY_0 << (st->st_retransmit + 1);		else if ((st->st_state == STATE_MAIN_I1 || st->st_state == STATE_AGGR_I1)		&& c->sa_keying_tries == 0		&& st->st_retransmit < MAXIMUM_RETRANSMISSIONS_INITIAL)		    delay = EVENT_RETRANSMIT_DELAY_0 << MAXIMUM_RETRANSMISSIONS;		else if (st->st_state == STATE_QUICK_R1		&& st->st_retransmit < MAXIMUM_RETRANSMISSIONS_QUICK_R1)		    delay = EVENT_RETRANSMIT_DELAY_0 << MAXIMUM_RETRANSMISSIONS;		if (delay != 0)		{		    st->st_retransmit++;		    whack_log(RC_RETRANSMISSION			, "%s: retransmission; will wait %lus for response"			, enum_name(&state_names, st->st_state)			, (unsigned long)delay);		    send_packet(st, "EVENT_RETRANSMIT");		    event_schedule(EVENT_RETRANSMIT, delay, st);		}		else		{		    /* check if we've tried rekeying enough times.		     * st->st_try == 0 means that this should be the only try.		     * c->sa_keying_tries == 0 means that there is no limit.		     */		    unsigned long try = st->st_try;		    unsigned long try_limit = c->sa_keying_tries;		    const char *details = "";		    switch (st->st_state)		    {		    case STATE_MAIN_I3:			details = ".  Possible authentication failure:"			    " no acceptable response to our"			    " first encrypted message";			break;		    case STATE_MAIN_I1:			details = ".  No response (or no acceptable response) to our"			    " first IKE message";			break;		    case STATE_QUICK_I1:			if (c->newest_ipsec_sa == SOS_NOBODY)			    details = ".  No acceptable response to our"				" first Quick Mode message:"				" perhaps peer likes no proposal";

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -