1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Make it a non-fatal error when one of two listeners can't be opened.

Unless given a specific listen address, we open two separate listening
sockets, one for IPv4 and one for IPv6. It was previously a fatal error if we
failed to create either socket. Now it is fatal only when all potential
listening addresses fail.

David Millis discovered that the IPv6 listener failed on Windows XP without
IPv6 configured.
Ncat: socket: An address incompatible with the requested protocol was used.  QUITTING.
http://seclists.org/nmap-dev/2013/q3/96
This commit is contained in:
david
2013-08-06 03:49:35 +00:00
parent bd64bba0e0
commit 2cda8ca150
2 changed files with 69 additions and 29 deletions

View File

@@ -233,6 +233,7 @@ static int ncat_listen_stream(int proto)
fd_set listen_fds;
struct timeval tv;
struct timeval *tvp = NULL;
unsigned int num_sockets;
/* clear out structs */
FD_ZERO(&master_readfds);
@@ -268,24 +269,36 @@ static int ncat_listen_stream(int proto)
for (i = 0; i < NUM_LISTEN_ADDRS; i++)
listen_socket[i] = -1;
num_sockets = 0;
for (i = 0; i < num_listenaddrs; i++) {
/* setup the main listening socket */
listen_socket[i] = do_listen(SOCK_STREAM, proto, &listenaddrs[i]);
if (listen_socket[i] == -1)
bye("do_listen: %s", socket_strerror(socket_errno()));
listen_socket[num_sockets] = do_listen(SOCK_STREAM, proto, &listenaddrs[i]);
if (listen_socket[num_sockets] == -1) {
logdebug("do_listen(\"%s\"): %s\n", inet_ntop_ez(&listenaddrs[i].storage, sizeof(listenaddrs[i].storage)), socket_strerror(socket_errno()));
continue;
}
/* Make our listening socket non-blocking because there are timing issues
* which could cause us to block on accept() even though select() says it's
* readable. See UNPv1 2nd ed, p422 for more.
*/
unblock_socket(listen_socket[i]);
unblock_socket(listen_socket[num_sockets]);
/* setup select sets and max fd */
FD_SET(listen_socket[i], &master_readfds);
add_fd(&client_fdlist, listen_socket[i]);
FD_SET(listen_socket[num_sockets], &master_readfds);
add_fd(&client_fdlist, listen_socket[num_sockets]);
FD_SET(listen_socket[i], &listen_fds);
FD_SET(listen_socket[num_sockets], &listen_fds);
num_sockets++;
}
if (num_sockets == 0) {
if (num_listenaddrs == 1)
bye("Unable to open listening socket on %s: %s", inet_ntop_ez(&listenaddrs[0].storage, sizeof(listenaddrs[0].storage)), socket_strerror(socket_errno()));
else
bye("Unable to open any listening sockets.");
}
add_fd(&client_fdlist, STDIN_FILENO);
init_fdlist(&broadcast_fdlist, o.conn_limit);
@@ -621,7 +634,10 @@ int read_socket(int recv_fd)
*/
static int ncat_listen_dgram(int proto)
{
int sockfd[NUM_LISTEN_ADDRS];
struct {
int fd;
union sockaddr_u addr;
} sockfd[NUM_LISTEN_ADDRS];
int i, fdn = -1;
int fdmax, nbytes, n, fds_ready;
char buf[DEFAULT_UDP_BUF_LEN] = { 0 };
@@ -631,9 +647,11 @@ static int ncat_listen_dgram(int proto)
socklen_t sslen = sizeof(remotess.storage);
struct timeval tv;
struct timeval *tvp = NULL;
unsigned int num_sockets;
for (i = 0; i < NUM_LISTEN_ADDRS; i++) {
sockfd[i] = -1;
sockfd[i].fd = -1;
sockfd[i].addr.storage.ss_family = AF_UNSPEC;
}
FD_ZERO(&read_fds);
@@ -658,13 +676,24 @@ static int ncat_listen_dgram(int proto)
FD_ZERO(&listen_fds);
init_fdlist(&listen_fdlist, num_listenaddrs);
num_sockets = 0;
for (i = 0; i < num_listenaddrs; i++) {
/* create the UDP listen sockets */
sockfd[i] = do_listen(SOCK_DGRAM, proto, &listenaddrs[i]);
if (sockfd[i] == -1)
bye("do_listen: %s", socket_strerror(socket_errno()));
FD_SET(sockfd[i], &listen_fds);
add_fd(&listen_fdlist, sockfd[i]);
sockfd[num_sockets].fd = do_listen(SOCK_DGRAM, proto, &listenaddrs[i]);
if (sockfd[num_sockets].fd == -1) {
logdebug("do_listen(\"%s\"): %s\n", inet_ntop_ez(&listenaddrs[i].storage, sizeof(listenaddrs[i].storage)), socket_strerror(socket_errno()));
continue;
}
FD_SET(sockfd[num_sockets].fd, &listen_fds);
add_fd(&listen_fdlist, sockfd[num_sockets].fd);
sockfd[num_sockets].addr = listenaddrs[i];
num_sockets++;
}
if (num_sockets == 0) {
if (num_listenaddrs == 1)
bye("Unable to open listening socket on %s: %s", inet_ntop_ez(&listenaddrs[0].storage, sizeof(listenaddrs[0].storage)), socket_strerror(socket_errno()));
else
bye("Unable to open any listening sockets.");
}
if (o.idletimeout > 0)
@@ -675,15 +704,15 @@ static int ncat_listen_dgram(int proto)
if (fdn != -1) {
/*remove socket descriptor which is burnt */
FD_CLR(sockfd[fdn], &listen_fds);
rm_fd(&listen_fdlist, sockfd[fdn]);
FD_CLR(sockfd[fdn].fd, &listen_fds);
rm_fd(&listen_fdlist, sockfd[fdn].fd);
/* Rebuild the udp socket which got burnt */
sockfd[fdn] = do_listen(SOCK_DGRAM, proto, &listenaddrs[fdn]);
if (sockfd[fdn] == -1)
sockfd[fdn].fd = do_listen(SOCK_DGRAM, proto, &sockfd[fdn].addr);
if (sockfd[fdn].fd == -1)
bye("do_listen: %s", socket_strerror(socket_errno()));
FD_SET(sockfd[fdn], &listen_fds);
add_fd(&listen_fdlist, sockfd[fdn]);
FD_SET(sockfd[fdn].fd, &listen_fds);
add_fd(&listen_fdlist, sockfd[fdn].fd);
}
fdn = -1;
@@ -720,8 +749,8 @@ static int ncat_listen_dgram(int proto)
continue;
/* Check each listening socket */
for (j = 0; j < num_listenaddrs; j++) {
if (i == sockfd[j]) {
for (j = 0; j < num_sockets; j++) {
if (i == sockfd[j].fd) {
if (o.debug > 1)
logdebug("Valid descriptor %d \n", i);
fdn = j;

View File

@@ -192,6 +192,7 @@ int ncat_http_server(void)
union sockaddr_u conn;
struct timeval tv;
struct timeval *tvp = NULL;
unsigned int num_sockets;
#ifndef WIN32
Signal(SIGCHLD, proxyreaper);
@@ -216,18 +217,28 @@ int ncat_http_server(void)
init_fdlist(&listen_fdlist, num_listenaddrs);
/* Listen on each address, set up lists for select */
num_sockets = 0;
for (i = 0; i < num_listenaddrs; i++) {
listen_socket[i] = do_listen(SOCK_STREAM, IPPROTO_TCP, &listenaddrs[i]);
if (listen_socket[i] == -1)
bye("do_listen: %s", socket_strerror(socket_errno()));
listen_socket[num_sockets] = do_listen(SOCK_STREAM, IPPROTO_TCP, &listenaddrs[i]);
if (listen_socket[num_sockets] == -1) {
logdebug("do_listen(\"%s\"): %s\n", inet_ntop_ez(&listenaddrs[i].storage, sizeof(listenaddrs[i].storage)), socket_strerror(socket_errno()));
continue;
}
/* make us not block on accepts in wierd cases. See ncat_listen.c:209 */
unblock_socket(listen_socket[i]);
unblock_socket(listen_socket[num_sockets]);
/* setup select sets and max fd */
FD_SET(listen_socket[i], &listen_fds);
add_fd(&listen_fdlist, listen_socket[i]);
FD_SET(listen_socket[num_sockets], &listen_fds);
add_fd(&listen_fdlist, listen_socket[num_sockets]);
num_sockets++;
}
if (num_sockets == 0) {
if (num_listenaddrs == 1)
bye("Unable to open listening socket on %s: %s", inet_ntop_ez(&listenaddrs[0].storage, sizeof(listenaddrs[0].storage)), socket_strerror(socket_errno()));
else
bye("Unable to open any listening sockets.");
}
if (o.idletimeout > 0)
@@ -261,7 +272,7 @@ int ncat_http_server(void)
continue;
/* Check each listening socket */
for (j = 0; j < num_listenaddrs; j++) {
for (j = 0; j < num_sockets; j++) {
if (i == listen_socket[j]) {
fds_ready--;
c = accept(i, &conn.sockaddr, &sslen);