On Thu, Jun 19, 2008 at 9:56 PM, Sob <s...@hisoftware.cz> wrote: > Hello, > > while experimenting with httpd and IPv6 on WinXP, I found out that it's not > working well. > In short, the code expects that IPv4 mapped addresses and IPV6_V6ONLY socket > option are supported. This is not true for NTs < 6.0. They have IPv4 and > IPv6 as two separate stacks and therefore all IPv6 sockets always behave as > V6ONLY and no IPv4 mapped addresses are possible. Unfortunately the > IPV6_V6ONLY option is not understood, so if the code tries to set it, if > fails with OS error. APR seems to be the best place where it can be fixed. > > The attached patch modifies apr_socket_opt_set(). When the requested option > is APR_IPV6_V6ONLY, it checks Windows version and if it's less than Vista, > it does not call setsockopt(), but instead it calls directly > apr_set_option() and pretends that the option was set. Then it returns > APR_SUCCESS or APR_ENOTIMPL depending on if it was requested to set or unset > the option. > I'm not exactly sure about returning APR_ENOTIMPL, but httpd would fail with > anything else. At first I just set "on = 1;" and let the original > apr_set_option() use it, but that wasn't right, because it always returned > APR_SUCCESS and some application other than httpd can depend on the result > and in case it requested to unset the option, returning APR_SUCCESS would be > wrong. Httpd doesn't really care about the result and checks the state later > using apr_socket_opt_get(). That's why always calling apr_set_option(sock, > APR_IPV6_V6ONLY, 1) is important. If omited, it would be possible (if > compiled with IPv4 mapped addresses support) for apr_socket_opt_get() to > return 0 (= socket can accept both IPv4 and 6), but that's not possible on > these older Windows and if some code is depending on it, it may fail (like > current httpd). > > Sob
See also http://msdn.microsoft.com/en-us/library/ms738574%28v=vs.85%29.aspx < Vista: socket option not supported, but behaves as if it is hard-coded to 1 >= Vista: socket option works, and IPV6_V6ONLY=1 is the default state Suggested changes to the patch: Move "apr_set_option(sock, APR_IPV6_V6ONLY, 1);" to creation of the socket, and make it unconditional (old or new Windows). That allows apr_socket_opt_get() to work even if apr_socket_opt_set() isn't called first.* (This reflects the default setting of 1 on levels of Windows that support the option, as documented above and confirmed on Windows 7.) Add the default definition of IPV6_V6ONLY right in sockopt.c. It won't be needed anywhere else. Thoughts? FWIW, I'm aware that some folks who have tested different IPv6 scenarios on old/new Windows boxes are using about the same code that Sob has posted. *This issue of socket_opt_get() before socket_opt_set() seems to be a wider issue with APR. There are a few options which must pass through to the OS to retrieve, but we don't do that.