X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=jbsockets.c;h=556c927b1a5c1bf89370c04b7c0d5979ba2525d1;hp=d650dba13dcfbdb950c8224efa30b712c0c2b4ca;hb=f01eaeb9da2b04ba020c5630fb5ae9fb9d8e12f5;hpb=f1a1b6181f2803a8e72edf8e262e8817c7519fa4 diff --git a/jbsockets.c b/jbsockets.c index d650dba1..556c927b 100644 --- a/jbsockets.c +++ b/jbsockets.c @@ -1,15 +1,14 @@ -const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.119 2012/10/23 10:17:36 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jbsockets.c,v $ * * Purpose : Contains wrappers for system-specific sockets code, - * so that the rest of Junkbuster can be more + * so that the rest of Privoxy can be more * OS-independent. Contains #ifdefs to make this work * on many platforms. * - * Copyright : Written by and Copyright (C) 2001-2011 the - * Privoxy team. http://www.privoxy.org/ + * Copyright : Written by and Copyright (C) 2001-2017 the + * Privoxy team. https://www.privoxy.org/ * * Based on the Internet Junkbuster originally written * by and Copyright (C) 1997 Anonymous Coders and @@ -50,6 +49,7 @@ const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.119 2012/10/23 10:17:36 fabia #ifndef STRICT #define STRICT #endif +#include #include #include #include @@ -99,14 +99,13 @@ const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.119 2012/10/23 10:17:36 fabia #include "jbsockets.h" #include "filters.h" #include "errlog.h" +#include "miscutil.h" /* Mac OSX doesn't define AI_NUMERICSESRV */ #ifndef AI_NUMERICSERV #define AI_NUMERICSERV 0 #endif -const char jbsockets_h_rcs[] = JBSOCKETS_H_VERSION; - /* * Maximum number of gethostbyname(_r) retries in case of * soft errors (TRY_AGAIN). @@ -114,14 +113,40 @@ const char jbsockets_h_rcs[] = JBSOCKETS_H_VERSION; */ #define MAX_DNS_RETRIES 10 -#define MAX_LISTEN_BACKLOG 128 - #ifdef HAVE_RFC2553 static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client_state *csp); #else static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct client_state *csp); #endif +/********************************************************************* + * + * Function : set_no_delay_flag + * + * Description : Disables the Nagle algorithm (TCP send coalescence) + * for the given socket. + * + * Parameters : + * 1 : fd = The file descriptor to operate on + * + * Returns : void + * + *********************************************************************/ +static void set_no_delay_flag(int fd) +{ +#ifdef TCP_NODELAY + int mi = 1; + + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &mi, sizeof(int))) + { + log_error(LOG_LEVEL_ERROR, + "Failed to disable TCP coalescence for socket %d", fd); + } +#else +#warning set_no_delay_flag() is a nop due to lack of TCP_NODELAY +#endif /* def TCP_NODELAY */ +} + /********************************************************************* * * Function : connect_to @@ -131,7 +156,7 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli * * Parameters : * 1 : host = hostname to connect to - * 2 : portnum = port to connent on (XXX: should be unsigned) + * 2 : portnum = port to connect to (XXX: should be unsigned) * 3 : csp = Current client state (buffers, headers, etc...) * * Returns : JB_INVALID_SOCKET => failure, else it is the socket @@ -182,14 +207,18 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client char service[6]; int retval; jb_socket fd; +#ifdef HAVE_POLL + struct pollfd poll_fd[1]; +#else fd_set wfds; struct timeval timeout; -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#endif +#if !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__) int flags; #endif int connect_failed; /* - * XXX: Initializeing it here is only necessary + * XXX: Initializing it here is only necessary * because not all situations are properly * covered yet. */ @@ -232,14 +261,7 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client return(JB_INVALID_SOCKET); } - csp->http->host_ip_addr_str = malloc(NI_MAXHOST); - if (NULL == csp->http->host_ip_addr_str) - { - freeaddrinfo(result); - log_error(LOG_LEVEL_ERROR, - "Out of memory while getting the server IP address."); - return JB_INVALID_SOCKET; - } + csp->http->host_ip_addr_str = malloc_or_die(NI_MAXHOST); for (rp = result; rp != NULL; rp = rp->ai_next) { @@ -278,20 +300,33 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client continue; } -#ifdef TCP_NODELAY - { /* turn off TCP coalescence */ - int mi = 1; - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &mi, sizeof (int)); +#ifndef HAVE_POLL +#ifndef _WIN32 + if (fd >= FD_SETSIZE) + { + log_error(LOG_LEVEL_ERROR, + "Server socket number too high to use select(): %d >= %d", + fd, FD_SETSIZE); + close_socket(fd); + freeaddrinfo(result); + return JB_INVALID_SOCKET; } -#endif /* def TCP_NODELAY */ +#endif +#endif -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#ifdef FEATURE_EXTERNAL_FILTERS + mark_socket_for_close_on_execute(fd); +#endif + + set_no_delay_flag(fd); + +#if !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__) if ((flags = fcntl(fd, F_GETFL, 0)) != -1) { flags |= O_NDELAY; fcntl(fd, F_SETFL, flags); } -#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ +#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__) */ connect_failed = 0; while (connect(fd, rp->ai_addr, rp->ai_addrlen) == JB_INVALID_SOCKET) @@ -322,14 +357,39 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client continue; } -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#if !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__) if (flags != -1) { flags &= ~O_NDELAY; fcntl(fd, F_SETFL, flags); } -#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ +#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__) */ +#ifdef HAVE_POLL + poll_fd[0].fd = fd; + poll_fd[0].events = POLLOUT; + + retval = poll(poll_fd, 1, 30000); + if (retval == 0) + { + if (rp->ai_next != NULL) + { + /* Log this now as we'll try another address next */ + log_error(LOG_LEVEL_CONNECT, + "Could not connect to [%s]:%s: Operation timed out.", + csp->http->host_ip_addr_str, service); + } + else + { + /* + * This is the last address, don't log this now + * as it would result in a duplicated log message. + */ + socket_error = ETIMEDOUT; + } + } + else if (retval > 0) +#else /* wait for connection to complete */ FD_ZERO(&wfds); FD_SET(fd, &wfds); @@ -340,6 +400,7 @@ static jb_socket rfc2553_connect_to(const char *host, int portnum, struct client /* MS Windows uses int, not SOCKET, for the 1st arg of select(). Weird! */ if ((select((int)fd + 1, NULL, &wfds, NULL, &timeout) > 0) && FD_ISSET(fd, &wfds)) +#endif { socklen_t optlen = sizeof(socket_error); if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, &socket_error, &optlen)) @@ -397,9 +458,13 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli struct sockaddr_in inaddr; jb_socket fd; unsigned int addr; +#ifdef HAVE_POLL + struct pollfd poll_fd[1]; +#else fd_set wfds; struct timeval tv[1]; -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#endif +#if !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__) int flags; #endif @@ -460,20 +525,31 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli return(JB_INVALID_SOCKET); } -#ifdef TCP_NODELAY - { /* turn off TCP coalescence */ - int mi = 1; - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &mi, sizeof (int)); +#ifndef HAVE_POLL +#ifndef _WIN32 + if (fd >= FD_SETSIZE) + { + log_error(LOG_LEVEL_ERROR, + "Server socket number too high to use select(): %d >= %d", + fd, FD_SETSIZE); + close_socket(fd); + return JB_INVALID_SOCKET; } -#endif /* def TCP_NODELAY */ +#endif +#endif + + set_no_delay_flag(fd); -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#if !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__) if ((flags = fcntl(fd, F_GETFL, 0)) != -1) { flags |= O_NDELAY; fcntl(fd, F_SETFL, flags); +#ifdef FEATURE_EXTERNAL_FILTERS + mark_socket_for_close_on_execute(fd); +#endif } -#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ +#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__) */ while (connect(fd, (struct sockaddr *) & inaddr, sizeof inaddr) == JB_INVALID_SOCKET) { @@ -499,14 +575,20 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli } } -#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) +#if !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__) if (flags != -1) { flags &= ~O_NDELAY; fcntl(fd, F_SETFL, flags); } -#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ +#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__) */ +#ifdef HAVE_POLL + poll_fd[0].fd = fd; + poll_fd[0].events = POLLOUT; + + if (poll(poll_fd, 1, 30000) <= 0) +#else /* wait for connection to complete */ FD_ZERO(&wfds); FD_SET(fd, &wfds); @@ -516,6 +598,7 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli /* MS Windows uses int, not SOCKET, for the 1st arg of select(). Weird! */ if (select((int)fd + 1, NULL, &wfds, NULL, tv) <= 0) +#endif { close_socket(fd); return(JB_INVALID_SOCKET); @@ -541,22 +624,26 @@ static jb_socket no_rfc2553_connect_to(const char *host, int portnum, struct cli * nonzero on error. * *********************************************************************/ -#ifdef AMIGA -int write_socket(jb_socket fd, const char *buf, ssize_t len) -#else int write_socket(jb_socket fd, const char *buf, size_t len) -#endif { if (len == 0) { return 0; } +#ifdef FUZZ + if (!daemon_mode && fd <= 3) + { + log_error(LOG_LEVEL_WRITING, "Pretending to write to socket %d: %N", fd, len, buf); + return 0; + } +#endif + log_error(LOG_LEVEL_WRITING, "to socket %d: %N", fd, len, buf); #if defined(_WIN32) return (send(fd, buf, (int)len, 0) != (int)len); -#elif defined(__BEOS__) || defined(AMIGA) +#elif defined(__BEOS__) return (send(fd, buf, len, 0) != len); #elif defined(__OS2__) /* @@ -586,6 +673,60 @@ int write_socket(jb_socket fd, const char *buf, size_t len) } +/********************************************************************* + * + * Function : write_socket_delayed + * + * Description : Write the contents of buf (for n bytes) to + * socket fd, optionally delaying the operation. + * + * Parameters : + * 1 : fd = File descriptor (aka. handle) of socket to write to. + * 2 : buf = Pointer to data to be written. + * 3 : len = Length of data to be written to the socket "fd". + * 4 : delay = Delay in milliseconds. + * + * Returns : 0 on success (entire buffer sent). + * nonzero on error. + * + *********************************************************************/ +int write_socket_delayed(jb_socket fd, const char *buf, size_t len, unsigned int delay) +{ + size_t i = 0; + + if (delay == 0) + { + return write_socket(fd, buf, len); + } + + while (i < len) + { + size_t write_length; + enum {MAX_WRITE_LENGTH = 10}; + + if ((i + MAX_WRITE_LENGTH) > len) + { + write_length = len - i; + } + else + { + write_length = MAX_WRITE_LENGTH; + } + + privoxy_millisleep(delay); + + if (write_socket(fd, buf + i, write_length) != 0) + { + return 1; + } + i += write_length; + } + + return 0; + +} + + /********************************************************************* * * Function : read_socket @@ -622,7 +763,7 @@ int read_socket(jb_socket fd, char *buf, int len) #if defined(_WIN32) ret = recv(fd, buf, len, 0); -#elif defined(__BEOS__) || defined(AMIGA) || defined(__OS2__) +#elif defined(__BEOS__) || defined(__OS2__) ret = recv(fd, buf, (size_t)len, 0); #else ret = (int)read(fd, buf, (size_t)len); @@ -653,10 +794,18 @@ int read_socket(jb_socket fd, char *buf, int len) *********************************************************************/ int data_is_available(jb_socket fd, int seconds_to_wait) { + int n; char buf[10]; +#ifdef HAVE_POLL + struct pollfd poll_fd[1]; + + poll_fd[0].fd = fd; + poll_fd[0].events = POLLIN; + + n = poll(poll_fd, 1, seconds_to_wait * 1000); +#else fd_set rfds; struct timeval timeout; - int n; memset(&timeout, 0, sizeof(timeout)); timeout.tv_sec = seconds_to_wait; @@ -670,6 +819,7 @@ int data_is_available(jb_socket fd, int seconds_to_wait) FD_SET(fd, &rfds); n = select(fd+1, &rfds, NULL, NULL, &timeout); +#endif /* * XXX: Do we care about the different error conditions? @@ -694,8 +844,6 @@ void close_socket(jb_socket fd) { #if defined(_WIN32) || defined(__BEOS__) closesocket(fd); -#elif defined(AMIGA) - CloseSocket(fd); #elif defined(__OS2__) soclose(fd); #else @@ -786,14 +934,15 @@ void drain_and_close_socket(jb_socket fd) * Parameters : * 1 : hostnam = TCP/IP address to bind/listen to * 2 : portnum = port to listen on - * 3 : pfd = pointer used to return file descriptor. + * 3 : backlog = Listen backlog + * 4 : pfd = pointer used to return file descriptor. * * Returns : if success, returns 0 and sets *pfd. * if failure, returns -3 if address is in use, * -2 if address unresolvable, * -1 otherwise *********************************************************************/ -int bind_port(const char *hostnam, int portnum, jb_socket *pfd) +int bind_port(const char *hostnam, int portnum, int backlog, jb_socket *pfd) { #ifdef HAVE_RFC2553 struct addrinfo hints; @@ -899,6 +1048,10 @@ int bind_port(const char *hostnam, int portnum, jb_socket *pfd) #endif } +#ifdef FEATURE_EXTERNAL_FILTERS + mark_socket_for_close_on_execute(fd); +#endif + #ifndef _WIN32 /* * This is not needed for Win32 - in fact, it stops @@ -915,6 +1068,10 @@ int bind_port(const char *hostnam, int portnum, jb_socket *pfd) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)); #endif /* ndef _WIN32 */ +#ifdef IP_FREEBIND + setsockopt(fd, IPPROTO_IP, IP_FREEBIND, (char *)&one, sizeof(one)); +#endif + #ifdef HAVE_RFC2553 if (bind(fd, rp->ai_addr, rp->ai_addrlen) < 0) #else @@ -964,10 +1121,11 @@ int bind_port(const char *hostnam, int portnum, jb_socket *pfd) } #endif /* ndef HAVE_RFC2553 */ - while (listen(fd, MAX_LISTEN_BACKLOG) == -1) + while (listen(fd, backlog) == -1) { if (errno != EINTR) { + close_socket(fd); return(-1); } } @@ -1012,7 +1170,7 @@ void get_host_information(jb_socket afd, char **ip_address, char **port, struct sockaddr_in server; struct hostent *host = NULL; #endif /* HAVE_RFC2553 */ -#if defined(_WIN32) || defined(__OS2__) || defined(__APPLE_CC__) || defined(AMIGA) +#if defined(_WIN32) || defined(__OS2__) /* according to accept_connection() this fixes a warning. */ int s_length, s_length_provided; #else @@ -1050,27 +1208,15 @@ void get_host_information(jb_socket afd, char **ip_address, char **port, * configured with --disable-ipv6-support. * The proper fix is to not use NI_MAXSERV in * that case. It works by accident on other platforms - * as in included unconditionally there. + * as is included unconditionally there. */ #ifndef NI_MAXSERV #define NI_MAXSERV 32 #endif - *port = malloc(NI_MAXSERV); - if (NULL == *port) - { - log_error(LOG_LEVEL_ERROR, - "Out of memory while getting the client's port."); - return; - } + *port = malloc_or_die(NI_MAXSERV); + #ifdef HAVE_RFC2553 - *ip_address = malloc(NI_MAXHOST); - if (NULL == *ip_address) - { - log_error(LOG_LEVEL_ERROR, - "Out of memory while getting the client's IP address."); - freez(*port); - return; - } + *ip_address = malloc_or_die(NI_MAXHOST); retval = getnameinfo((struct sockaddr *) &server, s_length, *ip_address, NI_MAXHOST, *port, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV); @@ -1096,13 +1242,7 @@ void get_host_information(jb_socket afd, char **ip_address, char **port, } #ifdef HAVE_RFC2553 - *hostname = malloc(NI_MAXHOST); - if (NULL == *hostname) - { - log_error(LOG_LEVEL_ERROR, - "Out of memory while getting the client's hostname."); - return; - } + *hostname = malloc_or_die(NI_MAXHOST); retval = getnameinfo((struct sockaddr *) &server, s_length, *hostname, NI_MAXHOST, NULL, 0, NI_NAMEREQD); if (retval) @@ -1182,8 +1322,8 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) struct sockaddr_in client; #endif jb_socket afd; -#if defined(_WIN32) || defined(__OS2__) || defined(__APPLE_CC__) || defined(AMIGA) - /* Wierdness - fix a warning. */ +#if defined(_WIN32) || defined(__OS2__) + /* Weirdness - fix a warning. */ int c_length; #else socklen_t c_length; @@ -1191,23 +1331,41 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) int retval; int i; int max_selected_socket; +#ifdef HAVE_POLL + struct pollfd poll_fds[MAX_LISTENING_SOCKETS]; + nfds_t polled_sockets; +#else fd_set selected_fds; +#endif jb_socket fd; + const char *host_addr; + size_t listen_addr_size; c_length = sizeof(client); +#ifdef HAVE_POLL + memset(poll_fds, 0, sizeof(poll_fds)); + polled_sockets = 0; +#else /* * Wait for a connection on any socket. * Return immediately if no socket is listening. * XXX: Why not treat this as fatal error? */ FD_ZERO(&selected_fds); +#endif max_selected_socket = 0; for (i = 0; i < MAX_LISTENING_SOCKETS; i++) { if (JB_INVALID_SOCKET != fds[i]) { +#ifdef HAVE_POLL + poll_fds[i].fd = fds[i]; + poll_fds[i].events = POLLIN; + polled_sockets++; +#else FD_SET(fds[i], &selected_fds); +#endif if (max_selected_socket < fds[i] + 1) { max_selected_socket = fds[i] + 1; @@ -1220,7 +1378,11 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) } do { +#ifdef HAVE_POLL + retval = poll(poll_fds, polled_sockets, -1); +#else retval = select(max_selected_socket, &selected_fds, NULL, NULL, NULL); +#endif } while (retval < 0 && errno == EINTR); if (retval <= 0) { @@ -1238,8 +1400,12 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) } return 0; } +#ifdef HAVE_POLL + for (i = 0; i < MAX_LISTENING_SOCKETS && (poll_fds[i].revents == 0); i++); +#else for (i = 0; i < MAX_LISTENING_SOCKETS && !FD_ISSET(fds[i], &selected_fds); i++); +#endif if (i >= MAX_LISTENING_SOCKETS) { log_error(LOG_LEVEL_ERROR, @@ -1260,14 +1426,8 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) #else do { -#if defined(FEATURE_ACCEPT_FILTER) && defined(SO_ACCEPTFILTER) - struct accept_filter_arg af_options; - bzero(&af_options, sizeof(af_options)); - strlcpy(af_options.af_name, "httpready", sizeof(af_options.af_name)); - setsockopt(fd, SOL_SOCKET, SO_ACCEPTFILTER, &af_options, sizeof(af_options)); -#endif afd = accept (fd, (struct sockaddr *) &client, &c_length); - } while (afd < 1 && errno == EINTR); + } while (afd < 0 && errno == EINTR); if (afd < 0) { return 0; @@ -1279,22 +1439,35 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) struct linger linger_options; linger_options.l_onoff = 1; linger_options.l_linger = 5; - if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger_options, sizeof(linger_options))) + if (0 != setsockopt(afd, SOL_SOCKET, SO_LINGER, &linger_options, sizeof(linger_options))) { log_error(LOG_LEVEL_ERROR, "Setting SO_LINGER on socket %d failed.", afd); } } #endif - csp->cfd = afd; -#ifdef HAVE_RFC2553 - csp->ip_addr_str = malloc(NI_MAXHOST); - if (NULL == csp->ip_addr_str) +#ifndef HAVE_POLL +#ifndef _WIN32 + if (afd >= FD_SETSIZE) { log_error(LOG_LEVEL_ERROR, - "Out of memory while getting the client's IP address."); + "Client socket number too high to use select(): %d >= %d", + afd, FD_SETSIZE); + close_socket(afd); return 0; } +#endif +#endif + +#ifdef FEATURE_EXTERNAL_FILTERS + mark_socket_for_close_on_execute(afd); +#endif + + set_no_delay_flag(afd); + + csp->cfd = afd; +#ifdef HAVE_RFC2553 + csp->ip_addr_str = malloc_or_die(NI_MAXHOST); retval = getnameinfo((struct sockaddr *) &client, c_length, csp->ip_addr_str, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (!csp->ip_addr_str || retval) @@ -1309,6 +1482,26 @@ int accept_connection(struct client_state * csp, jb_socket fds[]) csp->ip_addr_long = ntohl(client.sin_addr.s_addr); #endif /* def HAVE_RFC2553 */ + /* + * Save the name and port of the accepting socket for later lookup. + * + * The string needs space for strlen(...) + 7 characters: + * strlen(haddr[i]) + 1 (':') + 5 (port digits) + 1 ('\0') + */ + host_addr = (csp->config->haddr[i] != NULL) ? csp->config->haddr[i] : ""; + listen_addr_size = strlen(host_addr) + 7; + csp->listen_addr_str = malloc_or_die(listen_addr_size); + retval = snprintf(csp->listen_addr_str, listen_addr_size, + "%s:%d", host_addr, csp->config->hport[i]); + if ((-1 == retval) || listen_addr_size <= retval) + { + log_error(LOG_LEVEL_ERROR, + "Server name (%s) and port number (%d) ASCII decimal representation" + "don't fit into %d bytes", + host_addr, csp->config->hport[i], listen_addr_size); + return 0; + } + return 1; } @@ -1446,7 +1639,6 @@ int socket_is_still_alive(jb_socket sfd) { char buf[10]; int no_data_waiting; - #ifdef HAVE_POLL int poll_result; struct pollfd poll_fd[1]; @@ -1485,6 +1677,42 @@ int socket_is_still_alive(jb_socket sfd) } +#ifdef FEATURE_EXTERNAL_FILTERS +/********************************************************************* + * + * Function : mark_socket_for_close_on_execute + * + * Description : Marks a socket for close on execute. + * + * Used so that external filters have no direct + * access to sockets they shouldn't care about. + * + * Not implemented for all platforms. + * + * Parameters : + * 1 : fd = The socket to mark + * + * Returns : void. + * + *********************************************************************/ +void mark_socket_for_close_on_execute(jb_socket fd) +{ +#ifdef FEATURE_PTHREAD + int ret; + + ret = fcntl(fd, F_SETFD, FD_CLOEXEC); + + if (ret == -1) + { + log_error(LOG_LEVEL_ERROR, + "fcntl(%d, F_SETFD, FD_CLOEXEC) failed", fd); + } +#else +#warning "Sockets will be visible to external filters" +#endif +} +#endif /* def FEATURE_EXTERNAL_FILTERS */ + /* Local Variables: tab-width: 3