This fixes a bug introduced in revision 1.8 of timer.c that causes
evtimer_set() to be called on an already active event, which is an error
according to event_add(3):
>The event in the ev argument must be already initialized by event_set()
>and may not be used in calls to event_set() until it has timed out or
>been removed with event_del(). If the event in the ev argument already
>has a scheduled timeout, the old timeout will be replaced by the new
>one.
The simplest way to trigger the loop is by toggling the active/passive
knob via ikectl:
$ doas ikectl active # Calls event_set() and starts 2 second timer
$ doas ikectl active # Calls event_set() on an active timer
It can also be triggered by connecting to a peer and receiving
INVALID_KE_PAYLOAD notification from it, in which case event_set() will
be called in ikev2_pld_notify().
Index: timer.c
===================================================================
RCS file: /cvs/src/sbin/iked/timer.c,v
retrieving revision 1.12
diff -u -p -r1.12 timer.c
--- timer.c 16 Jan 2015 06:39:58 -0000 1.12
+++ timer.c 8 Sep 2016 14:40:16 -0000
@@ -37,6 +37,10 @@ void
timer_set(struct iked *env, struct iked_timer *tmr,
void (*cb)(struct iked *, void *), void *arg)
{
+ if (evtimer_initialized(&tmr->tmr_ev) &&
+ evtimer_pending(&tmr->tmr_ev, NULL))
+ evtimer_del(&tmr->tmr_ev);
+
tmr->tmr_env = env;
tmr->tmr_cb = cb;
tmr->tmr_cbarg = arg;
@@ -47,10 +51,6 @@ void
timer_add(struct iked *env, struct iked_timer *tmr, int timeout)
{
struct timeval tv = { timeout };
-
- if (evtimer_initialized(&tmr->tmr_ev) &&
- evtimer_pending(&tmr->tmr_ev, NULL))
- evtimer_del(&tmr->tmr_ev);
evtimer_add(&tmr->tmr_ev, &tv);
}