mirror of
https://github.com/curl/curl.git
synced 2026-06-05 09:14:15 +03:00
unix_socket: add support for abstract unix domain socket
In addition to unix domain sockets, Linux also supports an abstract namespace which is independent of the filesystem. In order to support it, add new CURLOPT_ABSTRACT_UNIX_SOCKET option which uses the same storage as CURLOPT_UNIX_SOCKET_PATH internally, along with a flag to specify abstract socket. On non-supporting platforms, the abstract address will be interpreted as an empty string and fail gracefully. Also add new --abstract-unix-socket tool parameter. Signed-off-by: Isaac Boukris <iboukris@gmail.com> Reported-by: Chungtsun Li (typeless) Reviewed-by: Daniel Stenberg Reviewed-by: Peter Wu Closes #1197 Fixes #1061
This commit is contained in:
parent
a7c73ae309
commit
1d786faee1
17 changed files with 139 additions and 19 deletions
|
|
@ -47,6 +47,8 @@
|
|||
# define in_addr_t unsigned long
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "curl_addrinfo.h"
|
||||
#include "inet_pton.h"
|
||||
#include "warnless.h"
|
||||
|
|
@ -483,24 +485,29 @@ Curl_addrinfo *Curl_str2addr(char *address, int port)
|
|||
* struct initialized with this path.
|
||||
* Set '*longpath' to TRUE if the error is a too long path.
|
||||
*/
|
||||
Curl_addrinfo *Curl_unix2addr(const char *path, int *longpath)
|
||||
Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
|
||||
{
|
||||
Curl_addrinfo *ai;
|
||||
struct sockaddr_un *sa_un;
|
||||
size_t path_len;
|
||||
|
||||
*longpath = FALSE;
|
||||
|
||||
ai = calloc(1, sizeof(Curl_addrinfo));
|
||||
if(!ai)
|
||||
return NULL;
|
||||
ai->ai_addr = calloc(1, sizeof(struct sockaddr_un));
|
||||
if(!ai->ai_addr) {
|
||||
free(ai);
|
||||
*longpath = FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sa_un = (void *) ai->ai_addr;
|
||||
sa_un->sun_family = AF_UNIX;
|
||||
|
||||
/* sun_path must be able to store the NUL-terminated path */
|
||||
path_len = strlen(path);
|
||||
if(path_len >= sizeof(sa_un->sun_path)) {
|
||||
path_len = strlen(path) + 1;
|
||||
if(path_len > sizeof(sa_un->sun_path)) {
|
||||
free(ai->ai_addr);
|
||||
free(ai);
|
||||
*longpath = TRUE;
|
||||
|
|
@ -509,10 +516,14 @@ Curl_addrinfo *Curl_unix2addr(const char *path, int *longpath)
|
|||
|
||||
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);
|
||||
sa_un = (void *) ai->ai_addr;
|
||||
sa_un->sun_family = AF_UNIX;
|
||||
memcpy(sa_un->sun_path, path, path_len + 1); /* copy NUL byte */
|
||||
ai->ai_addrlen = offsetof(struct sockaddr_un, sun_path) + path_len;
|
||||
|
||||
/* Abstract Unix domain socket have NULL prefix instead of suffix */
|
||||
if(abstract)
|
||||
memcpy(sa_un->sun_path + 1, path, path_len - 1);
|
||||
else
|
||||
memcpy(sa_un->sun_path, path, path_len); /* copy NUL byte */
|
||||
|
||||
return ai;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ 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, int *longpath);
|
||||
Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract);
|
||||
#endif
|
||||
|
||||
#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
|
||||
|
|
|
|||
14
lib/url.c
14
lib/url.c
|
|
@ -2814,6 +2814,12 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
|
|||
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
case CURLOPT_UNIX_SOCKET_PATH:
|
||||
data->set.abstract_unix_socket = FALSE;
|
||||
result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_ABSTRACT_UNIX_SOCKET:
|
||||
data->set.abstract_unix_socket = TRUE;
|
||||
result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
|
|
@ -3523,6 +3529,8 @@ ConnectionExists(struct Curl_easy *data,
|
|||
continue;
|
||||
if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
|
||||
continue;
|
||||
if(needle->abstract_unix_socket != check->abstract_unix_socket)
|
||||
continue;
|
||||
}
|
||||
else if(check->unix_domain_socket)
|
||||
continue;
|
||||
|
|
@ -5863,8 +5871,9 @@ static CURLcode resolve_server(struct Curl_easy *data,
|
|||
if(!hostaddr)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
else {
|
||||
int longpath=0;
|
||||
hostaddr->addr = Curl_unix2addr(path, &longpath);
|
||||
bool longpath = FALSE;
|
||||
hostaddr->addr = Curl_unix2addr(path, &longpath,
|
||||
conn->abstract_unix_socket);
|
||||
if(hostaddr->addr)
|
||||
hostaddr->inuse++;
|
||||
else {
|
||||
|
|
@ -6273,6 +6282,7 @@ static CURLcode create_conn(struct Curl_easy *data,
|
|||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
conn->abstract_unix_socket = data->set.abstract_unix_socket;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1133,6 +1133,7 @@ struct connectdata {
|
|||
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
char *unix_domain_socket;
|
||||
bool abstract_unix_socket;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -1754,6 +1755,8 @@ struct UserDefined {
|
|||
int stream_weight;
|
||||
|
||||
struct Curl_http2_dep *stream_dependents;
|
||||
|
||||
bool abstract_unix_socket;
|
||||
};
|
||||
|
||||
struct Names {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue