This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate:
authorNicholas Clark <nick@ccl4.org>
Fri, 10 Sep 2004 14:37:25 +0000 (14:37 +0000)
committerNicholas Clark <nick@ccl4.org>
Fri, 10 Sep 2004 14:37:25 +0000 (14:37 +0000)
[ 23200]
Fix [perl #24269] socket() call uses non-IFS providers
causing subsequent print/read to hang or misbehave

Patch supplied by Artiom Morozov <artiom@phreaker.net>
in the bug report at http://rt.perl.org/rt3/index.html?q=24269

(strictly actually use the alternative supplied "stable" patch)

[ 23275]
Implement new environment variable to allow the use of non-IFS
compatible LSP's on Windows to allow Perl to work in conjunction
with a firewall such as McAfee Guardian.

Bug report and possible solutions by Ken Fox <kfox@ford.com>;
further assistance by Artiom Morozov <artiom@phreaker.net>.
p4raw-link: @23275 on //depot/perl: 1c97260979b979af03b946d71d50e8e4c075665c
p4raw-link: @23200 on //depot/perl: 036c1c1eb70a0dfc5a7187959eb5e39d499c9396

p4raw-id: //depot/maint-5.8/perl@23317
p4raw-integrated: from //depot/perl@23316 'merge in' win32/Makefile
(@22887..) win32/makefile.mk (@22901..) pod/perlrun.pod
(@23185..)
p4raw-edited: from //depot/perl@23200 'edit in' win32/win32sck.c
(@21989..)
p4raw-integrated: from //depot/perl@23200 'merge in' README.win32
(@23172..)

README.win32
pod/perlrun.pod
win32/Makefile
win32/makefile.mk
win32/win32sck.c

index 0163441..ff75cef 100644 (file)
@@ -834,6 +834,12 @@ in the Win32 environment.  See L</"Building Extensions">.
 
 Most C<socket()> related calls are supported, but they may not
 behave as on Unix platforms.  See L<perlport> for the full list.
+Perl requires Winsock2 to be installed on the system. If you're
+running Win95, you can download Winsock upgrade from here:
+
+http://www.microsoft.com/windows95/downloads/contents/WUAdminTools/S_WUNetworkingTools/W95Sockets2/Default.asp
+
+Later OS versions already include Winsock2 support.
 
 Signal handling may not behave as on Unix platforms (where it
 doesn't exactly "behave", either :).  For instance, calling C<die()>
index 2de2311..325e7b0 100644 (file)
@@ -1101,6 +1101,20 @@ fit for interactive use, and setting COMSPEC to such a shell may
 interfere with the proper functioning of other programs (which usually
 look in COMSPEC to find a shell fit for interactive use).
 
+=item PERL_ALLOW_NON_IFS_LSP (specific to the Win32 port)
+
+Set to 1 to allow the use of non-IFS compatible LSP's.
+Perl normally searches for an IFS-compatible LSP because this is required
+for its emulation of Windows sockets as real filehandles.  However, this may
+cause problems if you have a firewall such as McAfee Guardian which requires
+all applications to use its LSP which is not IFS-compatible, because clearly
+Perl will normally avoid using such an LSP.
+Setting this environment variable to 1 means that Perl will simply use the
+first suitable LSP enumerated in the catalog, which keeps McAfee Guardian
+happy (and in that particular case Perl still works too because McAfee
+Guardian's LSP actually plays some other games which allow applications
+requiring IFS compatibility to work).
+
 =item PERL_DEBUG_MSTATS
 
 Relevant only if perl is compiled with the malloc included with the perl
index c9e171f..fcdb21a 100644 (file)
@@ -326,7 +326,7 @@ ARCHNAME    = $(ARCHNAME)-thread
 
 # VC 6.0 can load the socket dll on demand.  Makes the test suite
 # run in about 10% less time.
-DELAYLOAD      = -DELAYLOAD:wsock32.dll -DELAYLOAD:shell32.dll delayimp.lib
+DELAYLOAD      = -DELAYLOAD:ws2_32.dll -DELAYLOAD:shell32.dll delayimp.lib
 !ENDIF
 
 ARCHDIR                = ..\lib\$(ARCHNAME)
@@ -412,7 +412,7 @@ BUILDOPT    = $(BUILDOPT) -DPERL_MSVCRT_READFIX
 LIBBASEFILES   = $(CRYPT_LIB) \
                oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib \
                comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib \
-               netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib \
+               netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib \
                version.lib
 
 # win64 doesn't have some libs
index f4491cf..5108f61 100644 (file)
@@ -309,7 +309,7 @@ ARCHNAME    !:= $(ARCHNAME)-thread
 
 # VC 6.0 can load the socket dll on demand.  Makes the test suite
 # run in about 10% less time.
-DELAYLOAD      *= -DELAYLOAD:wsock32.dll -DELAYLOAD:shell32.dll delayimp.lib
+DELAYLOAD      *= -DELAYLOAD:ws2_32.dll -DELAYLOAD:shell32.dll delayimp.lib
 
 .IF "$(CFG)" == "Debug"
 .ELSE
@@ -419,7 +419,7 @@ LIBC                = -lmsvcrt
 LIBFILES       = $(CRYPT_LIB) $(LIBC) \
                  -lmoldname -lkernel32 -luser32 -lgdi32 \
                  -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 \
-                 -loleaut32 -lnetapi32 -luuid -lwsock32 -lmpr \
+                 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr \
                  -lwinmm -lversion -lodbc32
 
 .IF  "$(CFG)" == "Debug"
@@ -503,7 +503,7 @@ BUILDOPT    += -DPERL_MSVCRT_READFIX
 LIBBASEFILES   = $(CRYPT_LIB) \
                oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib \
                comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib \
-               netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib \
+               netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib \
                version.lib
 
 # win64 doesn't have some libs
index 9f47f50..e751dcd 100644 (file)
@@ -16,6 +16,8 @@
 #define Win32_Winsock
 #endif
 #include <windows.h>
+#include <ws2spi.h>
+
 #include "EXTERN.h"
 #include "perl.h"
 
@@ -86,11 +88,11 @@ start_sockets(void)
      * initalize the winsock interface and insure that it is
      * cleaned up at exit.
      */
-    version = 0x101;
+    version = 0x2;
     if(ret = WSAStartup(version, &retdata))
        Perl_croak_nocontext("Unable to locate winsock library!\n");
     if(retdata.wVersion != version)
-       Perl_croak_nocontext("Could not find version 1.1 of winsock dll\n");
+       Perl_croak_nocontext("Could not find version 2.0 of winsock dll\n");
 
     /* atexit((void (*)(void)) EndSockets); */
     wsock_started = 1;
@@ -103,14 +105,6 @@ set_socktype(void)
 #if defined(USE_5005THREADS) || defined(USE_ITHREADS)
     dTHX;
     if (!w32_init_socktype) {
-#endif
-       int iSockOpt = SO_SYNCHRONOUS_NONALERT;
-       /*
-        * Enable the use of sockets as filehandles
-        */
-       setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
-                   (char *)&iSockOpt, sizeof(iSockOpt));
-#if defined(USE_5005THREADS) || defined(USE_ITHREADS)
        w32_init_socktype = 1;
     }
 #endif
@@ -399,6 +393,70 @@ win32_closesocket(SOCKET s)
     return r;
 }
 
+#ifdef USE_SOCKETS_AS_HANDLES
+#define WIN32_OPEN_SOCKET(af, type, protocol) open_ifs_socket(af, type, protocol)
+
+void
+convert_proto_info_w2a(WSAPROTOCOL_INFOW *in, WSAPROTOCOL_INFOA *out)
+{
+    Copy(in, out, 1, WSAPROTOCOL_INFOA);
+    wcstombs(out->szProtocol, in->szProtocol, sizeof(out->szProtocol));
+}
+
+SOCKET
+open_ifs_socket(int af, int type, int protocol)
+{
+    dTHX;
+    char *s;
+    unsigned long proto_buffers_len = 0;
+    int error_code;
+    SOCKET out = INVALID_SOCKET;
+
+    if ((s = PerlEnv_getenv("PERL_ALLOW_NON_IFS_LSP")) && atoi(s))
+        return WSASocket(af, type, protocol, NULL, 0, 0);
+
+    if (WSCEnumProtocols(NULL, NULL, &proto_buffers_len, &error_code) == SOCKET_ERROR
+        && error_code == WSAENOBUFS)
+    {
+       WSAPROTOCOL_INFOW *proto_buffers;
+        int protocols_available = 0;       
+        New(1, proto_buffers, proto_buffers_len / sizeof(WSAPROTOCOL_INFOW),
+            WSAPROTOCOL_INFOW);
+
+        if ((protocols_available = WSCEnumProtocols(NULL, proto_buffers, 
+            &proto_buffers_len, &error_code)) != SOCKET_ERROR)
+        {
+            int i;
+            for (i = 0; i < protocols_available; i++)
+            {
+                WSAPROTOCOL_INFOA proto_info;
+
+                if ((af != AF_UNSPEC && af != proto_buffers[i].iAddressFamily)
+                    || (type != proto_buffers[i].iSocketType)
+                    || (protocol != 0 && protocol != proto_buffers[i].iProtocol))
+                    continue;
+
+                if ((proto_buffers[i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0)
+                    continue;
+
+                convert_proto_info_w2a(&(proto_buffers[i]), &proto_info);
+
+                out = WSASocket(af, type, protocol, &proto_info, 0, 0);
+                break;
+            }
+        }
+
+        Safefree(proto_buffers);
+    }
+
+    return out;
+}
+
+#else
+#define WIN32_OPEN_SOCKET(af, type, protocol) socket(af, type, protocol)
+#endif
+
 SOCKET
 win32_socket(int af, int type, int protocol)
 {
@@ -408,7 +466,8 @@ win32_socket(int af, int type, int protocol)
     SOCKET_TEST(s = socket(af, type, protocol), INVALID_SOCKET);
 #else
     StartSockets();
-    if((s = socket(af, type, protocol)) == INVALID_SOCKET)
+
+    if((s = WIN32_OPEN_SOCKET(af, type, protocol)) == INVALID_SOCKET)
        errno = WSAGetLastError();
     else
        s = OPEN_SOCKET(s);