[Openswan dev] Problem and proposed bug fix to Openswan when the system's time jumps forward multiple decades
arichards at cybertec.com.au
Thu Aug 4 01:33:53 EDT 2011
As requested by LetoTo I have forwarded my IRC message to email.
I came across a bug in Openswan. The box starts up. Openswan
connects. The date is set back to 1970, NTPD is started and sets the
date to be 2011.
After this, the command "ipsec auto --status" blocks indefinitely.
Analysis (based on 2.4 and verified in 2.6) is that in
timer.c:next_event(), the expression *evlist->ev_time - now()* is
negative (ev_time is 40 years ago). Hence next_event() returns 0,
causing the event to be triggered.
But when handle_timer_event() is called, the expression *now() <
ev->ev_time* evaluates to TRUE (due to long wrapping???), meaning that
the event is not removed from the event list.
Looking at /server.c/, the code becomes stuck in the loop ... in
/call_server()/ next_event() returns 0. This then sets ndes to 0 (and
osw_select() is NOT called). But when handle_timer_event() is called,
the function believes that there are no events to handle, so the event
queue does not change. So when call_server() loops it calls
next_event() which returns 0 again.
This blocks the thread from calling the select() function to handle all
the file descriptors. Hence *ipsec auto --status* never gets a reply to
its request, and will block forever. Likewise, all communications into
Openswan never gets a reply.
A proposed solution (that I have tested successfully in version 2.4) is
to change now() to use the systems uptime instead. This solution also
has the benefit that timing jitter is not introduced by people setting
the time on a device or programs such as ntpd.
Let me know if you have any questions.
*Proposed diff ...
diff --git a/lib/libopenswan/oswtime.c b/lib/libopenswan/oswtime.c
index 6440258..7e17529 100644
@@ -22,6 +22,7 @@
@@ -34,18 +35,18 @@
- static time_t delta = 0
- , last_time = 0;
- time_t n = time(NULL);
+ * Use uptime as it cannot jump unexpentantly,
+ * for example, when the time is changed forwards or backwards.
+ struct sysinfo info;
- passert(n != (time_t)-1);
- if (last_time > n)
+ if (sysinfo(&info) == 0)
- openswan_log("time moved backwards %ld seconds",
(long)(last_time - n));
- delta += last_time - n;
+ return (time_t)info.uptime;
- last_time = n;
- return n + delta;
+ return 0;
/* Names of the months */
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Dev