Skip to content

Commit 52f37c2

Browse files
committed
JSON converter: add option to convert octetArray fields always as hexa values
By default, if the options is not specified and octetArray fields have size less or equal to 8 bytes, they are interpreted as unsigned integer. This code modification preserves the previous behavior.
1 parent 1a5239d commit 52f37c2

4 files changed

Lines changed: 38 additions & 15 deletions

File tree

include/libfds/converters.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,7 @@ enum fds_convert_drec2json {
13881388
*/
13891389
FDS_CD2J_FORMAT_PROTO = (1U << 5),
13901390
/**
1391-
* Ingore non-printable charactes (newline, tab, control charactes, etc.)
1391+
* Ignore non-printable characters (newline, tab, control characters, etc.)
13921392
* in IPFIX string fields instead of escaping them.
13931393
*/
13941394
FDS_CD2J_NON_PRINTABLE = (1U << 6),
@@ -1402,7 +1402,13 @@ enum fds_convert_drec2json {
14021402
* Convert all timestamps to ISO 8601 textual representation of UTC with
14031403
* milliseconds, e.g. "2019-05-22T22:34:57.828Z"
14041404
*/
1405-
FDS_CD2J_TS_FORMAT_MSEC = (1U << 8)
1405+
FDS_CD2J_TS_FORMAT_MSEC = (1U << 8),
1406+
/**
1407+
* Always convert IPFIX octetArray field as hexadecimal value in network
1408+
* byte order i.e. never try to interpret is as unsigned integer.
1409+
* For example, "0x8BADF00D".
1410+
*/
1411+
FDS_CD2J_OCTETS_NOINT = (1U << 9)
14061412
};
14071413

14081414
/**
@@ -1421,7 +1427,11 @@ enum fds_convert_drec2json {
14211427
* format "enXX:idYY", where XX is an Enterprise Number and YY is
14221428
* an Information Element ID.
14231429
* - Fields with unknown definition of their Information Elements are
1424-
* interpreted as octetArray (i.e. hexadecimal value in network byte order).
1430+
* interpreted as octetArray.
1431+
* - Fields with octetArray type are interpreted as unsigned integer if their
1432+
* size is less or equal to 8 bytes. Fields with the size above the limit
1433+
* are formatted as hexadecimal value in network byte order. To change this
1434+
* behavior, see the conversion flags.
14251435
* - If conversion of an IPFIX field of the Data Record fails (for example,
14261436
* due to invalid size or value), "null" is used as its value.
14271437
* - All timestamps are formatted as number of milliseconds from UNIX Epoch.
@@ -1446,7 +1456,7 @@ enum fds_convert_drec2json {
14461456
* \return On success returns a number of characters (excluding the termination
14471457
* null byte) placed into the buffer \p str. Therefore, if the result is
14481458
* greater that or equal to zero, conversion was successful (Note: the null
1449-
* byte has been also successfuly added at the end of the JSON string)
1459+
* byte has been also successfully added at the end of the JSON string)
14501460
* \return #FDS_ERR_BUFFER if the length of the result string (including the
14511461
* termination null byte) would exceed \p str_size and #FDS_CD2J_ALLOW_REALLOC
14521462
* flag is not set. The context written to the output buffer \p str is

src/converters/json.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ to_uint(struct context *buffer, const struct fds_drec_field *field)
227227
static int
228228
to_octet(struct context *buffer, const struct fds_drec_field *field)
229229
{
230-
if (field->size <= 8) {
230+
if (field->size <= 8 && (buffer->flags & FDS_CD2J_OCTETS_NOINT) == 0) {
231231
// Print as unsigned integer
232232
return to_uint(buffer, field);
233233
}

tests/unit_tests/converters/data/iana.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,4 +1373,12 @@ and will be lost when the list is regenerated.
13731373
<status>current</status>
13741374
</element>
13751375

1376+
<element>
1377+
<id>1007</id>
1378+
<name>myOctetArray</name>
1379+
<dataType>octetArray</dataType>
1380+
<dataSemantics>default</dataSemantics>
1381+
<status>current</status>
1382+
</element>
1383+
13761384
</ipfix-elements>

tests/unit_tests/converters/json.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ class Drec_extra : public Drec_base {
625625
trec.add_field(1005,8); // myMInf
626626
trec.add_field(1006,8); // myNan
627627
trec.add_field(56, 6); // sourceMacAddress
628+
trec.add_field(1007, ipfix_trec::SIZE_VAR); // myOctetArray
628629
trec.add_field(95,10); // applicationId
629630

630631
// Prepare an IPFIX Data Record
@@ -655,6 +656,7 @@ class Drec_extra : public Drec_base {
655656
drec.append_float(VALUE_MY_MINF,8);
656657
drec.append_float(VALUE_MY_NAN, 8);
657658
drec.append_mac(VALUE_SRC_MAC);
659+
drec.append_octets(VALUE_MY_OCTETS.c_str(), (uint16_t) 6, true);
658660
drec.append_octets(VALUE_APP_ID.c_str(),(uint16_t)10, false);
659661

660662
register_template(trec);
@@ -663,7 +665,7 @@ class Drec_extra : public Drec_base {
663665

664666
std::string VALUE_SRC_IP4 = "127.0.0.1";
665667
std::string VALUE_SAMP_NAME1 = "\xc2\xa1\xc3\xbd";
666-
std::string VALUE_SAMP_NAME2 = "\xFF\xEE"; // invalid characterss
668+
std::string VALUE_SAMP_NAME2 = "\xFF\xEE"; // invalid characters
667669
std::string VALUE_SAMP_NAME3 = "\xef\xbf\xa6"; // FULLWIDTH WON SIGN (3 bytes)
668670
std::string VALUE_SAMP_NAME4 = "\xf0\x90\x8e\xa0"; // OLD PERSIAN SIGN A (4 bytes)
669671
std::string VALUE_DST_IP4 = "8.8.8.8";
@@ -686,11 +688,13 @@ class Drec_extra : public Drec_base {
686688
double VALUE_MY_FLOAT32 = 0.5678;
687689
signed VALUE_MY_INT = 1006;
688690
std::string VALUE_SRC_MAC = "01:12:1F:13:11:8A";
691+
std::string VALUE_MY_OCTETS = "\x1E\xA3\xAB\xAD\xC0\xDE"; // 33688308793566
692+
uint64_t VALUE_MY_OCTETS_NUM = 33688308793566ULL;
689693
std::string VALUE_APP_ID = "\x33\x23\x24\x30\x31\x32\x34\x35\x36\x37"; // 3#$0124567
690694

691695
};
692696

693-
// Test for diferent data types
697+
// Test of different data types
694698
TEST_F(Drec_extra, testTypes)
695699
{
696700
constexpr size_t BSIZE = 10U;
@@ -706,12 +710,12 @@ TEST_F(Drec_extra, testTypes)
706710
EXPECT_EQ((double)cfg["iana:myFloat32"], VALUE_MY_FLOAT32);
707711
EXPECT_EQ(cfg["iana:myBool"], VALUE_MY_BOOL);
708712
EXPECT_EQ((signed)cfg["iana:myInt"], VALUE_MY_INT);
713+
EXPECT_EQ(cfg["iana:myOctetArray"], VALUE_MY_OCTETS_NUM); // interpreted as number
709714
EXPECT_EQ(cfg["iana:sourceMacAddress"], VALUE_SRC_MAC);
710-
711715
free(buff);
712716
}
713717

714-
// Test for non printable characters (FDS_CD2J_NON_PRINTABLE)
718+
// Test of non printable characters (FDS_CD2J_NON_PRINTABLE)
715719
TEST_F(Drec_extra, nonPrintable)
716720
{
717721
constexpr size_t BSIZE = 10U;
@@ -728,7 +732,7 @@ TEST_F(Drec_extra, nonPrintable)
728732
free(buff);
729733
}
730734

731-
// Test for eskaping characters
735+
// Test of escaping characters
732736
TEST_F(Drec_extra, printableChar)
733737
{
734738
constexpr size_t BSIZE = 10U;
@@ -746,7 +750,7 @@ TEST_F(Drec_extra, printableChar)
746750
free(buff);
747751
}
748752

749-
// Test for NAN, +INF, -INF values
753+
// Test of NAN, +INF, -INF values
750754
TEST_F(Drec_extra, extraValue)
751755
{
752756
constexpr size_t BSIZE = 5U;
@@ -769,7 +773,7 @@ TEST_F(Drec_extra, extraValue)
769773
free(buff);
770774
}
771775

772-
// Test for other ASCII characters
776+
// Test of other ASCII characters
773777
TEST_F(Drec_extra, otherChar)
774778
{
775779
constexpr size_t BSIZE = 5U;
@@ -795,7 +799,7 @@ TEST_F(Drec_extra, otherChar)
795799
free(buff);
796800
}
797801

798-
// Test for other MAC adress
802+
// Test of other MAC address
799803
TEST_F(Drec_extra, macAdr)
800804
{
801805
constexpr size_t BSIZE = 5U;
@@ -813,19 +817,20 @@ TEST_F(Drec_extra, macAdr)
813817
free(buff);
814818
}
815819

816-
// Test for octet values
820+
// Test of octet values (FDS_CD2J_OCTETS_NOINT)
817821
TEST_F(Drec_extra, octVal)
818822
{
819823
constexpr size_t BSIZE = 5U;
820824
char* buff = (char*) malloc(BSIZE);
821-
uint32_t flags = FDS_CD2J_ALLOW_REALLOC;
825+
uint32_t flags = FDS_CD2J_ALLOW_REALLOC | FDS_CD2J_OCTETS_NOINT;
822826
size_t buff_size = BSIZE;
823827

824828
int rc = fds_drec2json(&m_drec, flags, m_iemgr.get(), &buff, &buff_size);
825829
ASSERT_GT(rc, 0);
826830
EXPECT_NE(buff_size, BSIZE);
827831
Config cfg = parse_string(buff, JSON, "drec2json");
828832
EXPECT_EQ((std::string)cfg["iana:applicationId"], "0x33232430313234353637");
833+
EXPECT_EQ((std::string)cfg["iana:myOctetArray"], "0x1EA3ABADC0DE");
829834

830835
free(buff);
831836
}

0 commit comments

Comments
 (0)