misc/130334: [libc] getaddrinfo() rejects numerical servnames when ai_socktype=0

Lucius Windschuh lwindschuh at googlemail.com
Fri Jan 9 11:50:04 PST 2009


>Number:         130334
>Category:       misc
>Synopsis:       [libc] getaddrinfo() rejects numerical servnames when ai_socktype=0
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jan 09 19:50:03 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator:     Lucius Windschuh
>Release:        CURRENT
>Organization:
>Environment:
FreeBSD current 8.0-CURRENT FreeBSD 8.0-CURRENT #4: Fri Jan  9 19:01:22 CET 2009     root at current:/usr/obj/usr/src/sys/CURRENT  i386
>Description:
Trying to use utorrent with wine on FreeBSD, the following happens:
- utorrent is unable to resolve DNS names

Reason:
- utorrent calls getaddrinfo() (implemented in wine/dlls/ws2_32/socket.c) with
 - the hostname
 - the port number as string as servname
 - a hint in which ai_sockaddr, ai_family and ai_protocol are set to 0.
 -> This seems valid according to the Microsoft specification.
- wine converts this call to a native getaddrinfo call with ai_family,
ai_socktype and ai_protocol also set to 0.
- FreeBSD libc's getaddrinfo rejects numeric servnames when ai_socktype is zero!

Quoting RFC 3493:
   The ai_socktype field to which argument hints points specifies the
   socket type for the service, as defined for socket().  If a specific
   socket type is not given (for example, a value of zero) and the
   service name could be interpreted as valid with multiple supported
   socket types, the implementation shall attempt to resolve the service
   name for all supported socket types and, in the absence of errors,
   all possible results shall be returned. [...]

This leads me to the conclusion that FreeBSD /should/ accept numeric servnames even if ai_socktype is zero.

This case could also be fixed in wine, but I do not see the point, why FreeBSD behaves this way. Documented in src/lib/libc/net/getaddrinfo.c:428:
  "(1) numeric servname is disallowed if socktype/protocol are left unspecified."

>How-To-Repeat:
- install wine from the ports
- download the utorrent installer
- execute it with wine
- it installs and starts utorrent
- download an arbitrary BitTorrent .torrent file which uses HTTP trackers
- load this file in utorrent
- watch as it states "hostname not found" in the Tab "Trackers" at the bottom of the main window

>Fix:
Apply the attached patch

Patch attached with submission follows:

--- src/lib/libc/net/getaddrinfo.c.old	2009-01-09 20:39:43.000000000 +0100
+++ src/lib/libc/net/getaddrinfo.c	2009-01-09 20:44:34.000000000 +0100
@@ -425,8 +425,7 @@ getaddrinfo(const char *hostname, const 
 	}
 
 	/*
-	 * check for special cases.  (1) numeric servname is disallowed if
-	 * socktype/protocol are left unspecified. (2) servname is disallowed
+	 * check for special cases. (1) servname is disallowed
 	 * for raw and other inet{,6} sockets.
 	 */
 	if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
@@ -1325,7 +1324,6 @@ get_port(struct addrinfo *ai, const char
 	const char *proto;
 	struct servent *sp;
 	int port, error;
-	int allownumeric;
 
 	if (servname == NULL)
 		return 0;
@@ -1344,10 +1342,7 @@ get_port(struct addrinfo *ai, const char
 		return EAI_SERVICE;
 	case SOCK_DGRAM:
 	case SOCK_STREAM:
-		allownumeric = 1;
-		break;
 	case ANY:
-		allownumeric = 0;
 		break;
 	default:
 		return EAI_SOCKTYPE;
@@ -1355,8 +1350,6 @@ get_port(struct addrinfo *ai, const char
 
 	error = str2number(servname, &port);
 	if (error == 0) {
-		if (!allownumeric)
-			return EAI_SERVICE;
 		if (port < 0 || port > 65535)
 			return EAI_SERVICE;
 		port = htons(port);


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list