]> git.proxmox.com Git - mirror_frr.git/commitdiff
*: introduce function for sequence numbers
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Thu, 19 Jan 2023 15:16:11 +0000 (12:16 -0300)
committerRafael Zalamena <rzalamena@opensourcerouting.org>
Fri, 20 Jan 2023 18:40:28 +0000 (15:40 -0300)
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 151981215197861519783 and 1519772)

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
eigrpd/eigrp_interface.c
lib/network.c
lib/network.h
ospf6d/ospf6_message.c
ospfd/ospf_interface.c
zebra/zebra_netns_id.c

index 28987b4af65e303f0c303afedf35e1e16a0b188f..891d282307482eb48c7a436e4c4c516140d00d46 100644 (file)
@@ -37,6 +37,7 @@
 #include "if.h"
 #include "table.h"
 #include "memory.h"
+#include "network.h"
 #include "command.h"
 #include "stream.h"
 #include "log.h"
@@ -83,7 +84,7 @@ struct eigrp_interface *eigrp_if_new(struct eigrp *eigrp, struct interface *ifp,
        /* 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++) {
index b60ad9a57c3800f97bae4cdde4708c133bd15e29..cd62b8b5930b35fe80397428a11b8cfbb09dba66 100644 (file)
@@ -122,3 +122,24 @@ float ntohf(float net)
 {
        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();
+}
index 10ed917572dbf5285554b64b69240b1a91c4f1d8..c163eab8f76e0f3b32142976212b95e070c6a499 100644 (file)
@@ -81,6 +81,24 @@ extern float ntohf(float);
 #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
index fb54ebab15c83e48fea2a09f43d7093439751ba1..3d29a65d1b15c9383bfc322ef485009c536f68bb 100644 (file)
@@ -28,6 +28,7 @@
 #include "linklist.h"
 #include "lib_errors.h"
 #include "checksum.h"
+#include "network.h"
 
 #include "ospf6_proto.h"
 #include "ospf6_lsa.h"
@@ -2300,7 +2301,7 @@ static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s)
        /* 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 */
index a0b14e73ee995ffe92162644b96af3fca238f4ef..831906b908afc5e1d2f3b9ac19ecad8f89e5cff1 100644 (file)
@@ -30,6 +30,7 @@
 #include "command.h"
 #include "stream.h"
 #include "log.h"
+#include "network.h"
 #include "zclient.h"
 #include "bfd.h"
 #include "ldp_sync.h"
@@ -274,7 +275,7 @@ struct ospf_interface *ospf_if_new(struct ospf *ospf, struct interface *ifp,
        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);
 
index 73d585c1a33118ce0323f01d36d014043ff278c0..8905b72ec5f2eb5b77a67d67020a876435957fd1 100644 (file)
@@ -23,6 +23,7 @@
 #include "vrf.h"
 #include "log.h"
 #include "lib_errors.h"
+#include "network.h"
 
 #include "zebra/rib.h"
 #include "zebra/zebra_dplane.h"
@@ -73,7 +74,7 @@ static struct nlmsghdr *initiate_nlh(char *buf, unsigned int *seq, int type)
        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;
 }