summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt8
-rw-r--r--configure.ac38
-rw-r--r--docs/libcurl/curl_easy_setopt.32
-rw-r--r--docs/libcurl/curl_version_info.33
-rw-r--r--docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.376
-rw-r--r--docs/libcurl/symbols-in-versions2
-rw-r--r--include/curl/curl.h4
-rw-r--r--lib/curl_addrinfo.c39
-rw-r--r--lib/curl_addrinfo.h4
-rw-r--r--lib/curl_config.h.cmake3
-rw-r--r--lib/url.c44
-rw-r--r--lib/urldata.h4
-rw-r--r--lib/version.c3
-rw-r--r--packages/OS400/curl.inc.in4
-rw-r--r--src/tool_help.c3
-rw-r--r--tests/server/sws.c2
16 files changed, 236 insertions, 3 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 17eacfa79..d6abaab77 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -527,6 +527,14 @@ if(CMAKE_USE_GSSAPI)
endif()
endif()
+option(ENABLE_UNIX_SOCKETS "Define if you want UNIX domain sockets support" ON)
+if(ENABLE_UNIX_SOCKETS)
+ include(CheckStructHasMember)
+ check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS)
+else()
+ unset(USE_UNIX_SOCKETS CACHE)
+endif()
+
# Check for header files
if(NOT UNIX)
check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H)
diff --git a/configure.ac b/configure.ac
index d2628d132..fb8dfd5b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -154,6 +154,7 @@ dnl initialize all the info variables
curl_tls_srp_msg="no (--enable-tls-srp)"
curl_res_msg="default (--enable-ares / --enable-threaded-resolver)"
curl_ipv6_msg="no (--enable-ipv6)"
+curl_unix_sockets_msg="no (--enable-unix-sockets)"
curl_idn_msg="no (--with-{libidn,winidn})"
curl_manual_msg="no (--enable-manual)"
curl_libcurl_msg="enabled (--disable-libcurl-option)"
@@ -3274,6 +3275,39 @@ if test "$want_tls_srp" = "yes" && ( test "x$HAVE_GNUTLS_SRP" = "x1" || test "x$
fi
dnl ************************************************************
+dnl disable UNIX domain sockets support
+dnl
+AC_MSG_CHECKING([whether to enable UNIX domain sockets])
+AC_ARG_ENABLE(unix-sockets,
+AC_HELP_STRING([--enable-unix-sockets],[Enable UNIX domain sockets])
+AC_HELP_STRING([--disable-unix-sockets],[Disable UNIX domain sockets]),
+[ case "$enableval" in
+ no) AC_MSG_RESULT(no)
+ want_unix_sockets=no
+ ;;
+ *) AC_MSG_RESULT(yes)
+ want_unix_sockets=yes
+ ;;
+ esac ], [
+ AC_MSG_RESULT(auto)
+ want_unix_sockets=auto
+ ]
+)
+if test "x$want_unix_sockets" != "xno"; then
+ AC_CHECK_MEMBER([struct sockaddr_un.sun_path], [
+ AC_DEFINE(USE_UNIX_SOCKETS, 1, [Use UNIX domain sockets])
+ AC_SUBST(USE_UNIX_SOCKETS, [1])
+ curl_unix_sockets_msg="enabled"
+ ], [
+ if test "x$want_unix_sockets" = "xyes"; then
+ AC_MSG_ERROR([--enable-unix-sockets is not available on this platform!])
+ fi
+ ], [
+ #include <sys/un.h>
+ ])
+fi
+
+dnl ************************************************************
dnl disable cookies support
dnl
AC_MSG_CHECKING([whether to enable support for cookies])
@@ -3356,6 +3390,9 @@ fi
if test "x$IPV6_ENABLED" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6"
fi
+if test "x$USE_UNIX_SOCKETS" = "x1"; then
+ SUPPORT_FEATURES="$SUPPORT_FEATURES unix-sockets"
+fi
if test "x$HAVE_LIBZ" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES libz"
fi
@@ -3563,6 +3600,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
TLS-SRP support: ${curl_tls_srp_msg}
resolver: ${curl_res_msg}
ipv6 support: ${curl_ipv6_msg}
+ UNIX sockets support: ${curl_unix_sockets_msg}
IDN support: ${curl_idn_msg}
Build libcurl: Shared=${enable_shared}, Static=${enable_static}
Built-in manual: ${curl_manual_msg}
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index d79a42b04..71f681b70 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -187,6 +187,8 @@ Enable TCP keep-alive. See \fICURLOPT_TCP_KEEPALIVE(3)\fP
Idle time before sending keep-alive. See \fICURLOPT_TCP_KEEPIDLE(3)\fP
.IP CURLOPT_TCP_KEEPINTVL
Interval between keep-alive probes. See \fICURLOPT_TCP_KEEPINTVL(3)\fP
+.IP CURLOPT_UNIX_SOCKET_PATH
+Path to a UNIX domain socket. See \fICURLOPT_UNIX_SOCKET_PATH(3)\fP
.SH NAMES and PASSWORDS OPTIONS (Authentication)
.IP CURLOPT_NETRC
Enable .netrc parsing. See \fICURLOPT_NETRC(3)\fP
diff --git a/docs/libcurl/curl_version_info.3 b/docs/libcurl/curl_version_info.3
index 3acf7851b..6e553463e 100644
--- a/docs/libcurl/curl_version_info.3
+++ b/docs/libcurl/curl_version_info.3
@@ -146,6 +146,9 @@ libcurl was built with support for NTLM delegation to a winbind helper.
.IP CURL_VERSION_HTTP2
libcurl was built with support for HTTP2.
(Added in 7.33.0)
+.IP CURL_VERSION_UNIX_SOCKETS
+libcurl was built with support for UNIX domain sockets.
+(Added in 7.40.0)
.RE
\fIssl_version\fP is an ASCII string for the OpenSSL version used. If libcurl
has no SSL support, this is NULL.
diff --git a/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3 b/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3
new file mode 100644
index 000000000..880c2f71f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3
@@ -0,0 +1,76 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at http://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_UNIX_SOCKET_PATH 3 "09 Oct 2014" "libcurl 7.40.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_UNIX_SOCKET_PATH \- set UNIX domain socket
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UNIX_SOCKET_PATH, char *path);
+.SH DESCRIPTION
+Enables the use of UNIX domain sockets as connection end point and sets the path
+to \fIpath\fP. If \fIpath\fP is NULL, then UNIX domain sockets are disabled. An
+empty string will result in an error at some point.
+
+When enabled, cURL will connect to the UNIX domain socket instead of
+establishing a TCP connection to a host. Since no TCP connection is established,
+cURL does not need to resolve the DNS hostname in the URL.
+
+The maximum path length on Cygwin, Linux and Solaris is 107. On other platforms
+might be even less.
+
+Proxy and TCP options such as
+.BR CURLOPT_TCP_NODELAY "(3)
+are not supported. Proxy options such as
+.BR CURLOPT_PROXY "(3)
+have no effect either as these are TCP-oriented, and asking a proxy server to
+connect to a certain UNIX domain socket is not possible.
+.SH DEFAULT
+Default is NULL, meaning that no UNIX domain sockets are used.
+.SH PROTOCOLS
+All protocols except for file:// and FTP are supported in theory. HTTP, IMAP,
+POP3 and SMTP should in particular work (including their SSL/TLS variants).
+.SH EXAMPLE
+Given that you have an nginx server running, listening on /tmp/nginx.sock, you
+can request a HTTP resource with:
+
+ curl_easy_setopt(curl_handle, CURLOPT_UNIX_SOCKET_PATH, "/tmp/nginx.sock");
+ curl_easy_setopt(curl_handle, CURLOPT_URL, "http://localhost/");
+
+If you are on Linux and somehow have a need for paths larger than 107 bytes, you
+could use the proc filesystem to bypass the limitation:
+
+ int dirfd = open(long_directory_path_to_socket, O_DIRECTORY | O_RDONLY);
+ char path[108];
+ snprintf(path, sizeof(path), "/proc/self/fd/%d/nginx.sock", dirfd);
+ curl_easy_setopt(curl_handle, CURLOPT_UNIX_SOCKET_PATH, path);
+ /* Be sure to keep dirfd valid until you discard the handle */
+
+.SH AVAILABILITY
+Since 7.40.0.
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_OPENSOCKETFUNCTION "(3)
+,
+.BR unix "(7)
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index 642cc19f4..b8b0838b0 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -529,6 +529,7 @@ CURLOPT_TLSAUTH_TYPE 7.21.4
CURLOPT_TLSAUTH_USERNAME 7.21.4
CURLOPT_TRANSFERTEXT 7.1.1
CURLOPT_TRANSFER_ENCODING 7.21.6
+CURLOPT_UNIX_SOCKET_PATH 7.40.0
CURLOPT_UNRESTRICTED_AUTH 7.10.4
CURLOPT_UPLOAD 7.1
CURLOPT_URL 7.1
@@ -749,6 +750,7 @@ CURL_VERSION_SPNEGO 7.10.8
CURL_VERSION_SSL 7.10
CURL_VERSION_SSPI 7.13.2
CURL_VERSION_TLSAUTH_SRP 7.21.4
+CURL_VERSION_UNIX_SOCKETS 7.40.0
CURL_WAIT_POLLIN 7.28.0
CURL_WAIT_POLLOUT 7.28.0
CURL_WAIT_POLLPRI 7.28.0
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 5ed4c3ea5..0d2076bd2 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -1619,6 +1619,9 @@ typedef enum {
this option is used only if SSL_VERIFYPEER is true */
CINIT(PINNEDPUBLICKEY, OBJECTPOINT, 230),
+ /* Path to UNIX domain socket */
+ CINIT(UNIX_SOCKET_PATH, OBJECTPOINT, 231),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2266,6 +2269,7 @@ typedef struct {
#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */
#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */
#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */
+#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* UNIX domain sockets support */
/*
* NAME curl_version_info()
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
index 94ed63d96..b8032f4df 100644
--- a/lib/curl_addrinfo.c
+++ b/lib/curl_addrinfo.c
@@ -33,6 +33,9 @@
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
#ifdef __VMS
# include <in.h>
@@ -477,6 +480,42 @@ Curl_addrinfo *Curl_str2addr(char *address, int port)
return NULL; /* bad input format */
}
+#ifdef USE_UNIX_SOCKETS
+/**
+ * Given a path to a UNIX domain socket, return a newly allocated Curl_addrinfo
+ * struct initialized with this path.
+ */
+Curl_addrinfo *Curl_unix2addr(const char *path)
+{
+ Curl_addrinfo *ai;
+ struct sockaddr_un *sun;
+ size_t path_len;
+
+ ai = calloc(1, sizeof(Curl_addrinfo));
+ if(!ai)
+ return NULL;
+ if((ai->ai_addr = calloc(1, sizeof(struct sockaddr_un))) == NULL) {
+ free(ai);
+ return NULL;
+ }
+ /* sun_path must be able to store the NUL-terminated path */
+ path_len = strlen(path);
+ if(path_len >= sizeof(sun->sun_path)) {
+ free(ai->ai_addr);
+ free(ai);
+ return NULL;
+ }
+
+ ai->ai_family = AF_UNIX;
+ ai->ai_socktype = SOCK_STREAM; /* assume reliable transport for HTTP */
+ ai->ai_addrlen = (curl_socklen_t) sizeof(struct sockaddr_un);
+ sun = (void *) ai->ai_addr;
+ sun->sun_family = AF_UNIX;
+ memcpy(sun->sun_path, path, path_len + 1); /* copy NUL byte */
+ return ai;
+}
+#endif
+
#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
/*
* curl_dofreeaddrinfo()
diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h
index 6d2b753eb..4ef882703 100644
--- a/lib/curl_addrinfo.h
+++ b/lib/curl_addrinfo.h
@@ -79,6 +79,10 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
Curl_addrinfo *Curl_str2addr(char *dotted, int port);
+#ifdef USE_UNIX_SOCKETS
+Curl_addrinfo *Curl_unix2addr(const char *path);
+#endif
+
#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
void
curl_dofreeaddrinfo(struct addrinfo *freethis,
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index 44014f5dd..bd367c28d 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -912,6 +912,9 @@
/* if SSL is enabled */
#cmakedefine USE_SSLEAY 1
+/* if UNIX domain sockets are enabled */
+#cmakedefine USE_UNIX_SOCKETS
+
/* Define to 1 if you are building a Windows target without large file
support. */
#cmakedefine USE_WIN32_LARGE_FILES 1
diff --git a/lib/url.c b/lib/url.c
index d8703921f..bb9a3bfbc 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -47,6 +47,10 @@
#include <inet.h>
#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
#ifndef HAVE_SOCKET
#error "We can't compile without socket() support!"
#endif
@@ -2574,6 +2578,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->set.ssl_enable_alpn = (0 != va_arg(param, long))?TRUE:FALSE;
break;
+#ifdef USE_UNIX_SOCKETS
+ case CURLOPT_UNIX_SOCKET_PATH:
+ result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
+ va_arg(param, char *));
+ break;
+#endif
+
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_UNKNOWN_OPTION;
@@ -5064,6 +5075,32 @@ static CURLcode resolve_server(struct SessionHandle *data,
/* set a pointer to the hostname we display */
fix_hostname(data, conn, &conn->host);
+#ifdef USE_UNIX_SOCKETS
+ if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
+ /* UNIX domain sockets are local. The host gets ignored, just use the
+ * specified domain socket address. Do not cache "DNS entries". There is
+ * no DNS involved and we already have the filesystem path available */
+ const char *path = data->set.str[STRING_UNIX_SOCKET_PATH];
+
+ hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
+ if(!hostaddr)
+ result = CURLE_OUT_OF_MEMORY;
+ else if((hostaddr->addr = Curl_unix2addr(path)) != NULL)
+ hostaddr->inuse++;
+ else {
+ /* Long paths are not supported for now */
+ if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
+ failf(data, "UNIX socket path too long: '%s'", path);
+ result = CURLE_COULDNT_RESOLVE_HOST;
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ free(hostaddr);
+ hostaddr = NULL;
+ }
+ }
+ else
+#endif
if(!conn->proxy.name || !*conn->proxy.name) {
/* If not connecting via a proxy, extract the port from the URL, if it is
* there, thus overriding any defaults that might have been set above. */
@@ -5379,6 +5416,13 @@ static CURLcode create_conn(struct SessionHandle *data,
else if(!proxy)
proxy = detect_proxy(conn);
+#ifdef USE_UNIX_SOCKETS
+ if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) {
+ free(proxy); /* UNIX domain sockets cannot be proxied, so disable it */
+ proxy = NULL;
+ }
+#endif
+
if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
free(proxy); /* Don't bother with an empty proxy string or if the
protocol doesn't work with network */
diff --git a/lib/urldata.h b/lib/urldata.h
index 075dca9b2..d61e8cefc 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1426,8 +1426,10 @@ enum dupstring {
STRING_TLSAUTH_USERNAME, /* TLS auth <username> */
STRING_TLSAUTH_PASSWORD, /* TLS auth <password> */
#endif
-
STRING_BEARER, /* <bearer>, if used */
+#ifdef USE_UNIX_SOCKETS
+ STRING_UNIX_SOCKET_PATH, /* path to UNIX socket, if used */
+#endif
/* -- end of zero-terminated strings -- */
diff --git a/lib/version.c b/lib/version.c
index 93317e19b..511562fe1 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -295,6 +295,9 @@ static curl_version_info_data version_info = {
#if defined(USE_NGHTTP2)
| CURL_VERSION_HTTP2
#endif
+#if defined(USE_UNIX_SOCKETS)
+ | CURL_VERSION_UNIX_SOCKETS
+#endif
,
NULL, /* ssl_version */
0, /* ssl_version_num, this is kept at zero */
diff --git a/packages/OS400/curl.inc.in b/packages/OS400/curl.inc.in
index bc4d848f5..fcbf7c7c5 100644
--- a/packages/OS400/curl.inc.in
+++ b/packages/OS400/curl.inc.in
@@ -121,6 +121,8 @@
d c X'00020000'
d CURL_VERSION_KERBEROS5...
d c X'00040000'
+ d CURL_VERSION_UNIX_SOCKETS...
+ d c X'00080000'
*
d HTTPPOST_FILENAME...
d c X'00000001'
@@ -1199,6 +1201,8 @@
d c 00229
d CURLOPT_PINNEDPUBLICKEY...
d c 10230
+ d CURLOPT_UNIX_SOCKET_PATH...
+ d c 10231
*
/if not defined(CURL_NO_OLDIES)
d CURLOPT_FILE c 10001
diff --git a/src/tool_help.c b/src/tool_help.c
index 280d33a87..6f8f29263 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -273,7 +273,8 @@ static const struct feat feats[] = {
{"libz", CURL_VERSION_LIBZ},
{"CharConv", CURL_VERSION_CONV},
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
- {"HTTP2", CURL_VERSION_HTTP2}
+ {"HTTP2", CURL_VERSION_HTTP2},
+ {"unix-sockets", CURL_VERSION_UNIX_SOCKETS},
};
void tool_help(void)
diff --git a/tests/server/sws.c b/tests/server/sws.c
index 03e0d0c3d..14153c6da 100644
--- a/tests/server/sws.c
+++ b/tests/server/sws.c
@@ -71,7 +71,7 @@ static enum {
, socket_domain_inet6 = AF_INET6
#endif
#ifdef USE_UNIX_SOCKETS
- socket_domain_unix = AF_UNIX,
+ , socket_domain_unix = AF_UNIX
#endif
} socket_domain = AF_INET;
static bool use_gopher = FALSE;