consomme: add support for dns over tcp#2807
consomme: add support for dns over tcp#2807damanm24 wants to merge 14 commits intomicrosoft:mainfrom
Conversation
|
This PR modifies files containing For more on why we check whole files, instead of just diffs, check out the Rustonomicon |
There was a problem hiding this comment.
Pull request overview
This PR adds DNS over TCP support to the consomme network stack, complementing the existing DNS over UDP functionality introduced in PR #2633. When a guest initiates a TCP connection to the gateway IP on port 53, consomme intercepts the connection and handles DNS queries using platform-specific system resolvers (DnsQueryRaw on Windows, res_nsend on Unix) instead of creating a real host socket.
Changes:
- Implements virtual TCP DNS handler that processes DNS queries over TCP without real sockets
- Adds TCP transport support to platform-specific DNS resolver backends (RES_USEVC flag for Unix, DNS_PROTOCOL_TCP for Windows)
- Refactors DNS backend to use Arc instead of Box to enable sharing between UDP and TCP handlers
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| vm/devices/net/net_consomme/consomme/src/lib.rs | Defines DNS_PORT constant at crate level for reuse |
| vm/devices/net/net_consomme/consomme/src/udp.rs | Updates UDP DNS handler to include transport type in DnsFlow |
| vm/devices/net/net_consomme/consomme/src/tcp/ring.rs | Removes test-only attribute from is_empty() method (now used in production) |
| vm/devices/net/net_consomme/consomme/src/tcp.rs | Adds TcpBackend enum, DNS TCP connection handling, and poll_dns_backend method |
| vm/devices/net/net_consomme/consomme/src/dns_resolver/mod.rs | Adds DnsTransport enum and changes backend from Box to Arc for sharing |
| vm/devices/net/net_consomme/consomme/src/dns_resolver/dns_tcp.rs | New module implementing DNS TCP framing and message handling per RFC 1035 |
| vm/devices/net/net_consomme/consomme/src/dns_resolver/windows/mod.rs | Adds DNS_PROTOCOL_TCP support to Windows resolver backend |
| vm/devices/net/net_consomme/consomme/src/dns_resolver/unix/glibc.rs | Adds RES_USEVC flag support for TCP queries and refactors ResState structure |
vm/devices/net/net_consomme/consomme/src/dns_resolver/dns_tcp.rs
Outdated
Show resolved
Hide resolved
vm/devices/net/net_consomme/consomme/src/dns_resolver/dns_tcp.rs
Outdated
Show resolved
Hide resolved
vm/devices/net/net_consomme/consomme/src/dns_resolver/dns_tcp.rs
Outdated
Show resolved
Hide resolved
vm/devices/net/net_consomme/consomme/src/dns_resolver/dns_tcp.rs
Outdated
Show resolved
Hide resolved
vm/devices/net/net_consomme/consomme/src/dns_resolver/dns_tcp.rs
Outdated
Show resolved
Hide resolved
| #[cfg(unix)] | ||
| { | ||
| let len = response.response_data.len() as u16; | ||
| self.tx_buf.extend(&len.to_be_bytes()); | ||
| } | ||
| self.tx_buf.extend(&response.response_data); |
There was a problem hiding this comment.
The code assumes that Windows DnsQueryRaw returns DNS responses that already include the 2-byte TCP length prefix when using DNS_PROTOCOL_TCP, while Unix res_nsend returns responses without the prefix. This assumption should be documented with a comment explaining the difference in behavior between the two APIs. Currently, only the input differences are documented (lines 90-94), but the output behavior is left implicit, which could lead to confusion or bugs if the assumption is incorrect.
| #[repr(C)] | ||
| #[derive(IntoBytes, Immutable, KnownLayout, FromZeros)] | ||
| struct ResStatePrefix { | ||
| retrans: c_int, | ||
| retry: c_int, | ||
| options: c_ulong, | ||
| } |
There was a problem hiding this comment.
The ResStatePrefix struct assumes that the first three fields of glibc's struct __res_state are laid out as int, int, unsigned long with no padding between them. While the #[repr(C)] attribute ensures C-compatible layout, different platforms or compilers might add padding for alignment. Consider adding a compile-time assertion to verify that size_of::<ResStatePrefix>() equals the expected size (e.g., 16 bytes on 64-bit platforms), or document the platform-specific assumptions more explicitly.
This PR adds support for DNS over TCP.
If a TCP connection is being initiated (by the guest), addressed to consommé's gateway IP on port 53, consommé's TCP module will intercept the request and instead of creating a socket on the host it will submit the DNS query on behalf of the guest using the resolver implementation that was introduced in #2633.