|
|
371a1e |
From 348947b3d573e2187db61fb43919d2260dcfc135 Mon Sep 17 00:00:00 2001
|
|
|
1050b1 |
From: Pavel Zhukov <pzhukov@redhat.com>
|
|
|
1050b1 |
Date: Wed, 24 Jul 2019 17:15:55 +0200
|
|
|
1050b1 |
Subject: [PATCH] Detect system time jumps
|
|
|
1050b1 |
|
|
|
1050b1 |
In case if system time was changed backward it's possible to have ip
|
|
|
1050b1 |
address dropped by the kernel due to lifetime expirity. Try to detect
|
|
|
1050b1 |
this situation using either monotonic time or saved timestamp and execute
|
|
|
1050b1 |
go_reboot() procedure to request lease extention
|
|
|
1050b1 |
---
|
|
|
371a1e |
lib/isc/include/isc/result.h | 3 ++-
|
|
|
371a1e |
lib/isc/include/isc/util.h | 3 +++
|
|
|
1050b1 |
lib/isc/result.c | 2 ++
|
|
|
371a1e |
lib/isc/unix/app.c | 39 +++++++++++++++++++++++++++++----
|
|
|
371a1e |
lib/isc/unix/include/isc/time.h | 20 +++++++++++++++++
|
|
|
371a1e |
lib/isc/unix/time.c | 22 +++++++++++++++++++
|
|
|
371a1e |
6 files changed, 84 insertions(+), 5 deletions(-)
|
|
|
1050b1 |
|
|
|
1050b1 |
diff --git a/lib/isc/include/isc/result.h b/lib/isc/include/isc/result.h
|
|
|
371a1e |
index 0fd4971..2add549 100644
|
|
|
1050b1 |
--- a/lib/isc/include/isc/result.h
|
|
|
1050b1 |
+++ b/lib/isc/include/isc/result.h
|
|
|
371a1e |
@@ -87,9 +87,10 @@
|
|
|
371a1e |
#define ISC_R_CRYPTOFAILURE 65 /*%< cryptography library failure */
|
|
|
371a1e |
#define ISC_R_DISCQUOTA 66 /*%< disc quota */
|
|
|
371a1e |
#define ISC_R_DISCFULL 67 /*%< disc full */
|
|
|
371a1e |
+#define ISC_R_TIMESHIFTED 68 /*%< system time changed */
|
|
|
371a1e |
|
|
|
1050b1 |
/*% Not a result code: the number of results. */
|
|
|
371a1e |
-#define ISC_R_NRESULTS 68
|
|
|
371a1e |
+#define ISC_R_NRESULTS 69
|
|
|
1050b1 |
|
|
|
1050b1 |
ISC_LANG_BEGINDECLS
|
|
|
1050b1 |
|
|
|
1050b1 |
diff --git a/lib/isc/include/isc/util.h b/lib/isc/include/isc/util.h
|
|
|
371a1e |
index 973c348..8160dd3 100644
|
|
|
1050b1 |
--- a/lib/isc/include/isc/util.h
|
|
|
1050b1 |
+++ b/lib/isc/include/isc/util.h
|
|
|
371a1e |
@@ -289,6 +289,9 @@ extern void mock_assert(const int result, const char* const expression,
|
|
|
1050b1 |
* Time
|
|
|
1050b1 |
*/
|
|
|
1050b1 |
#define TIME_NOW(tp) RUNTIME_CHECK(isc_time_now((tp)) == ISC_R_SUCCESS)
|
|
|
1050b1 |
+#ifdef CLOCK_BOOTTIME
|
|
|
1050b1 |
+#define TIME_MONOTONIC(tp) RUNTIME_CHECK(isc_time_boottime((tp)) == ISC_R_SUCCESS)
|
|
|
1050b1 |
+#endif
|
|
|
1050b1 |
|
|
|
1050b1 |
/*%
|
|
|
371a1e |
* Alignment
|
|
|
1050b1 |
diff --git a/lib/isc/result.c b/lib/isc/result.c
|
|
|
371a1e |
index abb6ed2..8c95a93 100644
|
|
|
1050b1 |
--- a/lib/isc/result.c
|
|
|
1050b1 |
+++ b/lib/isc/result.c
|
|
|
371a1e |
@@ -103,6 +103,7 @@ static const char *description[ISC_R_NRESULTS] = {
|
|
|
371a1e |
"crypto failure", /*%< 65 */
|
|
|
371a1e |
"disc quota", /*%< 66 */
|
|
|
371a1e |
"disc full", /*%< 67 */
|
|
|
371a1e |
+ "time changed", /*%< 68 */
|
|
|
1050b1 |
};
|
|
|
1050b1 |
|
|
|
1050b1 |
static const char *identifier[ISC_R_NRESULTS] = {
|
|
|
371a1e |
@@ -174,6 +175,7 @@ static const char *identifier[ISC_R_NRESULTS] = {
|
|
|
371a1e |
"ISC_R_CRYPTOFAILURE",
|
|
|
371a1e |
"ISC_R_DISCQUOTA",
|
|
|
371a1e |
"ISC_R_DISCFULL",
|
|
|
1050b1 |
+ "ISC_R_TIMESHIFTED",
|
|
|
1050b1 |
};
|
|
|
1050b1 |
|
|
|
1050b1 |
#define ISC_RESULT_RESULTSET 2
|
|
|
1050b1 |
diff --git a/lib/isc/unix/app.c b/lib/isc/unix/app.c
|
|
|
371a1e |
index 7e5a0ee..ceab74e 100644
|
|
|
1050b1 |
--- a/lib/isc/unix/app.c
|
|
|
1050b1 |
+++ b/lib/isc/unix/app.c
|
|
|
371a1e |
@@ -442,15 +442,48 @@ isc__app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task,
|
|
|
1050b1 |
static isc_result_t
|
|
|
1050b1 |
evloop(isc__appctx_t *ctx) {
|
|
|
1050b1 |
isc_result_t result;
|
|
|
1050b1 |
+ isc_time_t now;
|
|
|
1050b1 |
+#ifdef CLOCK_BOOTTIME
|
|
|
1050b1 |
+ isc_time_t monotonic;
|
|
|
371a1e |
+ uint64_t diff = 0;
|
|
|
1050b1 |
+#else
|
|
|
1050b1 |
+ isc_time_t prev;
|
|
|
1050b1 |
+ TIME_NOW(&prev;;
|
|
|
1050b1 |
+#endif
|
|
|
1050b1 |
+
|
|
|
1050b1 |
+
|
|
|
1050b1 |
|
|
|
1050b1 |
while (!ctx->want_shutdown) {
|
|
|
1050b1 |
int n;
|
|
|
1050b1 |
- isc_time_t when, now;
|
|
|
1050b1 |
+ isc_time_t when;
|
|
|
1050b1 |
struct timeval tv, *tvp;
|
|
|
1050b1 |
isc_socketwait_t *swait;
|
|
|
371a1e |
bool readytasks;
|
|
|
371a1e |
bool call_timer_dispatch = false;
|
|
|
371a1e |
-
|
|
|
371a1e |
+ uint64_t us;
|
|
|
1050b1 |
+
|
|
|
1050b1 |
+#ifdef CLOCK_BOOTTIME
|
|
|
1050b1 |
+ // TBD macros for following three lines
|
|
|
1050b1 |
+ TIME_NOW(&now;;
|
|
|
1050b1 |
+ TIME_MONOTONIC(&monotonic);
|
|
|
1050b1 |
+ INSIST(now.seconds > monotonic.seconds)
|
|
|
1050b1 |
+ us = isc_time_microdiff (&now, &monotonic);
|
|
|
371a1e |
+ if (us < diff){
|
|
|
1050b1 |
+ us = diff - us;
|
|
|
1050b1 |
+ if (us > 1000000){ // ignoring shifts less than one second
|
|
|
1050b1 |
+ return ISC_R_TIMESHIFTED;
|
|
|
1050b1 |
+ };
|
|
|
1050b1 |
+ diff = isc_time_microdiff (&now, &monotonic);
|
|
|
1050b1 |
+ } else {
|
|
|
1050b1 |
+ diff = isc_time_microdiff (&now, &monotonic);
|
|
|
1050b1 |
+ // not implemented
|
|
|
1050b1 |
+ }
|
|
|
1050b1 |
+#else
|
|
|
1050b1 |
+ TIME_NOW(&now;;
|
|
|
1050b1 |
+ if (isc_time_compare (&now, &prev) < 0)
|
|
|
1050b1 |
+ return ISC_R_TIMESHIFTED;
|
|
|
1050b1 |
+ TIME_NOW(&prev;;
|
|
|
371a1e |
+#endif
|
|
|
1050b1 |
/*
|
|
|
1050b1 |
* Check the reload (or suspend) case first for exiting the
|
|
|
1050b1 |
* loop as fast as possible in case:
|
|
|
371a1e |
@@ -475,8 +508,6 @@ evloop(isc__appctx_t *ctx) {
|
|
|
1050b1 |
if (result != ISC_R_SUCCESS)
|
|
|
1050b1 |
tvp = NULL;
|
|
|
1050b1 |
else {
|
|
|
371a1e |
- uint64_t us;
|
|
|
371a1e |
-
|
|
|
1050b1 |
TIME_NOW(&now;;
|
|
|
1050b1 |
us = isc_time_microdiff(&when, &now;;
|
|
|
1050b1 |
if (us == 0)
|
|
|
1050b1 |
diff --git a/lib/isc/unix/include/isc/time.h b/lib/isc/unix/include/isc/time.h
|
|
|
371a1e |
index b864c29..5dd43c9 100644
|
|
|
1050b1 |
--- a/lib/isc/unix/include/isc/time.h
|
|
|
1050b1 |
+++ b/lib/isc/unix/include/isc/time.h
|
|
|
371a1e |
@@ -132,6 +132,26 @@ isc_time_isepoch(const isc_time_t *t);
|
|
|
1050b1 |
*\li 't' is a valid pointer.
|
|
|
1050b1 |
*/
|
|
|
1050b1 |
|
|
|
1050b1 |
+#ifdef CLOCK_BOOTTIME
|
|
|
1050b1 |
+isc_result_t
|
|
|
1050b1 |
+isc_time_boottime(isc_time_t *t);
|
|
|
1050b1 |
+/*%<
|
|
|
1050b1 |
+ * Set 't' to monotonic time from previous boot
|
|
|
1050b1 |
+ * it's not affected by system time change. It also
|
|
|
1050b1 |
+ * includes the time system was suspended
|
|
|
1050b1 |
+ *
|
|
|
1050b1 |
+ * Requires:
|
|
|
1050b1 |
+ *\li 't' is a valid pointer.
|
|
|
1050b1 |
+ *
|
|
|
1050b1 |
+ * Returns:
|
|
|
1050b1 |
+ *
|
|
|
1050b1 |
+ *\li Success
|
|
|
1050b1 |
+ *\li Unexpected error
|
|
|
1050b1 |
+ * Getting the time from the system failed.
|
|
|
1050b1 |
+ */
|
|
|
1050b1 |
+#endif /* CLOCK_BOOTTIME */
|
|
|
1050b1 |
+
|
|
|
1050b1 |
+
|
|
|
1050b1 |
isc_result_t
|
|
|
1050b1 |
isc_time_now(isc_time_t *t);
|
|
|
1050b1 |
/*%<
|
|
|
1050b1 |
diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c
|
|
|
371a1e |
index 8edc9df..fe0bb91 100644
|
|
|
1050b1 |
--- a/lib/isc/unix/time.c
|
|
|
1050b1 |
+++ b/lib/isc/unix/time.c
|
|
|
371a1e |
@@ -498,3 +498,25 @@ isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len) {
|
|
|
1050b1 |
t->nanoseconds / NS_PER_MS);
|
|
|
1050b1 |
}
|
|
|
1050b1 |
}
|
|
|
1050b1 |
+
|
|
|
1050b1 |
+
|
|
|
1050b1 |
+#ifdef CLOCK_BOOTTIME
|
|
|
1050b1 |
+isc_result_t
|
|
|
1050b1 |
+isc_time_boottime(isc_time_t *t) {
|
|
|
1050b1 |
+ struct timespec ts;
|
|
|
1050b1 |
+
|
|
|
1050b1 |
+ char strbuf[ISC_STRERRORSIZE];
|
|
|
1050b1 |
+
|
|
|
1050b1 |
+ if (clock_gettime (CLOCK_BOOTTIME, &ts) != 0){
|
|
|
1050b1 |
+ isc__strerror(errno, strbuf, sizeof(strbuf));
|
|
|
1050b1 |
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
|
|
|
1050b1 |
+ return (ISC_R_UNEXPECTED);
|
|
|
1050b1 |
+ }
|
|
|
1050b1 |
+
|
|
|
1050b1 |
+ t->seconds = ts.tv_sec;
|
|
|
1050b1 |
+ t->nanoseconds = ts.tv_nsec;
|
|
|
1050b1 |
+
|
|
|
1050b1 |
+ return (ISC_R_SUCCESS);
|
|
|
1050b1 |
+
|
|
|
1050b1 |
+};
|
|
|
1050b1 |
+#endif
|
|
|
1050b1 |
--
|
|
|
1050b1 |
2.20.1
|
|
|
1050b1 |
|