9d7d3f
From 3fef242a1e1a74140a1678d84164086d0f47d83a Mon Sep 17 00:00:00 2001
9d7d3f
From: Peter Wu <peter@lekensteyn.nl>
9d7d3f
Date: Thu, 27 Nov 2014 23:59:19 +0100
9d7d3f
Subject: [PATCH 01/11] sws: move away from IPv4/IPv4-only assumption
9d7d3f
9d7d3f
Instead of depending the socket domain type on use_ipv6, specify the
9d7d3f
domain type (AF_INET / AF_INET6) as variable. An enum is used here with
9d7d3f
switch to avoid compiler warnings in connect_to, complaining that rc
9d7d3f
is possibly undefined (which is not possible as socket_domain is
9d7d3f
always set).
9d7d3f
9d7d3f
Besides abstracting the socket type, make the debugging messages be
9d7d3f
independent on IP (introduce location_str which points to "port XXXXX").
9d7d3f
Rename "ipv_inuse" to "socket_type" and tighten the scope (main).
9d7d3f
9d7d3f
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
9d7d3f
9d7d3f
Upstream-commit: cf6c5c222d86088cbfc9dee4c23f8ada96ee91e7
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 tests/server/sws.c | 88 ++++++++++++++++++++++++------------------------------
9d7d3f
 1 file changed, 39 insertions(+), 49 deletions(-)
9d7d3f
9d7d3f
diff --git a/tests/server/sws.c b/tests/server/sws.c
9d7d3f
index aef55ea..fa10d54 100644
9d7d3f
--- a/tests/server/sws.c
9d7d3f
+++ b/tests/server/sws.c
9d7d3f
@@ -65,11 +65,13 @@
9d7d3f
 #define ERANGE  34 /* errno.h value */
9d7d3f
 #endif
9d7d3f
 
9d7d3f
+static enum {
9d7d3f
+  socket_domain_inet = AF_INET,
9d7d3f
 #ifdef ENABLE_IPV6
9d7d3f
-static bool use_ipv6 = FALSE;
9d7d3f
+  socket_domain_inet6 = AF_INET6
9d7d3f
 #endif
9d7d3f
+} socket_domain = AF_INET;
9d7d3f
 static bool use_gopher = FALSE;
9d7d3f
-static const char *ipv_inuse = "IPv4";
9d7d3f
 static int serverlogslocked = 0;
9d7d3f
 static bool is_proxy = FALSE;
9d7d3f
 
9d7d3f
@@ -1285,7 +1287,7 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
9d7d3f
 #endif
9d7d3f
 
9d7d3f
 #ifdef ENABLE_IPV6
9d7d3f
-  if(use_ipv6) {
9d7d3f
+  if(socket_domain == AF_INET6) {
9d7d3f
     op_br = "[";
9d7d3f
     cl_br = "]";
9d7d3f
   }
9d7d3f
@@ -1297,14 +1299,8 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
9d7d3f
   logmsg("about to connect to %s%s%s:%hu",
9d7d3f
          op_br, ipaddr, cl_br, port);
9d7d3f
 
9d7d3f
-#ifdef ENABLE_IPV6
9d7d3f
-  if(!use_ipv6)
9d7d3f
-#endif
9d7d3f
-    serverfd = socket(AF_INET, SOCK_STREAM, 0);
9d7d3f
-#ifdef ENABLE_IPV6
9d7d3f
-  else
9d7d3f
-    serverfd = socket(AF_INET6, SOCK_STREAM, 0);
9d7d3f
-#endif
9d7d3f
+
9d7d3f
+  serverfd = socket(socket_domain, SOCK_STREAM, 0);
9d7d3f
   if(CURL_SOCKET_BAD == serverfd) {
9d7d3f
     error = SOCKERRNO;
9d7d3f
     logmsg("Error creating socket for server conection: (%d) %s",
9d7d3f
@@ -1322,9 +1318,8 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
9d7d3f
     logmsg("TCP_NODELAY set for server conection");
9d7d3f
 #endif
9d7d3f
 
9d7d3f
-#ifdef ENABLE_IPV6
9d7d3f
-  if(!use_ipv6) {
9d7d3f
-#endif
9d7d3f
+  switch(socket_domain) {
9d7d3f
+  case AF_INET:
9d7d3f
     memset(&serveraddr.sa4, 0, sizeof(serveraddr.sa4));
9d7d3f
     serveraddr.sa4.sin_family = AF_INET;
9d7d3f
     serveraddr.sa4.sin_port = htons(port);
9d7d3f
@@ -1335,9 +1330,9 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
9d7d3f
     }
9d7d3f
 
9d7d3f
     rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa4));
9d7d3f
+    break;
9d7d3f
 #ifdef ENABLE_IPV6
9d7d3f
-  }
9d7d3f
-  else {
9d7d3f
+  case AF_INET6:
9d7d3f
     memset(&serveraddr.sa6, 0, sizeof(serveraddr.sa6));
9d7d3f
     serveraddr.sa6.sin6_family = AF_INET6;
9d7d3f
     serveraddr.sa6.sin6_port = htons(port);
9d7d3f
@@ -1348,8 +1343,9 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
9d7d3f
     }
9d7d3f
 
9d7d3f
     rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa6));
9d7d3f
-  }
9d7d3f
+    break;
9d7d3f
 #endif /* ENABLE_IPV6 */
9d7d3f
+  }
9d7d3f
 
9d7d3f
   if(got_exit_signal) {
9d7d3f
     sclose(serverfd);
9d7d3f
@@ -1924,21 +1920,20 @@ int main(int argc, char *argv[])
9d7d3f
   int arg=1;
9d7d3f
   long pid;
9d7d3f
   const char *hostport = "127.0.0.1";
9d7d3f
+  const char *socket_type = "IPv4";
9d7d3f
+  char port_str[11];
9d7d3f
+  const char *location_str = port_str;
9d7d3f
   size_t socket_idx;
9d7d3f
 
9d7d3f
   memset(&req, 0, sizeof(req));
9d7d3f
 
9d7d3f
   while(argc>arg) {
9d7d3f
     if(!strcmp("--version", argv[arg])) {
9d7d3f
-      printf("sws IPv4%s"
9d7d3f
-             "\n"
9d7d3f
-             ,
9d7d3f
+      puts("sws IPv4"
9d7d3f
 #ifdef ENABLE_IPV6
9d7d3f
              "/IPv6"
9d7d3f
-#else
9d7d3f
-             ""
9d7d3f
 #endif
9d7d3f
-             );
9d7d3f
+          );
9d7d3f
       return 0;
9d7d3f
     }
9d7d3f
     else if(!strcmp("--pidfile", argv[arg])) {
9d7d3f
@@ -1957,16 +1952,16 @@ int main(int argc, char *argv[])
9d7d3f
       end_of_headers = "\r\n"; /* gopher style is much simpler */
9d7d3f
     }
9d7d3f
     else if(!strcmp("--ipv4", argv[arg])) {
9d7d3f
-#ifdef ENABLE_IPV6
9d7d3f
-      ipv_inuse = "IPv4";
9d7d3f
-      use_ipv6 = FALSE;
9d7d3f
-#endif
9d7d3f
+      socket_type = "IPv4";
9d7d3f
+      socket_domain = AF_INET;
9d7d3f
+      location_str = port_str;
9d7d3f
       arg++;
9d7d3f
     }
9d7d3f
     else if(!strcmp("--ipv6", argv[arg])) {
9d7d3f
 #ifdef ENABLE_IPV6
9d7d3f
-      ipv_inuse = "IPv6";
9d7d3f
-      use_ipv6 = TRUE;
9d7d3f
+      socket_type = "IPv6";
9d7d3f
+      socket_domain = AF_INET6;
9d7d3f
+      location_str = port_str;
9d7d3f
 #endif
9d7d3f
       arg++;
9d7d3f
     }
9d7d3f
@@ -2018,6 +2013,8 @@ int main(int argc, char *argv[])
9d7d3f
     }
9d7d3f
   }
9d7d3f
 
9d7d3f
+  snprintf(port_str, sizeof(port_str), "port %hu", port);
9d7d3f
+
9d7d3f
 #ifdef WIN32
9d7d3f
   win32_init();
9d7d3f
   atexit(win32_cleanup);
9d7d3f
@@ -2027,14 +2024,7 @@ int main(int argc, char *argv[])
9d7d3f
 
9d7d3f
   pid = (long)getpid();
9d7d3f
 
9d7d3f
-#ifdef ENABLE_IPV6
9d7d3f
-  if(!use_ipv6)
9d7d3f
-#endif
9d7d3f
-    sock = socket(AF_INET, SOCK_STREAM, 0);
9d7d3f
-#ifdef ENABLE_IPV6
9d7d3f
-  else
9d7d3f
-    sock = socket(AF_INET6, SOCK_STREAM, 0);
9d7d3f
-#endif
9d7d3f
+  sock = socket(socket_domain, SOCK_STREAM, 0);
9d7d3f
 
9d7d3f
   all_sockets[0] = sock;
9d7d3f
   num_sockets = 1;
9d7d3f
@@ -2061,33 +2051,33 @@ int main(int argc, char *argv[])
9d7d3f
     goto sws_cleanup;
9d7d3f
   }
9d7d3f
 
9d7d3f
-#ifdef ENABLE_IPV6
9d7d3f
-  if(!use_ipv6) {
9d7d3f
-#endif
9d7d3f
+  switch(socket_domain) {
9d7d3f
+  case AF_INET:
9d7d3f
     memset(&me.sa4, 0, sizeof(me.sa4));
9d7d3f
     me.sa4.sin_family = AF_INET;
9d7d3f
     me.sa4.sin_addr.s_addr = INADDR_ANY;
9d7d3f
     me.sa4.sin_port = htons(port);
9d7d3f
     rc = bind(sock, &me.sa, sizeof(me.sa4));
9d7d3f
+    break;
9d7d3f
 #ifdef ENABLE_IPV6
9d7d3f
-  }
9d7d3f
-  else {
9d7d3f
+  case AF_INET6:
9d7d3f
     memset(&me.sa6, 0, sizeof(me.sa6));
9d7d3f
     me.sa6.sin6_family = AF_INET6;
9d7d3f
     me.sa6.sin6_addr = in6addr_any;
9d7d3f
     me.sa6.sin6_port = htons(port);
9d7d3f
     rc = bind(sock, &me.sa, sizeof(me.sa6));
9d7d3f
-  }
9d7d3f
+    break;
9d7d3f
 #endif /* ENABLE_IPV6 */
9d7d3f
+  }
9d7d3f
   if(0 != rc) {
9d7d3f
     error = SOCKERRNO;
9d7d3f
-    logmsg("Error binding socket on port %hu: (%d) %s",
9d7d3f
-           port, error, strerror(error));
9d7d3f
+    logmsg("Error binding socket on %s: (%d) %s",
9d7d3f
+           location_str, error, strerror(error));
9d7d3f
     goto sws_cleanup;
9d7d3f
   }
9d7d3f
 
9d7d3f
-  logmsg("Running %s %s version on port %d",
9d7d3f
-         use_gopher?"GOPHER":"HTTP", ipv_inuse, (int)port);
9d7d3f
+  logmsg("Running %s %s version on %s",
9d7d3f
+         use_gopher?"GOPHER":"HTTP", socket_type, location_str);
9d7d3f
 
9d7d3f
   /* start accepting connections */
9d7d3f
   rc = listen(sock, 5);
9d7d3f
@@ -2251,8 +2241,8 @@ sws_cleanup:
9d7d3f
   restore_signal_handlers();
9d7d3f
 
9d7d3f
   if(got_exit_signal) {
9d7d3f
-    logmsg("========> %s sws (port: %d pid: %ld) exits with signal (%d)",
9d7d3f
-           ipv_inuse, (int)port, pid, exit_signal);
9d7d3f
+    logmsg("========> %s sws (%s pid: %ld) exits with signal (%d)",
9d7d3f
+           socket_type, location_str, pid, exit_signal);
9d7d3f
     /*
9d7d3f
      * To properly set the return status of the process we
9d7d3f
      * must raise the same signal SIGINT or SIGTERM that we
9d7d3f
-- 
9d7d3f
2.5.2
9d7d3f
9d7d3f
9d7d3f
From d8d875f7c528157feec0795c03bd065420903f5d Mon Sep 17 00:00:00 2001
9d7d3f
From: Steve Holme <steve_holme@hotmail.com>
9d7d3f
Date: Wed, 3 Dec 2014 00:00:40 +0000
9d7d3f
Subject: [PATCH 02/11] sws.c: Fixed compilation warning when IPv6 is disabled
9d7d3f
9d7d3f
sws.c:69: warning: comma at end of enumerator list
9d7d3f
9d7d3f
Upstream-commit: d784000a1468efc986c7d156d2e7c84d1920af87
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 tests/server/sws.c | 4 ++--
9d7d3f
 1 file changed, 2 insertions(+), 2 deletions(-)
9d7d3f
9d7d3f
diff --git a/tests/server/sws.c b/tests/server/sws.c
9d7d3f
index fa10d54..2b7e628 100644
9d7d3f
--- a/tests/server/sws.c
9d7d3f
+++ b/tests/server/sws.c
9d7d3f
@@ -66,9 +66,9 @@
9d7d3f
 #endif
9d7d3f
 
9d7d3f
 static enum {
9d7d3f
-  socket_domain_inet = AF_INET,
9d7d3f
+  socket_domain_inet = AF_INET
9d7d3f
 #ifdef ENABLE_IPV6
9d7d3f
-  socket_domain_inet6 = AF_INET6
9d7d3f
+  , socket_domain_inet6 = AF_INET6
9d7d3f
 #endif
9d7d3f
 } socket_domain = AF_INET;
9d7d3f
 static bool use_gopher = FALSE;
9d7d3f
-- 
9d7d3f
2.5.2
9d7d3f
9d7d3f
9d7d3f
From db2095dec37630309bacca6795cd4cfcf6557c9b Mon Sep 17 00:00:00 2001
9d7d3f
From: Peter Wu <peter@lekensteyn.nl>
9d7d3f
Date: Thu, 27 Nov 2014 23:59:20 +0100
9d7d3f
Subject: [PATCH 03/11] sws: restrict TCP_NODELAY to IP sockets
9d7d3f
9d7d3f
TCP_NODELAY does not make sense for Unix sockets, so enable it only if
9d7d3f
the socket is using IP.
9d7d3f
9d7d3f
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
9d7d3f
9d7d3f
Upstream-commit: fb7d7e0022f22035449bbc506068004f0568f8ae
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 tests/server/sws.c | 73 ++++++++++++++++++++++++++++++++----------------------
9d7d3f
 1 file changed, 44 insertions(+), 29 deletions(-)
9d7d3f
9d7d3f
diff --git a/tests/server/sws.c b/tests/server/sws.c
9d7d3f
index 2b7e628..0739a70 100644
9d7d3f
--- a/tests/server/sws.c
9d7d3f
+++ b/tests/server/sws.c
9d7d3f
@@ -331,6 +331,21 @@ static void restore_signal_handlers(void)
9d7d3f
 #endif
9d7d3f
 }
9d7d3f
 
9d7d3f
+/* returns true if the current socket is an IP one */
9d7d3f
+static bool socket_domain_is_ip(void)
9d7d3f
+{
9d7d3f
+  switch(socket_domain) {
9d7d3f
+  case AF_INET:
9d7d3f
+#ifdef ENABLE_IPV6
9d7d3f
+  case AF_INET6:
9d7d3f
+#endif
9d7d3f
+    return true;
9d7d3f
+  default:
9d7d3f
+  /* case AF_UNIX: */
9d7d3f
+    return false;
9d7d3f
+  }
9d7d3f
+}
9d7d3f
+
9d7d3f
 /* based on the testno, parse the correct server commands */
9d7d3f
 static int parse_servercmd(struct httprequest *req)
9d7d3f
 {
9d7d3f
@@ -1282,9 +1297,6 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
9d7d3f
   int rc;
9d7d3f
   const char *op_br = "";
9d7d3f
   const char *cl_br = "";
9d7d3f
-#ifdef TCP_NODELAY
9d7d3f
-  curl_socklen_t flag;
9d7d3f
-#endif
9d7d3f
 
9d7d3f
 #ifdef ENABLE_IPV6
9d7d3f
   if(socket_domain == AF_INET6) {
9d7d3f
@@ -1309,13 +1321,15 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
9d7d3f
   }
9d7d3f
 
9d7d3f
 #ifdef TCP_NODELAY
9d7d3f
-  /* Disable the Nagle algorithm */
9d7d3f
-  flag = 1;
9d7d3f
-  if(0 != setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY,
9d7d3f
-                     (void *)&flag, sizeof(flag)))
9d7d3f
-    logmsg("====> TCP_NODELAY for server conection failed");
9d7d3f
-  else
9d7d3f
-    logmsg("TCP_NODELAY set for server conection");
9d7d3f
+  if(socket_domain_is_ip()) {
9d7d3f
+    /* Disable the Nagle algorithm */
9d7d3f
+    curl_socklen_t flag = 1;
9d7d3f
+    if(0 != setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY,
9d7d3f
+                       (void *)&flag, sizeof(flag)))
9d7d3f
+      logmsg("====> TCP_NODELAY for server conection failed");
9d7d3f
+    else
9d7d3f
+      logmsg("TCP_NODELAY set for server conection");
9d7d3f
+  }
9d7d3f
 #endif
9d7d3f
 
9d7d3f
   switch(socket_domain) {
9d7d3f
@@ -1398,9 +1412,6 @@ static void http_connect(curl_socket_t *infdp,
9d7d3f
   bool poll_server_rd[2] = { TRUE, TRUE };
9d7d3f
   bool poll_client_wr[2] = { TRUE, TRUE };
9d7d3f
   bool poll_server_wr[2] = { TRUE, TRUE };
9d7d3f
-#ifdef TCP_NODELAY
9d7d3f
-  curl_socklen_t flag;
9d7d3f
-#endif
9d7d3f
   bool primary = FALSE;
9d7d3f
   bool secondary = FALSE;
9d7d3f
   int max_tunnel_idx; /* CTRL or DATA */
9d7d3f
@@ -1514,13 +1525,15 @@ static void http_connect(curl_socket_t *infdp,
9d7d3f
           memset(&req2, 0, sizeof(req2));
9d7d3f
           logmsg("====> Client connect DATA");
9d7d3f
 #ifdef TCP_NODELAY
9d7d3f
-          /* Disable the Nagle algorithm */
9d7d3f
-          flag = 1;
9d7d3f
-          if(0 != setsockopt(datafd, IPPROTO_TCP, TCP_NODELAY,
9d7d3f
-                             (void *)&flag, sizeof(flag)))
9d7d3f
-            logmsg("====> TCP_NODELAY for client DATA conection failed");
9d7d3f
-          else
9d7d3f
-            logmsg("TCP_NODELAY set for client DATA conection");
9d7d3f
+          if(socket_domain_is_ip()) {
9d7d3f
+            /* Disable the Nagle algorithm */
9d7d3f
+            curl_socklen_t flag = 1;
9d7d3f
+            if(0 != setsockopt(datafd, IPPROTO_TCP, TCP_NODELAY,
9d7d3f
+                               (void *)&flag, sizeof(flag)))
9d7d3f
+              logmsg("====> TCP_NODELAY for client DATA conection failed");
9d7d3f
+            else
9d7d3f
+              logmsg("TCP_NODELAY set for client DATA conection");
9d7d3f
+          }
9d7d3f
 #endif
9d7d3f
           req2.pipelining = FALSE;
9d7d3f
           init_httprequest(&req2);
9d7d3f
@@ -1826,15 +1839,17 @@ static curl_socket_t accept_connection(curl_socket_t sock)
9d7d3f
   num_sockets += 1;
9d7d3f
 
9d7d3f
 #ifdef TCP_NODELAY
9d7d3f
-  /*
9d7d3f
-   * Disable the Nagle algorithm to make it easier to send out a large
9d7d3f
-   * response in many small segments to torture the clients more.
9d7d3f
-   */
9d7d3f
-  if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY,
9d7d3f
-                     (void *)&flag, sizeof(flag)))
9d7d3f
-    logmsg("====> TCP_NODELAY failed");
9d7d3f
-  else
9d7d3f
-    logmsg("TCP_NODELAY set");
9d7d3f
+  if(socket_domain_is_ip()) {
9d7d3f
+    /*
9d7d3f
+     * Disable the Nagle algorithm to make it easier to send out a large
9d7d3f
+     * response in many small segments to torture the clients more.
9d7d3f
+     */
9d7d3f
+    if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY,
9d7d3f
+                       (void *)&flag, sizeof(flag)))
9d7d3f
+      logmsg("====> TCP_NODELAY failed");
9d7d3f
+    else
9d7d3f
+      logmsg("TCP_NODELAY set");
9d7d3f
+  }
9d7d3f
 #endif
9d7d3f
 
9d7d3f
   return msgsock;
9d7d3f
-- 
9d7d3f
2.5.2
9d7d3f
9d7d3f
9d7d3f
From 7ab987459a931e593dc9f533d6e6cb6e9a26d424 Mon Sep 17 00:00:00 2001
9d7d3f
From: Peter Wu <peter@lekensteyn.nl>
9d7d3f
Date: Wed, 3 Dec 2014 02:20:00 +0100
9d7d3f
Subject: [PATCH 04/11] sws: add UNIX domain socket support
9d7d3f
9d7d3f
This extends sws with a --unix-socket option which causes the port to
9d7d3f
be ignored (as the server now listens on the path specified by
9d7d3f
--unix-socket). This feature will be available in the following patch
9d7d3f
that enables checking for UNIX domain socket support.
9d7d3f
9d7d3f
Proxy support (CONNECT) is not considered nor tested. It does not make
9d7d3f
sense anyway, first connecting through a TCP proxy, then let that TCP
9d7d3f
proxy connect to a UNIX socket.
9d7d3f
9d7d3f
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
9d7d3f
9d7d3f
Upstream-commit: e9c7a86220ddf4e67b8bff56cddfc7388afcc9ef
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 tests/server/server_sockaddr.h |  9 ++++++-
9d7d3f
 tests/server/sws.c             | 53 ++++++++++++++++++++++++++++++++++++++++++
9d7d3f
 2 files changed, 61 insertions(+), 1 deletion(-)
9d7d3f
9d7d3f
diff --git a/tests/server/server_sockaddr.h b/tests/server/server_sockaddr.h
9d7d3f
index 6a17fe0..3f4cd67 100644
9d7d3f
--- a/tests/server/server_sockaddr.h
9d7d3f
+++ b/tests/server/server_sockaddr.h
9d7d3f
@@ -7,7 +7,7 @@
9d7d3f
  *                            | (__| |_| |  _ <| |___
9d7d3f
  *                             \___|\___/|_| \_\_____|
9d7d3f
  *
9d7d3f
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
9d7d3f
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
9d7d3f
  *
9d7d3f
  * This software is licensed as described in the file COPYING, which
9d7d3f
  * you should have received as part of this distribution. The terms
9d7d3f
@@ -23,12 +23,19 @@
9d7d3f
  ***************************************************************************/
9d7d3f
 #include "server_setup.h"
9d7d3f
 
9d7d3f
+#ifdef HAVE_SYS_UN_H
9d7d3f
+#include <sys/un.h> /* for sockaddr_un */
9d7d3f
+#endif
9d7d3f
+
9d7d3f
 typedef union {
9d7d3f
   struct sockaddr      sa;
9d7d3f
   struct sockaddr_in   sa4;
9d7d3f
 #ifdef ENABLE_IPV6
9d7d3f
   struct sockaddr_in6  sa6;
9d7d3f
 #endif
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+  struct sockaddr_un   sau;
9d7d3f
+#endif
9d7d3f
 } srvr_sockaddr_union_t;
9d7d3f
 
9d7d3f
 #endif /* HEADER_CURL_SERVER_SOCKADDR_H */
9d7d3f
diff --git a/tests/server/sws.c b/tests/server/sws.c
9d7d3f
index 0739a70..24ecb8f 100644
9d7d3f
--- a/tests/server/sws.c
9d7d3f
+++ b/tests/server/sws.c
9d7d3f
@@ -70,6 +70,9 @@ static enum {
9d7d3f
 #ifdef ENABLE_IPV6
9d7d3f
   , socket_domain_inet6 = AF_INET6
9d7d3f
 #endif
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+  , socket_domain_unix = AF_UNIX
9d7d3f
+#endif
9d7d3f
 } socket_domain = AF_INET;
9d7d3f
 static bool use_gopher = FALSE;
9d7d3f
 static int serverlogslocked = 0;
9d7d3f
@@ -1359,6 +1362,11 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
9d7d3f
     rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa6));
9d7d3f
     break;
9d7d3f
 #endif /* ENABLE_IPV6 */
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+  case AF_UNIX:
9d7d3f
+    logmsg("Proxying through UNIX socket is not (yet?) supported.");
9d7d3f
+    return CURL_SOCKET_BAD;
9d7d3f
+#endif /* USE_UNIX_SOCKETS */
9d7d3f
   }
9d7d3f
 
9d7d3f
   if(got_exit_signal) {
9d7d3f
@@ -1928,6 +1936,10 @@ int main(int argc, char *argv[])
9d7d3f
   int wrotepidfile = 0;
9d7d3f
   int flag;
9d7d3f
   unsigned short port = DEFAULT_PORT;
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+  const char *unix_socket = NULL;
9d7d3f
+  bool unlink_socket = false;
9d7d3f
+#endif
9d7d3f
   char *pidname= (char *)".http.pid";
9d7d3f
   struct httprequest req;
9d7d3f
   int rc;
9d7d3f
@@ -1948,6 +1960,9 @@ int main(int argc, char *argv[])
9d7d3f
 #ifdef ENABLE_IPV6
9d7d3f
              "/IPv6"
9d7d3f
 #endif
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+             "/unix"
9d7d3f
+#endif
9d7d3f
           );
9d7d3f
       return 0;
9d7d3f
     }
9d7d3f
@@ -1980,6 +1995,23 @@ int main(int argc, char *argv[])
9d7d3f
 #endif
9d7d3f
       arg++;
9d7d3f
     }
9d7d3f
+    else if(!strcmp("--unix-socket", argv[arg])) {
9d7d3f
+      arg++;
9d7d3f
+      if(argc>arg) {
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+        unix_socket = argv[arg];
9d7d3f
+        if(strlen(unix_socket) >= sizeof(me.sau.sun_path)) {
9d7d3f
+          fprintf(stderr, "sws: socket path must be shorter than %zu chars\n",
9d7d3f
+                  sizeof(me.sau.sun_path));
9d7d3f
+          return 0;
9d7d3f
+        }
9d7d3f
+        socket_type = "unix";
9d7d3f
+        socket_domain = AF_UNIX;
9d7d3f
+        location_str = unix_socket;
9d7d3f
+#endif
9d7d3f
+        arg++;
9d7d3f
+      }
9d7d3f
+    }
9d7d3f
     else if(!strcmp("--port", argv[arg])) {
9d7d3f
       arg++;
9d7d3f
       if(argc>arg) {
9d7d3f
@@ -2020,6 +2052,7 @@ int main(int argc, char *argv[])
9d7d3f
            " --pidfile [file]\n"
9d7d3f
            " --ipv4\n"
9d7d3f
            " --ipv6\n"
9d7d3f
+           " --unix-socket [file]\n"
9d7d3f
            " --port [port]\n"
9d7d3f
            " --srcdir [path]\n"
9d7d3f
            " --connect [ip4-addr]\n"
9d7d3f
@@ -2083,6 +2116,14 @@ int main(int argc, char *argv[])
9d7d3f
     rc = bind(sock, &me.sa, sizeof(me.sa6));
9d7d3f
     break;
9d7d3f
 #endif /* ENABLE_IPV6 */
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+  case AF_UNIX:
9d7d3f
+    memset(&me.sau, 0, sizeof(me.sau));
9d7d3f
+    me.sau.sun_family = AF_UNIX;
9d7d3f
+    strncpy(me.sau.sun_path, unix_socket, sizeof(me.sau.sun_path));
9d7d3f
+    rc = bind(sock, &me.sa, sizeof(me.sau));
9d7d3f
+    break;
9d7d3f
+#endif /* USE_UNIX_SOCKETS */
9d7d3f
   }
9d7d3f
   if(0 != rc) {
9d7d3f
     error = SOCKERRNO;
9d7d3f
@@ -2103,6 +2144,11 @@ int main(int argc, char *argv[])
9d7d3f
     goto sws_cleanup;
9d7d3f
   }
9d7d3f
 
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+  /* listen succeeds, so let's assume a valid listening UNIX socket */
9d7d3f
+  unlink_socket = true;
9d7d3f
+#endif
9d7d3f
+
9d7d3f
   /*
9d7d3f
   ** As soon as this server writes its pid file the test harness will
9d7d3f
   ** attempt to connect to this server and initiate its verification.
9d7d3f
@@ -2242,6 +2288,13 @@ sws_cleanup:
9d7d3f
   if(sock != CURL_SOCKET_BAD)
9d7d3f
     sclose(sock);
9d7d3f
 
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+  if(unlink_socket && socket_domain == AF_UNIX) {
9d7d3f
+    rc = unlink(unix_socket);
9d7d3f
+    logmsg("unlink(%s) = %d (%s)", unix_socket, rc, strerror(rc));
9d7d3f
+  }
9d7d3f
+#endif
9d7d3f
+
9d7d3f
   if(got_exit_signal)
9d7d3f
     logmsg("signalled to die");
9d7d3f
 
9d7d3f
-- 
9d7d3f
2.5.2
9d7d3f
9d7d3f
9d7d3f
From d04ea6f7f09e1556f80c4bbf4fc9497f83bc37a6 Mon Sep 17 00:00:00 2001
9d7d3f
From: Peter Wu <peter@lekensteyn.nl>
9d7d3f
Date: Thu, 27 Nov 2014 23:59:23 +0100
9d7d3f
Subject: [PATCH 05/11] tests: add HTTP UNIX socket server testing support
9d7d3f
9d7d3f
The variable `$ipvnum` can now contain "unix" besides the integers 4
9d7d3f
and 6 since the variable. Functions which receive this parameter
9d7d3f
have their `$port` parameter renamed to `$port_or_path` to support a
9d7d3f
path to the UNIX domain socket (as a "port" is only meaningful for TCP).
9d7d3f
9d7d3f
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
9d7d3f
9d7d3f
Upstream-commit: f1cc2a2c0cf8e191e606c6093c679fbee95e8809
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 tests/FILEFORMAT    |  2 ++
9d7d3f
 tests/README        |  3 ++
9d7d3f
 tests/httpserver.pl | 15 ++++++++-
9d7d3f
 tests/runtests.pl   | 96 +++++++++++++++++++++++++++++++++++++++++++++--------
9d7d3f
 tests/serverhelp.pm |  4 +--
9d7d3f
 5 files changed, 104 insertions(+), 16 deletions(-)
9d7d3f
9d7d3f
diff --git a/tests/FILEFORMAT b/tests/FILEFORMAT
9d7d3f
index 96cd5c8..702368f 100644
9d7d3f
--- a/tests/FILEFORMAT
9d7d3f
+++ b/tests/FILEFORMAT
9d7d3f
@@ -165,6 +165,7 @@ smtp
9d7d3f
 httptls+srp
9d7d3f
 httptls+srp-ipv6
9d7d3f
 http-proxy
9d7d3f
+http-unix
9d7d3f
 
9d7d3f
 Give only one per line.  This subsection is mandatory.
9d7d3f
 </server>
9d7d3f
@@ -284,6 +285,7 @@ Available substitute variables include:
9d7d3f
 %HTTPPORT  - Port number of the HTTP server
9d7d3f
 %HOST6IP   - IPv6 address of the host running this test
9d7d3f
 %HTTP6PORT - IPv6 port number of the HTTP server
9d7d3f
+%HTTPUNIXPATH - Path to the UNIX socket of the HTTP server
9d7d3f
 %HTTPSPORT - Port number of the HTTPS server
9d7d3f
 %PROXYPORT - Port number of the HTTP proxy
9d7d3f
 %FTPPORT   - Port number of the FTP server
9d7d3f
diff --git a/tests/README b/tests/README
9d7d3f
index fff618e..b442693 100644
9d7d3f
--- a/tests/README
9d7d3f
+++ b/tests/README
9d7d3f
@@ -80,6 +80,9 @@ The cURL Test Suite
9d7d3f
   machine, or just move the servers in case you have local services on any of
9d7d3f
   those ports.
9d7d3f
 
9d7d3f
+  The HTTP server supports listening on a UNIX domain socket, the default
9d7d3f
+  location is 'http.sock'.
9d7d3f
+
9d7d3f
  1.4 Run
9d7d3f
 
9d7d3f
   'make test'. This builds the test suite support code and invokes the
9d7d3f
diff --git a/tests/httpserver.pl b/tests/httpserver.pl
9d7d3f
index a38c3ce..1b8c3d2 100755
9d7d3f
--- a/tests/httpserver.pl
9d7d3f
+++ b/tests/httpserver.pl
9d7d3f
@@ -36,6 +36,7 @@ use serverhelp qw(
9d7d3f
 
9d7d3f
 my $verbose = 0;     # set to 1 for debugging
9d7d3f
 my $port = 8990;     # just a default
9d7d3f
+my $unix_socket;     # location to place a listening UNIX socket
9d7d3f
 my $ipvnum = 4;      # default IP version of http server
9d7d3f
 my $idnum = 1;       # dafault http server instance number
9d7d3f
 my $proto = 'http';  # protocol the http server speaks
9d7d3f
@@ -74,6 +75,13 @@ while(@ARGV) {
9d7d3f
     elsif($ARGV[0] eq '--ipv6') {
9d7d3f
         $ipvnum = 6;
9d7d3f
     }
9d7d3f
+    elsif($ARGV[0] eq '--unix-socket') {
9d7d3f
+        $ipvnum = 'unix';
9d7d3f
+        if($ARGV[1]) {
9d7d3f
+            $unix_socket = $ARGV[1];
9d7d3f
+            shift @ARGV;
9d7d3f
+        }
9d7d3f
+    }
9d7d3f
     elsif($ARGV[0] eq '--gopher') {
9d7d3f
         $gopher = 1;
9d7d3f
     }
9d7d3f
@@ -117,7 +125,12 @@ if(!$logfile) {
9d7d3f
 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
9d7d3f
 $flags .= "--gopher " if($gopher);
9d7d3f
 $flags .= "--connect $connect " if($connect);
9d7d3f
-$flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\"";
9d7d3f
+if($ipvnum eq 'unix') {
9d7d3f
+    $flags .= "--unix-socket '$unix_socket' ";
9d7d3f
+} else {
9d7d3f
+    $flags .= "--ipv$ipvnum --port $port ";
9d7d3f
+}
9d7d3f
+$flags .= "--srcdir \"$srcdir\"";
9d7d3f
 
9d7d3f
 if($verbose) {
9d7d3f
     print STDERR "RUN: server/sws $flags\n";
9d7d3f
diff --git a/tests/runtests.pl b/tests/runtests.pl
9d7d3f
index b39da66..fa96345 100755
9d7d3f
--- a/tests/runtests.pl
9d7d3f
+++ b/tests/runtests.pl
9d7d3f
@@ -140,6 +140,7 @@ my $GOPHER6PORT;         # Gopher IPv6 server port
9d7d3f
 my $HTTPTLSPORT;         # HTTP TLS (non-stunnel) server port
9d7d3f
 my $HTTPTLS6PORT;        # HTTP TLS (non-stunnel) IPv6 server port
9d7d3f
 my $HTTPPROXYPORT;       # HTTP proxy port, when using CONNECT
9d7d3f
+my $HTTPUNIXPATH;        # HTTP server UNIX domain socket path
9d7d3f
 
9d7d3f
 my $srcdir = $ENV{'srcdir'} || '.';
9d7d3f
 my $CURL="../src/curl".exe_ext(); # what curl executable to run on the tests
9d7d3f
@@ -201,10 +202,12 @@ my $ssl_version; # set if libcurl is built with SSL support
9d7d3f
 my $large_file;  # set if libcurl is built with large file support
9d7d3f
 my $has_idn;     # set if libcurl is built with IDN support
9d7d3f
 my $http_ipv6;   # set if HTTP server has IPv6 support
9d7d3f
+my $http_unix;   # set if HTTP server has UNIX sockets support
9d7d3f
 my $ftp_ipv6;    # set if FTP server has IPv6 support
9d7d3f
 my $tftp_ipv6;   # set if TFTP server has IPv6 support
9d7d3f
 my $gopher_ipv6; # set if Gopher server has IPv6 support
9d7d3f
 my $has_ipv6;    # set if libcurl is built with IPv6 support
9d7d3f
+my $has_unix;    # set if libcurl is built with UNIX sockets support
9d7d3f
 my $has_libz;    # set if libcurl is built with libz support
9d7d3f
 my $has_getrlimit;  # set if system has getrlimit()
9d7d3f
 my $has_ntlm;    # set if libcurl is built with NTLM support
9d7d3f
@@ -358,6 +361,13 @@ sub init_serverpidfile_hash {
9d7d3f
       }
9d7d3f
     }
9d7d3f
   }
9d7d3f
+  for my $proto (('http', 'imap', 'pop3', 'smtp')) {
9d7d3f
+    for my $ssl (('', 's')) {
9d7d3f
+      my $serv = servername_id("$proto$ssl", "unix", 1);
9d7d3f
+      my $pidf = server_pidfilename("$proto$ssl", "unix", 1);
9d7d3f
+      $serverpidfile{$serv} = $pidf;
9d7d3f
+    }
9d7d3f
+  }
9d7d3f
 }
9d7d3f
 
9d7d3f
 #######################################################################
9d7d3f
@@ -641,11 +651,11 @@ sub stopserver {
9d7d3f
     # All servers relative to the given one must be stopped also
9d7d3f
     #
9d7d3f
     my @killservers;
9d7d3f
-    if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|))$/) {
9d7d3f
+    if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
9d7d3f
         # given a stunnel based ssl server, also kill non-ssl underlying one
9d7d3f
         push @killservers, "${1}${2}";
9d7d3f
     }
9d7d3f
-    elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|))$/) {
9d7d3f
+    elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|-unix|))$/) {
9d7d3f
         # given a non-ssl server, also kill stunnel based ssl piggybacking one
9d7d3f
         push @killservers, "${1}s${2}";
9d7d3f
     }
9d7d3f
@@ -691,10 +701,12 @@ sub stopserver {
9d7d3f
 # assign requested address")
9d7d3f
 #
9d7d3f
 sub verifyhttp {
9d7d3f
-    my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
9d7d3f
+    my ($proto, $ipvnum, $idnum, $ip, $port_or_path) = @_;
9d7d3f
     my $server = servername_id($proto, $ipvnum, $idnum);
9d7d3f
     my $pid = 0;
9d7d3f
     my $bonus="";
9d7d3f
+    # $port_or_path contains a path for UNIX sockets, sws ignores the port
9d7d3f
+    my $port = ($ipvnum eq "unix") ? 80 : $port_or_path;
9d7d3f
 
9d7d3f
     my $verifyout = "$LOGDIR/".
9d7d3f
         servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
9d7d3f
@@ -714,6 +726,7 @@ sub verifyhttp {
9d7d3f
     $flags .= "--silent ";
9d7d3f
     $flags .= "--verbose ";
9d7d3f
     $flags .= "--globoff ";
9d7d3f
+    $flags .= "--unix-socket '$port_or_path' " if $ipvnum eq "unix";
9d7d3f
     $flags .= "-1 "         if($has_axtls);
9d7d3f
     $flags .= "--insecure " if($proto eq 'https');
9d7d3f
     $flags .= "\"$proto://$ip:$port/${bonus}verifiedserver\"";
9d7d3f
@@ -1160,7 +1173,7 @@ sub responsiveserver {
9d7d3f
 # start the http server
9d7d3f
 #
9d7d3f
 sub runhttpserver {
9d7d3f
-    my ($proto, $verbose, $alt, $port) = @_;
9d7d3f
+    my ($proto, $verbose, $alt, $port_or_path) = @_;
9d7d3f
     my $ip = $HOSTIP;
9d7d3f
     my $ipvnum = 4;
9d7d3f
     my $idnum = 1;
9d7d3f
@@ -1188,6 +1201,10 @@ sub runhttpserver {
9d7d3f
     if ($doesntrun{$pidfile}) {
9d7d3f
         return (0,0);
9d7d3f
     }
9d7d3f
+    elsif($alt eq "unix") {
9d7d3f
+        # IP (protocol) is mutually exclusive with UNIX sockets
9d7d3f
+        $ipvnum = "unix";
9d7d3f
+    }
9d7d3f
 
9d7d3f
     my $pid = processexists($pidfile);
9d7d3f
     if($pid > 0) {
9d7d3f
@@ -1204,7 +1221,12 @@ sub runhttpserver {
9d7d3f
     $flags .= "--verbose " if($debugprotocol);
9d7d3f
     $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
9d7d3f
     $flags .= "--id $idnum " if($idnum > 1);
9d7d3f
-    $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\"";
9d7d3f
+    if($ipvnum eq "unix") {
9d7d3f
+        $flags .= "--unix-socket '$port_or_path' ";
9d7d3f
+    } else {
9d7d3f
+        $flags .= "--ipv$ipvnum --port $port_or_path ";
9d7d3f
+    }
9d7d3f
+    $flags .= "--srcdir \"$srcdir\"";
9d7d3f
 
9d7d3f
     my $cmd = "$perl $srcdir/httpserver.pl $flags";
9d7d3f
     my ($httppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
9d7d3f
@@ -1219,7 +1241,7 @@ sub runhttpserver {
9d7d3f
     }
9d7d3f
 
9d7d3f
     # Server is up. Verify that we can speak to it.
9d7d3f
-    my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
9d7d3f
+    my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
9d7d3f
     if(!$pid3) {
9d7d3f
         logmsg "RUN: $srvrname server failed verification\n";
9d7d3f
         # failed to talk to it properly. Kill the server and return failure
9d7d3f
@@ -1984,7 +2006,7 @@ sub runsocksserver {
9d7d3f
 # be used to verify that a server present in %run hash is still functional
9d7d3f
 #
9d7d3f
 sub responsive_http_server {
9d7d3f
-    my ($proto, $verbose, $alt, $port) = @_;
9d7d3f
+    my ($proto, $verbose, $alt, $port_or_path) = @_;
9d7d3f
     my $ip = $HOSTIP;
9d7d3f
     my $ipvnum = 4;
9d7d3f
     my $idnum = 1;
9d7d3f
@@ -1997,8 +2019,12 @@ sub responsive_http_server {
9d7d3f
     elsif($alt eq "proxy") {
9d7d3f
         $idnum = 2;
9d7d3f
     }
9d7d3f
+    elsif($alt eq "unix") {
9d7d3f
+        # IP (protocol) is mutually exclusive with UNIX sockets
9d7d3f
+        $ipvnum = "unix";
9d7d3f
+    }
9d7d3f
 
9d7d3f
-    return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
9d7d3f
+    return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
9d7d3f
 }
9d7d3f
 
9d7d3f
 #######################################################################
9d7d3f
@@ -2264,9 +2290,10 @@ sub checksystem {
9d7d3f
             @protocols = split(' ', lc($1));
9d7d3f
 
9d7d3f
             # Generate a "proto-ipv6" version of each protocol to match the
9d7d3f
-            # IPv6 <server> name. This works even if IPv6 support isn't
9d7d3f
+            # IPv6 <server> name and a "proto-unix" to match the variant which
9d7d3f
+            # uses UNIX domain sockets. This works even if support isn't
9d7d3f
             # compiled in because the <features> test will fail.
9d7d3f
-            push @protocols, map($_ . '-ipv6', @protocols);
9d7d3f
+            push @protocols, map(("$_-ipv6", "$_-unix"), @protocols);
9d7d3f
 
9d7d3f
             # 'http-proxy' is used in test cases to do CONNECT through
9d7d3f
             push @protocols, 'http-proxy';
9d7d3f
@@ -2299,6 +2326,9 @@ sub checksystem {
9d7d3f
             if($feat =~ /IPv6/i) {
9d7d3f
                 $has_ipv6 = 1;
9d7d3f
             }
9d7d3f
+            if($feat =~ /unix-sockets/i) {
9d7d3f
+                $has_unix = 1;
9d7d3f
+            }
9d7d3f
             if($feat =~ /libz/i) {
9d7d3f
                 $has_libz = 1;
9d7d3f
             }
9d7d3f
@@ -2396,6 +2426,12 @@ sub checksystem {
9d7d3f
         }
9d7d3f
     }
9d7d3f
 
9d7d3f
+    if($has_unix) {
9d7d3f
+        # client has UNIX sockets support, check whether the HTTP server has it
9d7d3f
+        my @sws = `server/sws --version`;
9d7d3f
+        $http_unix = 1 if($sws[0] =~ /unix/);
9d7d3f
+    }
9d7d3f
+
9d7d3f
     if(!$curl_debug && $torture) {
9d7d3f
         die "can't run torture tests since curl was not built with curldebug";
9d7d3f
     }
9d7d3f
@@ -2423,6 +2459,7 @@ sub checksystem {
9d7d3f
     logmsg sprintf("  track memory: %s\n", $curl_debug?"ON ":"OFF");
9d7d3f
     logmsg sprintf("* valgrind:     %8s", $valgrind?"ON ":"OFF");
9d7d3f
     logmsg sprintf("  HTTP IPv6     %s\n", $http_ipv6?"ON ":"OFF");
9d7d3f
+    logmsg sprintf("* HTTP UNIX     %s\n", $http_unix?"ON ":"OFF");
9d7d3f
     logmsg sprintf("* FTP IPv6      %8s", $ftp_ipv6?"ON ":"OFF");
9d7d3f
     logmsg sprintf("  Libtool lib:  %s\n", $libtool?"ON ":"OFF");
9d7d3f
     logmsg sprintf("* Shared build:      %s\n", $has_shared);
9d7d3f
@@ -2473,6 +2510,13 @@ sub checksystem {
9d7d3f
         logmsg "\n";
9d7d3f
     }
9d7d3f
 
9d7d3f
+    if($has_unix) {
9d7d3f
+        logmsg "* UNIX socket paths:\n";
9d7d3f
+        if($http_unix) {
9d7d3f
+            logmsg sprintf("*   HTTP-UNIX:%s\n", $HTTPUNIXPATH);
9d7d3f
+        }
9d7d3f
+    }
9d7d3f
+
9d7d3f
     $has_textaware = ($^O eq 'MSWin32') || ($^O eq 'msys');
9d7d3f
 
9d7d3f
     logmsg "***************************************** \n";
9d7d3f
@@ -2520,6 +2564,10 @@ sub subVariables {
9d7d3f
   $$thing =~ s/%TFTP6PORT/$TFTP6PORT/g;
9d7d3f
   $$thing =~ s/%TFTPPORT/$TFTPPORT/g;
9d7d3f
 
9d7d3f
+  # server UNIX domain socket paths
9d7d3f
+
9d7d3f
+  $$thing =~ s/%HTTPUNIXPATH/$HTTPUNIXPATH/g;
9d7d3f
+
9d7d3f
   # client IP addresses
9d7d3f
 
9d7d3f
   $$thing =~ s/%CLIENT6IP/$CLIENT6IP/g;
9d7d3f
@@ -2707,6 +2755,11 @@ sub singletest {
9d7d3f
                 next;
9d7d3f
             }
9d7d3f
         }
9d7d3f
+        elsif($f eq "unix-sockets") {
9d7d3f
+            if($has_unix) {
9d7d3f
+                next;
9d7d3f
+            }
9d7d3f
+        }
9d7d3f
         elsif($f eq "libz") {
9d7d3f
             if($has_libz) {
9d7d3f
                 next;
9d7d3f
@@ -3219,11 +3272,11 @@ sub singletest {
9d7d3f
         my @killservers;
9d7d3f
         foreach my $server (@killtestservers) {
9d7d3f
             chomp $server;
9d7d3f
-            if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|))$/) {
9d7d3f
+            if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
9d7d3f
                 # given a stunnel ssl server, also kill non-ssl underlying one
9d7d3f
                 push @killservers, "${1}${2}";
9d7d3f
             }
9d7d3f
-            elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|))$/) {
9d7d3f
+            elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|-unix|))$/) {
9d7d3f
                 # given a non-ssl server, also kill stunnel piggybacking one
9d7d3f
                 push @killservers, "${1}s${2}";
9d7d3f
             }
9d7d3f
@@ -3728,7 +3781,7 @@ sub startservers {
9d7d3f
         $what =~ s/[^a-z0-9-]//g;
9d7d3f
 
9d7d3f
         my $certfile;
9d7d3f
-        if($what =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|))$/) {
9d7d3f
+        if($what =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
9d7d3f
             $certfile = ($whatlist[1]) ? $whatlist[1] : 'stunnel.pem';
9d7d3f
         }
9d7d3f
 
9d7d3f
@@ -4066,6 +4119,22 @@ sub startservers {
9d7d3f
                 }
9d7d3f
             }
9d7d3f
         }
9d7d3f
+        elsif($what eq "http-unix") {
9d7d3f
+            if($torture && $run{'http-unix'} &&
9d7d3f
+               !responsive_http_server("http", $verbose, "unix", $HTTPUNIXPATH)) {
9d7d3f
+                stopserver('http-unix');
9d7d3f
+            }
9d7d3f
+            if(!$run{'http-unix'}) {
9d7d3f
+                ($pid, $pid2) = runhttpserver("http", $verbose, "unix",
9d7d3f
+                                              $HTTPUNIXPATH);
9d7d3f
+                if($pid <= 0) {
9d7d3f
+                    return "failed starting HTTP-unix server";
9d7d3f
+                }
9d7d3f
+                logmsg sprintf("* pid http-unix => %d %d\n", $pid, $pid2)
9d7d3f
+                    if($verbose);
9d7d3f
+                $run{'http-unix'}="$pid $pid2";
9d7d3f
+            }
9d7d3f
+        }
9d7d3f
         elsif($what eq "none") {
9d7d3f
             logmsg "* starts no server\n" if ($verbose);
9d7d3f
         }
9d7d3f
@@ -4502,6 +4571,7 @@ $GOPHER6PORT     = $base++; # Gopher IPv6 server port
9d7d3f
 $HTTPTLSPORT     = $base++; # HTTP TLS (non-stunnel) server port
9d7d3f
 $HTTPTLS6PORT    = $base++; # HTTP TLS (non-stunnel) IPv6 server port
9d7d3f
 $HTTPPROXYPORT   = $base++; # HTTP proxy port, when using CONNECT
9d7d3f
+$HTTPUNIXPATH    = 'http.sock'; # HTTP server UNIX domain socket path
9d7d3f
 
9d7d3f
 #######################################################################
9d7d3f
 # clear and create logging directory:
9d7d3f
diff --git a/tests/serverhelp.pm b/tests/serverhelp.pm
9d7d3f
index a1d1dc3..1fc621b 100644
9d7d3f
--- a/tests/serverhelp.pm
9d7d3f
+++ b/tests/serverhelp.pm
9d7d3f
@@ -109,8 +109,8 @@ sub servername_str {
9d7d3f
 
9d7d3f
     $ipver = (not $ipver) ? 'ipv4' : lc($ipver);
9d7d3f
     die "unsupported IP version: '$ipver'" unless($ipver &&
9d7d3f
-        ($ipver =~ /^(4|6|ipv4|ipv6|-ipv4|-ipv6)$/));
9d7d3f
-    $ipver = ($ipver =~ /6$/) ? '-IPv6' : '';
9d7d3f
+        ($ipver =~ /^(4|6|ipv4|ipv6|-ipv4|-ipv6|unix)$/));
9d7d3f
+    $ipver = ($ipver =~ /6$/) ? '-IPv6' : (($ipver =~ /unix$/) ? '-unix' : '');
9d7d3f
 
9d7d3f
     $idnum = 1 if(not $idnum);
9d7d3f
     die "unsupported ID number: '$idnum'" unless($idnum &&
9d7d3f
-- 
9d7d3f
2.5.2
9d7d3f
9d7d3f
9d7d3f
From d2f7b1d51e356586356da87d1ae32c0c44274887 Mon Sep 17 00:00:00 2001
9d7d3f
From: Peter Wu <peter@lekensteyn.nl>
9d7d3f
Date: Thu, 27 Nov 2014 23:59:24 +0100
9d7d3f
Subject: [PATCH 06/11] tests: add two HTTP over UNIX socket tests
9d7d3f
9d7d3f
test1435: a simple test that checks whether a HTTP request can be
9d7d3f
performed over the UNIX socket. The hostname/port are interpreted
9d7d3f
by sws and should be ignored by cURL.
9d7d3f
9d7d3f
test1436: test for the ability to do two requests to the same host,
9d7d3f
interleaved with one to a different hostname.
9d7d3f
9d7d3f
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
9d7d3f
9d7d3f
Upstream-commit: 479abdd32eee15dab78d0cd6b1786d569680f0ac
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 tests/data/Makefile.am |  1 +
9d7d3f
 tests/data/Makefile.in |  1 +
9d7d3f
 tests/data/test1435    | 46 +++++++++++++++++++++++++++
9d7d3f
 tests/data/test1436    | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++
9d7d3f
 4 files changed, 133 insertions(+)
9d7d3f
 create mode 100644 tests/data/test1435
9d7d3f
 create mode 100644 tests/data/test1436
9d7d3f
9d7d3f
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
9d7d3f
index c4f76df..35bc6eb 100644
9d7d3f
--- a/tests/data/Makefile.am
9d7d3f
+++ b/tests/data/Makefile.am
9d7d3f
@@ -93,6 +93,7 @@ test1379 test1380 test1381 test1382 test1383 test1384 test1385 test1386 \
9d7d3f
 test1387 test1388 test1389 test1390 test1391 test1392 test1393 \
9d7d3f
 test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \
9d7d3f
 test1408 test1409 test1410 test1411 test1412 test1413 test1415 \
9d7d3f
+test1435 test1436 \
9d7d3f
 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
9d7d3f
 test1508 test1529 \
9d7d3f
 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
9d7d3f
diff --git a/tests/data/Makefile.in b/tests/data/Makefile.in
9d7d3f
index e73ca96..d5e5f01 100644
9d7d3f
--- a/tests/data/Makefile.in
9d7d3f
+++ b/tests/data/Makefile.in
9d7d3f
@@ -357,6 +357,7 @@ test1379 test1380 test1381 test1382 test1383 test1384 test1385 test1386 \
9d7d3f
 test1387 test1388 test1389 test1390 test1391 test1392 test1393 \
9d7d3f
 test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \
9d7d3f
 test1408 test1409 test1410 test1411 test1412 test1413 test1415 \
9d7d3f
+test1435 test1436 \
9d7d3f
 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
9d7d3f
 test1508 test1529 \
9d7d3f
 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
9d7d3f
diff --git a/tests/data/test1435 b/tests/data/test1435
9d7d3f
new file mode 100644
9d7d3f
index 0000000..56ff9d1
9d7d3f
--- /dev/null
9d7d3f
+++ b/tests/data/test1435
9d7d3f
@@ -0,0 +1,46 @@
9d7d3f
+<testcase>
9d7d3f
+<info>
9d7d3f
+<keywords>
9d7d3f
+HTTP
9d7d3f
+HTTP GET
9d7d3f
+unix sockets
9d7d3f
+</keywords>
9d7d3f
+</info>
9d7d3f
+
9d7d3f
+<reply>
9d7d3f
+<data>
9d7d3f
+HTTP/1.1 200 OK
9d7d3f
+Date: Sun, 16 Nov 2014 23:47:38 GMT
9d7d3f
+Content-Length: 17
9d7d3f
+
9d7d3f
+Based on test300
9d7d3f
+</data>
9d7d3f
+</reply>
9d7d3f
+
9d7d3f
+<client>
9d7d3f
+<features>
9d7d3f
+unix-sockets
9d7d3f
+</features>
9d7d3f
+<server>
9d7d3f
+http-unix
9d7d3f
+</server>
9d7d3f
+ <name>
9d7d3f
+simple HTTP GET over UNIX socket
9d7d3f
+ </name>
9d7d3f
+ <command>
9d7d3f
+--unix-socket %HTTPUNIXPATH http://server-interpreted.example.com/1435
9d7d3f
+</command>
9d7d3f
+</client>
9d7d3f
+
9d7d3f
+<verify>
9d7d3f
+<strip>
9d7d3f
+^User-Agent:.*
9d7d3f
+</strip>
9d7d3f
+<protocol>
9d7d3f
+GET /1435 HTTP/1.1
9d7d3f
+Host: server-interpreted.example.com
9d7d3f
+Accept: */*
9d7d3f
+
9d7d3f
+</protocol>
9d7d3f
+</verify>
9d7d3f
+</testcase>
9d7d3f
diff --git a/tests/data/test1436 b/tests/data/test1436
9d7d3f
new file mode 100644
9d7d3f
index 0000000..b16eadd
9d7d3f
--- /dev/null
9d7d3f
+++ b/tests/data/test1436
9d7d3f
@@ -0,0 +1,85 @@
9d7d3f
+<testcase>
9d7d3f
+<info>
9d7d3f
+<keywords>
9d7d3f
+HTTP
9d7d3f
+HTTP GET
9d7d3f
+unix sockets
9d7d3f
+</keywords>
9d7d3f
+</info>
9d7d3f
+
9d7d3f
+<reply>
9d7d3f
+<data1>
9d7d3f
+HTTP/1.1 200 OK
9d7d3f
+Date: Mon, 17 Nov 2014 13:42:47 GMT
9d7d3f
+Content-Length: 6
9d7d3f
+
9d7d3f
+First
9d7d3f
+</data1>
9d7d3f
+<data2>
9d7d3f
+HTTP/1.1 200 OK
9d7d3f
+Date: Mon, 17 Nov 2014 13:42:48 GMT
9d7d3f
+Content-Length: 7
9d7d3f
+
9d7d3f
+Second
9d7d3f
+</data2>
9d7d3f
+<data3>
9d7d3f
+HTTP/1.1 200 OK
9d7d3f
+Date: Mon, 17 Nov 2014 13:42:49 GMT
9d7d3f
+Content-Length: 6
9d7d3f
+
9d7d3f
+Third
9d7d3f
+</data3>
9d7d3f
+</reply>
9d7d3f
+
9d7d3f
+<client>
9d7d3f
+<features>
9d7d3f
+unix-sockets
9d7d3f
+</features>
9d7d3f
+<server>
9d7d3f
+http-unix
9d7d3f
+</server>
9d7d3f
+ <name>
9d7d3f
+HTTP requests with multiple connections over UNIX socket
9d7d3f
+ </name>
9d7d3f
+ <command>
9d7d3f
+--unix-socket %HTTPUNIXPATH http://one.example.com/14360001 http://two.example.com/14360002 http://one.example.com/14360003
9d7d3f
+</command>
9d7d3f
+</client>
9d7d3f
+
9d7d3f
+<verify>
9d7d3f
+<strip>
9d7d3f
+^User-Agent:.*
9d7d3f
+</strip>
9d7d3f
+<protocol>
9d7d3f
+GET /14360001 HTTP/1.1
9d7d3f
+Host: one.example.com
9d7d3f
+Accept: */*
9d7d3f
+
9d7d3f
+GET /14360002 HTTP/1.1
9d7d3f
+Host: two.example.com
9d7d3f
+Accept: */*
9d7d3f
+
9d7d3f
+GET /14360003 HTTP/1.1
9d7d3f
+Host: one.example.com
9d7d3f
+Accept: */*
9d7d3f
+
9d7d3f
+</protocol>
9d7d3f
+<stdout>
9d7d3f
+HTTP/1.1 200 OK
9d7d3f
+Date: Mon, 17 Nov 2014 13:42:47 GMT
9d7d3f
+Content-Length: 6
9d7d3f
+
9d7d3f
+First
9d7d3f
+HTTP/1.1 200 OK
9d7d3f
+Date: Mon, 17 Nov 2014 13:42:48 GMT
9d7d3f
+Content-Length: 7
9d7d3f
+
9d7d3f
+Second
9d7d3f
+HTTP/1.1 200 OK
9d7d3f
+Date: Mon, 17 Nov 2014 13:42:49 GMT
9d7d3f
+Content-Length: 6
9d7d3f
+
9d7d3f
+Third
9d7d3f
+</stdout>
9d7d3f
+</verify>
9d7d3f
+</testcase>
9d7d3f
-- 
9d7d3f
2.5.2
9d7d3f
9d7d3f
9d7d3f
From f784b2d3d6cf08193662a23aae9305f11c4a4559 Mon Sep 17 00:00:00 2001
9d7d3f
From: Peter Wu <peter@lekensteyn.nl>
9d7d3f
Date: Thu, 27 Nov 2014 23:59:25 +0100
9d7d3f
Subject: [PATCH 07/11] libcurl: add UNIX domain sockets support
9d7d3f
9d7d3f
The ability to do HTTP requests over a UNIX domain socket has been
9d7d3f
requested before, in Apr 2008 [0][1] and Sep 2010 [2]. While a
9d7d3f
discussion happened, no patch seems to get through. I decided to give it
9d7d3f
a go since I need to test a nginx HTTP server which listens on a UNIX
9d7d3f
domain socket.
9d7d3f
9d7d3f
One patch [3] seems to make it possible to use the
9d7d3f
CURLOPT_OPENSOCKETFUNCTION function to gain a UNIX domain socket.
9d7d3f
Another person wrote a Go program which can do HTTP over a UNIX socket
9d7d3f
for Docker[4] which uses a special URL scheme (though the name contains
9d7d3f
cURL, it has no relation to the cURL library).
9d7d3f
9d7d3f
This patch considers support for UNIX domain sockets at the same level
9d7d3f
as HTTP proxies / IPv6, it acts as an intermediate socket provider and
9d7d3f
not as a separate protocol. Since this feature affects network
9d7d3f
operations, a new feature flag was added ("unix-sockets") with a
9d7d3f
corresponding CURL_VERSION_UNIX_SOCKETS macro.
9d7d3f
9d7d3f
A new CURLOPT_UNIX_SOCKET_PATH option is added and documented. This
9d7d3f
option enables UNIX domain sockets support for all requests on the
9d7d3f
handle (replacing IP sockets and skipping proxies).
9d7d3f
9d7d3f
A new configure option (--enable-unix-sockets) and CMake option
9d7d3f
(ENABLE_UNIX_SOCKETS) can disable this optional feature. Note that I
9d7d3f
deliberately did not mark this feature as advanced, this is a
9d7d3f
feature/component that should easily be available.
9d7d3f
9d7d3f
 [0]: http://curl.haxx.se/mail/lib-2008-04/0279.html
9d7d3f
 [1]: http://daniel.haxx.se/blog/2008/04/14/http-over-unix-domain-sockets/
9d7d3f
 [2]: http://sourceforge.net/p/curl/feature-requests/53/
9d7d3f
 [3]: http://curl.haxx.se/mail/lib-2008-04/0361.html
9d7d3f
 [4]: https://github.com/Soulou/curl-unix-socket
9d7d3f
9d7d3f
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
9d7d3f
9d7d3f
Upstream-commit: 970c22f970f0172e6a4c98ccc3176c740ddaa1c6
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 configure                        | 112 +++++++++++++++++++++++++++++++++++++++
9d7d3f
 configure.ac                     |  38 +++++++++++++
9d7d3f
 docs/libcurl/curl_easy_setopt.3  |  12 +++++
9d7d3f
 docs/libcurl/curl_version_info.3 |   2 +
9d7d3f
 docs/libcurl/symbols-in-versions |   2 +
9d7d3f
 include/curl/curl.h              |   4 ++
9d7d3f
 lib/Makefile.in                  |   1 +
9d7d3f
 lib/curl_addrinfo.c              |  39 ++++++++++++++
9d7d3f
 lib/curl_addrinfo.h              |   4 ++
9d7d3f
 lib/curl_config.h.in             |   3 ++
9d7d3f
 lib/url.c                        |  44 +++++++++++++++
9d7d3f
 lib/urldata.h                    |   4 ++
9d7d3f
 lib/version.c                    |   3 ++
9d7d3f
 src/Makefile.in                  |   1 +
9d7d3f
 src/tool_getparam.c              |   3 +-
9d7d3f
 tests/server/Makefile.in         |   1 +
9d7d3f
 16 files changed, 272 insertions(+), 1 deletion(-)
9d7d3f
9d7d3f
diff --git a/configure b/configure
9d7d3f
index c5d1817..3e1f5d3 100755
9d7d3f
--- a/configure
9d7d3f
+++ b/configure
9d7d3f
@@ -889,6 +889,7 @@ SONAME_BUMP_TRUE
9d7d3f
 CFLAG_CURL_SYMBOL_HIDING
9d7d3f
 DOING_CURL_SYMBOL_HIDING_FALSE
9d7d3f
 DOING_CURL_SYMBOL_HIDING_TRUE
9d7d3f
+USE_UNIX_SOCKETS
9d7d3f
 BUILD_LIBHOSTNAME_FALSE
9d7d3f
 BUILD_LIBHOSTNAME_TRUE
9d7d3f
 USE_EMBEDDED_ARES_FALSE
9d7d3f
@@ -1159,6 +1160,7 @@ enable_sspi
9d7d3f
 enable_crypto_auth
9d7d3f
 enable_ntlm_wb
9d7d3f
 enable_tls_srp
9d7d3f
+enable_unix_sockets
9d7d3f
 enable_cookies
9d7d3f
 enable_soname_bump
9d7d3f
 '
9d7d3f
@@ -1873,6 +1875,8 @@ Optional Features:
9d7d3f
                           helper
9d7d3f
   --enable-tls-srp        Enable TLS-SRP authentication
9d7d3f
   --disable-tls-srp       Disable TLS-SRP authentication
9d7d3f
+  --enable-unix-sockets   Enable UNIX domain sockets
9d7d3f
+  --disable-unix-sockets  Disable UNIX domain sockets
9d7d3f
   --enable-cookies        Enable cookies support
9d7d3f
   --disable-cookies       Disable cookies support
9d7d3f
   --enable-soname-bump    Enable enforced SONAME bump
9d7d3f
@@ -2607,6 +2611,61 @@ $as_echo "$ac_res" >&6; }
9d7d3f
   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
9d7d3f
 
9d7d3f
 } # ac_fn_c_check_type
9d7d3f
+
9d7d3f
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
9d7d3f
+# ----------------------------------------------------
9d7d3f
+# Tries to find if the field MEMBER exists in type AGGR, after including
9d7d3f
+# INCLUDES, setting cache variable VAR accordingly.
9d7d3f
+ac_fn_c_check_member ()
9d7d3f
+{
9d7d3f
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
9d7d3f
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
9d7d3f
+$as_echo_n "checking for $2.$3... " >&6; }
9d7d3f
+if eval \${$4+:} false; then :
9d7d3f
+  $as_echo_n "(cached) " >&6
9d7d3f
+else
9d7d3f
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
9d7d3f
+/* end confdefs.h.  */
9d7d3f
+$5
9d7d3f
+int main (void)
9d7d3f
+{
9d7d3f
+static $2 ac_aggr;
9d7d3f
+if (ac_aggr.$3)
9d7d3f
+return 0;
9d7d3f
+ ;
9d7d3f
+ return 0;
9d7d3f
+}
9d7d3f
+_ACEOF
9d7d3f
+if ac_fn_c_try_compile "$LINENO"; then :
9d7d3f
+  eval "$4=yes"
9d7d3f
+else
9d7d3f
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
9d7d3f
+/* end confdefs.h.  */
9d7d3f
+$5
9d7d3f
+int main (void)
9d7d3f
+{
9d7d3f
+static $2 ac_aggr;
9d7d3f
+if (sizeof ac_aggr.$3)
9d7d3f
+return 0;
9d7d3f
+ ;
9d7d3f
+ return 0;
9d7d3f
+}
9d7d3f
+_ACEOF
9d7d3f
+if ac_fn_c_try_compile "$LINENO"; then :
9d7d3f
+  eval "$4=yes"
9d7d3f
+else
9d7d3f
+  eval "$4=no"
9d7d3f
+fi
9d7d3f
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
9d7d3f
+fi
9d7d3f
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
9d7d3f
+fi
9d7d3f
+eval ac_res=\$$4
9d7d3f
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
9d7d3f
+$as_echo "$ac_res" >&6; }
9d7d3f
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
9d7d3f
+
9d7d3f
+} # ac_fn_c_check_member
9d7d3f
 cat >config.log <<_ACEOF
9d7d3f
 This file contains any messages produced by compilers while
9d7d3f
 running configure, to aid debugging if configure makes a mistake.
9d7d3f
@@ -5447,6 +5506,7 @@ PKGADD_VENDOR="curl.haxx.se"
9d7d3f
 curl_tls_srp_msg="no      (--enable-tls-srp)"
9d7d3f
     curl_res_msg="default (--enable-ares / --enable-threaded-resolver)"
9d7d3f
    curl_ipv6_msg="no      (--enable-ipv6)"
9d7d3f
+curl_unix_sockets_msg="no      (--enable-unix-sockets)"
9d7d3f
     curl_idn_msg="no      (--with-{libidn,winidn})"
9d7d3f
  curl_manual_msg="no      (--enable-manual)"
9d7d3f
 curl_libcurl_msg="enabled (--disable-libcurl-option)"
9d7d3f
@@ -39239,6 +39299,53 @@ $as_echo "#define USE_TLS_SRP 1" >>confdefs.h
9d7d3f
    curl_tls_srp_msg="enabled"
9d7d3f
 fi
9d7d3f
 
9d7d3f
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable UNIX domain sockets" >&5
9d7d3f
+$as_echo_n "checking whether to enable UNIX domain sockets... " >&6; }
9d7d3f
+# Check whether --enable-unix-sockets was given.
9d7d3f
+if test "${enable_unix_sockets+set}" = set; then :
9d7d3f
+  enableval=$enable_unix_sockets;  case "$enableval" in
9d7d3f
+  no)  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
9d7d3f
+$as_echo "no" >&6; }
9d7d3f
+       want_unix_sockets=no
9d7d3f
+       ;;
9d7d3f
+  *)   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
9d7d3f
+$as_echo "yes" >&6; }
9d7d3f
+       want_unix_sockets=yes
9d7d3f
+       ;;
9d7d3f
+  esac
9d7d3f
+else
9d7d3f
+
9d7d3f
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: auto" >&5
9d7d3f
+$as_echo "auto" >&6; }
9d7d3f
+       want_unix_sockets=auto
9d7d3f
+
9d7d3f
+
9d7d3f
+fi
9d7d3f
+
9d7d3f
+if test "x$want_unix_sockets" != "xno"; then
9d7d3f
+  ac_fn_c_check_member "$LINENO" "struct sockaddr_un" "sun_path" "ac_cv_member_struct_sockaddr_un_sun_path" "
9d7d3f
+    #include <sys/un.h>
9d7d3f
+
9d7d3f
+"
9d7d3f
+if test "x$ac_cv_member_struct_sockaddr_un_sun_path" = xyes; then :
9d7d3f
+
9d7d3f
+
9d7d3f
+$as_echo "#define USE_UNIX_SOCKETS 1" >>confdefs.h
9d7d3f
+
9d7d3f
+    USE_UNIX_SOCKETS=1
9d7d3f
+
9d7d3f
+    curl_unix_sockets_msg="enabled"
9d7d3f
+
9d7d3f
+else
9d7d3f
+
9d7d3f
+    if test "x$want_unix_sockets" = "xyes"; then
9d7d3f
+      as_fn_error $? "--enable-unix-sockets is not available on this platform!" "$LINENO" 5
9d7d3f
+    fi
9d7d3f
+
9d7d3f
+fi
9d7d3f
+
9d7d3f
+fi
9d7d3f
+
9d7d3f
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable support for cookies" >&5
9d7d3f
 $as_echo_n "checking whether to enable support for cookies... " >&6; }
9d7d3f
 # Check whether --enable-cookies was given.
9d7d3f
@@ -39357,6 +39464,9 @@ fi
9d7d3f
 if test "x$IPV6_ENABLED" = "x1"; then
9d7d3f
   SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6"
9d7d3f
 fi
9d7d3f
+if test "x$USE_UNIX_SOCKETS" = "x1"; then
9d7d3f
+  SUPPORT_FEATURES="$SUPPORT_FEATURES unix-sockets"
9d7d3f
+fi
9d7d3f
 if test "x$HAVE_LIBZ" = "x1"; then
9d7d3f
   SUPPORT_FEATURES="$SUPPORT_FEATURES libz"
9d7d3f
 fi
9d7d3f
@@ -42289,6 +42399,7 @@ _EOF
9d7d3f
   TLS-SRP support:  ${curl_tls_srp_msg}
9d7d3f
   resolver:         ${curl_res_msg}
9d7d3f
   ipv6 support:     ${curl_ipv6_msg}
9d7d3f
+  UNIX sockets support: ${curl_unix_sockets_msg}
9d7d3f
   IDN support:      ${curl_idn_msg}
9d7d3f
   Build libcurl:    Shared=${enable_shared}, Static=${enable_static}
9d7d3f
   Built-in manual:  ${curl_manual_msg}
9d7d3f
@@ -42319,6 +42430,7 @@ $as_echo "$as_me: Configured to build curl/libcurl:
9d7d3f
   TLS-SRP support:  ${curl_tls_srp_msg}
9d7d3f
   resolver:         ${curl_res_msg}
9d7d3f
   ipv6 support:     ${curl_ipv6_msg}
9d7d3f
+  UNIX sockets support: ${curl_unix_sockets_msg}
9d7d3f
   IDN support:      ${curl_idn_msg}
9d7d3f
   Build libcurl:    Shared=${enable_shared}, Static=${enable_static}
9d7d3f
   Built-in manual:  ${curl_manual_msg}
9d7d3f
diff --git a/configure.ac b/configure.ac
9d7d3f
index 60a6b58..9612c2f 100644
9d7d3f
--- a/configure.ac
9d7d3f
+++ b/configure.ac
9d7d3f
@@ -156,6 +156,7 @@ dnl initialize all the info variables
9d7d3f
 curl_tls_srp_msg="no      (--enable-tls-srp)"
9d7d3f
     curl_res_msg="default (--enable-ares / --enable-threaded-resolver)"
9d7d3f
    curl_ipv6_msg="no      (--enable-ipv6)"
9d7d3f
+curl_unix_sockets_msg="no      (--enable-unix-sockets)"
9d7d3f
     curl_idn_msg="no      (--with-{libidn,winidn})"
9d7d3f
  curl_manual_msg="no      (--enable-manual)"
9d7d3f
 curl_libcurl_msg="enabled (--disable-libcurl-option)"
9d7d3f
@@ -3302,6 +3303,39 @@ if test "$want_tls_srp" = "yes" && ( test "x$HAVE_GNUTLS_SRP" = "x1" || test "x$
9d7d3f
 fi
9d7d3f
 
9d7d3f
 dnl ************************************************************
9d7d3f
+dnl disable UNIX domain sockets support
9d7d3f
+dnl
9d7d3f
+AC_MSG_CHECKING([whether to enable UNIX domain sockets])
9d7d3f
+AC_ARG_ENABLE(unix-sockets,
9d7d3f
+AC_HELP_STRING([--enable-unix-sockets],[Enable UNIX domain sockets])
9d7d3f
+AC_HELP_STRING([--disable-unix-sockets],[Disable UNIX domain sockets]),
9d7d3f
+[ case "$enableval" in
9d7d3f
+  no)  AC_MSG_RESULT(no)
9d7d3f
+       want_unix_sockets=no
9d7d3f
+       ;;
9d7d3f
+  *)   AC_MSG_RESULT(yes)
9d7d3f
+       want_unix_sockets=yes
9d7d3f
+       ;;
9d7d3f
+  esac ], [
9d7d3f
+       AC_MSG_RESULT(auto)
9d7d3f
+       want_unix_sockets=auto
9d7d3f
+       ]
9d7d3f
+)
9d7d3f
+if test "x$want_unix_sockets" != "xno"; then
9d7d3f
+  AC_CHECK_MEMBER([struct sockaddr_un.sun_path], [
9d7d3f
+    AC_DEFINE(USE_UNIX_SOCKETS, 1, [Use UNIX domain sockets])
9d7d3f
+    AC_SUBST(USE_UNIX_SOCKETS, [1])
9d7d3f
+    curl_unix_sockets_msg="enabled"
9d7d3f
+  ], [
9d7d3f
+    if test "x$want_unix_sockets" = "xyes"; then
9d7d3f
+      AC_MSG_ERROR([--enable-unix-sockets is not available on this platform!])
9d7d3f
+    fi
9d7d3f
+  ], [
9d7d3f
+    #include <sys/un.h>
9d7d3f
+  ])
9d7d3f
+fi
9d7d3f
+
9d7d3f
+dnl ************************************************************
9d7d3f
 dnl disable cookies support
9d7d3f
 dnl
9d7d3f
 AC_MSG_CHECKING([whether to enable support for cookies])
9d7d3f
@@ -3382,6 +3416,9 @@ fi
9d7d3f
 if test "x$IPV6_ENABLED" = "x1"; then
9d7d3f
   SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6"
9d7d3f
 fi
9d7d3f
+if test "x$USE_UNIX_SOCKETS" = "x1"; then
9d7d3f
+  SUPPORT_FEATURES="$SUPPORT_FEATURES unix-sockets"
9d7d3f
+fi
9d7d3f
 if test "x$HAVE_LIBZ" = "x1"; then
9d7d3f
   SUPPORT_FEATURES="$SUPPORT_FEATURES libz"
9d7d3f
 fi
9d7d3f
@@ -3557,6 +3594,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
9d7d3f
   TLS-SRP support:  ${curl_tls_srp_msg}
9d7d3f
   resolver:         ${curl_res_msg}
9d7d3f
   ipv6 support:     ${curl_ipv6_msg}
9d7d3f
+  UNIX sockets support: ${curl_unix_sockets_msg}
9d7d3f
   IDN support:      ${curl_idn_msg}
9d7d3f
   Build libcurl:    Shared=${enable_shared}, Static=${enable_static}
9d7d3f
   Built-in manual:  ${curl_manual_msg}
9d7d3f
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
9d7d3f
index d73b664..ad739e1 100644
9d7d3f
--- a/docs/libcurl/curl_easy_setopt.3
9d7d3f
+++ b/docs/libcurl/curl_easy_setopt.3
9d7d3f
@@ -961,6 +961,18 @@ systems support this option. (Added in 7.25.0)
9d7d3f
 Pass a long. Sets the interval, in seconds, that the operating system will wait
9d7d3f
 between sending keepalive probes. Not all operating systems support this
9d7d3f
 option. (Added in 7.25.0)
9d7d3f
+.IP CURLOPT_UNIX_SOCKET_PATH
9d7d3f
+Pass a \fIpath\fP to a UNIX domain socket. This enables the use of UNIX domain
9d7d3f
+sockets as connection end point and sets the path to \fIpath\fP. If \fIpath\fP
9d7d3f
+is NULL, then UNIX domain sockets are disabled. An empty string will result in
9d7d3f
+an error at some point.
9d7d3f
+
9d7d3f
+When enabled, cURL will connect to the UNIX domain socket instead of
9d7d3f
+establishing a TCP connection to a host. Since no TCP connection is
9d7d3f
+established, cURL does not need to resolve the DNS hostname in the URL.
9d7d3f
+
9d7d3f
+The maximum path length on Cygwin, Linux and Solaris is 107. On other platforms
9d7d3f
+might be even less.
9d7d3f
 .SH NAMES and PASSWORDS OPTIONS (Authentication)
9d7d3f
 .IP CURLOPT_NETRC
9d7d3f
 This parameter controls the preference of libcurl between using user names and
9d7d3f
diff --git a/docs/libcurl/curl_version_info.3 b/docs/libcurl/curl_version_info.3
9d7d3f
index ccb2028..c148cbc 100644
9d7d3f
--- a/docs/libcurl/curl_version_info.3
9d7d3f
+++ b/docs/libcurl/curl_version_info.3
9d7d3f
@@ -133,6 +133,8 @@ libcurl was built with support for TLS-SRP. (Added in 7.21.4)
9d7d3f
 .IP CURL_VERSION_NTLM_WB
9d7d3f
 libcurl was built with support for NTLM delegation to a winbind helper.
9d7d3f
 (Added in 7.22.0)
9d7d3f
+.IP CURL_VERSION_UNIX_SOCKETS
9d7d3f
+libcurl was built with support for UNIX domain sockets.
9d7d3f
 .RE
9d7d3f
 \fIssl_version\fP is an ASCII string for the OpenSSL version used. If libcurl
9d7d3f
 has no SSL support, this is NULL.
9d7d3f
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
9d7d3f
index b275900..0f7469d 100644
9d7d3f
--- a/docs/libcurl/symbols-in-versions
9d7d3f
+++ b/docs/libcurl/symbols-in-versions
9d7d3f
@@ -503,6 +503,7 @@ CURLOPT_TLSAUTH_TYPE            7.21.4
9d7d3f
 CURLOPT_TLSAUTH_USERNAME        7.21.4
9d7d3f
 CURLOPT_TRANSFERTEXT            7.1.1
9d7d3f
 CURLOPT_TRANSFER_ENCODING       7.21.6
9d7d3f
+CURLOPT_UNIX_SOCKET_PATH        7.40.0
9d7d3f
 CURLOPT_UNRESTRICTED_AUTH       7.10.4
9d7d3f
 CURLOPT_UPLOAD                  7.1
9d7d3f
 CURLOPT_URL                     7.1
9d7d3f
@@ -703,6 +704,7 @@ CURL_VERSION_SPNEGO             7.10.8
9d7d3f
 CURL_VERSION_SSL                7.10
9d7d3f
 CURL_VERSION_SSPI               7.13.2
9d7d3f
 CURL_VERSION_TLSAUTH_SRP        7.21.4
9d7d3f
+CURL_VERSION_UNIX_SOCKETS       7.40.0
9d7d3f
 CURL_WAIT_POLLIN                7.28.0
9d7d3f
 CURL_WAIT_POLLOUT               7.28.0
9d7d3f
 CURL_WAIT_POLLPRI               7.28.0
9d7d3f
diff --git a/include/curl/curl.h b/include/curl/curl.h
9d7d3f
index 8e548e3..14f6fd7 100644
9d7d3f
--- a/include/curl/curl.h
9d7d3f
+++ b/include/curl/curl.h
9d7d3f
@@ -1536,6 +1536,9 @@ typedef enum {
9d7d3f
   /* set the SMTP auth originator */
9d7d3f
   CINIT(MAIL_AUTH, OBJECTPOINT, 217),
9d7d3f
 
9d7d3f
+  /* Path to UNIX domain socket */
9d7d3f
+  CINIT(UNIX_SOCKET_PATH, OBJECTPOINT, 231),
9d7d3f
+
9d7d3f
   CURLOPT_LASTENTRY /* the last unused */
9d7d3f
 } CURLoption;
9d7d3f
 
9d7d3f
@@ -2154,6 +2157,7 @@ typedef struct {
9d7d3f
 #define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */
9d7d3f
 #define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
9d7d3f
 #define CURL_VERSION_NTLM_WB   (1<<15) /* NTLM delegating to winbind helper */
9d7d3f
+#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* UNIX domain sockets support */
9d7d3f
 
9d7d3f
  /*
9d7d3f
  * NAME curl_version_info()
9d7d3f
diff --git a/lib/Makefile.in b/lib/Makefile.in
9d7d3f
index ca02e27..5ad2600 100644
9d7d3f
--- a/lib/Makefile.in
9d7d3f
+++ b/lib/Makefile.in
9d7d3f
@@ -386,6 +386,7 @@ USE_OPENLDAP = @USE_OPENLDAP@
9d7d3f
 USE_POLARSSL = @USE_POLARSSL@
9d7d3f
 USE_SCHANNEL = @USE_SCHANNEL@
9d7d3f
 USE_SSLEAY = @USE_SSLEAY@
9d7d3f
+USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@
9d7d3f
 USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@
9d7d3f
 VERSION = @VERSION@
9d7d3f
 VERSIONED_FLAVOUR = @VERSIONED_FLAVOUR@
9d7d3f
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
9d7d3f
index 10652c6..52e45ce 100644
9d7d3f
--- a/lib/curl_addrinfo.c
9d7d3f
+++ b/lib/curl_addrinfo.c
9d7d3f
@@ -33,6 +33,9 @@
9d7d3f
 #ifdef HAVE_ARPA_INET_H
9d7d3f
 #  include <arpa/inet.h>
9d7d3f
 #endif
9d7d3f
+#ifdef HAVE_SYS_UN_H
9d7d3f
+#  include <sys/un.h>
9d7d3f
+#endif
9d7d3f
 
9d7d3f
 #ifdef __VMS
9d7d3f
 #  include <in.h>
9d7d3f
@@ -477,6 +480,42 @@ Curl_addrinfo *Curl_str2addr(char *address, int port)
9d7d3f
   return NULL; /* bad input format */
9d7d3f
 }
9d7d3f
 
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+/**
9d7d3f
+ * Given a path to a UNIX domain socket, return a newly allocated Curl_addrinfo
9d7d3f
+ * struct initialized with this path.
9d7d3f
+ */
9d7d3f
+Curl_addrinfo *Curl_unix2addr(const char *path)
9d7d3f
+{
9d7d3f
+  Curl_addrinfo *ai;
9d7d3f
+  struct sockaddr_un *sun;
9d7d3f
+  size_t path_len;
9d7d3f
+
9d7d3f
+  ai = calloc(1, sizeof(Curl_addrinfo));
9d7d3f
+  if(!ai)
9d7d3f
+    return NULL;
9d7d3f
+  if((ai->ai_addr = calloc(1, sizeof(struct sockaddr_un))) == NULL) {
9d7d3f
+    free(ai);
9d7d3f
+    return NULL;
9d7d3f
+  }
9d7d3f
+  /* sun_path must be able to store the NUL-terminated path */
9d7d3f
+  path_len = strlen(path);
9d7d3f
+  if(path_len >= sizeof(sun->sun_path)) {
9d7d3f
+    free(ai->ai_addr);
9d7d3f
+    free(ai);
9d7d3f
+    return NULL;
9d7d3f
+  }
9d7d3f
+
9d7d3f
+  ai->ai_family = AF_UNIX;
9d7d3f
+  ai->ai_socktype = SOCK_STREAM; /* assume reliable transport for HTTP */
9d7d3f
+  ai->ai_addrlen = (curl_socklen_t) sizeof(struct sockaddr_un);
9d7d3f
+  sun = (void *) ai->ai_addr;
9d7d3f
+  sun->sun_family = AF_UNIX;
9d7d3f
+  memcpy(sun->sun_path, path, path_len + 1); /* copy NUL byte */
9d7d3f
+  return ai;
9d7d3f
+}
9d7d3f
+#endif
9d7d3f
+
9d7d3f
 #if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
9d7d3f
 /*
9d7d3f
  * curl_dofreeaddrinfo()
9d7d3f
diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h
9d7d3f
index 6d2b753..4ef8827 100644
9d7d3f
--- a/lib/curl_addrinfo.h
9d7d3f
+++ b/lib/curl_addrinfo.h
9d7d3f
@@ -79,6 +79,10 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
9d7d3f
 
9d7d3f
 Curl_addrinfo *Curl_str2addr(char *dotted, int port);
9d7d3f
 
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+Curl_addrinfo *Curl_unix2addr(const char *path);
9d7d3f
+#endif
9d7d3f
+
9d7d3f
 #if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
9d7d3f
 void
9d7d3f
 curl_dofreeaddrinfo(struct addrinfo *freethis,
9d7d3f
diff --git a/lib/curl_config.h.in b/lib/curl_config.h.in
9d7d3f
index 1716c96..19b66fa 100644
9d7d3f
--- a/lib/curl_config.h.in
9d7d3f
+++ b/lib/curl_config.h.in
9d7d3f
@@ -1017,6 +1017,9 @@
9d7d3f
 /* Use TLS-SRP authentication */
9d7d3f
 #undef USE_TLS_SRP
9d7d3f
 
9d7d3f
+/* Use UNIX domain sockets */
9d7d3f
+#undef USE_UNIX_SOCKETS
9d7d3f
+
9d7d3f
 /* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */
9d7d3f
 #undef USE_WIN32_IDN
9d7d3f
 
9d7d3f
diff --git a/lib/url.c b/lib/url.c
9d7d3f
index 57944e4..7257b5e 100644
9d7d3f
--- a/lib/url.c
9d7d3f
+++ b/lib/url.c
9d7d3f
@@ -47,6 +47,10 @@
9d7d3f
 #include <inet.h>
9d7d3f
 #endif
9d7d3f
 
9d7d3f
+#ifdef HAVE_SYS_UN_H
9d7d3f
+#include <sys/un.h>
9d7d3f
+#endif
9d7d3f
+
9d7d3f
 #ifndef HAVE_SOCKET
9d7d3f
 #error "We can't compile without socket() support!"
9d7d3f
 #endif
9d7d3f
@@ -2429,6 +2433,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
9d7d3f
     data->set.tcp_keepintvl = va_arg(param, long);
9d7d3f
     break;
9d7d3f
 
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+  case CURLOPT_UNIX_SOCKET_PATH:
9d7d3f
+    result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
9d7d3f
+                       va_arg(param, char *));
9d7d3f
+    break;
9d7d3f
+#endif
9d7d3f
+
9d7d3f
   default:
9d7d3f
     /* unknown tag and its companion, just ignore: */
9d7d3f
     result = CURLE_UNKNOWN_OPTION;
9d7d3f
@@ -4764,6 +4775,32 @@ static CURLcode resolve_server(struct SessionHandle *data,
9d7d3f
     /* set a pointer to the hostname we display */
9d7d3f
     fix_hostname(data, conn, &conn->host);
9d7d3f
 
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+    if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
9d7d3f
+      /* UNIX domain sockets are local. The host gets ignored, just use the
9d7d3f
+       * specified domain socket address. Do not cache "DNS entries". There is
9d7d3f
+       * no DNS involved and we already have the filesystem path available */
9d7d3f
+      const char *path = data->set.str[STRING_UNIX_SOCKET_PATH];
9d7d3f
+
9d7d3f
+      hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
9d7d3f
+      if(!hostaddr)
9d7d3f
+        result = CURLE_OUT_OF_MEMORY;
9d7d3f
+      else if((hostaddr->addr = Curl_unix2addr(path)) != NULL)
9d7d3f
+        hostaddr->inuse++;
9d7d3f
+      else {
9d7d3f
+        /* Long paths are not supported for now */
9d7d3f
+        if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
9d7d3f
+          failf(data, "UNIX socket path too long: '%s'", path);
9d7d3f
+          result = CURLE_COULDNT_RESOLVE_HOST;
9d7d3f
+        }
9d7d3f
+        else
9d7d3f
+          result = CURLE_OUT_OF_MEMORY;
9d7d3f
+        free(hostaddr);
9d7d3f
+        hostaddr = NULL;
9d7d3f
+      }
9d7d3f
+    }
9d7d3f
+    else
9d7d3f
+#endif
9d7d3f
     if(!conn->proxy.name || !*conn->proxy.name) {
9d7d3f
       /* If not connecting via a proxy, extract the port from the URL, if it is
9d7d3f
        * there, thus overriding any defaults that might have been set above. */
9d7d3f
@@ -5071,6 +5108,13 @@ static CURLcode create_conn(struct SessionHandle *data,
9d7d3f
   else if(!proxy)
9d7d3f
     proxy = detect_proxy(conn);
9d7d3f
 
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+  if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) {
9d7d3f
+    free(proxy);  /* UNIX domain sockets cannot be proxied, so disable it */
9d7d3f
+    proxy = NULL;
9d7d3f
+  }
9d7d3f
+#endif
9d7d3f
+
9d7d3f
   if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
9d7d3f
     free(proxy);  /* Don't bother with an empty proxy string or if the
9d7d3f
                      protocol doesn't work with network */
9d7d3f
diff --git a/lib/urldata.h b/lib/urldata.h
9d7d3f
index b3ee7e3..723e40d 100644
9d7d3f
--- a/lib/urldata.h
9d7d3f
+++ b/lib/urldata.h
9d7d3f
@@ -1375,6 +1375,10 @@ enum dupstring {
9d7d3f
   STRING_TLSAUTH_PASSWORD,     /* TLS auth <password> */
9d7d3f
 #endif
9d7d3f
 
9d7d3f
+#ifdef USE_UNIX_SOCKETS
9d7d3f
+  STRING_UNIX_SOCKET_PATH,  /* path to UNIX socket, if used */
9d7d3f
+#endif
9d7d3f
+
9d7d3f
   /* -- end of zero-terminated strings -- */
9d7d3f
 
9d7d3f
   STRING_LASTZEROTERMINATED,
9d7d3f
diff --git a/lib/version.c b/lib/version.c
9d7d3f
index d39fe0c..e798738 100644
9d7d3f
--- a/lib/version.c
9d7d3f
+++ b/lib/version.c
9d7d3f
@@ -278,6 +278,9 @@ static curl_version_info_data version_info = {
9d7d3f
 #if defined(USE_TLS_SRP)
9d7d3f
   | CURL_VERSION_TLSAUTH_SRP
9d7d3f
 #endif
9d7d3f
+#if defined(USE_UNIX_SOCKETS)
9d7d3f
+  | CURL_VERSION_UNIX_SOCKETS
9d7d3f
+#endif
9d7d3f
   ,
9d7d3f
   NULL, /* ssl_version */
9d7d3f
   0,    /* ssl_version_num, this is kept at zero */
9d7d3f
diff --git a/src/Makefile.in b/src/Makefile.in
9d7d3f
index 5f739a9..948092f 100644
9d7d3f
--- a/src/Makefile.in
9d7d3f
+++ b/src/Makefile.in
9d7d3f
@@ -272,6 +272,7 @@ USE_OPENLDAP = @USE_OPENLDAP@
9d7d3f
 USE_POLARSSL = @USE_POLARSSL@
9d7d3f
 USE_SCHANNEL = @USE_SCHANNEL@
9d7d3f
 USE_SSLEAY = @USE_SSLEAY@
9d7d3f
+USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@
9d7d3f
 USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@
9d7d3f
 VERSION = @VERSION@
9d7d3f
 VERSIONED_FLAVOUR = @VERSIONED_FLAVOUR@
9d7d3f
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
9d7d3f
index 98d53a7..0cd84d5 100644
9d7d3f
--- a/src/tool_getparam.c
9d7d3f
+++ b/src/tool_getparam.c
9d7d3f
@@ -285,7 +285,8 @@ static const struct feat feats[] = {
9d7d3f
   {"krb4",           CURL_VERSION_KERBEROS4},
9d7d3f
   {"libz",           CURL_VERSION_LIBZ},
9d7d3f
   {"CharConv",       CURL_VERSION_CONV},
9d7d3f
-  {"TLS-SRP",        CURL_VERSION_TLSAUTH_SRP}
9d7d3f
+  {"TLS-SRP",        CURL_VERSION_TLSAUTH_SRP},
9d7d3f
+  {"unix-sockets",   CURL_VERSION_UNIX_SOCKETS}
9d7d3f
 };
9d7d3f
 
9d7d3f
 ParameterError getparameter(char *flag,    /* f or -long-flag */
9d7d3f
diff --git a/tests/server/Makefile.in b/tests/server/Makefile.in
9d7d3f
index 0ca4380..055fe9b 100644
9d7d3f
--- a/tests/server/Makefile.in
9d7d3f
+++ b/tests/server/Makefile.in
9d7d3f
@@ -329,6 +329,7 @@ USE_OPENLDAP = @USE_OPENLDAP@
9d7d3f
 USE_POLARSSL = @USE_POLARSSL@
9d7d3f
 USE_SCHANNEL = @USE_SCHANNEL@
9d7d3f
 USE_SSLEAY = @USE_SSLEAY@
9d7d3f
+USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@
9d7d3f
 USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@
9d7d3f
 VERSION = @VERSION@
9d7d3f
 VERSIONED_FLAVOUR = @VERSIONED_FLAVOUR@
9d7d3f
-- 
9d7d3f
2.5.2
9d7d3f
9d7d3f
9d7d3f
From 877e40cd741b5b65f503236a6947e38c28a2d6ce Mon Sep 17 00:00:00 2001
9d7d3f
From: Peter Wu <peter@lekensteyn.nl>
9d7d3f
Date: Thu, 27 Nov 2014 23:59:26 +0100
9d7d3f
Subject: [PATCH 08/11] tool: add --unix-socket option
9d7d3f
9d7d3f
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
9d7d3f
9d7d3f
Upstream-commit: c8644d1f638fdd8f4bf34fe64e910ba704fb26c0
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 src/tool_cfgable.c  | 1 +
9d7d3f
 src/tool_cfgable.h  | 2 ++
9d7d3f
 src/tool_getparam.c | 6 +++++-
9d7d3f
 src/tool_help.c     | 1 +
9d7d3f
 src/tool_operate.c  | 4 ++++
9d7d3f
 5 files changed, 13 insertions(+), 1 deletion(-)
9d7d3f
9d7d3f
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
9d7d3f
index da11f4a..2479b73 100644
9d7d3f
--- a/src/tool_cfgable.c
9d7d3f
+++ b/src/tool_cfgable.c
9d7d3f
@@ -98,6 +98,7 @@ void free_config_fields(struct Configurable *config)
9d7d3f
 
9d7d3f
   config->trace_stream = NULL; /* closed elsewhere when appropriate */
9d7d3f
 
9d7d3f
+  Curl_safefree(config->unix_socket_path);
9d7d3f
   Curl_safefree(config->writeout);
9d7d3f
 
9d7d3f
   config->errors = NULL; /* closed elsewhere when appropriate */
9d7d3f
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
9d7d3f
index 1f6f948..a9b033b 100644
9d7d3f
--- a/src/tool_cfgable.h
9d7d3f
+++ b/src/tool_cfgable.h
9d7d3f
@@ -204,6 +204,8 @@ struct Configurable {
9d7d3f
   bool use_metalink;        /* process given URLs as metalink XML file */
9d7d3f
   metalinkfile *metalinkfile_list; /* point to the first node */
9d7d3f
   metalinkfile *metalinkfile_last; /* point to the last/current node */
9d7d3f
+
9d7d3f
+  char *unix_socket_path;   /* path to UNIX domain socket */
9d7d3f
 }; /* struct Configurable */
9d7d3f
 
9d7d3f
 void free_config_fields(struct Configurable *config);
9d7d3f
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
9d7d3f
index 0cd84d5..57cf97d 100644
9d7d3f
--- a/src/tool_getparam.c
9d7d3f
+++ b/src/tool_getparam.c
9d7d3f
@@ -144,7 +144,7 @@ static const struct LongShort aliases[]= {
9d7d3f
   {"$v", "ssl-reqd",                 FALSE},
9d7d3f
          /* 'ssl-reqd' new in 7.20.0, previously this was ftp-ssl-reqd */
9d7d3f
   {"$w", "sessionid",                FALSE},
9d7d3f
-         /* ¡sessionid' listed as --no-sessionid in the help */
9d7d3f
+         /* ?sessionid' listed as --no-sessionid in the help */
9d7d3f
   {"$x", "ftp-ssl-control",          FALSE},
9d7d3f
   {"$y", "ftp-ssl-ccc",              FALSE},
9d7d3f
   {"$j", "ftp-ssl-ccc-mode",         TRUE},
9d7d3f
@@ -173,6 +173,7 @@ static const struct LongShort aliases[]= {
9d7d3f
   {"$H", "mail-auth",                TRUE},
9d7d3f
   {"$I", "post303",                  FALSE},
9d7d3f
   {"$J", "metalink",                 FALSE},
9d7d3f
+  {"$M", "unix-socket",              TRUE},
9d7d3f
   {"0",  "http1.0",                  FALSE},
9d7d3f
   {"1",  "tlsv1",                    FALSE},
9d7d3f
   {"10",  "tlsv1.0",                 FALSE},
9d7d3f
@@ -862,6 +863,9 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */
9d7d3f
 #endif
9d7d3f
           break;
9d7d3f
         }
9d7d3f
+      case 'M': /* --unix-socket */
9d7d3f
+        GetStr(&config->unix_socket_path, nextarg);
9d7d3f
+        break;
9d7d3f
       }
9d7d3f
       break;
9d7d3f
     case '#': /* --progress-bar */
9d7d3f
diff --git a/src/tool_help.c b/src/tool_help.c
9d7d3f
index f7cd618..3a64e35 100644
9d7d3f
--- a/src/tool_help.c
9d7d3f
+++ b/src/tool_help.c
9d7d3f
@@ -214,6 +214,7 @@ static const char *const helptext[] = {
9d7d3f
   "     --tlsuser USER  TLS username",
9d7d3f
   "     --tlspassword STRING TLS password",
9d7d3f
   "     --tlsauthtype STRING  TLS authentication type (default SRP)",
9d7d3f
+  "     --unix-socket FILE    Connect through this UNIX domain socket",
9d7d3f
   " -A, --user-agent STRING  User-Agent to send to server (H)",
9d7d3f
   " -v, --verbose       Make the operation more talkative",
9d7d3f
   " -V, --version       Show version number and quit",
9d7d3f
diff --git a/src/tool_operate.c b/src/tool_operate.c
9d7d3f
index 4166fc2..7a13fcf 100644
9d7d3f
--- a/src/tool_operate.c
9d7d3f
+++ b/src/tool_operate.c
9d7d3f
@@ -1320,6 +1320,10 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
9d7d3f
         if(config->mail_auth)
9d7d3f
           my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
9d7d3f
 
9d7d3f
+        /* new in 7.40.0 */
9d7d3f
+        if(config->unix_socket_path)
9d7d3f
+          my_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, config->unix_socket_path);
9d7d3f
+
9d7d3f
         /* initialize retry vars for loop below */
9d7d3f
         retry_sleep_default = (config->retry_delay) ?
9d7d3f
           config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
9d7d3f
-- 
9d7d3f
2.5.2
9d7d3f
9d7d3f
9d7d3f
From 60bdcf03a1696b3d09ad1c04824816766c513dcd Mon Sep 17 00:00:00 2001
9d7d3f
From: Daniel Stenberg <daniel@haxx.se>
9d7d3f
Date: Wed, 3 Dec 2014 02:35:12 +0100
9d7d3f
Subject: [PATCH 09/11] curl.1: added --unix-socket
9d7d3f
9d7d3f
Upstream-commit: 7853c1cfe6fc7828afbb812791a383781aca3be3
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 docs/curl.1 | 3 +++
9d7d3f
 1 file changed, 3 insertions(+)
9d7d3f
9d7d3f
diff --git a/docs/curl.1 b/docs/curl.1
9d7d3f
index 7f3571b..38fa084 100644
9d7d3f
--- a/docs/curl.1
9d7d3f
+++ b/docs/curl.1
9d7d3f
@@ -1471,6 +1471,9 @@ If this option is used several times, the last one will be used.
9d7d3f
 .IP "--trace-time"
9d7d3f
 Prepends a time stamp to each trace or verbose line that curl displays.
9d7d3f
 (Added in 7.14.0)
9d7d3f
+.IP "--unix-socket <path>"
9d7d3f
+(HTTP) Connect through this UNIX domain socket, instead of using the
9d7d3f
+network. (Added in 7.40.0)
9d7d3f
 .IP "-u, --user <user:password>"
9d7d3f
 Specify the user name and password to use for server authentication. Overrides
9d7d3f
 \fI-n, --netrc\fP and \fI--netrc-optional\fP.
9d7d3f
-- 
9d7d3f
2.5.2
9d7d3f
9d7d3f
9d7d3f
From af6fa1e00657c637d52cc24eab6d769b8eb793a9 Mon Sep 17 00:00:00 2001
9d7d3f
From: Daniel Stenberg <daniel@haxx.se>
9d7d3f
Date: Thu, 4 Dec 2014 02:46:15 +0100
9d7d3f
Subject: [PATCH 10/11] updateconninfo: clear destination struct before
9d7d3f
 getsockname()
9d7d3f
9d7d3f
Otherwise we may read uninitialized bytes later in the unix-domain
9d7d3f
sockets case.
9d7d3f
9d7d3f
Upstream-commit: 9730c9fb7075792a112b65a023379fad3ec8dda4
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 lib/connect.c | 1 +
9d7d3f
 1 file changed, 1 insertion(+)
9d7d3f
9d7d3f
diff --git a/lib/connect.c b/lib/connect.c
9d7d3f
index ba9ab92..5aa53fe 100644
9d7d3f
--- a/lib/connect.c
9d7d3f
+++ b/lib/connect.c
9d7d3f
@@ -630,6 +630,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
9d7d3f
     }
9d7d3f
 
9d7d3f
     len = sizeof(struct Curl_sockaddr_storage);
9d7d3f
+    memset(&ssloc, 0, sizeof(ssloc));
9d7d3f
     if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
9d7d3f
       error = SOCKERRNO;
9d7d3f
       failf(data, "getsockname() failed with errno %d: %s",
9d7d3f
-- 
9d7d3f
2.5.2
9d7d3f
9d7d3f
9d7d3f
From 8d951bb327fb6a1e107e044dbc179096883c4489 Mon Sep 17 00:00:00 2001
9d7d3f
From: Peter Wu <peter@lekensteyn.nl>
9d7d3f
Date: Thu, 4 Dec 2014 11:01:41 -0800
9d7d3f
Subject: [PATCH 11/11] tool: fix CURLOPT_UNIX_SOCKET_PATH in --libcurl output
9d7d3f
9d7d3f
Mark CURLOPT_UNIX_SOCKET_PATH as string to ensure that it ends up as
9d7d3f
option in the file generated by --libcurl.
9d7d3f
9d7d3f
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
9d7d3f
9d7d3f
Upstream-commit: 2e557de09431854e4ad137cd741a582caa917517
9d7d3f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
9d7d3f
---
9d7d3f
 src/tool_operate.c | 3 ++-
9d7d3f
 1 file changed, 2 insertions(+), 1 deletion(-)
9d7d3f
9d7d3f
diff --git a/src/tool_operate.c b/src/tool_operate.c
9d7d3f
index 7a13fcf..41b0e6b 100644
9d7d3f
--- a/src/tool_operate.c
9d7d3f
+++ b/src/tool_operate.c
9d7d3f
@@ -1322,7 +1322,8 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
9d7d3f
 
9d7d3f
         /* new in 7.40.0 */
9d7d3f
         if(config->unix_socket_path)
9d7d3f
-          my_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, config->unix_socket_path);
9d7d3f
+          my_setopt_str(curl, CURLOPT_UNIX_SOCKET_PATH,
9d7d3f
+                        config->unix_socket_path);
9d7d3f
 
9d7d3f
         /* initialize retry vars for loop below */
9d7d3f
         retry_sleep_default = (config->retry_delay) ?
9d7d3f
-- 
9d7d3f
2.5.2
9d7d3f