]> The Tcpdump Group git mirrors - libpcap/commitdiff
Call WSAStartup/WSACleanup for each use. Fixes #1333
authorDaniel Miller <[email protected]>
Tue, 17 Sep 2024 16:03:01 +0000 (09:03 -0700)
committerGuy Harris <[email protected]>
Sat, 21 Sep 2024 22:26:21 +0000 (15:26 -0700)
WSACleanup cannot be called from atexit() because that's run in DllMain
context. Instead, start and cleanup at each use, using new static inline
functions pcapint_sockinit() and pcapint_sockcleanup()

gencode.c
pcap-npf.c
pcap.3pcap.in
pcap.c
pcap_init.3pcap
portability.h
rpcapd/log.c
testprogs/filtertest.c

index ac6681e29ab25127e129f3d1d9b5012751b803b8..d543d97a9cae1867eb4068602d5de8bf290233ef 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -726,9 +726,6 @@ int
 pcap_compile(pcap_t *p, struct bpf_program *program,
             const char *buf, int optimize, bpf_u_int32 mask)
 {
-#ifdef _WIN32
-       static int done = 0;
-#endif
        compiler_state_t cstate;
        const char * volatile xbuf = buf;
        yyscan_t scanner = NULL;
@@ -746,12 +743,9 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
                return (PCAP_ERROR);
        }
 
-#ifdef _WIN32
-       if (!done) {
-               pcap_wsockinit();
-               done = 1;
+       if(0 != pcapint_sockinit()) {
+               return (PCAP_ERROR);
        }
-#endif
 
 #ifdef ENABLE_REMOTE
        /*
@@ -875,6 +869,8 @@ quit:
         */
        freechunks(&cstate);
 
+       pcapint_sockcleanup();
+
        return (rc);
 }
 
index b8916712f190ff88d0d9f8b2a28a1cc757cadbeb..2b7ff1705477daa0468c585483fc6614b4fef65b 100644 (file)
@@ -1080,9 +1080,6 @@ pcap_activate_npf(pcap_t *p)
                }
        }
 
-       /* Init Winsock if it hasn't already been initialized */
-       pcap_wsockinit();
-
        pw->adapter = PacketOpenAdapter(p->opt.device);
 
        if (pw->adapter == NULL)
index acaa3876e76dc20595650e2853a0f60242700c82..846ba92b3c3dc3dbe8fd5753df75c90cf7365178 100644 (file)
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP 3PCAP "4 March 2024"
+.TH PCAP 3PCAP "18 September 2024"
 .SH NAME
 pcap \- Packet Capture library
 .SH SYNOPSIS
@@ -72,15 +72,7 @@ makes an attempt to check whether the string passed as an argument is a
 UTF-16LE string - note that this attempt is unsafe, as it may run past
 the end of the string - to handle
 .BR pcap_lookupdev ()
-returning a UTF-16LE string. Programs that don't call
-.BR pcap_init ()
-should, on Windows, call
-.BR pcap_wsockinit ()
-to initialize Winsock; this is not necessary if
-.BR pcap_init ()
-is called, as
-.BR pcap_init ()
-will initialize Winsock itself on Windows.
+returning a UTF-16LE string.
 .TP
 .B Routines
 .RS
diff --git a/pcap.c b/pcap.c
index 9e9cec8d9e47dcc0793c6d0f02bcd87b969b3793..2ff17e1629074fb842bb876d317b031c86377900 100644 (file)
--- a/pcap.c
+++ b/pcap.c
@@ -152,9 +152,10 @@ struct rtentry;            /* declarations in <net/if.h> */
  *
  * So we don't initialize Winsock in a DllMain() routine.
  *
- * pcap_init() should be called to initialize pcap on both UN*X and
- * Windows; it will initialize Winsock on Windows.  (It will also be
- * initialized as needed if pcap_init() hasn't been called.)
+ * Similarly, we cannot register an atexit() handler to call WSACleanup()
+ * because that handler will be run in the context of DllMain. Therefore, we
+ * call WSAStartup each time Winsock is needed and WSACleanup as soon as it is
+ * no longer needed.
  */
 
 /*
@@ -177,32 +178,7 @@ internal_wsockfini(void)
 static int
 internal_wsockinit(char *errbuf)
 {
-       WORD wVersionRequested;
-       WSADATA wsaData;
-       static int err = -1;
-       static int done = 0;
-       int status;
-
-       if (done)
-               return (err);
-
-       /*
-        * Versions of Windows that don't support Winsock 2.2 are
-        * too old for us.
-        */
-       wVersionRequested = MAKEWORD(2, 2);
-       status = WSAStartup(wVersionRequested, &wsaData);
-       done = 1;
-       if (status != 0) {
-               if (errbuf != NULL) {
-                       pcapint_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
-                           status, "WSAStartup() failed");
-               }
-               return (err);
-       }
-       atexit(internal_wsockfini);
-       err = 0;
-       return (err);
+       return 0;
 }
 
 /*
@@ -311,16 +287,6 @@ pcap_init(unsigned int opts, char *errbuf)
                return (0);
        }
 
-#ifdef _WIN32
-       /*
-        * Now set up Winsock.
-        */
-       if (internal_wsockinit(errbuf) == -1) {
-               /* Failed. */
-               return (PCAP_ERROR);
-       }
-#endif
-
        /*
         * We're done.
         */
index 54ee5f7c67f74309fb196a00fc8dee12e608c329..34a993be43643e522db76bb37dbca8ee22d84f24 100644 (file)
@@ -17,7 +17,7 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.TH PCAP_INIT 3PCAP "30 November 2023"
+.TH PCAP_INIT 3PCAP "18 September 2024"
 .SH NAME
 pcap_init \- initialize the library
 .SH SYNOPSIS
@@ -76,15 +76,7 @@ makes an attempt to check whether the string passed as an argument is a
 UTF-16LE string - note that this attempt is unsafe, as it may run past
 the end of the string - to handle
 .BR pcap_lookupdev ()
-returning a UTF-16LE string. Programs that don't call
-.BR pcap_init ()
-should, on Windows, call
-.BR pcap_wsockinit ()
-to initialize Winsock; this is not necessary if
-.BR pcap_init ()
-is called, as
-.BR pcap_init ()
-will initialize Winsock itself on Windows.
+returning a UTF-16LE string.
 .SH RETURN VALUE
 .BR pcap_init ()
 returns
index 5a2496c932d9fc32dac031deb676089ecf483dd5..8646a6a94a06ed9e664d795d69dc1093626f06ff 100644 (file)
@@ -157,8 +157,26 @@ extern int pcapint_vasprintf(char **, PCAP_FORMAT_STRING(const char *), va_list
   #if !defined(__cplusplus)
     #define inline __inline
   #endif
+#include <winsock2.h>
 #endif /* _WIN32 */
 
+static inline int pcapint_sockinit(void)
+{
+#ifdef _WIN32
+  WSADATA wsaData;
+  return WSAStartup(MAKEWORD(2,2), &wsaData);
+#else
+  return 0;
+#endif /* _WIN32 */
+}
+
+static inline void pcapint_sockcleanup(void)
+{
+#ifdef _WIN32
+  WSACleanup();
+#endif /* _WIN32 */
+}
+
 #ifdef __cplusplus
 }
 #endif
index 71668a195bec558675e479bb9026a56abb87ab17..e23296781194b05bb7beea4c037308f40003c0f1 100644 (file)
@@ -26,6 +26,9 @@
 #include <stdlib.h>
 
 #ifdef _WIN32
+/* Prevent inclusion of winsock.h, which causes redefinition errors when
+ * winsock2.h is included later */
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #else
 #include <syslog.h>
index 17299755640251356d107f66550af9f2607e03e5..a5da943c4f5e93b9440f01ebcad01d8e07cd4c47 100644 (file)
@@ -221,8 +221,10 @@ main(int argc, char **argv)
        struct bpf_program fcode;
 
 #ifdef _WIN32
-       if (pcap_wsockinit() != 0)
+       WSADATA wsaData;
+       if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
                return 1;
+       atexit ((void(*)(void))WSACleanup);
 #endif /* _WIN32 */
 
        dflag = 1;