Skip to content

Commit

Permalink
Add big endian support to the dns parser (envoyproxy#34456)
Browse files Browse the repository at this point in the history
Fixes:
//test/extensions/filters/udp/dns_filter:dns_filter_integration_test
//test/extensions/filters/udp/dns_filter:dns_filter_test
on big endian platforms.

Signed-off-by: Jonathan Albrecht <jonathan.albrecht@ibm.com>
  • Loading branch information
jonathan-albrecht-ibm authored Jun 8, 2024
1 parent 89d7b57 commit a679292
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 3 deletions.
5 changes: 5 additions & 0 deletions source/extensions/filters/udp/dns_filter/dns_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,13 @@ bool DnsAnswerRecord::serialize(Buffer::OwnedImpl& output) {
// Store the 128bit address with 2 64 bit writes
const absl::uint128 addr6 = ip_address->ipv6()->address();
output.writeBEInt<uint16_t>(sizeof(addr6));
#ifdef ABSL_IS_BIG_ENDIAN
output.writeBEInt<uint64_t>(absl::Uint128High64(addr6));
output.writeBEInt<uint64_t>(absl::Uint128Low64(addr6));
#else
output.writeLEInt<uint64_t>(absl::Uint128Low64(addr6));
output.writeLEInt<uint64_t>(absl::Uint128High64(addr6));
#endif
} else if (ip_address->ipv4() != nullptr) {
output.writeBEInt<uint16_t>(4);
output.writeLEInt<uint32_t>(ip_address->ipv4()->address());
Expand Down
21 changes: 18 additions & 3 deletions source/extensions/filters/udp/dns_filter/dns_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,23 @@ struct DnsParserCounters {
queries_with_ans_or_authority_rrs(queries_with_ans_or_authority_rrs) {}
};

// The flags have been verified with dig and this structure should not be modified. The flag
// order here does not match the RFC, but takes byte ordering into account so that serialization
// does not bitwise operations.
// The flags have been verified with dig and this structure should not be modified. On little
// endian platforms, the flag order here does not match the RFC, but takes byte ordering into
// account so that serialization does not bitwise operations.
#if ABSL_IS_BIG_ENDIAN
PACKED_STRUCT(struct DnsHeaderFlags {
unsigned qr : 1; // query or response
unsigned opcode : 4; // operation code
unsigned aa : 1; // authoritative answer
unsigned tc : 1; // truncated response
unsigned rd : 1; // recursion desired
unsigned ra : 1; // recursion available
unsigned z : 1; // z - bit (must be zero in queries per RFC1035)
unsigned ad : 1; // authenticated data
unsigned cd : 1; // checking disabled
unsigned rcode : 4; // return code
});
#else
PACKED_STRUCT(struct DnsHeaderFlags {
unsigned rcode : 4; // return code
unsigned cd : 1; // checking disabled
Expand All @@ -152,6 +166,7 @@ PACKED_STRUCT(struct DnsHeaderFlags {
unsigned opcode : 4; // operation code
unsigned qr : 1; // query or response
});
#endif

/**
* Structure representing the DNS header as it appears in a packet
Expand Down
6 changes: 6 additions & 0 deletions test/extensions/filters/udp/dns_filter/dns_filter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1910,6 +1910,12 @@ TEST_F(DnsFilterTest, InvalidShortBufferTest) {
}

TEST_F(DnsFilterTest, RandomizeFirstAnswerTest) {
#if defined(__linux__) && defined(__s390x__)
// Skip on s390x because this test incorrectly depends on the ordering of
// addresses that happens to work on other platforms.
// See https://github.com/envoyproxy/envoy/pull/24330
GTEST_SKIP() << "Skipping RandomizeFirstAnswerTest on s390x";
#endif
InSequence s;

setup(forward_query_off_config);
Expand Down

0 comments on commit a679292

Please sign in to comment.