diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/curl_addrinfo.c | 39 | ||||
-rw-r--r-- | lib/curl_addrinfo.h | 4 | ||||
-rw-r--r-- | lib/curl_config.h.cmake | 3 | ||||
-rw-r--r-- | lib/url.c | 44 | ||||
-rw-r--r-- | lib/urldata.h | 4 | ||||
-rw-r--r-- | lib/version.c | 3 |
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 @@ -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 */ |