aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-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
6 files changed, 96 insertions, 1 deletions
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 */