------------------------------------------------------------------------ r25227 | shinnok | 2011-07-23 00:35:23 +0300 (Sat, 23 Jul 2011) | 6 lines Merge /nmap-exp/shinnok/ncat-sslhang branch into trunk ncat. This fixes issues with Ncat blocking while an ssl handshake is taking place or waiting to complete. ------------------------------------------------------------------------ Index: ncat_listen.c =================================================================== --- ncat_listen.c (revision 25226) +++ ncat_listen.c (revision 25227) @@ -114,11 +114,20 @@ /* read_fds is the clients we are accepting data from. broadcast_fds is the clients were are sending data to. broadcast_fds doesn't include the listening socket and stdin. Network clients are not added to read_fds when --send-only - is used, because they would be always selected without having data read. */ -static fd_set read_fds, broadcast_fds; + is used, because they would be always selected without having data read. + write_fds is the list of clients that are waiting for some kind of response + from us, like a pending ssl negotiation. */ +static fd_set master_readfds, master_writefds, master_broadcastfds; +#ifdef HAVE_OPENSSL +/* sslpending_fds containts the list of ssl sockets that are waiting to complete + the ssl handshake */ +static fd_set sslpending_fds; +#endif + /* These are bookkeeping data structures that are parallel to read_fds and broadcast_fds. */ -static fd_list_t read_fdlist, broadcast_fdlist; +static fd_list_t client_fdlist, broadcast_fdlist; + static int listen_socket[NUM_LISTEN_ADDRS]; /* Has stdin seen EOF? */ static int stdin_eof = 0; @@ -127,6 +136,7 @@ static void handle_connection(int socket_accept); static int read_stdin(void); static int read_socket(int recv_fd); +static void post_handle_connection(struct fdinfo sinfo); /* The number of connected clients is the difference of conn_inc and conn_dec. It is split up into two variables for signal safety. conn_dec is modified @@ -174,10 +184,14 @@ #endif /* clear out structs */ - FD_ZERO(&read_fds); - FD_ZERO(&broadcast_fds); + FD_ZERO(&master_readfds); + FD_ZERO(&master_writefds); + FD_ZERO(&master_broadcastfds); FD_ZERO(&listen_fds); - zmem(&read_fdlist, sizeof(read_fdlist)); +#ifdef HAVE_OPENSSL + FD_ZERO(&sslpending_fds); +#endif + zmem(&client_fdlist, sizeof(client_fdlist)); zmem(&broadcast_fdlist, sizeof(broadcast_fdlist)); #ifdef WIN32 @@ -198,7 +212,7 @@ /* We need a list of fds to keep current fdmax. The second parameter is a number added to the supplied connection limit, that will compensate maxfds for the added by default listen and stdin sockets. */ - init_fdlist(&read_fdlist, sadd(o.conn_limit, num_listenaddrs + 1)); + init_fdlist(&client_fdlist, sadd(o.conn_limit, num_listenaddrs + 1)); for (i = 0; i < NUM_LISTEN_ADDRS; i++) listen_socket[i] = -1; @@ -214,23 +228,25 @@ unblock_socket(listen_socket[i]); /* setup select sets and max fd */ - FD_SET(listen_socket[i], &read_fds); - add_fd(&read_fdlist, listen_socket[i]); + FD_SET(listen_socket[i], &master_readfds); + add_fd(&client_fdlist, listen_socket[i]); FD_SET(listen_socket[i], &listen_fds); } - add_fd(&read_fdlist, STDIN_FILENO); + add_fd(&client_fdlist, STDIN_FILENO); init_fdlist(&broadcast_fdlist, o.conn_limit); while (1) { - fd_set fds; + /* We pass these temporary descriptor sets to fselect, since fselect + modifies the sets it receives. */ + fd_set readfds = master_readfds, writefds = master_writefds; + struct fdinfo *fdi = NULL; if (o.debug > 1) - logdebug("selecting, fdmax %d\n", read_fdlist.fdmax); + logdebug("selecting, fdmax %d\n", client_fdlist.fdmax); - fds = read_fds; - fds_ready = fselect(read_fdlist.fdmax + 1, &fds, NULL, NULL, NULL); + fds_ready = fselect(client_fdlist.fdmax + 1, &readfds, &writefds, NULL, NULL); if (o.debug > 1) logdebug("select returned %d fds ready\n", fds_ready); @@ -241,14 +257,48 @@ * large, say 500, and none close to it, that you'll loop many times for * nothing. */ - for (i = 0; i <= read_fdlist.fdmax && fds_ready > 0; i++) { + for (i = 0; i <= client_fdlist.fdmax && fds_ready > 0; i++) { /* Loop through descriptors until there's something to read */ - if (!FD_ISSET(i, &fds)) + if (!FD_ISSET(i, &readfds) && !FD_ISSET(i, &writefds)) continue; if (o.debug > 1) logdebug("fd %d is ready\n", i); +#ifdef HAVE_OPENSSL + /* Is this an ssl socket pending a handshake? If so handle it. */ + if (o.ssl && FD_ISSET(i, &sslpending_fds)) { + FD_CLR(i, &master_readfds); + FD_CLR(i, &master_writefds); + fdi = get_fdinfo(&client_fdlist, i); + switch(ssl_handshake(fdi)){ + case NCAT_SSL_HANDSHAKE_COMPLETED: + /* Clear from sslpending_fds once ssl is established */ + FD_CLR(i, &sslpending_fds); + rm_fd(&client_fdlist, i); + post_handle_connection(*fdi); + break; + case NCAT_SSL_HANDSHAKE_PENDING_WRITE: + FD_SET(i, &master_writefds); + break; + case NCAT_SSL_HANDSHAKE_PENDING_READ: + FD_SET(i, &master_readfds); + break; + case NCAT_SSL_HANDSHAKE_FAILED: + default: + SSL_free(fdi->ssl); + Close(fdi->fd); + FD_CLR(i, &sslpending_fds); + FD_CLR(i, &master_readfds); + rm_fd(&client_fdlist, i); + /* Are we in single listening mode(without -k)? If so + then we should quit also. */ + if (!o.keepopen) + return 1; + break; + } + } else +#endif if (FD_ISSET(i, &listen_fds)) { /* we have a new connection request */ handle_connection(i); @@ -285,6 +335,8 @@ struct fdinfo s = { 0 }; int conn_count; + zmem(&s, sizeof(s)); + ss_len = sizeof(remoteaddr.storage); errno = 0; s.fd = accept(socket_accept, &remoteaddr.sockaddr, &ss_len); @@ -301,8 +353,8 @@ int i; for (i = 0; i < num_listenaddrs; i++) { Close(listen_socket[i]); - FD_CLR(listen_socket[i], &read_fds); - rm_fd(&read_fdlist, listen_socket[i]); + FD_CLR(listen_socket[i], &master_readfds); + rm_fd(&client_fdlist, listen_socket[i]); } } @@ -324,50 +376,52 @@ return; } - /* On Linux the new socket will be blocking, but on BSD it inherits the - non-blocking status of the listening socket. The socket must be blocking - for operations like SSL_accept to work in the way that we use them. */ - block_socket(s.fd); + s.remoteaddr = remoteaddr; -#ifdef HAVE_OPENSSL + conn_inc++; + + unblock_socket(s.fd); + + #ifdef HAVE_OPENSSL if (o.ssl) { - s.ssl = new_ssl(s.fd); - if (SSL_accept(s.ssl) != 1) { - if (o.verbose) { - loguser("Failed SSL connection from %s: %s\n", - inet_socktop(&remoteaddr), ERR_error_string(ERR_get_error(), NULL)); - } - SSL_free(s.ssl); - Close(s.fd); - return; - } - } -#endif + /* Add the socket to the necessary descriptor lists. */ + FD_SET(s.fd, &sslpending_fds); + FD_SET(s.fd, &master_readfds); + FD_SET(s.fd, &master_writefds); + /* Add it to our list of fds too for maintaining maxfd. */ + if (add_fdinfo(&client_fdlist, &s) < 0) + bye("add_fdinfo() failed."); + } else + #endif + post_handle_connection(s); +} - conn_inc++; - +/* This function handles the post connection specific actions that are needed + * after a socket has been initialized(normal socket or ssl socket). */ +static void post_handle_connection(struct fdinfo sinfo) +{ /* - * are we executing a command? if so then don't add this guy + * Are we executing a command? If so then don't add this guy * to our descriptor list or set. */ if (o.cmdexec) { if (o.keepopen) - netrun(&s, o.cmdexec); + netrun(&sinfo, o.cmdexec); else - netexec(&s, o.cmdexec); + netexec(&sinfo, o.cmdexec); } else { /* Now that a client is connected, pay attention to stdin. */ if (!stdin_eof) - FD_SET(STDIN_FILENO, &read_fds); + FD_SET(STDIN_FILENO, &master_readfds); if (!o.sendonly) { /* add to our lists */ - FD_SET(s.fd, &read_fds); + FD_SET(sinfo.fd, &master_readfds); /* add it to our list of fds for maintaining maxfd */ - if (add_fdinfo(&read_fdlist, &s) < 0) + if (add_fdinfo(&client_fdlist, &sinfo) < 0) bye("add_fdinfo() failed."); } - FD_SET(s.fd, &broadcast_fds); - if (add_fdinfo(&broadcast_fdlist, &s) < 0) + FD_SET(sinfo.fd, &master_broadcastfds); + if (add_fdinfo(&broadcast_fdlist, &sinfo) < 0) bye("add_fdinfo() failed."); } } @@ -388,7 +442,7 @@ logdebug("EOF on stdin\n"); /* Don't close the file because that allows a socket to be fd 0. */ - FD_CLR(STDIN_FILENO, &read_fds); + FD_CLR(STDIN_FILENO, &master_readfds); /* Buf mark that we've seen EOF so it doesn't get re-added to the select list. */ stdin_eof = 1; @@ -404,11 +458,11 @@ /* Write to everything in the broadcast set. */ if (tempbuf != NULL) { - ncat_broadcast(&broadcast_fds, &broadcast_fdlist, tempbuf, nbytes); + ncat_broadcast(&master_broadcastfds, &broadcast_fdlist, tempbuf, nbytes); free(tempbuf); tempbuf = NULL; } else { - ncat_broadcast(&broadcast_fds, &broadcast_fdlist, buf, nbytes); + ncat_broadcast(&master_broadcastfds, &broadcast_fdlist, buf, nbytes); } return nbytes; @@ -422,7 +476,7 @@ struct fdinfo *fdn; int nbytes, pending; - fdn = get_fdinfo(&read_fdlist, recv_fd); + fdn = get_fdinfo(&client_fdlist, recv_fd); assert(fdn != NULL); nbytes = 0; @@ -441,14 +495,14 @@ } #endif close(recv_fd); - FD_CLR(recv_fd, &read_fds); - rm_fd(&read_fdlist, recv_fd); - FD_CLR(recv_fd, &broadcast_fds); + FD_CLR(recv_fd, &master_readfds); + rm_fd(&client_fdlist, recv_fd); + FD_CLR(recv_fd, &master_broadcastfds); rm_fd(&broadcast_fdlist, recv_fd); conn_inc--; if (get_conn_count() == 0) - FD_CLR(STDIN_FILENO, &read_fds); + FD_CLR(STDIN_FILENO, &master_readfds); return n; } Index: ncat_ssl.c =================================================================== --- ncat_ssl.c (revision 25226) +++ ncat_ssl.c (revision 25227) @@ -559,6 +559,51 @@ return strbuf; } + +/* Tries to complete an ssl handshake on the socket received by fdinfo struct + if ssl is enabled on that socket. */ + +int ssl_handshake(struct fdinfo *sinfo) +{ + int ret = 0; + int sslerr = 0; + + if(sinfo == NULL) { + if (o.debug) + logdebug("ncat_ssl.c: Invoking ssl_handshake() with a NULL parameter " + "is a serious bug. Please fix it.\n"); + return -1; + } + + if(!o.ssl) + return -1; + + /* Initialize the socket too if it isn't. */ + if(!sinfo->ssl) + sinfo->ssl = new_ssl(sinfo->fd); + + ret = SSL_accept(sinfo->ssl); + + if(ret == 1) + return NCAT_SSL_HANDSHAKE_COMPLETED; + + sslerr = SSL_get_error(sinfo->ssl, ret); + + if(ret == -1) { + if(sslerr == SSL_ERROR_WANT_READ) + return NCAT_SSL_HANDSHAKE_PENDING_READ; + if(sslerr == SSL_ERROR_WANT_WRITE) + return NCAT_SSL_HANDSHAKE_PENDING_WRITE; + } + + if (o.verbose) { + loguser("Failed SSL connection from %s: %s\n", + inet_socktop(&sinfo->remoteaddr), + ERR_error_string(ERR_get_error(), NULL)); + } + return NCAT_SSL_HANDSHAKE_FAILED; +} + #endif Index: ncat_ssl.h =================================================================== --- ncat_ssl.h (revision 25226) +++ ncat_ssl.h (revision 25227) @@ -101,6 +101,15 @@ SHA1_STRING_LENGTH = SHA1_BYTES * 2 + (SHA1_BYTES / 2 - 1) }; +/* These status variables are returned by ssl_handshake() to describe the + * status of a pending non-blocking ssl handshake(SSL_accept()). */ +enum { + NCAT_SSL_HANDSHAKE_COMPLETED = 0, + NCAT_SSL_HANDSHAKE_PENDING_READ = 1, + NCAT_SSL_HANDSHAKE_PENDING_WRITE = 2, + NCAT_SSL_HANDSHAKE_FAILED = 3 +}; + extern SSL_CTX *setup_ssl_listen(void); extern SSL *new_ssl(int fd); @@ -111,4 +120,9 @@ extern int ssl_load_default_ca_certs(SSL_CTX *ctx); +/* Try to complete an ssl handshake in a non-blocking way for the socket given + * in sinfo. Initialize the socket too with new_ssl() if it hasn't been done + * already. */ +extern int ssl_handshake(struct fdinfo *sinfo); + #endif Index: util.h =================================================================== --- util.h (revision 25226) +++ util.h (revision 25227) @@ -150,6 +150,7 @@ struct fdinfo { int fd; + union sockaddr_u remoteaddr; #ifdef HAVE_OPENSSL SSL *ssl; #endif Index: test/ncat-test.pl =================================================================== --- test/ncat-test.pl (revision 25226) +++ test/ncat-test.pl (revision 25227) @@ -731,13 +731,16 @@ # Server immediately quits after the first connection ssl negotiation fails without --keep-open { -local $xfail = 1; ($s_pid, $s_out, $s_in) = ncat_server("--ssl"); test "Server quits after a failed ssl negotiation without --keep-open", sub { my $resp; - my ($c_pid, $c_out, $c_in) = ncat_client(""); + # Let's sleep for one second here, since in some cases the server might not + # get the chance to start listening before the client tries to connect. + sleep 1; + + my ($c_pid, $c_out, $c_in) = ncat_client(); syswrite($c_in, "abc\n"); kill "TERM", $c_pid; @@ -2106,8 +2109,7 @@ kill_children; { -local $xfail = 1; -($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem", "--keep-open"); +($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem"); test "SSL server doesn't block during handshake", sub { my $resp; @@ -2118,13 +2120,28 @@ my ($c2_pid, $c2_out, $c2_in) = ncat_client("--ssl"); syswrite($c2_in, "abc\n"); $resp = timeout_read($s_out); - $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\""; + !$resp or die "Server is still accepting connections."; }; kill_children; } { -local $xfail = 1; +($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem", "--keep-open"); +test "SSL server doesn't block during handshake(--keep-open)", +sub { + my $resp; + + # Connect without SSL so the handshake isn't completed. + my ($c1_pid, $c1_out, $c1_in) = ncat_client(); + + my ($c2_pid, $c2_out, $c2_in) = ncat_client("--ssl"); + syswrite($c2_in, "abc\n"); + $resp = timeout_read($s_out); + $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\""; +}; +kill_children; +} +{ ($s_pid, $s_out, $s_in) = ncat_server("--ssl", "--exec","/usr/bin/perl -e \$|=1;while(<>){tr/a-z/A-Z/;print}", "--ssl-key", "test-cert.pem", "--ssl-cert", "test-cert.pem", "--keep-open"); test "SSL --exec server doesn't block during handshake", sub { Property changes on: test/ncat-test.pl ___________________________________________________________________ Deleted: svn:mergeinfo Index: ncat_broker.c =================================================================== --- ncat_broker.c (revision 25226) +++ ncat_broker.c (revision 25227) @@ -114,11 +114,19 @@ /* read_fds is the clients we are accepting data from. broadcast_fds is the clients were are sending data to. broadcast_fds doesn't include the listening socket and stdin. Network clients are not added to read_fds when --send-only - is used, because they would be always selected without having data read. */ -static fd_set read_fds, broadcast_fds; + is used, because they would be always selected without having data read. + write_fds is the list of clients that are waiting for some kind of response + from us, like a pending ssl negotiation. */ +static fd_set master_readfds, master_writefds, master_broadcastfds; +#ifdef HAVE_OPENSSL +/* sslpending_fds containts the list of ssl sockets that are waiting to complete + the ssl handshake */ +static fd_set sslpending_fds; +#endif + /* These are bookkeeping data structures that are parallel to read_fds and broadcast_fds. */ -static fd_list_t read_fdlist, broadcast_fdlist; +static fd_list_t client_fdlist, broadcast_fdlist; static int listen_socket[NUM_LISTEN_ADDRS]; static int conn_count = 0; /* Has stdin seen EOF? */ @@ -126,6 +134,7 @@ static int crlf_state = 0; static void handle_connection(int listen_sock); +static void post_handle_connection(struct fdinfo sinfo); static void read_and_broadcast(int recv_socket); static int chat_announce_connect(int fd, const union sockaddr_u *su); static int chat_announce_disconnect(int fd); @@ -139,10 +148,13 @@ #endif /* clear out structs */ - FD_ZERO(&read_fds); - FD_ZERO(&broadcast_fds); + FD_ZERO(&master_readfds); + FD_ZERO(&master_broadcastfds); FD_ZERO(&listen_fds); - zmem(&read_fdlist, sizeof(read_fdlist)); +#ifdef HAVE_OPENSSL + FD_ZERO(&sslpending_fds); +#endif + zmem(&client_fdlist, sizeof(client_fdlist)); zmem(&broadcast_fdlist, sizeof(broadcast_fdlist)); int i; @@ -161,7 +173,7 @@ #endif /* we need a list of fds to keep current fdmax */ - init_fdlist(&read_fdlist, sadd(o.conn_limit, num_listenaddrs + 1)); + init_fdlist(&client_fdlist, sadd(o.conn_limit, num_listenaddrs + 1)); for (i = 0; i < num_listenaddrs; i++) { /* setup the main listening socket */ @@ -174,25 +186,27 @@ unblock_socket(listen_socket[i]); /* setup select sets and max fd */ - FD_SET(listen_socket[i], &read_fds); - add_fd(&read_fdlist, listen_socket[i]); + FD_SET(listen_socket[i], &master_readfds); + add_fd(&client_fdlist, listen_socket[i]); FD_SET(listen_socket[i], &listen_fds); }; - add_fd(&read_fdlist, STDIN_FILENO); + add_fd(&client_fdlist, STDIN_FILENO); init_fdlist(&broadcast_fdlist, o.conn_limit); while (1) { - fd_set fds; + /* We pass these temporary descriptor sets to fselect, since fselect + modifies the sets it receives. */ + fd_set readfds = master_readfds, writefds = master_writefds; int i, fds_ready; + struct fdinfo *fdi = NULL; if (o.debug > 1) logdebug("Broker connection count is %d\n", conn_count); - fds = read_fds; - fds_ready = fselect(read_fdlist.fdmax + 1, &fds, NULL, NULL, NULL); + fds_ready = fselect(client_fdlist.fdmax + 1, &readfds, &writefds, NULL, NULL); if (o.debug > 1) logdebug("select returned %d fds ready\n", fds_ready); @@ -203,14 +217,44 @@ * large, say 500, and none close to it, that you'll loop many times for * nothing. */ - for (i = 0; i <= read_fdlist.fdmax && fds_ready > 0; i++) { + for (i = 0; i <= client_fdlist.fdmax && fds_ready > 0; i++) { /* Loop through descriptors until there's something to read */ - if (!FD_ISSET(i, &fds)) + if (!FD_ISSET(i, &readfds) && !FD_ISSET(i, &writefds)) continue; if (o.debug > 1) logdebug("fd %d is ready\n", i); +#ifdef HAVE_OPENSSL + /* Is this an ssl socket pending a handshake? If so handle it. */ + if (o.ssl && FD_ISSET(i, &sslpending_fds)) { + FD_CLR(i, &master_readfds); + FD_CLR(i, &master_writefds); + fdi = get_fdinfo(&client_fdlist, i); + switch(ssl_handshake(fdi)){ + case NCAT_SSL_HANDSHAKE_COMPLETED: + /* Clear from sslpending_fds once ssl is established */ + FD_CLR(i, &sslpending_fds); + rm_fd(&client_fdlist, i); + post_handle_connection(*fdi); + break; + case NCAT_SSL_HANDSHAKE_PENDING_WRITE: + FD_SET(i, &master_writefds); + break; + case NCAT_SSL_HANDSHAKE_PENDING_READ: + FD_SET(i, &master_readfds); + break; + case NCAT_SSL_HANDSHAKE_FAILED: + default: + SSL_free(fdi->ssl); + Close(fdi->fd); + FD_CLR(i, &sslpending_fds); + FD_CLR(i, &master_readfds); + rm_fd(&client_fdlist, i); + break; + } + } else +#endif if (FD_ISSET(i, &listen_fds)) { /* we have a new connection request */ handle_connection(i); @@ -234,6 +278,8 @@ socklen_t ss_len; struct fdinfo s = { 0 }; + zmem(&s, sizeof(s)); + ss_len = sizeof(remoteaddr.storage); errno = 0; s.fd = accept(listen_sock, &remoteaddr.sockaddr, &ss_len); @@ -267,44 +313,46 @@ return; } - /* On Linux the new socket will be blocking, but on BSD it inherits the - non-blocking status of the listening socket. The socket must be blocking - for operations like SSL_accept to work in the way that we use them. */ - block_socket(s.fd); + s.remoteaddr = remoteaddr; + conn_count++; + + unblock_socket(s.fd); + #ifdef HAVE_OPENSSL - if (o.ssl) { - s.ssl = new_ssl(s.fd); - if (SSL_accept(s.ssl) != 1) { - if (o.verbose) { - loguser("Failed SSL connection from %s: %s\n", - inet_socktop(&remoteaddr), ERR_error_string(ERR_get_error(), NULL)); - } - SSL_free(s.ssl); - Close(s.fd); - return; - } - } + if (o.ssl) { + /* Add the socket to the necessary descriptor lists. */ + FD_SET(s.fd, &sslpending_fds); + FD_SET(s.fd, &master_readfds); + FD_SET(s.fd, &master_writefds); + /* Add it to our list of fds too for maintaining maxfd. */ + if (add_fdinfo(&client_fdlist, &s) < 0) + bye("add_fdinfo() failed."); + } else #endif + post_handle_connection(s); +} - conn_count++; - +/* This function handles the post connection specific actions that are needed + * after a socket has been initialized(normal socket or ssl socket). */ +static void post_handle_connection(struct fdinfo sinfo) +{ /* Now that a client is connected, pay attention to stdin. */ if (!stdin_eof) - FD_SET(STDIN_FILENO, &read_fds); + FD_SET(STDIN_FILENO, &master_readfds); if (!o.sendonly) { /* add to our lists */ - FD_SET(s.fd, &read_fds); + FD_SET(sinfo.fd, &master_readfds); /* add it to our list of fds for maintaining maxfd */ - if (add_fdinfo(&read_fdlist, &s) < 0) + if (add_fdinfo(&client_fdlist, &sinfo) < 0) bye("add_fdinfo() failed."); } - FD_SET(s.fd, &broadcast_fds); - if (add_fdinfo(&broadcast_fdlist, &s) < 0) + FD_SET(sinfo.fd, &master_broadcastfds); + if (add_fdinfo(&broadcast_fdlist, &sinfo) < 0) bye("add_fdinfo() failed."); if (o.chat) - chat_announce_connect(s.fd, &remoteaddr); + chat_announce_connect(sinfo.fd, &sinfo.remoteaddr); } /* Read from recv_fd and broadcast whatever is read to all other descriptors in @@ -316,7 +364,7 @@ struct fdinfo *fdn; int pending; - fdn = get_fdinfo(&read_fdlist, recv_fd); + fdn = get_fdinfo(&client_fdlist, recv_fd); assert(fdn); /* Loop while ncat_recv indicates data is pending. */ @@ -324,7 +372,7 @@ char buf[DEFAULT_TCP_BUF_LEN]; char *chatbuf, *outbuf; char *tempbuf = NULL; - fd_set fds; + fd_set broadcastfds; int n; /* Behavior differs depending on whether this is stdin or a socket. */ @@ -338,7 +386,7 @@ /* Don't close the file because that allows a socket to be fd 0. */ - FD_CLR(recv_fd, &read_fds); + FD_CLR(recv_fd, &master_readfds); /* But mark that we've seen EOF so it doesn't get re-added to the select list. */ stdin_eof = 1; @@ -365,14 +413,14 @@ } #endif close(recv_fd); - FD_CLR(recv_fd, &read_fds); - rm_fd(&read_fdlist, recv_fd); - FD_CLR(recv_fd, &broadcast_fds); + FD_CLR(recv_fd, &master_readfds); + rm_fd(&client_fdlist, recv_fd); + FD_CLR(recv_fd, &master_broadcastfds); rm_fd(&broadcast_fdlist, recv_fd); conn_count--; if (conn_count == 0) - FD_CLR(STDIN_FILENO, &read_fds); + FD_CLR(STDIN_FILENO, &master_readfds); if (o.chat) chat_announce_disconnect(recv_fd); @@ -402,9 +450,9 @@ } /* Send to everyone except the one who sent this message. */ - fds = broadcast_fds; - FD_CLR(recv_fd, &fds); - ncat_broadcast(&fds, &broadcast_fdlist, outbuf, n); + broadcastfds = master_broadcastfds; + FD_CLR(recv_fd, &broadcastfds); + ncat_broadcast(&broadcastfds, &broadcast_fdlist, outbuf, n); free(chatbuf); free(tempbuf); @@ -424,11 +472,11 @@ strbuf_sprintf(&buf, &size, &offset, " already connected: "); count = 0; - for (i = 0; i < read_fdlist.fdmax; i++) { + for (i = 0; i < client_fdlist.fdmax; i++) { union sockaddr_u su; socklen_t len = sizeof(su.storage); - if (i == fd || !FD_ISSET(i, &broadcast_fds)) + if (i == fd || !FD_ISSET(i, &master_broadcastfds)) continue; if (getpeername(i, &su.sockaddr, &len) == -1) @@ -445,7 +493,7 @@ strbuf_sprintf(&buf, &size, &offset, "nobody"); strbuf_sprintf(&buf, &size, &offset, ".\n"); - ret = ncat_broadcast(&broadcast_fds, &broadcast_fdlist, buf, offset); + ret = ncat_broadcast(&master_broadcastfds, &broadcast_fdlist, buf, offset); free(buf); @@ -462,7 +510,7 @@ if (n >= sizeof(buf) || n < 0) return -1; - return ncat_broadcast(&broadcast_fds, &broadcast_fdlist, buf, n); + return ncat_broadcast(&master_broadcastfds, &broadcast_fdlist, buf, n); } /*