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

View File

@@ -192,6 +192,7 @@ int ncat_http_server(void)
union sockaddr_u conn; union sockaddr_u conn;
struct timeval tv; struct timeval tv;
struct timeval *tvp = NULL; struct timeval *tvp = NULL;
unsigned int num_sockets;
#ifndef WIN32 #ifndef WIN32
Signal(SIGCHLD, proxyreaper); Signal(SIGCHLD, proxyreaper);
@@ -216,18 +217,28 @@ int ncat_http_server(void)
init_fdlist(&listen_fdlist, num_listenaddrs); init_fdlist(&listen_fdlist, num_listenaddrs);
/* Listen on each address, set up lists for select */ /* Listen on each address, set up lists for select */
num_sockets = 0;
for (i = 0; i < num_listenaddrs; i++) { for (i = 0; i < num_listenaddrs; i++) {
listen_socket[i] = do_listen(SOCK_STREAM, IPPROTO_TCP, &listenaddrs[i]); listen_socket[num_sockets] = do_listen(SOCK_STREAM, IPPROTO_TCP, &listenaddrs[i]);
if (listen_socket[i] == -1) if (listen_socket[num_sockets] == -1) {
bye("do_listen: %s", socket_strerror(socket_errno())); 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 */ /* 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 */ /* setup select sets and max fd */
FD_SET(listen_socket[i], &listen_fds); FD_SET(listen_socket[num_sockets], &listen_fds);
add_fd(&listen_fdlist, listen_socket[i]); 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) if (o.idletimeout > 0)
@@ -261,7 +272,7 @@ int ncat_http_server(void)
continue; continue;
/* Check each listening socket */ /* Check each listening socket */
for (j = 0; j < num_listenaddrs; j++) { for (j = 0; j < num_sockets; j++) {
if (i == listen_socket[j]) { if (i == listen_socket[j]) {
fds_ready--; fds_ready--;
c = accept(i, &conn.sockaddr, &sslen); c = accept(i, &conn.sockaddr, &sslen);