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
* 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:
AC_REPLACE_FUNCS([setproctitle])
AC_CHECK_FUNCS([setproctitle_init])
# Other functions
+AC_SEARCH_LIBS([clock_gettime], [rt])
AC_REPLACE_FUNCS([strlcpy
strnlen
strndup
getline
asprintf
vsyslog
- daemon])
+ daemon
+ clock_gettime])
# Optional functions
AC_CHECK_FUNCS([setresuid setresgid])
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
#include <string.h>
#include "../log.h"
+#include "../now.h"
#include "client.h"
static void
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))
--- /dev/null
+/* -*- 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;
+}
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
+#include <time.h>
#undef getopt
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
/* 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;
(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;
}
}
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;
#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
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);
}
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. */
#include <time.h>
#include "lldpd-structs.h"
#include "log.h"
+#include "now.h"
void
lldpd_chassis_mgmt_cleanup(struct lldpd_chassis *chassis)
{
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) {
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);
}
--- /dev/null
+/* -*- 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;
+}
--- /dev/null
+/* -*- 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