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:
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user