Project

General

Profile

Actions

Bug #16273

open

getaddrinfo(3XNET) does not correctly handle an unspecified socket type

Added by Joshua M. Clulow 10 days ago. Updated 10 days ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
lib - userland libraries
Start date:
Due date:
% Done:

0%

Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:
External Bug:

Description

I have a short Python program which demonstrates a difference between our getaddrinfo(3XNET) and the getaddrinfo() behaviour on other systems.

#!/usr/bin/env python3

import socket

print("WITH type set:")
print(socket.getaddrinfo("0.0.0.0", 9009,
    type=socket.SOCK_STREAM, flags=socket.AI_PASSIVE))

print("WITHOUT type set:")
print(socket.getaddrinfo("0.0.0.0", 9009))

On illumos, this results in the following output:

WITH type set:
[(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 2>, 6, '', ('0.0.0.0', 9009))]
WITHOUT type set:
Traceback (most recent call last):
  File "/tmp/sigh_test.py", line 10, in <module>
    print(socket.getaddrinfo("0.0.0.0", 9009))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/socket.py", line 962, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
socket.gaierror: [Errno 9] service name not available for the specified socket type

Note in the first case where we provide the "type" argument, we get the expected address back. In the latter case we are failing with EAI_SERVICE. Digging in with DTrace I was able to confirm that Python is using __xnet_getaddrinfo() and in the case of the call that does not work, it is passing a hints address with everything (including ai_socktype) set to zero.

Looking at the manual for getaddrinfo(3XNET), it seems that this is not the behaviour we should expect:

       The ai_socktype member to which argument hints points specifies the
       socket type for the service, as defined in socket(3XNET). If a specific
       socket type is not given (for example, a value of 0) and the service
       name could be interpreted as valid with multiple supported socket
       types, the implementation attempts to resolve the service name for all
       supported socket types and, in the absence of errors, all possible
       results are returned. A non-zero socket type value limits the returned
       information to values with the specified socket type.

While it's suggested that all possible results will be returned "in the absence of errors", and we clearly have an error here, I think that "for all supported socket types" needs to override that error in this case: the error, EAI_SERVICE, is merely telling us that this socket type should be skipped.

Indeed, looking at various other popular operating systems, we find that the behaviour is as described in our manual; e.g., for Ubuntu 22.04:

WITH type set:
[(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('0.0.0.0', 9009))]
WITHOUT type set:
[(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('0.0.0.0', 9009)), (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_DGRAM: 2>, 17, '', ('0.0.0.0', 9009)), (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_RAW: 3>, 0, '', ('0.0.0.0', 9009))]

And for Mac OS X 10.15.7:

WITH type set:
[(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('0.0.0.0', 9009))]
WITHOUT type set:
[(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_DGRAM: 2>, 17, '', ('0.0.0.0', 9009)), (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('0.0.0.0', 9009))]

Note that the variant (without the socket type) that doesn't work for us is actually not correct code in the original Python program from which this reproduction is derived. The program is attempting to bind a listen socket for a (TCP) web server, so it should be specifying both the socket type (SOCK_STREAM) and the AI_PASSIVE flag. Even so, we should fix our implementation so that this code would have worked as-is.

Actions #1

Updated by Marcel Telka 10 days ago

FYI, something different, but related (issue in eventlet): service name not available for the specified socket type

Actions

Also available in: Atom PDF