89 #ifdef HAVE_NETINET_IN_H 90 #include <netinet/in.h> 92 #ifdef HAVE_ARPA_INET_H 93 #include <arpa/inet.h> 99 #define ENABLE_CURLX_PRINTF 123 #define DEFAULT_PORT 8999 125 #ifndef DEFAULT_LOGFILE 126 #define DEFAULT_LOGFILE "log/sockfilt.log" 149 #ifndef HAVE_SIGINTERRUPT 150 #define siginterrupt(x,y) do {} while(0) 177 #if defined(SIGBREAK) && defined(WIN32) 196 int old_errno = errno;
209 old_sighup_handler = signal(SIGHUP, SIG_IGN);
210 if(old_sighup_handler == SIG_ERR)
211 logmsg(
"cannot install SIGHUP handler: %s", strerror(errno));
215 old_sigpipe_handler = signal(SIGPIPE, SIG_IGN);
216 if(old_sigpipe_handler == SIG_ERR)
217 logmsg(
"cannot install SIGPIPE handler: %s", strerror(errno));
221 old_sigalrm_handler = signal(SIGALRM, SIG_IGN);
222 if(old_sigalrm_handler == SIG_ERR)
223 logmsg(
"cannot install SIGALRM handler: %s", strerror(errno));
228 if(old_sigint_handler == SIG_ERR)
229 logmsg(
"cannot install SIGINT handler: %s", strerror(errno));
236 if(old_sigterm_handler == SIG_ERR)
237 logmsg(
"cannot install SIGTERM handler: %s", strerror(errno));
241 #if defined(SIGBREAK) && defined(WIN32) 244 if(old_sigbreak_handler == SIG_ERR)
245 logmsg(
"cannot install SIGBREAK handler: %s", strerror(errno));
254 if(SIG_ERR != old_sighup_handler)
255 (void)signal(SIGHUP, old_sighup_handler);
258 if(SIG_ERR != old_sigpipe_handler)
259 (void)signal(SIGPIPE, old_sigpipe_handler);
262 if(SIG_ERR != old_sigalrm_handler)
263 (void)signal(SIGALRM, old_sigalrm_handler);
266 if(SIG_ERR != old_sigint_handler)
267 (void)signal(SIGINT, old_sigint_handler);
270 if(SIG_ERR != old_sigterm_handler)
271 (void)signal(SIGTERM, old_sigterm_handler);
273 #if defined(SIGBREAK) && defined(WIN32) 274 if(SIG_ERR != old_sigbreak_handler)
275 (void)signal(SIGBREAK, old_sigbreak_handler);
283 static ssize_t read_wincon(
int fd,
void *
buf,
size_t count)
285 HANDLE handle = NULL;
286 DWORD mode, rcount = 0;
290 handle = GetStdHandle(STD_INPUT_HANDLE);
293 return read(fd,
buf, count);
296 if(GetConsoleMode(handle, &mode)) {
297 success = ReadConsole(handle,
buf,
curlx_uztoul(count), &rcount, NULL);
306 errno = GetLastError();
310 #define read(a,b,c) read_wincon(a,b,c) 315 static ssize_t write_wincon(
int fd,
const void *
buf,
size_t count)
317 HANDLE handle = NULL;
318 DWORD mode, wcount = 0;
321 if(fd ==
fileno(stdout)) {
322 handle = GetStdHandle(STD_OUTPUT_HANDLE);
324 else if(fd ==
fileno(stderr)) {
325 handle = GetStdHandle(STD_ERROR_HANDLE);
328 return write(fd,
buf, count);
331 if(GetConsoleMode(handle, &mode)) {
332 success = WriteConsole(handle,
buf,
curlx_uztoul(count), &wcount, NULL);
341 errno = GetLastError();
345 #define write(a,b,c) write_wincon(a,b,c) 362 rc = read(filedes, (
unsigned char *)buffer + nread, nbytes - nread);
365 logmsg(
"signalled to die");
371 if((error == EINTR) || (error ==
EAGAIN))
373 logmsg(
"reading from file descriptor: %d,", filedes);
374 logmsg(
"unrecoverable read() failure: (%d) %s",
375 error, strerror(error));
380 logmsg(
"got 0 reading from stdin");
386 }
while((
size_t)nread < nbytes);
389 logmsg(
"read %zd bytes", nread);
408 wc = write(filedes, (
const unsigned char *)buffer + nwrite,
412 logmsg(
"signalled to die");
418 if((error == EINTR) || (error ==
EAGAIN))
420 logmsg(
"writing to file descriptor: %d,", filedes);
421 logmsg(
"unrecoverable write() failure: (%d) %s",
422 error, strerror(error));
427 logmsg(
"put 0 writing to stdout");
433 }
while((
size_t)nwrite < nbytes);
436 logmsg(
"wrote %zd bytes", nwrite);
468 if(nwrite != (
ssize_t)nbytes) {
482 int left =
sizeof(
data);
484 for(i = 0; i<
len; i++) {
500 ptr[i] == 0x20) ?ptr[i]:
'.');
531 struct select_ws_wait_data {
535 static DWORD WINAPI select_ws_wait_thread(LPVOID lpParameter)
537 struct select_ws_wait_data *
data;
539 INPUT_RECORD inputrecord;
540 LARGE_INTEGER
size, pos;
544 data = (
struct select_ws_wait_data *) lpParameter;
546 handle = data->handle;
547 handles[0] = data->event;
555 type = GetFileType(handle);
566 while(WaitForMultipleObjectsEx(1, handles,
FALSE, 0,
FALSE)
571 size.LowPart = GetFileSize(handle, &length);
572 if((size.LowPart != INVALID_FILE_SIZE) ||
574 size.HighPart = length;
577 pos.LowPart = SetFilePointer(handle, 0, &pos.HighPart,
579 if((pos.LowPart != INVALID_SET_FILE_POINTER) ||
582 if(size.QuadPart == pos.QuadPart) {
602 while(WaitForMultipleObjectsEx(2, handles,
FALSE, INFINITE,
FALSE)
603 == WAIT_OBJECT_0 + 1) {
606 if(GetConsoleMode(handle, &length)) {
609 if(PeekConsoleInput(handle, &inputrecord, 1, &length)) {
611 if(length == 1 && inputrecord.EventType != KEY_EVENT) {
613 ReadConsoleInput(handle, &inputrecord, 1, &length);
631 while(WaitForMultipleObjectsEx(1, handles,
FALSE, 0,
FALSE)
635 if(PeekNamedPipe(handle, NULL, 0, NULL, &length, NULL)) {
644 if(GetLastError() == ERROR_BROKEN_PIPE) {
656 WaitForMultipleObjectsEx(2, handles,
FALSE, INFINITE,
FALSE);
662 static HANDLE select_ws_wait(HANDLE handle, HANDLE event)
664 struct select_ws_wait_data *
data;
665 HANDLE thread = NULL;
668 data =
malloc(
sizeof(
struct select_ws_wait_data));
670 data->handle = handle;
674 thread = CreateThread(NULL, 0,
675 &select_ws_wait_thread,
686 struct select_ws_data {
692 static int select_ws(
int nfds, fd_set *readfds, fd_set *writefds,
695 DWORD milliseconds, wait, idx;
696 WSANETWORKEVENTS wsanetevents;
697 struct select_ws_data *
data;
703 HANDLE waitevent = NULL;
704 DWORD nfd = 0, thd = 0, wsa = 0;
715 Sleep((timeout->
tv_sec*1000)+(DWORD)(((
double)timeout->
tv_usec)/1000.0));
720 waitevent = CreateEvent(NULL,
TRUE,
FALSE, NULL);
727 data =
malloc(nfds *
sizeof(
struct select_ws_data));
734 handles =
malloc(nfds *
sizeof(HANDLE));
735 if(handles == NULL) {
742 memset(data, 0, nfds *
sizeof(
struct select_ws_data));
743 memset(handles, 0, nfds *
sizeof(HANDLE));
746 for(fds = 0; fds < nfds; fds++) {
750 if(FD_ISSET(fds, readfds))
751 networkevents |= FD_READ|FD_ACCEPT|FD_CLOSE;
753 if(FD_ISSET(fds, writefds))
754 networkevents |= FD_WRITE|FD_CONNECT;
756 if(FD_ISSET(fds, exceptfds))
757 networkevents |= FD_OOB|FD_CLOSE;
761 data[nfd].fd = curlx_sitosk(fds);
762 if(fds ==
fileno(stdin)) {
763 handle = GetStdHandle(STD_INPUT_HANDLE);
764 handle = select_ws_wait(handle, waitevent);
765 handles[nfd] = handle;
766 data[thd].thread = handle;
769 else if(fds ==
fileno(stdout)) {
770 handles[nfd] = GetStdHandle(STD_OUTPUT_HANDLE);
772 else if(fds ==
fileno(stderr)) {
773 handles[nfd] = GetStdHandle(STD_ERROR_HANDLE);
776 wsaevent = WSACreateEvent();
777 if(wsaevent != WSA_INVALID_EVENT) {
778 error = WSAEventSelect(fds, wsaevent, networkevents);
779 if(error != SOCKET_ERROR) {
780 handle = (HANDLE) wsaevent;
781 handles[nfd] = handle;
782 data[wsa].wsasock = curlx_sitosk(fds);
783 data[wsa].wsaevent = wsaevent;
787 WSACloseEvent(wsaevent);
788 handle = (HANDLE) curlx_sitosk(fds);
789 handle = select_ws_wait(handle, waitevent);
790 handles[nfd] = handle;
791 data[thd].thread = handle;
802 milliseconds = ((timeout->
tv_sec * 1000) + (timeout->
tv_usec / 1000));
805 milliseconds = INFINITE;
809 wait = WaitForMultipleObjectsEx(nfd, handles,
FALSE, milliseconds,
FALSE);
815 for(idx = 0; idx < nfd; idx++) {
816 handle = handles[idx];
818 fds = curlx_sktosi(sock);
821 if(wait != WAIT_FAILED && (wait - WAIT_OBJECT_0) <= idx &&
822 WaitForSingleObjectEx(handle, 0,
FALSE) == WAIT_OBJECT_0) {
824 if(fds ==
fileno(stdin)) {
826 FD_CLR(sock, writefds);
827 FD_CLR(sock, exceptfds);
829 else if(fds ==
fileno(stdout) || fds ==
fileno(stderr)) {
831 FD_CLR(sock, readfds);
832 FD_CLR(sock, exceptfds);
836 wsanetevents.lNetworkEvents = 0;
837 error = WSAEnumNetworkEvents(fds, handle, &wsanetevents);
838 if(error != SOCKET_ERROR) {
840 if(!(wsanetevents.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE)))
841 FD_CLR(sock, readfds);
844 if(!(wsanetevents.lNetworkEvents & (FD_WRITE|FD_CONNECT)))
845 FD_CLR(sock, writefds);
857 if(!(wsanetevents.lNetworkEvents & (FD_OOB|FD_CLOSE)))
858 FD_CLR(sock, exceptfds);
863 if(FD_ISSET(sock, readfds) || FD_ISSET(sock, writefds) ||
864 FD_ISSET(sock, exceptfds)) {
870 FD_CLR(sock, readfds);
871 FD_CLR(sock, writefds);
872 FD_CLR(sock, exceptfds);
876 for(fds = 0; fds < nfds; fds++) {
877 if(FD_ISSET(fds, readfds))
878 logmsg(
"select_ws: %d is readable", fds);
880 if(FD_ISSET(fds, writefds))
881 logmsg(
"select_ws: %d is writable", fds);
883 if(FD_ISSET(fds, exceptfds))
884 logmsg(
"select_ws: %d is excepted", fds);
887 for(idx = 0; idx < wsa; idx++) {
888 WSAEventSelect(data[idx].wsasock, NULL, 0);
889 WSACloseEvent(data[idx].wsaevent);
892 for(idx = 0; idx < thd; idx++) {
893 WaitForSingleObject(data[idx].thread, INFINITE);
894 CloseHandle(data[idx].thread);
897 CloseHandle(waitevent);
904 #define select(a,b,c,d,e) select_ws(a,b,c,d,e) 931 unsigned char buffer[17010];
935 logmsg(
"signalled to die, exiting...");
943 logmsg(
"process becomes orphan, exiting");
964 FD_SET(sockfd, &fds_read);
973 logmsg(
"socket is -1! on %s:%d", __FILE__, __LINE__);
978 FD_SET(sockfd, &fds_read);
980 FD_SET(sockfd, &fds_err);
991 FD_SET(sockfd, &fds_read);
993 FD_SET(sockfd, &fds_err);
998 logmsg(
"No socket to read on");
1005 logmsg(
"disconnected, no socket to read on");
1017 rc = select(maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);
1020 logmsg(
"signalled to die, exiting...");
1024 }
while((rc == -1) && ((error = errno) == EINTR));
1027 logmsg(
"select() failed with error: (%d) %s",
1028 error, strerror(error));
1037 if(FD_ISSET(
fileno(stdin), &fds_read)) {
1056 logmsg(
"Received %c%c%c%c (on stdin)",
1057 buffer[0], buffer[1], buffer[2], buffer[3]);
1059 if(!memcmp(
"PING", buffer, 4)) {
1065 else if(!memcmp(
"PORT", buffer, 4)) {
1070 snprintf(data,
sizeof(data),
"PORT\n%04zx\n", buffer_len);
1076 else if(!memcmp(
"QUIT", buffer, 4)) {
1081 else if(!memcmp(
"DATA", buffer, 4)) {
1091 logmsg(
"ERROR: Buffer size (%zu bytes) too small for data size " 1092 "(%zd bytes)",
sizeof(buffer), buffer_len);
1095 logmsg(
"> %zd bytes data, server => client", buffer_len);
1100 lograw(buffer, buffer_len);
1103 logmsg(
"*** We are disconnected!");
1109 bytes_written = swrite(sockfd, buffer, buffer_len);
1110 if(bytes_written != buffer_len) {
1111 logmsg(
"Not all data was sent. Bytes to send: %zd sent: %zd",
1112 buffer_len, bytes_written);
1116 else if(!memcmp(
"DISC", buffer, 4)) {
1121 logmsg(
"====> Client forcibly disconnected");
1130 logmsg(
"attempt to close already dead connection");
1143 newfd = accept(sockfd, NULL, NULL);
1146 logmsg(
"accept(%d, NULL, NULL) failed with error: (%d) %s",
1147 sockfd, error, strerror(error));
1150 logmsg(
"====> Client connect");
1160 nread_socket = sread(sockfd, buffer,
sizeof(buffer));
1162 if(nread_socket > 0) {
1163 snprintf(data,
sizeof(data),
"DATA\n%04zx\n", nread_socket);
1169 logmsg(
"< %zd bytes data, client => server", nread_socket);
1170 lograw(buffer, nread_socket);
1173 if(nread_socket <= 0
1175 || FD_ISSET(sockfd, &fds_err)
1178 logmsg(
"====> Client disconnect");
1195 unsigned short *listenport)
1210 rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1211 (
void *)&flag,
sizeof(flag));
1214 logmsg(
"setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
1215 error, strerror(error));
1221 logmsg(
"wait_ms() failed with error: (%d) %s",
1222 error, strerror(error));
1227 logmsg(
"signalled to die, exiting...");
1235 }
while(rc && maxretr--);
1238 logmsg(
"setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error: (%d) %s",
1239 attempt, totdelay, error, strerror(error));
1240 logmsg(
"Continuing anyway...");
1249 memset(&listener.
sa4, 0,
sizeof(listener.
sa4));
1250 listener.
sa4.sin_family = AF_INET;
1251 listener.
sa4.sin_addr.s_addr = INADDR_ANY;
1252 listener.
sa4.sin_port = htons(*listenport);
1253 rc =
bind(sock, &listener.
sa,
sizeof(listener.
sa4));
1257 memset(&listener.sa6, 0,
sizeof(listener.sa6));
1258 listener.sa6.sin6_family = AF_INET6;
1259 listener.sa6.sin6_addr = in6addr_any;
1260 listener.sa6.sin6_port = htons(*listenport);
1261 rc =
bind(sock, &listener.
sa,
sizeof(listener.sa6));
1266 logmsg(
"Error binding socket on port %hu: (%d) %s",
1267 *listenport, error, strerror(error));
1280 la_size =
sizeof(localaddr.
sa4);
1283 la_size =
sizeof(localaddr.sa6);
1285 memset(&localaddr.
sa, 0, (
size_t)la_size);
1286 if(getsockname(sock, &localaddr.
sa, &la_size) < 0) {
1288 logmsg(
"getsockname() failed with error: (%d) %s",
1289 error, strerror(error));
1293 switch(localaddr.
sa.sa_family) {
1295 *listenport = ntohs(localaddr.
sa4.sin_port);
1299 *listenport = ntohs(localaddr.sa6.sin6_port);
1307 logmsg(
"Apparently getsockname() succeeded, with listener port zero.");
1308 logmsg(
"A valid reason for this failure is a binary built without");
1309 logmsg(
"proper network library linkage. This might not be the only");
1310 logmsg(
"reason, but double check it before anything else.");
1318 logmsg(
"instructed to bind port without listening");
1323 rc = listen(sock, 5);
1326 logmsg(
"listen(%d, 5) failed with error: (%d) %s",
1327 sock, error, strerror(error));
1342 const char *
pidname =
".sockfilt.pid";
1348 const char *addr = NULL;
1351 if(!strcmp(
"--version", argv[arg])) {
1352 printf(
"sockfilt IPv4%s\n",
1361 else if(!strcmp(
"--verbose", argv[arg])) {
1365 else if(!strcmp(
"--pidfile", argv[arg])) {
1368 pidname = argv[arg++];
1370 else if(!strcmp(
"--logfile", argv[arg])) {
1375 else if(!strcmp(
"--ipv6", argv[arg])) {
1382 else if(!strcmp(
"--ipv4", argv[arg])) {
1390 else if(!strcmp(
"--bindonly", argv[arg])) {
1394 else if(!strcmp(
"--port", argv[arg])) {
1398 unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
1399 if((endptr != argv[arg] + strlen(argv[arg])) ||
1400 ((ulnum != 0UL) && ((ulnum < 1025UL) || (ulnum > 65535UL)))) {
1401 fprintf(stderr,
"sockfilt: invalid --port argument (%s)\n",
1409 else if(!strcmp(
"--connect", argv[arg])) {
1415 unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
1416 if((endptr != argv[arg] + strlen(argv[arg])) ||
1417 (ulnum < 1025UL) || (ulnum > 65535UL)) {
1418 fprintf(stderr,
"sockfilt: invalid --connect argument (%s)\n",
1426 else if(!strcmp(
"--addr", argv[arg])) {
1435 puts(
"Usage: sockfilt [option]\n" 1438 " --logfile [file]\n" 1439 " --pidfile [file]\n" 1444 " --connect [port]\n" 1445 " --addr [address]");
1464 sock = socket(AF_INET, SOCK_STREAM, 0);
1467 sock = socket(AF_INET6, SOCK_STREAM, 0);
1472 logmsg(
"Error creating socket: (%d) %s",
1473 error, strerror(error));
1475 goto sockfilt_cleanup;
1484 memset(&me.
sa4, 0,
sizeof(me.
sa4));
1485 me.
sa4.sin_family = AF_INET;
1487 me.
sa4.sin_addr.s_addr = INADDR_ANY;
1496 memset(&me.sa6, 0,
sizeof(me.sa6));
1497 me.sa6.sin6_family = AF_INET6;
1503 rc =
connect(sock, &me.
sa,
sizeof(me.sa6));
1508 logmsg(
"Error connecting to port %hu: (%d) %s",
1511 goto sockfilt_cleanup;
1513 logmsg(
"====> Client connect");
1521 goto sockfilt_cleanup;
1531 logmsg(
"Bound without listening on port %hu",
port);
1538 goto sockfilt_cleanup;
1542 juggle_again =
juggle(&msgsock, sock, &mode);
1543 }
while(juggle_again);
1568 logmsg(
"============> sockfilt quits");
static bool juggle(curl_socket_t *sockfdp, curl_socket_t listenfd, enum sockmode *mode)
static void lograw(unsigned char *buffer, ssize_t len)
static volatile int exit_signal
#define siginterrupt(x, y)
static unsigned short connectport
UNITTEST_START char * ptr
RETSIGTYPE(* SIGHANDLER_T)(int)
int write_pidfile(const char *filename)
static void install_signal_handlers(void)
static void restore_signal_handlers(void)
static bool read_stdin(void *buffer, size_t nbytes)
static void win32_cleanup(void)
static curl_socket_t sockdaemon(curl_socket_t sock, unsigned short *listenport)
unsigned short curlx_ultous(unsigned long ulnum)
static ssize_t fullwrite(int filedes, const void *buffer, size_t nbytes)
const char * serverlogfile
CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t
unsigned long curlx_uztoul(size_t uznum)
static const char * ipv_inuse
void logmsg(const char *msg,...)
UNITTEST_START struct Curl_easy data
static ssize_t fullread(int filedes, void *buffer, size_t nbytes)
static RETSIGTYPE exit_signal_handler(int signum)
int Curl_inet_pton(int af, const char *src, void *dst)
static unsigned short port
static CURLcode win32_init(void)
int main(int argc, char *argv[])
SIG_ATOMIC_T got_exit_signal
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
static CURL * handles[MAX_URLS]
static const char * pidname
static bool write_stdout(const void *buffer, size_t nbytes)