Skip to content

Fix DomainNamingService rejecting IPv6 addresses - #3741

Open
PDGGK wants to merge 1 commit into
apache:masterfrom
PDGGK:fix-domain-ns-ipv6-literal
Open

PDGGK wants to merge 1 commit into
apache:masterfrom
PDGGK:fix-domain-ns-ipv6-literal

Conversation

@PDGGK

@PDGGK PDGGK commented Nov 13, 2026

Copy link
Copy Markdown

What problem does this PR solve?

Issue Number: resolve #2283

Problem Summary:

A channel initialized with a load balancer and an IPv6 address in an http:// URL never finds a server. With a brpc server listening on [::1]:8765, Init("http://[::1]:8765", "rr", &options) returns 0, but every call then fails with [E61]Fail to select server from http://[::1]:8765 lb=rr, and the naming service logs No port after colon in '[::1]:8765'. Init with the same URL and no load balancer succeeds, because the single-server path already parses bracketed addresses.

DomainNamingService::GetServers (registered for http, https and redis) copies the host up to the first :, so for [::1]:8765 the host is [ and the port parse fails. The address from the issue, [fdbd:dc03:ff:501:b783:830f:f0f5:aa6a]:2280, fails the same way.

What is changed and the side effects?

Changed:

When the name starts with [, the host runs to the matching ]. After it only :port, a /path or the end of the string is accepted, and the port is parsed as before. The bracketed address goes straight to butil::str2endpoint, the parser the single-server path uses, without a DNS lookup. That does not depend on -dns_support_ipv6, since there is no name to resolve. Host names and IPv4 addresses take the same path as before.

NamingServiceTest.domain_with_ipv6_address covers an address with a port, the address from the issue, a trailing path, the default port, and five malformed forms (missing ], empty port, garbage after ], port out of range, not an address). Without the change it fails at the first assertion with Which is: -1 and the same No port after colon log.

I tested in Docker on Ubuntu 22.04 (gcc 11.4, CMake build with BUILD_UNIT_TESTS=ON). All 14 tests in brpc_naming_service_unittest pass with the change. Without it, the other 13 pass and the new one fails. A small client and server program on [::1]:8765 gets OK from /health through "rr" with the change, and the E61 error above without it. domain_naming_service.cpp also compiles with the CI warning flags plus -Werror under gcc 11.4 and clang 14. I did not run the Make or Bazel builds or the rest of the test suite, and I did not test on macOS.

Side effects:

  • Performance effects: none. A bracketed address skips the DNS lookup it could never pass anyway.

  • Breaking backward compatibility: no. A name that starts with [ could not be resolved before.


Check List:

The http://, https:// and redis:// naming services cut the host at the
first colon, so an address such as `[::1]:8765` failed with "No port
after colon" and a channel initialized with a load balancer could not
select any server. Keep the bracketed address as the host and turn it
into an endpoint directly, since there is nothing to resolve.
@wwbmmm
wwbmmm requested a lite review from Copilot November 13, 2026 09:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

5 open issues
What changed in this PR

Fixes DomainNamingService failing to parse bracketed IPv6 endpoints (e.g. [::1]:8765) so load-balanced channels can successfully select servers when initialized with IPv6 addresses.

Changes:

  • Update DomainNamingService::GetServers to treat bracketed hosts as IPv6 addresses and parse them via butil::str2endpoint (skipping DNS).
  • Add a unit test suite covering valid/invalid bracketed IPv6 forms, including ports, default port, and paths.
File Description
test/​brpc_naming_service_unittest.cpp Adds test coverage for bracketed IPv6 address parsing in DomainNamingService.
src/​brpc/​policy/​domain_naming_service.cpp Fixes host/port parsing for bracketed IPv6 endpoints and bypasses DNS resolution for direct addresses.

Review effort: Lite

#include "butil/build_config.h" // OS_MACOSX
#include <netdb.h> // gethostbyname_r
#include <stdlib.h> // strtol
#include <string.h> // strchr, memcpy
Comment on lines +49 to +50
// IPv6 address such as `[::1]:8080'. Keep the brackets, which
// butil::str2endpoint() expects.
if (close == nullptr ||
static_cast<size_t>(close - dns_name) + 1 >= sizeof(buf) ||
(close[1] != '\0' && close[1] != ':' && close[1] != '/')) {
LOG(ERROR) << "Invalid ipv6 address in `" << dns_name << '\'';
// An address, not a name: nothing to resolve.
butil::EndPoint point;
if (butil::str2endpoint(buf, port, &point) != 0) {
LOG(ERROR) << "Invalid ipv6 address in `" << dns_name << '\'';
Comment on lines +170 to +191

ASSERT_EQ(0, dns.GetServers("[::1]:1234", &servers));
ASSERT_EQ(1u, servers.size());
ASSERT_STREQ("[::1]:1234", butil::endpoint2str(servers[0].addr).c_str());

ASSERT_EQ(0, dns.GetServers("[fdbd:dc03:ff:501:b783:830f:f0f5:aa6a]:2280", &servers));
ASSERT_EQ(1u, servers.size());
ASSERT_STREQ("[fdbd:dc03:ff:501:b783:830f:f0f5:aa6a]:2280",
butil::endpoint2str(servers[0].addr).c_str());

ASSERT_EQ(0, dns.GetServers("[::1]:1234/useless1/useless2", &servers));
ASSERT_EQ(1u, servers.size());
ASSERT_STREQ("[::1]:1234", butil::endpoint2str(servers[0].addr).c_str());

ASSERT_EQ(0, dns.GetServers("[::1]", &servers));
ASSERT_EQ(1u, servers.size());
ASSERT_STREQ("[::1]:80", butil::endpoint2str(servers[0].addr).c_str());

ASSERT_EQ(-1, dns.GetServers("[::1", &servers));
ASSERT_EQ(-1, dns.GetServers("[::1]:", &servers));
ASSERT_EQ(-1, dns.GetServers("[::1]1234", &servers));
ASSERT_EQ(-1, dns.GetServers("[::1]:99999", &servers));
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.

dns 解析 ipv6 地址失败

2 participants