From owner-freebsd-bugs@FreeBSD.ORG Tue Nov 25 11:00:14 2008 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 828131065675 for ; Tue, 25 Nov 2008 11:00:14 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id E314C8FC21 for ; Tue, 25 Nov 2008 11:00:13 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id mAPB0DaB045761 for ; Tue, 25 Nov 2008 11:00:13 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id mAPB0Da7045760; Tue, 25 Nov 2008 11:00:13 GMT (envelope-from gnats) Resent-Date: Tue, 25 Nov 2008 11:00:13 GMT Resent-Message-Id: <200811251100.mAPB0Da7045760@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Steven Hartland Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 534341065676 for ; Tue, 25 Nov 2008 10:55:54 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 431398FC1C for ; Tue, 25 Nov 2008 10:55:54 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id mAPAtrxI046311 for ; Tue, 25 Nov 2008 10:55:53 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id mAPAtr3P046310; Tue, 25 Nov 2008 10:55:53 GMT (envelope-from nobody) Message-Id: <200811251055.mAPAtr3P046310@www.freebsd.org> Date: Tue, 25 Nov 2008 10:55:53 GMT From: Steven Hartland To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/129169: Linux Emulation ENOTCONN error using non-blocking TCP X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Nov 2008 11:00:14 -0000 >Number: 129169 >Category: kern >Synopsis: Linux Emulation ENOTCONN error using non-blocking TCP >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Nov 25 11:00:13 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Steven Hartland >Release: 7.0 RELEASE >Organization: Multiplay >Environment: FreeBSD loncore0.multiplay.co.uk 7.0-RELEASE-p3 FreeBSD 7.0-RELEASE-p3 #8: Sat Nov 22 18:46:41 GMT 2008 root@loncore0.multiplay.co.uk:/usr/src/sys/amd64/compile/MULTIPLAY amd64 >Description: In the Linux ABI a send() in a socket that is set non-blocking after a connect can produce ENOTCONN. This is caused by the underlying FreeBSD kernel call sendto() which checks for a connected end point, as this is still in progress, due to socket being non-blocking. The fix is to check this condition in the Linux ABI and instead return EAGAIN which is what linux applications are expecting. N.B. This currently breaks running Call of Duty World at War servers, specifically the server fails to authenticate with the global master server. >How-To-Repeat: In a linux application 1. Create a tcp socket 2. Set socket non-blocking 3. Connect to an end point 4. Perform a non-blocking send 5. ENOTCONN is returned. >Fix: Apply the attached patch or derivative there of. Patch attached with submission follows: --- linux_socket.c.orig 2008-11-22 18:26:27.000000000 +0000 +++ linux_socket.c 2008-11-22 18:44:56.000000000 +0000 @@ -878,4 +878,6 @@ } */ bsd_args; int error; + struct socket *so; + u_int fflag; if ((error = copyin(args, &linux_args, sizeof(linux_args)))) @@ -888,5 +890,26 @@ bsd_args.to = NULL; bsd_args.tolen = 0; - return sendto(td, &bsd_args); + error = sendto(td, &bsd_args); + if ( ENOTCONN == error ) + { + /* + * Linux doesn't return ENOTCONN for non-blocking sockets. + * Instead it returns the EAGAIN. + * + * XXXRW: Instead of using fgetsock(), check that it is a + * socket and use the file descriptor reference instead of + * creating a new one. + */ + error = fgetsock(td, linux_args.s, &so, &fflag); + if ( 0 == error ) + { + if ( fflag & FNONBLOCK ) + { + error = EAGAIN; + } + fputsock(so); + } + } + return (error); } >Release-Note: >Audit-Trail: >Unformatted: