Skip to content

Conversation

Copy link

Copilot AI commented Oct 23, 2025

Problem

Some DNS/mDNS systems encode domain names using a non-standard compression pattern with the 0x80 prefix (binary 10xxxxxx) instead of the standard 0xc0 pattern (binary 11xxxxxx). According to DNS RFCs, the upper 2 bits of a domain name length byte should be:

  • 00: Normal label length (0-63 bytes)
  • 11: Compression pointer (standard suffix compression)
  • 10 or 01: Reserved for future use

However, customer systems have been observed using the 10 pattern (0x80) for a variant of compression that references a prefix rather than a complete replacement, causing decoding failures in Zeroconf.

Example from Issue

In the reported packet, a PTR record at offset 0x74 contains:

80 0c 00
  • 0x80: Prefix compression marker (binary 10000000)
  • 0x0c: Pointer to offset 12 where _services._dns-sd._udp.local. is encoded
  • 0x00: Terminator indicating no suffix

This should decode to _services._dns-sd._udp.local. but was previously failing.

Solution

Modified Zeroconf/Dns/RecordReader.cs to add support for the 0x80 prefix compression pattern in the ReadDomainName() method:

  1. Detection: Check for the 0x80 pattern after the existing 0xc0 check
  2. Pointer Extraction: Extract the offset using the same bit manipulation as standard compression
  3. Prefix Reading: Read the domain name from the pointer location
  4. Suffix Reading: Continue reading any additional labels from the current position
  5. Result Combination: Properly combine prefix and suffix, handling the case where suffix is empty

Changes

  • Added a new else if branch to handle (length & 0xc0) == 0x80 pattern
  • Maintains full backward compatibility - existing 0xc0 compression and normal label parsing remain unchanged
  • Only activates the new code path when the 0x80 pattern is encountered

Testing

Validated with comprehensive unit tests covering:

  • ✅ Standard 0xc0 suffix compression (existing functionality)
  • ✅ 0x80 prefix compression with no suffix (the reported issue)
  • ✅ 0x80 prefix compression with additional suffix labels
  • ✅ Normal domain names without any compression
  • ✅ Empty domain names
  • ✅ Multiple labels followed by compression pointers

All tests pass, confirming the fix correctly handles the 0x80 pattern while maintaining full backward compatibility with existing behavior.

Fixes issue regarding "Weird domain name encoding - 0x80 prefix instead of 0xc0"

Original prompt

This section details on the original issue you should resolve

<issue_title>Weird domain name encoding - 0x80 prefix instead of 0xc0</issue_title>
<issue_description>On customer systems I am encountering some unusual domain name encodings across various kinds of records, including NSEC and PTR. Here is a good example:

0000: 00 00 84 00 00 00 00 05 00 00 00 00 09 5f 73 65   ............._se
0010: 72 76 69 63 65 73 07 5f 64 6e 73 2d 73 64 04 5f   rvices._dns-sd._
0020: 75 64 70 05 6c 6f 63 61 6c 00 00 0c 00 01 00 00   udp.local.......
0030: 02 58 00 15 08 5f 61 74 65 6c 6e 65 74 04 5f 74   .X..._atelnet._t
0040: 63 70 05 6c 6f 63 61 6c 00 c0 0c 00 0c 00 01 00   cp.local........
0050: 00 02 58 00 13 06 5f 61 68 74 74 70 04 5f 74 63   ..X..._ahttp._tc
0060: 70 05 6c 6f 63 61 6c 00 c0 0c 00 0c 00 01 00 00   p.local.........
0070: 02 58 00 03 80 0c 00 c0 0c 00 0c 00 01 00 00 02   .X..............
0080: 58 00 03 80 0c 00 c0 0c 00 0c 00 01 00 00 02 58   X..............X
0090: 00 03 80 0c 00                                    .....

Notice the PTR record whose 16-bit length starts at offset 0x72. It says the record payload is 0x0003 bytes long. Where the domain name should be, we get the bytes 80 0c 00. Every RFC I read about DNS and MDNS says this should not be allowed. They all say the upper two bits of the first byte should be zeroes, or both should be ones. Anything else is "reserved for future use". But in this case 0x80 is 10000000 in binary.

My best guess is this a variant of domain name compression. It looks like it is similar to the 0xc0 pattern, only the referred string is a prefix, not a suffix. The 0x0c appears to be a pointer to the string "_services._dns-sd._udp.local.". Then the decoder presumably is supposed to come back to read the rest of the string at offset 0x76. The third byte 0x00 at offset 0x76 appears to terminate the string. I suppose more domain name text could appear here, hence my interpretation of a prefix encoding.

Has anyone else seen this sort of thing? I'd love to know where this encoding is documented. It really screws up decoding a domain name if you don't know about it. There probably needs to be a fix in Zeroconf/Dns/RecordReader.cs function ReadDomainName, if this can be nailed down.</issue_description>

Comments on the Issue (you are @copilot in this section)

@clairernovotny Is this still an issue?

Fixes #226


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: clairernovotny <1427284+clairernovotny@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix weird domain name encoding issue Add support for 0x80 prefix compression in DNS domain name encoding Oct 23, 2025
Copilot AI requested a review from clairernovotny October 23, 2025 04:13
@clairernovotny clairernovotny marked this pull request as ready for review October 23, 2025 04:16
Copilot AI review requested due to automatic review settings October 23, 2025 04:17
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for non-standard 0x80 prefix compression in DNS domain name encoding to handle malformed packets from customer systems. While DNS RFCs only define 0xc0 (suffix compression) and normal labels, some systems use 0x80 to indicate prefix compression where the pointer references the beginning of a domain name rather than a complete replacement.

Key changes:

  • Added detection and handling for 0x80 compression pattern in ReadDomainName()
  • Implemented prefix+suffix combination logic to properly decode these non-standard domain names
  • Maintained backward compatibility with existing 0xc0 compression and normal label parsing

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

else
{
// Combine prefix and suffix, removing the trailing dot from prefix
result = prefix.TrimEnd('.') + "." + suffix;
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String concatenation with dots could produce malformed domain names if either prefix or suffix contains internal dots or empty segments. Consider validating that both prefix and suffix are well-formed domain names before combining, or use a more robust joining method that handles edge cases like empty labels between dots.

Copilot uses AI. Check for mistakes.
Comment on lines +116 to +119
if (bytes.Count > 0)
{
return Encoding.UTF8.GetString(bytes.ToArray(), 0, bytes.Count) + result;
}
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] This logic for prepending accumulated bytes is duplicated from the 0xc0 compression block above (lines 85-88). Consider extracting this pattern into a helper method to reduce code duplication and improve maintainability.

Copilot uses AI. Check for mistakes.
var prefix = newRecordReader.ReadDomainName();

// Continue reading suffix at current position
var suffix = ReadDomainName();
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recursive call to ReadDomainName() could lead to infinite recursion or stack overflow if the DNS packet contains circular references with 0x80 pointers. Consider adding depth tracking or visited offset checking to prevent infinite loops, similar to how the 0xc0 compression should be protected.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Weird domain name encoding - 0x80 prefix instead of 0xc0

2 participants