Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#8503 closed Bugs (invalid)

Cannot connect to localhost without global connectivity

Reported by: Edward@… Owned by: chris_kohlhoff
Milestone: To Be Determined Component: asio
Version: Boost 1.53.0 Severity: Problem
Keywords: localhost AI_ADDRCONFIG Cc:

Description

On Windows, if there are no network cards installed or they are all disabled, attempts to resolve localhost fail. The problem is that by default, the default value for the basic_resolver_query constructor's resolve_flags parameter is address_configured, which is AI_ADDRCONFIG on Windows. However, as implemented AI_ADDRCONFIG is actually detrimental, particularly for resolution of loopback and link-local addresses.

The rationale from the Google Chrome source code explains this. Here is the relevant snippet from SystemHostResolverCall in host_resolver_proc.cc:

#if defined(OS_WIN)
  // DO NOT USE AI_ADDRCONFIG ON WINDOWS.
  //
  // The following comment in <winsock2.h> is the best documentation I found
  // on AI_ADDRCONFIG for Windows:
  //   Flags used in "hints" argument to getaddrinfo()
  //       - AI_ADDRCONFIG is supported starting with Vista
  //       - default is AI_ADDRCONFIG ON whether the flag is set or not
  //         because the performance penalty in not having ADDRCONFIG in
  //         the multi-protocol stack environment is severe;
  //         this defaulting may be disabled by specifying the AI_ALL flag,
  //         in that case AI_ADDRCONFIG must be EXPLICITLY specified to
  //         enable ADDRCONFIG behavior
  //
  // Not only is AI_ADDRCONFIG unnecessary, but it can be harmful.  If the
  // computer is not connected to a network, AI_ADDRCONFIG causes getaddrinfo
  // to fail with WSANO_DATA (11004) for "localhost", probably because of the
  // following note on AI_ADDRCONFIG in the MSDN getaddrinfo page:
  //   The IPv4 or IPv6 loopback address is not considered a valid global
  //   address.
  // See http://crbug.com/5234.
  //
  // OpenBSD does not support it, either.
  hints.ai_flags = 0;
#else
  hints.ai_flags = AI_ADDRCONFIG;
#endif

The developers of XCB arrived at a similar conclusion. See their discussion on Bug: Can’t connect to localhost without global connectivity.

Code using ASIO can work around this problem, but doing so would require platform-specific code and intricate knowledge of poorly documented platform-specific behavior.

Change History (2)

comment:1 by chris_kohlhoff, 9 years ago

Resolution: invalid
Status: newclosed

This behaviour is not specific to Windows (e.g. I've seen it on Linux too). It looks like AI_ADDRCONFIG is behaving as POSIX intended.

If you don't want to use the AI_ADDRCONFIG option, please explicitly specify the flags when constructing the query. You can do this in portable code.

in reply to:  1 comment:2 by Edward Brey <Edward@…>, 9 years ago

I realize that it is in theory possible to override the default when creating a query. Sometimes, however, that option gets abstracted away. I ran into this problem when using the WebSocket++ library, which in endpoint.hpp creates a query using the default options without exposing the options to users of the library. Of course, exposing the options would be one resolution to the open issue, but it's nice to keep the API smaller if there is a "it just works" solution.

Am I missing something about the virtues of AI_ADDRCONFIG? If 99% of the time, it's best to override the default and turn the flag off, isn't keeping AI_ADDRCONFIG as the default likely to trip up unsuspecting developers and lead to a lot of "Why doesn't this work on localhost?" headaches like I experienced.

As computers become more mobile, this gotcha will grow more frequent. I encountered it simply by turning on airplane mode on my laptop (a commonly used Windows 8 feature).

Note: See TracTickets for help on using tickets.