mirror of
https://github.com/nmap/nmap.git
synced 2026-01-05 22:19:03 +00:00
Ncat supports DNS failover, including fallback to IPv4 from IPv6
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
# Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o [Ncat][GH#157] Ncat will now continue trying to connect to each resolved
|
||||
address for a hostname before declaring the connection refused, allowing it
|
||||
to fallback from IPv6 to IPv4 or to connect to names that use DNS failover.
|
||||
[Jaromir Koncicky, Michal Hlavinka]
|
||||
|
||||
o [NSE][GH#743] New script broadcast-ospf2-discover discovers OSPF 2 routers
|
||||
and neighbors. OSPFv2 authentication is supported. [Emiliano Ticci]
|
||||
|
||||
|
||||
@@ -137,16 +137,19 @@ the tool? Many of these examples suppose a Unix environment. -->
|
||||
</para>
|
||||
|
||||
<para>
|
||||
By default, Ncat uses TCP and IPv4. The option
|
||||
By default, Ncat uses TCP. The option
|
||||
<option>--udp</option><indexterm><primary><option>--udp</option> (Ncat option)</primary></indexterm>
|
||||
or
|
||||
<option>-u</option><indexterm><primary><option>-u</option> (Ncat option)</primary><see><option>--udp</option></see></indexterm>
|
||||
enables UDP instead,
|
||||
<option>--sctp</option><indexterm><primary><option>--sctp</option> (Ncat option)</primary></indexterm>
|
||||
enables SCTP,<indexterm><primary>SCTP</primary><secondary>in Ncat</secondary></indexterm>
|
||||
and
|
||||
<option>--sctp</option><indexterm><primary><option>--sctp</option> (Ncat option)</primary></indexterm>
|
||||
enables SCTP.<indexterm><primary>SCTP</primary><secondary>in Ncat</secondary></indexterm>
|
||||
Ncat listens on both IPv4 and IPv6, and connects to either address family as well. The
|
||||
<option>-6</option><indexterm><primary><option>-6</option> (Ncat option)</primary></indexterm>
|
||||
enables IPv6. See <xref linkend="ncat-protocols"/> for more details.
|
||||
option forces IPv6-only, and
|
||||
<option>-4</option><indexterm><primary><option>-4</option> (Ncat option)</primary></indexterm>
|
||||
forces IPv4-only. See <xref linkend="ncat-protocols"/> for more details.
|
||||
The rest of this guide documents all the Ncat options through
|
||||
descriptions and examples. For a quick summary of options at any time,
|
||||
run
|
||||
@@ -331,8 +334,8 @@ Content-Type: text/html; charset=UTF-8
|
||||
|
||||
<para>
|
||||
IPv4,<indexterm significance="preferred"><primary>IPv4</primary><secondary>in Ncat</secondary></indexterm>
|
||||
the Internet Protocol version 4, is the dominant version of the
|
||||
Internet Protocol in use. Ncat uses it by default. Using the
|
||||
the Internet Protocol version 4, is the most popular version of the
|
||||
Internet Protocol in use. Using the
|
||||
<option>-4</option><indexterm><primary><option>-4 (Ncat option)</option></primary></indexterm>
|
||||
puts Ncat into IPv4-only mode; only IPv4 addresses will be used even
|
||||
if, for example, as hostname resolves to IPv6 addresses as well.
|
||||
@@ -343,6 +346,8 @@ Content-Type: text/html; charset=UTF-8
|
||||
is the lesser-used successor to IPv4. Use
|
||||
<option>-6</option><indexterm><primary><option>-6</option> (Ncat option)</primary></indexterm>
|
||||
to put Ncat into IPv6-only mode.
|
||||
By default, Ncat will listen on both IPv4 and IPv6, and will connect to
|
||||
resolved addresses in the order they are returned by the operating system.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
@@ -171,6 +171,7 @@ static struct conn_state cs = {
|
||||
0
|
||||
};
|
||||
|
||||
static void try_nsock_connect(nsock_pool nsp, struct sockaddr_list *conn_addr);
|
||||
static void connect_handler(nsock_pool nsp, nsock_event evt, void *data);
|
||||
static void post_connect(nsock_pool nsp, nsock_iod iod);
|
||||
static void read_stdin_handler(nsock_pool nsp, nsock_event evt, void *data);
|
||||
@@ -551,8 +552,8 @@ static int do_proxy_socks4(void)
|
||||
socket_buffer_init(&stateful_buf, sd);
|
||||
|
||||
if (o.verbose) {
|
||||
loguser("Connected to proxy %s:%hu\n", inet_socktop(&targetss),
|
||||
inet_port(&targetss));
|
||||
loguser("Connected to proxy %s:%hu\n", inet_socktop(&targetaddrs->addr),
|
||||
inet_port(&targetaddrs->addr));
|
||||
}
|
||||
|
||||
/* Fill the socks4_data struct */
|
||||
@@ -652,8 +653,8 @@ static int do_proxy_socks5(void)
|
||||
socket_buffer_init(&stateful_buf, sd);
|
||||
|
||||
if (o.verbose) {
|
||||
loguser("Connected to proxy %s:%hu\n", inet_socktop(&targetss),
|
||||
inet_port(&targetss));
|
||||
loguser("Connected to proxy %s:%hu\n", inet_socktop(&targetaddrs->addr),
|
||||
inet_port(&targetaddrs->addr));
|
||||
}
|
||||
|
||||
zmem(&socks5msg,sizeof(socks5msg));
|
||||
@@ -983,7 +984,7 @@ int ncat_connect(void)
|
||||
|
||||
if (o.af != AF_INET)
|
||||
bye("Sorry, -g can only currently be used with IPv4.");
|
||||
ipopts = buildsrcrte(targetss.in.sin_addr, o.srcrtes, o.numsrcrtes, o.srcrteptr, &ipoptslen);
|
||||
ipopts = buildsrcrte(targetaddrs->addr.in.sin_addr, o.srcrtes, o.numsrcrtes, o.srcrteptr, &ipoptslen);
|
||||
|
||||
nsock_iod_set_ipoptions(cs.sock_nsi, ipopts, ipoptslen);
|
||||
free(ipopts); /* Nsock has its own copy */
|
||||
@@ -993,49 +994,18 @@ int ncat_connect(void)
|
||||
if (o.af == AF_UNIX) {
|
||||
if (o.proto == IPPROTO_UDP) {
|
||||
nsock_connect_unixsock_datagram(mypool, cs.sock_nsi, connect_handler, NULL,
|
||||
&targetss.sockaddr,
|
||||
SUN_LEN((struct sockaddr_un *)&targetss.sockaddr));
|
||||
&targetaddrs->addr.sockaddr,
|
||||
SUN_LEN((struct sockaddr_un *)&targetaddrs->addr.sockaddr));
|
||||
} else {
|
||||
nsock_connect_unixsock_stream(mypool, cs.sock_nsi, connect_handler, o.conntimeout,
|
||||
NULL, &targetss.sockaddr,
|
||||
SUN_LEN((struct sockaddr_un *)&targetss.sockaddr));
|
||||
NULL, &targetaddrs->addr.sockaddr,
|
||||
SUN_LEN((struct sockaddr_un *)&targetaddrs->addr.sockaddr));
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (o.proto == IPPROTO_UDP) {
|
||||
nsock_connect_udp(mypool, cs.sock_nsi, connect_handler,
|
||||
NULL, &targetss.sockaddr, targetsslen,
|
||||
inet_port(&targetss));
|
||||
}
|
||||
#ifdef HAVE_OPENSSL
|
||||
else if (o.proto == IPPROTO_SCTP && o.ssl) {
|
||||
nsock_connect_ssl(mypool, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, NULL,
|
||||
&targetss.sockaddr, targetsslen,
|
||||
IPPROTO_SCTP, inet_port(&targetss),
|
||||
NULL);
|
||||
}
|
||||
#endif
|
||||
else if (o.proto == IPPROTO_SCTP) {
|
||||
nsock_connect_sctp(mypool, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, NULL,
|
||||
&targetss.sockaddr, targetsslen,
|
||||
inet_port(&targetss));
|
||||
}
|
||||
#ifdef HAVE_OPENSSL
|
||||
else if (o.ssl) {
|
||||
nsock_connect_ssl(mypool, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, NULL,
|
||||
&targetss.sockaddr, targetsslen,
|
||||
IPPROTO_TCP, inet_port(&targetss),
|
||||
NULL);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
nsock_connect_tcp(mypool, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, NULL,
|
||||
&targetss.sockaddr, targetsslen,
|
||||
inet_port(&targetss));
|
||||
{
|
||||
/* Add connection to first resolved address. */
|
||||
try_nsock_connect(mypool, targetaddrs);
|
||||
}
|
||||
} else {
|
||||
/* A proxy connection. */
|
||||
@@ -1071,6 +1041,8 @@ int ncat_connect(void)
|
||||
/* connect */
|
||||
rc = nsock_loop(mypool, -1);
|
||||
|
||||
free_sockaddr_list(targetaddrs);
|
||||
|
||||
if (o.verbose) {
|
||||
struct timeval end_time;
|
||||
double time;
|
||||
@@ -1094,6 +1066,45 @@ int ncat_connect(void)
|
||||
return rc == NSOCK_LOOP_ERROR ? 1 : 0;
|
||||
}
|
||||
|
||||
static void try_nsock_connect(nsock_pool nsp, struct sockaddr_list *conn_addr)
|
||||
{
|
||||
if (o.proto == IPPROTO_UDP) {
|
||||
nsock_connect_udp(nsp, cs.sock_nsi, connect_handler, (void *)conn_addr->next,
|
||||
&conn_addr->addr.sockaddr, conn_addr->addrlen,
|
||||
inet_port(&conn_addr->addr));
|
||||
}
|
||||
#ifdef HAVE_OPENSSL
|
||||
else if (o.proto == IPPROTO_SCTP && o.ssl) {
|
||||
nsock_connect_ssl(nsp, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, (void *)conn_addr->next,
|
||||
&conn_addr->addr.sockaddr, conn_addr->addrlen,
|
||||
IPPROTO_SCTP, inet_port(&conn_addr->addr),
|
||||
NULL);
|
||||
}
|
||||
#endif
|
||||
else if (o.proto == IPPROTO_SCTP) {
|
||||
nsock_connect_sctp(nsp, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, (void *)conn_addr->next,
|
||||
&conn_addr->addr.sockaddr, conn_addr->addrlen,
|
||||
inet_port(&conn_addr->addr));
|
||||
}
|
||||
#ifdef HAVE_OPENSSL
|
||||
else if (o.ssl) {
|
||||
nsock_connect_ssl(nsp, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, (void *)conn_addr->next,
|
||||
&conn_addr->addr.sockaddr, conn_addr->addrlen,
|
||||
IPPROTO_TCP, inet_port(&conn_addr->addr),
|
||||
NULL);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
nsock_connect_tcp(nsp, cs.sock_nsi, connect_handler,
|
||||
o.conntimeout, (void *)conn_addr->next,
|
||||
&conn_addr->addr.sockaddr, conn_addr->addrlen,
|
||||
inet_port(&conn_addr->addr));
|
||||
}
|
||||
}
|
||||
|
||||
static void send_udp_null(nsock_pool nsp)
|
||||
{
|
||||
char *NULL_PROBE = "\0";
|
||||
@@ -1105,17 +1116,31 @@ static void connect_handler(nsock_pool nsp, nsock_event evt, void *data)
|
||||
{
|
||||
enum nse_status status = nse_status(evt);
|
||||
enum nse_type type = nse_type(evt);
|
||||
struct sockaddr_list *next_addr = (struct sockaddr_list *)data;
|
||||
|
||||
ncat_assert(type == NSE_TYPE_CONNECT || type == NSE_TYPE_CONNECT_SSL);
|
||||
|
||||
if (status == NSE_STATUS_ERROR) {
|
||||
if (!o.zerobyte||o.verbose)
|
||||
loguser("%s.\n", socket_strerror(nse_errorcode(evt)));
|
||||
exit(1);
|
||||
} else if (status == NSE_STATUS_TIMEOUT) {
|
||||
if (!o.zerobyte||o.verbose)
|
||||
loguser("%s.\n", socket_strerror(ETIMEDOUT));
|
||||
exit(1);
|
||||
if (status == NSE_STATUS_ERROR || status == NSE_STATUS_TIMEOUT) {
|
||||
int errcode = (status == NSE_STATUS_TIMEOUT)?ETIMEDOUT:nse_errorcode(evt);
|
||||
/* If there are more resolved addresses, try connecting to next one */
|
||||
if (next_addr != NULL) {
|
||||
if (o.verbose) {
|
||||
union sockaddr_u peer;
|
||||
zmem(&peer, sizeof(peer.storage));
|
||||
nsock_iod_get_communication_info(cs.sock_nsi, NULL, NULL, NULL,
|
||||
&peer.sockaddr, sizeof(peer.storage));
|
||||
loguser("Connection to %s failed: %s.\n", inet_socktop(&peer), socket_strerror(errcode));
|
||||
loguser("Trying next address...\n");
|
||||
}
|
||||
try_nsock_connect(nsp, next_addr);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
free_sockaddr_list(targetaddrs);
|
||||
if (!o.zerobyte||o.verbose)
|
||||
loguser("%s.\n", socket_strerror(errcode));
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
ncat_assert(status == NSE_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -153,8 +153,7 @@ int num_listenaddrs = 0;
|
||||
union sockaddr_u srcaddr;
|
||||
size_t srcaddrlen;
|
||||
|
||||
union sockaddr_u targetss;
|
||||
size_t targetsslen;
|
||||
struct sockaddr_list *targetaddrs;
|
||||
|
||||
/* Global options structure. */
|
||||
struct options o;
|
||||
@@ -220,18 +219,22 @@ void options_init(void)
|
||||
}
|
||||
|
||||
/* Internal helper for resolve and resolve_numeric. addl_flags is ored into
|
||||
hints.ai_flags, so you can add AI_NUMERICHOST. */
|
||||
hints.ai_flags, so you can add AI_NUMERICHOST.
|
||||
sl is a pointer to first element of sockaddr linked list, which is always
|
||||
statically allocated. Next list elements are dynamically allocated.
|
||||
If multiple_addrs is false then only first address is returned. */
|
||||
static int resolve_internal(const char *hostname, unsigned short port,
|
||||
struct sockaddr_storage *ss, size_t *sslen, int af, int addl_flags)
|
||||
struct sockaddr_list *sl, int af, int addl_flags, int multiple_addrs)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result;
|
||||
struct addrinfo *next;
|
||||
struct sockaddr_list **item_ptr = &sl;
|
||||
struct sockaddr_list *new_item;
|
||||
char portbuf[16];
|
||||
int rc;
|
||||
|
||||
ncat_assert(hostname != NULL);
|
||||
ncat_assert(ss != NULL);
|
||||
ncat_assert(sslen != NULL);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = af;
|
||||
@@ -248,8 +251,19 @@ static int resolve_internal(const char *hostname, unsigned short port,
|
||||
if (result == NULL)
|
||||
return EAI_NONAME;
|
||||
ncat_assert(result->ai_addrlen > 0 && result->ai_addrlen <= (int) sizeof(struct sockaddr_storage));
|
||||
*sslen = result->ai_addrlen;
|
||||
memcpy(ss, result->ai_addr, *sslen);
|
||||
for (next = result; next != NULL; next = next->ai_next) {
|
||||
if (*item_ptr == NULL)
|
||||
{
|
||||
*item_ptr = (struct sockaddr_list *)safe_malloc(sizeof(struct sockaddr_list));
|
||||
(**item_ptr).next = NULL;
|
||||
}
|
||||
new_item = *item_ptr;
|
||||
new_item->addrlen = next->ai_addrlen;
|
||||
memcpy(&new_item->addr.storage, next->ai_addr, next->ai_addrlen);
|
||||
if (!multiple_addrs)
|
||||
break;
|
||||
item_ptr = &new_item->next;
|
||||
}
|
||||
freeaddrinfo(result);
|
||||
|
||||
return 0;
|
||||
@@ -268,12 +282,42 @@ int resolve(const char *hostname, unsigned short port,
|
||||
struct sockaddr_storage *ss, size_t *sslen, int af)
|
||||
{
|
||||
int flags;
|
||||
struct sockaddr_list sl;
|
||||
int result;
|
||||
|
||||
flags = 0;
|
||||
if (o.nodns)
|
||||
flags |= AI_NUMERICHOST;
|
||||
|
||||
return resolve_internal(hostname, port, ss, sslen, af, flags);
|
||||
result = resolve_internal(hostname, port, &sl, af, flags, 0);
|
||||
*ss = sl.addr.storage;
|
||||
*sslen = sl.addrlen;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Resolves the given hostname or IP address with getaddrinfo, and stores
|
||||
all results into a linked list.
|
||||
The rest of the behavior is same as resolve(). */
|
||||
int resolve_multi(const char *hostname, unsigned short port,
|
||||
struct sockaddr_list *sl, int af)
|
||||
{
|
||||
int flags;
|
||||
|
||||
flags = 0;
|
||||
if (o.nodns)
|
||||
flags |= AI_NUMERICHOST;
|
||||
|
||||
return resolve_internal(hostname, port, sl, af, flags, 1);
|
||||
}
|
||||
|
||||
void free_sockaddr_list(struct sockaddr_list *sl)
|
||||
{
|
||||
struct sockaddr_list *current, *next = sl;
|
||||
while (next != NULL) {
|
||||
current = next;
|
||||
next = current->next;
|
||||
free(current);
|
||||
}
|
||||
}
|
||||
|
||||
int fdinfo_close(struct fdinfo *fdn)
|
||||
|
||||
@@ -139,14 +139,20 @@
|
||||
a IPV4 INADDR_ANY and a IPV6 in6addr_any at most or a user defined address */
|
||||
#define NUM_LISTEN_ADDRS 2
|
||||
|
||||
/* Structure to store a linked list of resolved addresses. */
|
||||
struct sockaddr_list {
|
||||
union sockaddr_u addr;
|
||||
size_t addrlen;
|
||||
struct sockaddr_list* next;
|
||||
};
|
||||
|
||||
extern union sockaddr_u listenaddrs[NUM_LISTEN_ADDRS];
|
||||
extern int num_listenaddrs;
|
||||
|
||||
extern union sockaddr_u srcaddr;
|
||||
extern size_t srcaddrlen;
|
||||
|
||||
extern union sockaddr_u targetss;
|
||||
extern size_t targetsslen;
|
||||
extern struct sockaddr_list *targetaddrs;
|
||||
|
||||
enum exec_mode {
|
||||
EXEC_PLAIN,
|
||||
@@ -235,6 +241,14 @@ void options_init(void);
|
||||
int resolve(const char *hostname, unsigned short port,
|
||||
struct sockaddr_storage *ss, size_t *sslen, int af);
|
||||
|
||||
/* Resolves the given hostname or IP address with getaddrinfo, and stores
|
||||
all results into a linked list.
|
||||
The rest of behavior is same as resolve(). */
|
||||
int resolve_multi(const char *hostname, unsigned short port,
|
||||
struct sockaddr_list *sl, int af);
|
||||
|
||||
void free_sockaddr_list(struct sockaddr_list *sl);
|
||||
|
||||
int fdinfo_close(struct fdinfo *fdn);
|
||||
int fdinfo_recv(struct fdinfo *fdn, char *buf, size_t size);
|
||||
int fdinfo_send(struct fdinfo *fdn, const char *buf, size_t size);
|
||||
|
||||
@@ -688,15 +688,18 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
#endif /* HAVE_SYS_UN_H */
|
||||
|
||||
/* Create a static target address, because at least one target address must be always allocated */
|
||||
targetaddrs = (struct sockaddr_list *)safe_zalloc(sizeof(struct sockaddr_list));
|
||||
|
||||
/* Will be AF_INET or AF_INET6 or AF_UNIX when valid */
|
||||
memset(&targetss.storage, 0, sizeof(targetss.storage));
|
||||
targetss.storage.ss_family = AF_UNSPEC;
|
||||
srcaddr.storage = targetss.storage;
|
||||
memset(&srcaddr.storage, 0, sizeof(srcaddr.storage));
|
||||
srcaddr.storage.ss_family = AF_UNSPEC;
|
||||
targetaddrs->addr.storage = srcaddr.storage;
|
||||
|
||||
/* Clear the listenaddrs array */
|
||||
int i;
|
||||
for (i = 0; i < NUM_LISTEN_ADDRS; i++) {
|
||||
listenaddrs[i].storage = targetss.storage;
|
||||
listenaddrs[i].storage = srcaddr.storage;
|
||||
}
|
||||
|
||||
if (o.proxyaddr) {
|
||||
@@ -712,12 +715,12 @@ int main(int argc, char *argv[])
|
||||
* (due to the colons in the IPv6 address and host:port separator).
|
||||
*/
|
||||
|
||||
targetsslen = parseproxy(o.proxyaddr,
|
||||
&targetss.storage, &targetsslen, &proxyport);
|
||||
targetaddrs->addrlen = parseproxy(o.proxyaddr,
|
||||
&targetaddrs->addr.storage, &targetaddrs->addrlen, &proxyport);
|
||||
if (o.af == AF_INET) {
|
||||
targetss.in.sin_port = htons(proxyport);
|
||||
targetaddrs->addr.in.sin_port = htons(proxyport);
|
||||
} else { // might modify to else if and test AF_{INET6|UNIX|UNSPEC}
|
||||
targetss.in6.sin6_port = htons(proxyport);
|
||||
targetaddrs->addr.in6.sin6_port = htons(proxyport);
|
||||
}
|
||||
} else {
|
||||
bye("Invalid proxy type \"%s\".", o.proxytype);
|
||||
@@ -796,10 +799,10 @@ int main(int argc, char *argv[])
|
||||
} else {
|
||||
#if HAVE_SYS_UN_H
|
||||
if (o.af == AF_UNIX) {
|
||||
memset(&targetss.storage, 0, sizeof(struct sockaddr_un));
|
||||
targetss.un.sun_family = AF_UNIX;
|
||||
strncpy(targetss.un.sun_path, argv[optind], sizeof(targetss.un.sun_path));
|
||||
targetsslen = SUN_LEN(&targetss.un);
|
||||
memset(&targetaddrs->addr.storage, 0, sizeof(struct sockaddr_un));
|
||||
targetaddrs->addr.un.sun_family = AF_UNIX;
|
||||
strncpy(targetaddrs->addr.un.sun_path, argv[optind], sizeof(targetaddrs->addr.un.sun_path));
|
||||
targetaddrs->addrlen = SUN_LEN(&targetaddrs->addr.un);
|
||||
o.target = argv[optind];
|
||||
optind++;
|
||||
} else
|
||||
@@ -813,7 +816,7 @@ int main(int argc, char *argv[])
|
||||
* targetss contains data already and you don't want remove them
|
||||
*/
|
||||
if( !o.proxytype
|
||||
&& (rc = resolve(o.target, 0, &targetss.storage, &targetsslen, o.af)) != 0)
|
||||
&& (rc = resolve_multi(o.target, 0, targetaddrs, o.af)) != 0)
|
||||
|
||||
bye("Could not resolve hostname \"%s\": %s.", o.target, gai_strerror(rc));
|
||||
optind++;
|
||||
@@ -851,21 +854,28 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (o.proxytype && !o.listen)
|
||||
; /* Do nothing - port is already set to proxyport */
|
||||
else if (targetss.storage.ss_family == AF_INET)
|
||||
targetss.in.sin_port = htons(o.portno);
|
||||
else {
|
||||
struct sockaddr_list *targetaddrs_item = targetaddrs;
|
||||
while (targetaddrs_item != NULL)
|
||||
{
|
||||
if (targetaddrs_item->addr.storage.ss_family == AF_INET)
|
||||
targetaddrs_item->addr.in.sin_port = htons(o.portno);
|
||||
#ifdef HAVE_IPV6
|
||||
else if (targetss.storage.ss_family == AF_INET6)
|
||||
targetss.in6.sin6_port = htons(o.portno);
|
||||
else if (targetaddrs_item->addr.storage.ss_family == AF_INET6)
|
||||
targetaddrs_item->addr.in6.sin6_port = htons(o.portno);
|
||||
#endif
|
||||
#if HAVE_SYS_UN_H
|
||||
/* If we use Unix domain sockets, we have to count with them. */
|
||||
else if (targetss.storage.ss_family == AF_UNIX)
|
||||
; /* Do nothing. */
|
||||
/* If we use Unix domain sockets, we have to count with them. */
|
||||
else if (targetaddrs_item->addr.storage.ss_family == AF_UNIX)
|
||||
; /* Do nothing. */
|
||||
#endif
|
||||
else if (targetss.storage.ss_family == AF_UNSPEC)
|
||||
; /* Leave unspecified. */
|
||||
else
|
||||
bye("Unknown address family %d.", targetss.storage.ss_family);
|
||||
else if (targetaddrs_item->addr.storage.ss_family == AF_UNSPEC)
|
||||
; /* Leave unspecified. */
|
||||
else
|
||||
bye("Unknown address family %d.", targetaddrs_item->addr.storage.ss_family);
|
||||
targetaddrs_item = targetaddrs_item->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (srcport != -1) {
|
||||
if (o.listen) {
|
||||
@@ -877,7 +887,7 @@ int main(int argc, char *argv[])
|
||||
/* We have a source port but not an explicit source address;
|
||||
fill in an unspecified address of the same family as the
|
||||
target. */
|
||||
srcaddr.storage.ss_family = targetss.storage.ss_family;
|
||||
srcaddr.storage.ss_family = targetaddrs->addr.storage.ss_family;
|
||||
if (srcaddr.storage.ss_family == AF_INET)
|
||||
srcaddr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
else if (srcaddr.storage.ss_family == AF_INET6)
|
||||
@@ -969,8 +979,8 @@ static int ncat_listen_mode(void)
|
||||
bye("/bin/sh is not executable, so `-c' won't work.");
|
||||
#endif
|
||||
|
||||
if (targetss.storage.ss_family != AF_UNSPEC) {
|
||||
listenaddrs[num_listenaddrs++] = targetss;
|
||||
if (targetaddrs->addr.storage.ss_family != AF_UNSPEC) {
|
||||
listenaddrs[num_listenaddrs++] = targetaddrs->addr;
|
||||
} else {
|
||||
size_t ss_len;
|
||||
int rc;
|
||||
|
||||
@@ -600,6 +600,29 @@ sub {
|
||||
};
|
||||
kill_children;
|
||||
|
||||
($s_pid, $s_out, $s_in) = ncat("-4", "-lk");
|
||||
test "Connect fallback with IPv4 server",
|
||||
sub {
|
||||
my $resp;
|
||||
|
||||
my ($c_pid, $c_out, $c_in) = ncat("localhost");
|
||||
syswrite($c_in, "abc\n");
|
||||
$resp = timeout_read($s_out);
|
||||
$resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
|
||||
};
|
||||
|
||||
($s_pid, $s_out, $s_in) = ncat("-6", "-lk");
|
||||
test "Connect fallback with IPv6 server",
|
||||
sub {
|
||||
my $resp;
|
||||
|
||||
my ($c_pid, $c_out, $c_in) = ncat("localhost");
|
||||
syswrite($c_in, "abc\n");
|
||||
$resp = timeout_read($s_out);
|
||||
$resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\"";
|
||||
};
|
||||
|
||||
kill_children;
|
||||
# Test UNIX domain sockets listening
|
||||
{
|
||||
local $xfail = 1 if !$HAVE_UNIXSOCK;
|
||||
|
||||
@@ -510,7 +510,7 @@ int do_connect(int type)
|
||||
/* We need a socket that can be inherited by child processes in
|
||||
ncat_exec_win.c, for --exec and --sh-exec. inheritable_socket is from
|
||||
nbase. */
|
||||
sock = inheritable_socket(targetss.storage.ss_family, type, 0);
|
||||
sock = inheritable_socket(targetaddrs->addr.storage.ss_family, type, 0);
|
||||
|
||||
if (srcaddr.storage.ss_family != AF_UNSPEC) {
|
||||
size_t sa_len;
|
||||
@@ -527,7 +527,7 @@ int do_connect(int type)
|
||||
}
|
||||
|
||||
if (sock != -1) {
|
||||
if (connect(sock, &targetss.sockaddr, (int) targetsslen) != -1)
|
||||
if (connect(sock, &targetaddrs->addr.sockaddr, (int) targetaddrs->addrlen) != -1)
|
||||
return sock;
|
||||
else if (socket_errno() == EINPROGRESS || socket_errno() == EAGAIN)
|
||||
return sock;
|
||||
|
||||
Reference in New Issue
Block a user