]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add fr_dbuff_net_from_uint*() and associated tests (#3423)
authorJames Jones <jejones3141@gmail.com>
Tue, 5 May 2020 13:35:20 +0000 (08:35 -0500)
committerGitHub <noreply@github.com>
Tue, 5 May 2020 13:35:20 +0000 (08:35 -0500)
src/lib/util/dbuff.h
src/lib/util/dbuff_tests.c

index 59fb3da1801ab239ff299737b1b7d6484e56ee41..d6cf02db9ef98d1428acb8072a998e539d92f650 100644 (file)
@@ -30,6 +30,7 @@ extern "C" {
 #  endif
 
 #include <freeradius-devel/util/debug.h>
+#include <freeradius-devel/util/net.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -337,6 +338,78 @@ static inline ssize_t fr_dbuff_memset(fr_dbuff_t *dbuff, uint8_t c, size_t inlen
 }
 #define FR_DBUFF_MEMSET_RETURN(_dbuff, _c, _inlen) FR_DBUFF_RETURN(fr_dbuff_memset, _dbuff, _c, _inlen)
 
+/** Copy an unsigned 16-bit integer into a buffer in wire format (big endian)
+ *
+ * @param[in] dbuff    to copy data to
+ * @param[in] num      value to copy
+ * @return
+ *     0       no data set
+ *     >0      (2, actually) the number of bytes set in the dbuff
+ *     <0      the number of bytes required
+ */
+static inline ssize_t fr_dbuff_net_from_uint16(fr_dbuff_t *dbuff, uint16_t num)
+{
+       size_t  freespace = fr_dbuff_remaining(dbuff);
+
+       fr_assert(!dbuff->is_const);
+
+       if (sizeof(uint16_t) > freespace) return -(sizeof(uint16_t) - freespace);
+
+       fr_net_from_uint16(dbuff->p, num);
+       dbuff->p += sizeof(uint16_t);
+
+       return dbuff->parent ? _fr_dbuff_advance(dbuff->parent, sizeof(uint16_t)) : ((ssize_t) sizeof(uint16_t));
+}
+#define FR_DBUFF_NET_FROM_UINT16_RETURN(_dbuff, _num) FR_DBUFF_RETURN(fr_dbuff_net_from_uint16, _dbuff, _num)
+
+/** Copy an unsigned 32-bit integer into a buffer in wire format (big endian)
+ *
+ * @param[in] dbuff    to copy data to
+ * @param[in] num      value to copy
+ * @return
+ *     0       no data set
+ *     >0      (4, actually) the number of bytes set in the dbuff
+ *     <0      the number of bytes required
+ */
+static inline ssize_t fr_dbuff_net_from_uint32(fr_dbuff_t *dbuff, uint32_t num)
+{
+       size_t freespace = fr_dbuff_remaining(dbuff);
+
+       fr_assert(!dbuff->is_const);
+
+       if (sizeof(uint32_t) > freespace) return -(sizeof(uint32_t) - freespace);
+
+       fr_net_from_uint32(dbuff->p, num);
+       dbuff->p += sizeof(uint32_t);
+
+       return dbuff->parent ? _fr_dbuff_advance(dbuff->parent, sizeof(uint32_t)) : ((ssize_t) sizeof(uint32_t));
+}
+#define FR_DBUFF_NET_FROM_UINT32_RETURN(_dbuff, _num) FR_DBUFF_RETURN(fr_dbuff_net_from_uint32, _dbuff, _num)
+
+/** Copy an unsigned 64-bit integer into a buffer in wire format (big endian)
+ *
+ * @param[in] dbuff    to copy data to
+ * @param[in] num      value to copy
+ * @return
+ *     0       no data set
+ *     >0      (8, actually) the number of bytes set in the dbuff
+ *     <0      the number of bytes required
+ */
+static inline ssize_t fr_dbuff_net_from_uint64(fr_dbuff_t *dbuff, uint64_t num)
+{
+       size_t freespace = fr_dbuff_remaining(dbuff);
+
+       fr_assert(!dbuff->is_const);
+
+       if (sizeof(uint64_t) > freespace) return -(sizeof(uint64_t) - freespace);
+
+       fr_net_from_uint64(dbuff->p, num);
+       dbuff->p += sizeof(uint64_t);
+
+       return dbuff->parent ? _fr_dbuff_advance(dbuff->parent, sizeof(uint64_t)) : ((ssize_t) sizeof(uint64_t));
+}
+#define FR_DBUFF_NET_FROM_UINT64_RETURN(_dbuff, _num) FR_DBUFF_RETURN(fr_dbuff_net_from_uint64, _dbuff, _num)
+
 /** @} */
 
 #ifdef __cplusplus
index 7d6f38f476edd7e2e921f8ddef1f2f961d85becb..3504e3e2f52ead390f8b65800a89c55e123e837c 100644 (file)
@@ -42,12 +42,58 @@ static void test_dbuff_init_no_parent(void)
        TEST_CHECK(dbuff.parent == NULL);
 }
 
+static void test_dbuff_net_from(void)
+{
+       uint8_t         buff[sizeof(uint64_t)];
+       fr_dbuff_t      dbuff;
+
+       TEST_CASE("Generate wire format 16-bit value");
+       memset(buff, 0, sizeof(buff));
+       fr_dbuff_init(&dbuff, buff, sizeof(buff));
+
+       TEST_CHECK(fr_dbuff_net_from_uint16(&dbuff, 0x1234) == sizeof(uint16_t));
+       TEST_CHECK(buff[0] == 0x12);
+       TEST_CHECK(buff[1] == 0x34);
+
+       TEST_CASE("Generate wire format 32-bit value");
+       memset(buff, 0, sizeof(buff));
+       fr_dbuff_init(&dbuff, buff, sizeof(buff));
+
+       TEST_CHECK(fr_dbuff_net_from_uint32(&dbuff, 0x12345678) == sizeof(uint32_t));
+       TEST_CHECK(buff[0] == 0x12);
+       TEST_CHECK(buff[1] == 0x34);
+       TEST_CHECK(buff[2] == 0x56);
+       TEST_CHECK(buff[3] == 0x78);
+
+       TEST_CASE("Generate wire format 64-bit value");
+       memset(buff, 0, sizeof(buff));
+       fr_dbuff_init(&dbuff, buff, sizeof(buff));
+
+       TEST_CHECK(fr_dbuff_net_from_uint64(&dbuff, 0x123456789abcdef0) == sizeof(uint64_t));
+       TEST_CHECK(buff[0] == 0x12);
+       TEST_CHECK(buff[1] == 0x34);
+       TEST_CHECK(buff[2] == 0x56);
+       TEST_CHECK(buff[3] == 0x78);
+       TEST_CHECK(buff[4] == 0x9a);
+       TEST_CHECK(buff[5] == 0xbc);
+       TEST_CHECK(buff[6] == 0xde);
+       TEST_CHECK(buff[7] == 0xf0);
+
+       TEST_CASE("Refuse to write to too-small space");
+       fr_dbuff_init(&dbuff, buff, sizeof(uint32_t));
+
+       TEST_CHECK(fr_dbuff_net_from_uint64(&dbuff,
+                                           0x123456789abcdef0) == -(ssize_t)(sizeof(uint64_t) - sizeof(uint32_t)));
+}
+
+
 TEST_LIST = {
        /*
         *      Basic tests
         */
        { "fr_dbuff_init",                              test_dbuff_init },
        { "fr_dbuff_init_no_parent",                    test_dbuff_init_no_parent },
+       { "fr_dbuff_net_from",                          test_dbuff_net_from },
 
        { NULL }
 };