From: James Jones Date: Tue, 5 May 2020 13:35:20 +0000 (-0500) Subject: Add fr_dbuff_net_from_uint*() and associated tests (#3423) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d64f1c448c491396c83eb60fee19a52ced647986;p=thirdparty%2Ffreeradius-server.git Add fr_dbuff_net_from_uint*() and associated tests (#3423) --- diff --git a/src/lib/util/dbuff.h b/src/lib/util/dbuff.h index 59fb3da1801..d6cf02db9ef 100644 --- a/src/lib/util/dbuff.h +++ b/src/lib/util/dbuff.h @@ -30,6 +30,7 @@ extern "C" { # endif #include +#include #include #include #include @@ -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 diff --git a/src/lib/util/dbuff_tests.c b/src/lib/util/dbuff_tests.c index 7d6f38f476e..3504e3e2f52 100644 --- a/src/lib/util/dbuff_tests.c +++ b/src/lib/util/dbuff_tests.c @@ -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 } };