conversion from 8 spaces to 4 spaces per tab
This commit is contained in:
+403
-403
@@ -31,7 +31,7 @@
|
||||
#include "connections.h"
|
||||
#include "state.h"
|
||||
#include "demux.h"
|
||||
#include "ipsec_doi.h" /* needs demux.h and state.h */
|
||||
#include "ipsec_doi.h" /* needs demux.h and state.h */
|
||||
#include "kernel.h"
|
||||
#include "server.h"
|
||||
#include "log.h"
|
||||
@@ -44,18 +44,18 @@
|
||||
time_t
|
||||
now(void)
|
||||
{
|
||||
static time_t delta = 0
|
||||
, last_time = 0;
|
||||
time_t n = time((time_t)NULL);
|
||||
static time_t delta = 0
|
||||
, last_time = 0;
|
||||
time_t n = time((time_t)NULL);
|
||||
|
||||
passert(n != (time_t)-1);
|
||||
if (last_time > n)
|
||||
{
|
||||
plog("time moved backwards %ld seconds", (long)(last_time - n));
|
||||
delta += last_time - n;
|
||||
}
|
||||
last_time = n;
|
||||
return n + delta;
|
||||
passert(n != (time_t)-1);
|
||||
if (last_time > n)
|
||||
{
|
||||
plog("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
|
||||
@@ -72,67 +72,67 @@ static struct event *evlist = (struct event *) NULL;
|
||||
void
|
||||
event_schedule(enum event_type type, time_t tm, struct state *st)
|
||||
{
|
||||
struct event *ev = malloc_thing(struct event);
|
||||
struct event *ev = malloc_thing(struct event);
|
||||
|
||||
ev->ev_type = type;
|
||||
ev->ev_time = tm + now();
|
||||
ev->ev_state = st;
|
||||
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)
|
||||
/* 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)
|
||||
{
|
||||
passert(st->st_dpd_event == NULL);
|
||||
st->st_dpd_event = ev;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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));
|
||||
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;
|
||||
}
|
||||
ev->ev_next = evt->ev_next;
|
||||
evt->ev_next = ev;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -141,299 +141,299 @@ event_schedule(enum event_type type, time_t tm, struct state *st)
|
||||
void
|
||||
handle_timer_event(void)
|
||||
{
|
||||
time_t tm;
|
||||
struct event *ev = evlist;
|
||||
int type;
|
||||
struct state *st;
|
||||
struct connection *c = NULL;
|
||||
ip_address peer;
|
||||
time_t tm;
|
||||
struct event *ev = evlist;
|
||||
int type;
|
||||
struct state *st;
|
||||
struct connection *c = NULL;
|
||||
ip_address peer;
|
||||
|
||||
if (ev == (struct event *) NULL) /* Just paranoid */
|
||||
{
|
||||
DBG(DBG_CONTROL, DBG_log("empty event list, yet we're called"));
|
||||
return;
|
||||
}
|
||||
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;
|
||||
type = ev->ev_type;
|
||||
st = ev->ev_state;
|
||||
|
||||
tm = now();
|
||||
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)));
|
||||
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.
|
||||
/* 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,
|
||||
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)));
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
evlist = evlist->ev_next; /* Ok, we'll handle this event */
|
||||
|
||||
DBG(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)));
|
||||
|
||||
/* 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(GLOBALS_ARE_RESET());
|
||||
if (st != NULL)
|
||||
{
|
||||
passert(st->st_dpd_event == ev);
|
||||
st->st_dpd_event = 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);
|
||||
}
|
||||
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;
|
||||
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;
|
||||
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.
|
||||
*/
|
||||
{
|
||||
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
|
||||
&& c->sa_keying_tries == 0
|
||||
&& st->st_retransmit < MAXIMUM_RETRANSMISSIONS_INITIAL)
|
||||
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";
|
||||
case EVENT_LOG_DAILY:
|
||||
daily_log_event();
|
||||
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";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
loglog(RC_NORETRANSMISSION
|
||||
, "max number of retransmissions (%d) reached %s%s"
|
||||
, st->st_retransmit
|
||||
, enum_show(&state_names, st->st_state), details);
|
||||
if (try != 0 && try != try_limit)
|
||||
{
|
||||
/* A lot like EVENT_SA_REPLACE, but over again.
|
||||
* Since we know that st cannot be in use,
|
||||
* we can delete it right away.
|
||||
|
||||
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.
|
||||
*/
|
||||
char story[80]; /* arbitrary limit */
|
||||
|
||||
try++;
|
||||
snprintf(story, sizeof(story), try_limit == 0
|
||||
? "starting keying attempt %ld of an unlimited number"
|
||||
: "starting keying attempt %ld of at most %ld"
|
||||
, try, try_limit);
|
||||
|
||||
if (st->st_whack_sock != NULL_FD)
|
||||
{
|
||||
/* Release whack because the observer will get bored. */
|
||||
loglog(RC_COMMENT, "%s, but releasing whack"
|
||||
, story);
|
||||
release_pending_whacks(st, story);
|
||||
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
|
||||
&& c->sa_keying_tries == 0
|
||||
&& st->st_retransmit < MAXIMUM_RETRANSMISSIONS_INITIAL)
|
||||
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";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
loglog(RC_NORETRANSMISSION
|
||||
, "max number of retransmissions (%d) reached %s%s"
|
||||
, st->st_retransmit
|
||||
, enum_show(&state_names, st->st_state), details);
|
||||
if (try != 0 && try != try_limit)
|
||||
{
|
||||
/* A lot like EVENT_SA_REPLACE, but over again.
|
||||
* Since we know that st cannot be in use,
|
||||
* we can delete it right away.
|
||||
*/
|
||||
char story[80]; /* arbitrary limit */
|
||||
|
||||
try++;
|
||||
snprintf(story, sizeof(story), try_limit == 0
|
||||
? "starting keying attempt %ld of an unlimited number"
|
||||
: "starting keying attempt %ld of at most %ld"
|
||||
, try, try_limit);
|
||||
|
||||
if (st->st_whack_sock != NULL_FD)
|
||||
{
|
||||
/* Release whack because the observer will get bored. */
|
||||
loglog(RC_COMMENT, "%s, but releasing whack"
|
||||
, story);
|
||||
release_pending_whacks(st, story);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no whack: just log to syslog */
|
||||
plog("%s", story);
|
||||
}
|
||||
ipsecdoi_replace(st, try);
|
||||
}
|
||||
delete_state(st);
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
case EVENT_SA_REPLACE:
|
||||
case EVENT_SA_REPLACE_IF_USED:
|
||||
{
|
||||
/* no whack: just log to syslog */
|
||||
plog("%s", story);
|
||||
so_serial_t newest = IS_PHASE1(st->st_state)
|
||||
? c->newest_isakmp_sa : c->newest_ipsec_sa;
|
||||
|
||||
if (newest != st->st_serialno
|
||||
&& newest != SOS_NOBODY)
|
||||
{
|
||||
/* not very interesting: no need to replace */
|
||||
DBG(DBG_LIFECYCLE
|
||||
, plog("not replacing stale %s SA: #%lu will do"
|
||||
, IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"
|
||||
, newest));
|
||||
}
|
||||
else if (type == EVENT_SA_REPLACE_IF_USED
|
||||
&& st->st_outbound_time <= tm - c->sa_rekey_margin)
|
||||
{
|
||||
/* we observed no recent use: no need to replace
|
||||
*
|
||||
* The sampling effects mean that st_outbound_time
|
||||
* could be up to SHUNT_SCAN_INTERVAL more recent
|
||||
* than actual traffic because the sampler looks at change
|
||||
* over that interval.
|
||||
* st_outbound_time could also not yet reflect traffic
|
||||
* in the last SHUNT_SCAN_INTERVAL.
|
||||
* We expect that SHUNT_SCAN_INTERVAL is smaller than
|
||||
* c->sa_rekey_margin so that the effects of this will
|
||||
* be unimportant.
|
||||
* This is just an optimization: correctness is not
|
||||
* at stake.
|
||||
*
|
||||
* Note: we are abusing the DBG mechanism to control
|
||||
* normal log output.
|
||||
*/
|
||||
DBG(DBG_LIFECYCLE
|
||||
, plog("not replacing stale %s SA: inactive for %lus"
|
||||
, IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"
|
||||
, (unsigned long)(tm - st->st_outbound_time)));
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(DBG_LIFECYCLE
|
||||
, plog("replacing stale %s SA"
|
||||
, IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"));
|
||||
ipsecdoi_replace(st, 1);
|
||||
}
|
||||
delete_dpd_event(st);
|
||||
event_schedule(EVENT_SA_EXPIRE, st->st_margin, st);
|
||||
}
|
||||
ipsecdoi_replace(st, try);
|
||||
}
|
||||
delete_state(st);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case EVENT_SA_REPLACE:
|
||||
case EVENT_SA_REPLACE_IF_USED:
|
||||
{
|
||||
so_serial_t newest = IS_PHASE1(st->st_state)
|
||||
? c->newest_isakmp_sa : c->newest_ipsec_sa;
|
||||
case EVENT_SA_EXPIRE:
|
||||
{
|
||||
const char *satype;
|
||||
so_serial_t latest;
|
||||
|
||||
if (newest != st->st_serialno
|
||||
&& newest != SOS_NOBODY)
|
||||
{
|
||||
/* not very interesting: no need to replace */
|
||||
DBG(DBG_LIFECYCLE
|
||||
, plog("not replacing stale %s SA: #%lu will do"
|
||||
, IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"
|
||||
, newest));
|
||||
}
|
||||
else if (type == EVENT_SA_REPLACE_IF_USED
|
||||
&& st->st_outbound_time <= tm - c->sa_rekey_margin)
|
||||
{
|
||||
/* we observed no recent use: no need to replace
|
||||
*
|
||||
* The sampling effects mean that st_outbound_time
|
||||
* could be up to SHUNT_SCAN_INTERVAL more recent
|
||||
* than actual traffic because the sampler looks at change
|
||||
* over that interval.
|
||||
* st_outbound_time could also not yet reflect traffic
|
||||
* in the last SHUNT_SCAN_INTERVAL.
|
||||
* We expect that SHUNT_SCAN_INTERVAL is smaller than
|
||||
* c->sa_rekey_margin so that the effects of this will
|
||||
* be unimportant.
|
||||
* This is just an optimization: correctness is not
|
||||
* at stake.
|
||||
*
|
||||
* Note: we are abusing the DBG mechanism to control
|
||||
* normal log output.
|
||||
*/
|
||||
DBG(DBG_LIFECYCLE
|
||||
, plog("not replacing stale %s SA: inactive for %lus"
|
||||
, IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"
|
||||
, (unsigned long)(tm - st->st_outbound_time)));
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(DBG_LIFECYCLE
|
||||
, plog("replacing stale %s SA"
|
||||
, IS_PHASE1(st->st_state)? "ISAKMP" : "IPsec"));
|
||||
ipsecdoi_replace(st, 1);
|
||||
}
|
||||
delete_dpd_event(st);
|
||||
event_schedule(EVENT_SA_EXPIRE, st->st_margin, st);
|
||||
}
|
||||
break;
|
||||
if (IS_PHASE1(st->st_state))
|
||||
{
|
||||
satype = "ISAKMP";
|
||||
latest = c->newest_isakmp_sa;
|
||||
}
|
||||
else
|
||||
{
|
||||
satype = "IPsec";
|
||||
latest = c->newest_ipsec_sa;
|
||||
}
|
||||
|
||||
case EVENT_SA_EXPIRE:
|
||||
{
|
||||
const char *satype;
|
||||
so_serial_t latest;
|
||||
if (st->st_serialno != latest)
|
||||
{
|
||||
/* not very interesting: already superseded */
|
||||
DBG(DBG_LIFECYCLE
|
||||
, plog("%s SA expired (superseded by #%lu)"
|
||||
, satype, latest));
|
||||
}
|
||||
else
|
||||
{
|
||||
plog("%s SA expired (%s)", satype
|
||||
, (c->policy & POLICY_DONT_REKEY)
|
||||
? "--dontrekey"
|
||||
: "LATEST!"
|
||||
);
|
||||
}
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case EVENT_SO_DISCARD:
|
||||
/* Delete this state object. It must be in the hash table. */
|
||||
delete_state(st);
|
||||
break;
|
||||
|
||||
if (IS_PHASE1(st->st_state))
|
||||
{
|
||||
satype = "ISAKMP";
|
||||
latest = c->newest_isakmp_sa;
|
||||
}
|
||||
else
|
||||
{
|
||||
satype = "IPsec";
|
||||
latest = c->newest_ipsec_sa;
|
||||
}
|
||||
case EVENT_DPD:
|
||||
dpd_outI(st);
|
||||
break;
|
||||
case EVENT_DPD_TIMEOUT:
|
||||
dpd_timeout(st);
|
||||
break;
|
||||
case EVENT_NAT_T_KEEPALIVE:
|
||||
nat_traversal_ka_event();
|
||||
break;
|
||||
default:
|
||||
loglog(RC_LOG_SERIOUS, "INTERNAL ERROR: ignoring unknown expiring event %s"
|
||||
, enum_show(&timer_event_names, type));
|
||||
}
|
||||
|
||||
if (st->st_serialno != latest)
|
||||
{
|
||||
/* not very interesting: already superseded */
|
||||
DBG(DBG_LIFECYCLE
|
||||
, plog("%s SA expired (superseded by #%lu)"
|
||||
, satype, latest));
|
||||
}
|
||||
else
|
||||
{
|
||||
plog("%s SA expired (%s)", satype
|
||||
, (c->policy & POLICY_DONT_REKEY)
|
||||
? "--dontrekey"
|
||||
: "LATEST!"
|
||||
);
|
||||
}
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case EVENT_SO_DISCARD:
|
||||
/* Delete this state object. It must be in the hash table. */
|
||||
delete_state(st);
|
||||
break;
|
||||
|
||||
case EVENT_DPD:
|
||||
dpd_outI(st);
|
||||
break;
|
||||
case EVENT_DPD_TIMEOUT:
|
||||
dpd_timeout(st);
|
||||
break;
|
||||
case EVENT_NAT_T_KEEPALIVE:
|
||||
nat_traversal_ka_event();
|
||||
break;
|
||||
default:
|
||||
loglog(RC_LOG_SERIOUS, "INTERNAL ERROR: ignoring unknown expiring event %s"
|
||||
, enum_show(&timer_event_names, type));
|
||||
}
|
||||
|
||||
free(ev);
|
||||
reset_cur_state();
|
||||
free(ev);
|
||||
reset_cur_state();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -443,28 +443,28 @@ handle_timer_event(void)
|
||||
long
|
||||
next_event(void)
|
||||
{
|
||||
time_t tm;
|
||||
time_t tm;
|
||||
|
||||
if (evlist == (struct event *) NULL)
|
||||
return -1;
|
||||
if (evlist == (struct event *) NULL)
|
||||
return -1;
|
||||
|
||||
tm = now();
|
||||
tm = now();
|
||||
|
||||
DBG(DBG_CONTROL,
|
||||
if (evlist->ev_state == NULL)
|
||||
DBG_log("next event %s in %ld seconds"
|
||||
, enum_show(&timer_event_names, evlist->ev_type)
|
||||
, (long)evlist->ev_time - (long)tm);
|
||||
DBG(DBG_CONTROL,
|
||||
if (evlist->ev_state == NULL)
|
||||
DBG_log("next event %s in %ld seconds"
|
||||
, enum_show(&timer_event_names, evlist->ev_type)
|
||||
, (long)evlist->ev_time - (long)tm);
|
||||
else
|
||||
DBG_log("next event %s in %ld seconds for #%lu"
|
||||
, enum_show(&timer_event_names, evlist->ev_type)
|
||||
, (long)evlist->ev_time - (long)tm
|
||||
, evlist->ev_state->st_serialno));
|
||||
|
||||
if (evlist->ev_time - tm <= 0)
|
||||
return 0;
|
||||
else
|
||||
DBG_log("next event %s in %ld seconds for #%lu"
|
||||
, enum_show(&timer_event_names, evlist->ev_type)
|
||||
, (long)evlist->ev_time - (long)tm
|
||||
, evlist->ev_state->st_serialno));
|
||||
|
||||
if (evlist->ev_time - tm <= 0)
|
||||
return 0;
|
||||
else
|
||||
return evlist->ev_time - tm;
|
||||
return evlist->ev_time - tm;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -473,33 +473,33 @@ next_event(void)
|
||||
void
|
||||
delete_event(struct state *st)
|
||||
{
|
||||
if (st->st_event != (struct event *) NULL)
|
||||
{
|
||||
struct event **ev;
|
||||
|
||||
for (ev = &evlist; ; ev = &(*ev)->ev_next)
|
||||
if (st->st_event != (struct event *) NULL)
|
||||
{
|
||||
if (*ev == NULL)
|
||||
{
|
||||
DBG(DBG_CONTROL, DBG_log("event %s to be deleted not found",
|
||||
enum_show(&timer_event_names, st->st_event->ev_type)));
|
||||
break;
|
||||
}
|
||||
if ((*ev) == st->st_event)
|
||||
{
|
||||
*ev = (*ev)->ev_next;
|
||||
struct event **ev;
|
||||
|
||||
if (st->st_event->ev_type == EVENT_RETRANSMIT)
|
||||
for (ev = &evlist; ; ev = &(*ev)->ev_next)
|
||||
{
|
||||
st->st_retransmit = 0;
|
||||
}
|
||||
free(st->st_event);
|
||||
st->st_event = (struct event *) NULL;
|
||||
if (*ev == NULL)
|
||||
{
|
||||
DBG(DBG_CONTROL, DBG_log("event %s to be deleted not found",
|
||||
enum_show(&timer_event_names, st->st_event->ev_type)));
|
||||
break;
|
||||
}
|
||||
if ((*ev) == st->st_event)
|
||||
{
|
||||
*ev = (*ev)->ev_next;
|
||||
|
||||
break;
|
||||
}
|
||||
if (st->st_event->ev_type == EVENT_RETRANSMIT)
|
||||
{
|
||||
st->st_retransmit = 0;
|
||||
}
|
||||
free(st->st_event);
|
||||
st->st_event = (struct event *) NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -508,27 +508,27 @@ delete_event(struct state *st)
|
||||
void
|
||||
delete_dpd_event(struct state *st)
|
||||
{
|
||||
if (st->st_dpd_event != (struct event *) NULL)
|
||||
{
|
||||
struct event **ev;
|
||||
if (st->st_dpd_event != (struct event *) NULL)
|
||||
{
|
||||
struct event **ev;
|
||||
|
||||
for (ev = &evlist; ; ev = &(*ev)->ev_next)
|
||||
{
|
||||
if (*ev == NULL)
|
||||
{
|
||||
DBG(DBG_CONTROL, DBG_log("event %s to be deleted not found",
|
||||
enum_show(&timer_event_names, st->st_dpd_event->ev_type)));
|
||||
break;
|
||||
}
|
||||
if ((*ev) == st->st_dpd_event)
|
||||
{
|
||||
*ev = (*ev)->ev_next;
|
||||
free(st->st_dpd_event);
|
||||
st->st_dpd_event = (struct event *) NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ev = &evlist; ; ev = &(*ev)->ev_next)
|
||||
{
|
||||
if (*ev == NULL)
|
||||
{
|
||||
DBG(DBG_CONTROL, DBG_log("event %s to be deleted not found",
|
||||
enum_show(&timer_event_names, st->st_dpd_event->ev_type)));
|
||||
break;
|
||||
}
|
||||
if ((*ev) == st->st_dpd_event)
|
||||
{
|
||||
*ev = (*ev)->ev_next;
|
||||
free(st->st_dpd_event);
|
||||
st->st_dpd_event = (struct event *) NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -537,16 +537,16 @@ delete_dpd_event(struct state *st)
|
||||
void
|
||||
free_events(void)
|
||||
{
|
||||
struct event *ev_tmp, *ev;
|
||||
struct event *ev_tmp, *ev;
|
||||
|
||||
ev = evlist;
|
||||
evlist = NULL;
|
||||
ev = evlist;
|
||||
evlist = NULL;
|
||||
|
||||
while (ev)
|
||||
{
|
||||
ev_tmp = ev;
|
||||
ev = ev->ev_next;
|
||||
free(ev_tmp);
|
||||
}
|
||||
while (ev)
|
||||
{
|
||||
ev_tmp = ev;
|
||||
ev = ev->ev_next;
|
||||
free(ev_tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user