curl_fuzzer
curl_fuzzer_seed_corpus.zip
libstandaloneengine.a
+tests/string
const char *reqlogfile = DEFAULT_REQFILE;
static const char *configfile = DEFAULT_CONFIG;
-#ifdef ENABLE_IPV6
-static bool use_ipv6 = FALSE;
-#endif
-static const char *ipv_inuse = "IPv4";
+static const char *socket_type = "IPv4";
static unsigned short port = DEFAULT_PORT;
static void resetdefaults(void)
return num & 0xffff;
}
+static enum {
+ socket_domain_inet = AF_INET
+#ifdef ENABLE_IPV6
+ , socket_domain_inet6 = AF_INET6
+#endif
+#ifdef USE_UNIX_SOCKETS
+ , socket_domain_unix = AF_UNIX
+#endif
+} socket_domain = AF_INET;
+
static void getconfig(void)
{
FILE *fp = fopen(configfile, FOPEN_READTEXT);
}
static curl_socket_t sockdaemon(curl_socket_t sock,
- unsigned short *listenport)
+ unsigned short *listenport
+#ifdef USE_UNIX_SOCKETS
+ , const char *unix_socket
+#endif
+ )
{
/* passive daemon style */
srvr_sockaddr_union_t listener;
/* When the specified listener port is zero, it is actually a
request to let the system choose a non-zero available port. */
+ switch(socket_domain) {
+ case AF_INET:
+ memset(&listener.sa4, 0, sizeof(listener.sa4));
+ listener.sa4.sin_family = AF_INET;
+ listener.sa4.sin_addr.s_addr = INADDR_ANY;
+ listener.sa4.sin_port = htons(*listenport);
+ rc = bind(sock, &listener.sa, sizeof(listener.sa4));
+ break;
#ifdef ENABLE_IPV6
- if(!use_ipv6) {
+ case AF_INET6:
+ memset(&listener.sa6, 0, sizeof(listener.sa6));
+ listener.sa6.sin6_family = AF_INET6;
+ listener.sa6.sin6_addr = in6addr_any;
+ listener.sa6.sin6_port = htons(*listenport);
+ rc = bind(sock, &listener.sa, sizeof(listener.sa6));
+ break;
+#endif /* ENABLE_IPV6 */
+#ifdef USE_UNIX_SOCKETS
+ case AF_UNIX:
+ rc = bind_unix_socket(sock, unix_socket, &listener.sau);
#endif
- memset(&listener.sa4, 0, sizeof(listener.sa4));
- listener.sa4.sin_family = AF_INET;
- listener.sa4.sin_addr.s_addr = INADDR_ANY;
- listener.sa4.sin_port = htons(*listenport);
- rc = bind(sock, &listener.sa, sizeof(listener.sa4));
-#ifdef ENABLE_IPV6
- }
- else {
- memset(&listener.sa6, 0, sizeof(listener.sa6));
- listener.sa6.sin6_family = AF_INET6;
- listener.sa6.sin6_addr = in6addr_any;
- listener.sa6.sin6_port = htons(*listenport);
- rc = bind(sock, &listener.sa, sizeof(listener.sa6));
}
-#endif /* ENABLE_IPV6 */
+
if(rc) {
error = SOCKERRNO;
logmsg("Error binding socket on port %hu: (%d) %s",
return CURL_SOCKET_BAD;
}
- if(!*listenport) {
+ if(!*listenport
+#ifdef USE_UNIX_SOCKETS
+ && !unix_socket
+#endif
+ ) {
/* The system was supposed to choose a port number, figure out which
port we actually got and update the listener port value with it. */
curl_socklen_t la_size;
srvr_sockaddr_union_t localaddr;
#ifdef ENABLE_IPV6
- if(!use_ipv6)
-#endif
- la_size = sizeof(localaddr.sa4);
-#ifdef ENABLE_IPV6
- else
+ if(socket_domain == AF_INET6)
la_size = sizeof(localaddr.sa6);
+ else
#endif
+ la_size = sizeof(localaddr.sa4);
memset(&localaddr.sa, 0, (size_t)la_size);
if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
error = SOCKERRNO;
int error;
int arg = 1;
+#ifdef USE_UNIX_SOCKETS
+ const char *unix_socket = NULL;
+ bool unlink_socket = false;
+#endif
+
while(argc>arg) {
if(!strcmp("--version", argv[arg])) {
printf("socksd IPv4%s\n",
}
else if(!strcmp("--ipv6", argv[arg])) {
#ifdef ENABLE_IPV6
- ipv_inuse = "IPv6";
- use_ipv6 = TRUE;
+ socket_domain = AF_INET6;
+ socket_type = "IPv6";
#endif
arg++;
}
else if(!strcmp("--ipv4", argv[arg])) {
/* for completeness, we support this option as well */
#ifdef ENABLE_IPV6
- ipv_inuse = "IPv4";
- use_ipv6 = FALSE;
+ socket_type = "IPv4";
#endif
arg++;
}
+ else if(!strcmp("--unix-socket", argv[arg])) {
+ arg++;
+ if(argc>arg) {
+#ifdef USE_UNIX_SOCKETS
+ struct sockaddr_un sau;
+ unix_socket = argv[arg];
+ if(strlen(unix_socket) >= sizeof(sau.sun_path)) {
+ fprintf(stderr,
+ "socksd: socket path must be shorter than %zu chars\n",
+ sizeof(sau.sun_path));
+ return 0;
+ }
+ socket_domain = AF_UNIX;
+ socket_type = "unix";
+#endif
+ arg++;
+ }
+ }
else if(!strcmp("--port", argv[arg])) {
arg++;
if(argc>arg) {
" --reqfile [file]\n"
" --ipv4\n"
" --ipv6\n"
+ " --unix-socket [file]\n"
" --bindonly\n"
" --port [port]\n");
return 0;
install_signal_handlers(false);
-#ifdef ENABLE_IPV6
- if(!use_ipv6)
-#endif
- sock = socket(AF_INET, SOCK_STREAM, 0);
-#ifdef ENABLE_IPV6
- else
- sock = socket(AF_INET6, SOCK_STREAM, 0);
-#endif
+ sock = socket(socket_domain, SOCK_STREAM, 0);
if(CURL_SOCKET_BAD == sock) {
error = SOCKERRNO;
{
/* passive daemon style */
- sock = sockdaemon(sock, &port);
+ sock = sockdaemon(sock, &port
+#ifdef USE_UNIX_SOCKETS
+ , unix_socket
+#endif
+ );
if(CURL_SOCKET_BAD == sock) {
goto socks5_cleanup;
}
+#ifdef USE_UNIX_SOCKETS
+ unlink_socket = true;
+#endif
msgsock = CURL_SOCKET_BAD; /* no stream socket yet */
}
- logmsg("Running %s version", ipv_inuse);
+ logmsg("Running %s version", socket_type);
+
+#ifdef USE_UNIX_SOCKETS
+ if(socket_domain == AF_UNIX)
+ logmsg("Listening on unix socket %s", unix_socket);
+ else
+#endif
logmsg("Listening on port %hu", port);
wrotepidfile = write_pidfile(pidname);
if(sock != CURL_SOCKET_BAD)
sclose(sock);
+#ifdef USE_UNIX_SOCKETS
+ if(unlink_socket && socket_domain == AF_UNIX) {
+ error = unlink(unix_socket);
+ logmsg("unlink(%s) = %d (%s)", unix_socket, error, strerror(error));
+ }
+#endif
+
if(wrotepidfile)
unlink(pidname);
if(wroteportfile)
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, 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
#endif /* ENABLE_IPV6 */
#ifdef USE_UNIX_SOCKETS
case AF_UNIX:
- memset(&me.sau, 0, sizeof(me.sau));
- me.sau.sun_family = AF_UNIX;
- strncpy(me.sau.sun_path, unix_socket, sizeof(me.sau.sun_path) - 1);
- rc = bind(sock, &me.sa, sizeof(me.sau));
- if(0 != rc && errno == EADDRINUSE) {
- struct_stat statbuf;
- /* socket already exists. Perhaps it is stale? */
- curl_socket_t unixfd = socket(AF_UNIX, SOCK_STREAM, 0);
- if(CURL_SOCKET_BAD == unixfd) {
- error = SOCKERRNO;
- logmsg("Error binding socket, failed to create socket at %s: (%d) %s",
- unix_socket, error, strerror(error));
- goto sws_cleanup;
- }
- /* check whether the server is alive */
- rc = connect(unixfd, &me.sa, sizeof(me.sau));
- error = errno;
- sclose(unixfd);
- if(ECONNREFUSED != error) {
- logmsg("Error binding socket, failed to connect to %s: (%d) %s",
- unix_socket, error, strerror(error));
- goto sws_cleanup;
- }
- /* socket server is not alive, now check if it was actually a socket. */
-#ifdef WIN32
- /* Windows does not have lstat function. */
- rc = curlx_win32_stat(unix_socket, &statbuf);
-#else
- rc = lstat(unix_socket, &statbuf);
-#endif
- if(0 != rc) {
- logmsg("Error binding socket, failed to stat %s: (%d) %s",
- unix_socket, errno, strerror(errno));
- goto sws_cleanup;
- }
-#ifdef S_IFSOCK
- if((statbuf.st_mode & S_IFSOCK) != S_IFSOCK) {
- logmsg("Error binding socket, failed to stat %s: (%d) %s",
- unix_socket, error, strerror(error));
- goto sws_cleanup;
- }
-#endif
- /* dead socket, cleanup and retry bind */
- rc = unlink(unix_socket);
- if(0 != rc) {
- logmsg("Error binding socket, failed to unlink %s: (%d) %s",
- unix_socket, errno, strerror(errno));
- goto sws_cleanup;
- }
- /* stale socket is gone, retry bind */
- rc = bind(sock, &me.sa, sizeof(me.sau));
- }
- break;
+ rc = bind_unix_socket(sock, unix_socket, &me.sau);
#endif /* USE_UNIX_SOCKETS */
}
if(0 != rc) {
}
#endif
}
+
+#ifdef USE_UNIX_SOCKETS
+
+int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
+ struct sockaddr_un *sau) {
+ int error;
+ int rc;
+
+ memset(sau, 0, sizeof(struct sockaddr_un));
+ sau->sun_family = AF_UNIX;
+ strncpy(sau->sun_path, unix_socket, sizeof(sau->sun_path) - 1);
+ rc = bind(sock, (struct sockaddr*)sau, sizeof(struct sockaddr_un));
+ if(0 != rc && errno == EADDRINUSE) {
+ struct_stat statbuf;
+ /* socket already exists. Perhaps it is stale? */
+ curl_socket_t unixfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(CURL_SOCKET_BAD == unixfd) {
+ error = SOCKERRNO;
+ logmsg("Error binding socket, failed to create socket at %s: (%d) %s",
+ unix_socket, error, strerror(error));
+ return rc;
+ }
+ /* check whether the server is alive */
+ rc = connect(unixfd, (struct sockaddr*)sau, sizeof(struct sockaddr_un));
+ error = errno;
+ sclose(unixfd);
+ if(ECONNREFUSED != error) {
+ logmsg("Error binding socket, failed to connect to %s: (%d) %s",
+ unix_socket, error, strerror(error));
+ return rc;
+ }
+ /* socket server is not alive, now check if it was actually a socket. */
+#ifdef WIN32
+ /* Windows does not have lstat function. */
+ rc = curlx_win32_stat(unix_socket, &statbuf);
+#else
+ rc = lstat(unix_socket, &statbuf);
+#endif
+ if(0 != rc) {
+ logmsg("Error binding socket, failed to stat %s: (%d) %s",
+ unix_socket, errno, strerror(errno));
+ return rc;
+ }
+#ifdef S_IFSOCK
+ if((statbuf.st_mode & S_IFSOCK) != S_IFSOCK) {
+ logmsg("Error binding socket, failed to stat %s: (%d) %s",
+ unix_socket, error, strerror(error));
+ return rc;
+ }
+#endif
+ /* dead socket, cleanup and retry bind */
+ rc = unlink(unix_socket);
+ if(0 != rc) {
+ logmsg("Error binding socket, failed to unlink %s: (%d) %s",
+ unix_socket, errno, strerror(errno));
+ return rc;
+ }
+ /* stale socket is gone, retry bind */
+ rc = bind(sock, (struct sockaddr*)sau, sizeof(struct sockaddr_un));
+ }
+ return rc;
+}
+#endif
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, 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
void install_signal_handlers(bool keep_sigalrm);
void restore_signal_handlers(bool keep_sigalrm);
+#ifdef USE_UNIX_SOCKETS
+
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h> /* for sockaddr_un */
+#endif /* HAVE_SYS_UN_H */
+
+int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
+ struct sockaddr_un *sau);
+#endif /* USE_UNIX_SOCKETS */
+
#endif /* HEADER_CURL_SERVER_UTIL_H */