Don't directly use `time()` for generating sequence numbers for two
reasons:
1. `time()` can go backwards (due to NTP or time adjustments)
2. Coverity Scan warns every time we truncate a `time_t` variable for
good reason (verify that we are Y2K38 ready).
Found by Coverity Scan (CID
1519812,
1519786,
1519783 and
1519772)
Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
#include "if.h"
#include "table.h"
#include "memory.h"
+#include "network.h"
#include "command.h"
#include "stream.h"
#include "log.h"
/* Initialize neighbor list. */
ei->nbrs = list_new();
- ei->crypt_seqnum = time(NULL);
+ ei->crypt_seqnum = frr_sequence32_next();
/* Initialize lists */
for (i = 0; i < EIGRP_FILTER_MAX; i++) {
{
return htonf(net);
}
+
+uint64_t frr_sequence_next(void)
+{
+ static uint64_t last_sequence;
+ struct timespec ts;
+
+ (void)clock_gettime(CLOCK_MONOTONIC, &ts);
+ if (last_sequence == (uint64_t)ts.tv_sec) {
+ last_sequence++;
+ return last_sequence;
+ }
+
+ last_sequence = ts.tv_sec;
+ return last_sequence;
+}
+
+uint32_t frr_sequence32_next(void)
+{
+ /* coverity[Y2K38_SAFETY] */
+ return (uint32_t)frr_sequence_next();
+}
#error nobody expects the endianish inquisition. check OS endian.h headers.
#endif
+/**
+ * Generate a sequence number using monotonic clock with a same second call
+ * protection to help guarantee a unique incremental sequence number that never
+ * goes back (except when wrapping/overflow).
+ *
+ * **NOTE** this function is not thread safe since it uses `static` variable.
+ *
+ * This function and `frr_sequence32_next` should be used to initialize
+ * sequence numbers without directly calling other `time_t` returning
+ * functions because of `time_t` truncation warnings.
+ *
+ * \returns `uint64_t` number based on the monotonic clock.
+ */
+extern uint64_t frr_sequence_next(void);
+
+/** Same as `frr_sequence_next` but returns truncated number. */
+extern uint32_t frr_sequence32_next(void);
+
/**
* Helper function that returns a random long value. The main purpose of
* this function is to hide a `random()` call that gets flagged by coverity
#include "linklist.h"
#include "lib_errors.h"
#include "checksum.h"
+#include "network.h"
#include "ospf6_proto.h"
#include "ospf6_lsa.h"
/* if this is initial one, initialize sequence number for DbDesc */
if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
&& (on->dbdesc_seqnum == 0)) {
- on->dbdesc_seqnum = monotime(NULL);
+ on->dbdesc_seqnum = frr_sequence32_next();
}
/* reserved */
#include "command.h"
#include "stream.h"
#include "log.h"
+#include "network.h"
#include "zclient.h"
#include "bfd.h"
#include "ldp_sync.h"
oi->t_ls_upd_event = NULL;
oi->t_ls_ack_direct = NULL;
- oi->crypt_seqnum = time(NULL);
+ oi->crypt_seqnum = frr_sequence32_next();
ospf_opaque_type9_lsa_init(oi);
#include "vrf.h"
#include "log.h"
#include "lib_errors.h"
+#include "network.h"
#include "zebra/rib.h"
#include "zebra/zebra_dplane.h"
nlh->nlmsg_flags = NLM_F_REQUEST;
if (type == RTM_NEWNSID)
nlh->nlmsg_flags |= NLM_F_ACK;
- nlh->nlmsg_seq = *seq = time(NULL);
+ nlh->nlmsg_seq = *seq = frr_sequence32_next();
return nlh;
}