windows: Implement socketpair() using TCP sockets
authorMartin Willi <martin@revosec.ch>
Wed, 16 Oct 2013 15:44:32 +0000 (17:44 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 4 Jun 2014 13:52:59 +0000 (15:52 +0200)
src/libstrongswan/utils/windows.c
src/libstrongswan/utils/windows.h

index 6627a6c..a519b3b 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "utils.h"
 
+#include <errno.h>
+
 /**
  * See header
  */
@@ -33,3 +35,65 @@ void windows_deinit()
 {
        WSACleanup();
 }
+
+/**
+ * See header
+ */
+int socketpair(int domain, int type, int protocol, int sv[2])
+{
+       struct sockaddr_in addr = {
+               .sin_family = AF_INET,
+               .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+       };
+       socklen_t len = sizeof(addr);
+       int s, c, sc;
+       BOOL on;
+
+       /* We don't check domain for AF_INET, as we use it as replacement for
+        * AF_UNIX. */
+       if (type != SOCK_STREAM)
+       {
+               errno = EINVAL;
+               return -1;
+       }
+       if (protocol != 0 && protocol != IPPROTO_TCP)
+       {
+               errno = EINVAL;
+               return -1;
+       }
+       s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       if (s == -1)
+       {
+               return -1;
+       }
+       c = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       if (c == -1)
+       {
+               closesocket(c);
+               return -1;
+       }
+       if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) == 0 &&
+               getsockname(s,(struct sockaddr*)&addr, &len) == 0 &&
+               listen(s, 0) == 0 &&
+               connect(c, (struct sockaddr*)&addr, sizeof(addr)) == 0)
+       {
+               sc = accept(s, NULL, NULL);
+               if (sc > 0)
+               {
+                       closesocket(s);
+                       s = sc;
+                       if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
+                                                  (void*)&on, sizeof(on)) == 0 &&
+                               setsockopt(c, IPPROTO_TCP, TCP_NODELAY,
+                                                  (void*)&on, sizeof(on)) == 0)
+                       {
+                               sv[0] = s;
+                               sv[1] = c;
+                               return 0;
+                       }
+               }
+       }
+       closesocket(s);
+       closesocket(c);
+       return -1;
+}
index 1104980..23a6666 100644 (file)
@@ -246,6 +246,11 @@ static inline int dlclose(void *handle)
        return FreeLibrary((HMODULE)handle);
 }
 
+/**
+ * socketpair(2) for SOCK_STREAM, uses TCP on loopback
+ */
+int socketpair(int domain, int type, int protocol, int sv[2]);
+
 /* Windows does not support "ll" format printf length modifiers. Mingw
  * therefore maps these to the Windows specific I64 length modifier. That
  * won't work for us, as we use our own printf backend on Windows, which works