]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
daemon: use monotonic clock for age
authorVincent Bernat <vincent@bernat.ch>
Thu, 18 May 2023 13:25:35 +0000 (15:25 +0200)
committerVincent Bernat <vincent@bernat.ch>
Thu, 18 May 2023 14:05:33 +0000 (16:05 +0200)
Fix #572.

However, this break two things:

 - existing client comparing the age to the non-monotonic clock
 - SNMP agent which should report time since start time which is not
   monotonic either

14 files changed:
NEWS
configure.ac
src/Makefile.am
src/client/display.c
src/compat/clock_gettime.c [new file with mode: 0644]
src/compat/compat.h
src/daemon/event.c
src/daemon/lldpd.c
src/daemon/lldpd.h
src/daemon/protocols/lldp.c
src/lib/lldpctl.h
src/lldpd-structs.c
src/now.c [new file with mode: 0644]
src/now.h [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 6fda933e5afd6ac64ff0e689fa2d8fec07a15422..ceeeb1046bb05449c3d290cd3d9ff54571a4e48e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ lldpd (1.0.17)
  * Fix:
    + Read overflow when parsing CDP addresses. Thanks to Matteo Memelli.
    + Don't output empty lines on configure commands.
+   + Use monotonic clock for age (this may break some clients).
 
 lldpd (1.0.16)
  * Fix:
index 65e828aa848a99f952de92fc42342d4974287458..42fccd84f59f63710bdf4a5505fc37810e58a39d 100644 (file)
@@ -239,6 +239,7 @@ fi
 AC_REPLACE_FUNCS([setproctitle])
 AC_CHECK_FUNCS([setproctitle_init])
 # Other functions
+AC_SEARCH_LIBS([clock_gettime], [rt])
 AC_REPLACE_FUNCS([strlcpy
                   strnlen
                   strndup
@@ -246,7 +247,8 @@ AC_REPLACE_FUNCS([strlcpy
                   getline
                   asprintf
                   vsyslog
-                  daemon])
+                  daemon
+                  clock_gettime])
 # Optional functions
 AC_CHECK_FUNCS([setresuid setresgid])
 
index 19644f3e345dfa578fcb98e59462632d1b55f451..ebdaa083ea933eef7fed36b8401f6611caf45be3 100644 (file)
@@ -9,8 +9,9 @@ libcommon_daemon_lib_la_SOURCES = \
        log.c log.h version.c \
        marshal.c marshal.h \
        ctl.c ctl.h \
+       now.c now.h \
        lldpd-structs.c lldpd-structs.h lldp-const.h
 libcommon_daemon_lib_la_LIBADD  = compat/libcompat.la
 
-libcommon_daemon_client_la_SOURCES = log.c log.h version.c lldp-const.h
+libcommon_daemon_client_la_SOURCES = log.c log.h now.c now.h version.c lldp-const.h
 libcommon_daemon_client_la_LIBADD  = compat/libcompat.la
index c59c4788c875cd2d534e032e06e9971640e2250a..c6825200cd6bfb93f500948887d0b006b3b30bdf 100644 (file)
@@ -28,6 +28,7 @@
 #include <string.h>
 
 #include "../log.h"
+#include "../now.h"
 #include "client.h"
 
 static void
@@ -684,7 +685,7 @@ static const char *
 display_age(time_t lastchange)
 {
        static char sage[30];
-       int age = (int)(time(NULL) - lastchange);
+       int age = (int)(monotonic_now() - lastchange);
        if (snprintf(sage, sizeof(sage), "%d day%s, %02d:%02d:%02d",
                age / (60 * 60 * 24), (age / (60 * 60 * 24) > 1) ? "s" : "",
                (age / (60 * 60)) % 24, (age / 60) % 60, age % 60) >= sizeof(sage))
diff --git a/src/compat/clock_gettime.c b/src/compat/clock_gettime.c
new file mode 100644 (file)
index 0000000..b687baf
--- /dev/null
@@ -0,0 +1,27 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2023 Vincent Bernat <bernat@luffy.cx>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "compat.h"
+#include <time.h>
+
+int
+clock_gettime(clockid_t clk_id, struct timespec *ts)
+{
+       ts->tv_sec = time(NULL);
+       ts->tv_nsec = 0;
+       return 0;
+}
index 91ff4ade25b6b3d55ca2e1ad93d9d1bde17a9781..fde975afaead8cdeee8f290f411cb2082d2ac9f1 100644 (file)
@@ -42,6 +42,7 @@
 #include <stdarg.h>
 #include <string.h>
 #include <unistd.h>
+#include <time.h>
 
 #undef getopt
 
@@ -90,4 +91,13 @@ void *malloc(size_t size);
 void *realloc(void *ptr, size_t size);
 #endif
 
+#ifndef CLOCK_MONOTONIC
+#  define CLOCK_MONOTONIC -1
+#endif
+
+#if !HAVE_CLOCK_GETTIME
+typedef int clockid_t;
+int clock_gettime(clockid_t, struct timespec *);
+#endif
+
 #endif
index 971500f24b851070f66d7c77fd838249f04e230f..90593d4162371a155fd7573358a2382ee3c4f39c 100644 (file)
@@ -775,7 +775,7 @@ levent_schedule_cleanup(struct lldpd *cfg)
 
        /* Compute the next TTL event */
        struct timeval tv = { cfg->g_config.c_ttl, 0 };
-       time_t now = time(NULL);
+       time_t now = monotonic_now();
        time_t next;
        struct lldpd_hardware *hardware;
        struct lldpd_port *port;
index c7f1082fd90c34300d493384908a73c3578a5fef..57ca49335289738c711383a908f7982b5ae31ba9 100644 (file)
@@ -575,7 +575,7 @@ lldpd_decode(struct lldpd *cfg, char *frame, int s, struct lldpd_hardware *hardw
                    (memcmp(oport->p_lastframe->frame, frame, s) == 0)) {
                        /* Already received the same frame */
                        log_debug("decode", "duplicate frame, no need to decode");
-                       oport->p_lastupdate = time(NULL);
+                       oport->p_lastupdate = monotonic_now();
                        return;
                }
        }
@@ -684,7 +684,8 @@ lldpd_decode(struct lldpd *cfg, char *frame, int s, struct lldpd_hardware *hardw
                log_debug("decode", "%d different systems are known", i);
        }
        /* Add port */
-       port->p_lastchange = port->p_lastupdate = time(NULL);
+
+       port->p_lastchange = port->p_lastupdate = monotonic_now();
        if ((port->p_lastframe = (struct lldpd_frame *)malloc(
                 s + sizeof(struct lldpd_frame))) != NULL) {
                port->p_lastframe->size = s;
index b8952945ceb7e4f60b16c5b1afdd11c8ea9e451a..25bf7332931b10347c55247908d959daf21c16c8 100644 (file)
@@ -54,6 +54,7 @@
 #include "../marshal.h"
 #include "../log.h"
 #include "../ctl.h"
+#include "../now.h"
 #include "../lldpd-structs.h"
 
 /* We don't want to import event2/event.h. We only need those as
index 4f689a0cb0674ecaff2cb053b7b888a45bfcd90e..fe172b443ef76a34063bafcd7f49abd2a19b569e 100644 (file)
@@ -496,7 +496,7 @@ end:
                         frame->size) != 0)) {
                        free(hardware->h_lport.p_lastframe);
                        hardware->h_lport.p_lastframe = frame;
-                       hardware->h_lport.p_lastchange = time(NULL);
+                       hardware->h_lport.p_lastchange = monotonic_now();
                } else
                        free(frame);
        }
index f1cb1d047c3470ae81500502effded955dda4b0b..dd9792a6474e45b8f02a7773de13d0741f4845f3 100644 (file)
@@ -738,7 +738,8 @@ typedef enum {
        lldpctl_k_port_neighbors = 1200,
        lldpctl_k_port_protocol, /**< `(IS)` The protocol that was used to retrieve this
                                    information. */
-       lldpctl_k_port_age,      /**< `(I)`  Age of information, seconds from epoch. */
+       lldpctl_k_port_age,      /**< `(I)`  Age of information (using system monotonic
+                                   clock) */
        lldpctl_k_port_id_subtype, /**< `(IS)` The subtype ID of this port.  */
        lldpctl_k_port_id,         /**< `(BS,WO)` The ID of this port. */
        lldpctl_k_port_descr,      /**< `(S,WO)` The description of this port. */
index 6b42713cfc7771a7fe179b06ae7707e95469df25..5a4f70de8effb50825178e78d75c8c87d014a6c4 100644 (file)
@@ -20,6 +20,7 @@
 #include <time.h>
 #include "lldpd-structs.h"
 #include "log.h"
+#include "now.h"
 
 void
 lldpd_chassis_mgmt_cleanup(struct lldpd_chassis *chassis)
@@ -154,7 +155,7 @@ lldpd_remote_cleanup(struct lldpd_hardware *hardware,
 {
        struct lldpd_port *port, *port_next;
        int del;
-       time_t now = time(NULL);
+       time_t now = monotonic_now();
 
        log_debug("alloc", "cleanup remote port on %s", hardware->h_ifname);
        for (port = TAILQ_FIRST(&hardware->h_rports); port != NULL; port = port_next) {
@@ -175,7 +176,7 @@ lldpd_remote_cleanup(struct lldpd_hardware *hardware,
                        hardware->h_delete_cnt++;
                        /* Register last removal to be able to report
                         * lldpStatsRemTablesLastChangeTime */
-                       hardware->h_lport.p_lastremove = time(NULL);
+                       hardware->h_lport.p_lastremove = monotonic_now();
                        lldpd_port_cleanup(port, 1);
                        free(port);
                }
diff --git a/src/now.c b/src/now.c
new file mode 100644 (file)
index 0000000..166c80a
--- /dev/null
+++ b/src/now.c
@@ -0,0 +1,31 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2023 Vincent Bernat <bernat@luffy.cx>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <time.h>
+
+#include "now.h"
+#include "compat/compat.h"
+
+time_t
+monotonic_now()
+{
+       struct timespec tp;
+       if (clock_gettime(CLOCK_MONOTONIC, &tp) != 0) {
+               return time(NULL);
+       }
+       return tp.tv_sec;
+}
diff --git a/src/now.h b/src/now.h
new file mode 100644 (file)
index 0000000..2a5becf
--- /dev/null
+++ b/src/now.h
@@ -0,0 +1,29 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2023 Vincent Bernat <bernat@luffy.cx>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _NOW_H
+#define _NOW_H
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <time.h>
+
+time_t monotonic_now();
+
+#endif