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);
 }

Reply via email to