241 lines
6.9 KiB
Diff
241 lines
6.9 KiB
Diff
|
From: Aron Xu <aron@debian.org>
|
||
|
Date: Mon, 13 Feb 2012 15:56:51 +0800
|
||
|
Subject: dccp support
|
||
|
|
||
|
---
|
||
|
nc.1 | 4 ++
|
||
|
netcat.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++----------
|
||
|
2 files changed, 82 insertions(+), 15 deletions(-)
|
||
|
|
||
|
--- a/nc.1
|
||
|
+++ b/nc.1
|
||
|
@@ -33,7 +33,7 @@
|
||
|
.Nd arbitrary TCP and UDP connections and listens
|
||
|
.Sh SYNOPSIS
|
||
|
.Nm nc
|
||
|
-.Op Fl 46CDdFhklNnrStUuvz
|
||
|
+.Op Fl 46CDdFhklNnrStUuvZz
|
||
|
.Op Fl I Ar length
|
||
|
.Op Fl i Ar interval
|
||
|
.Op Fl M Ar ttl
|
||
|
@@ -286,6 +286,8 @@ for SOCKS, 3128 for HTTPS).
|
||
|
An IPv6 address can be specified unambiguously by enclosing
|
||
|
.Ar proxy_address
|
||
|
in square brackets.
|
||
|
+.It Fl Z
|
||
|
+DCCP mode.
|
||
|
.It Fl z
|
||
|
Specifies that
|
||
|
.Nm
|
||
|
--- a/netcat.c
|
||
|
+++ b/netcat.c
|
||
|
@@ -147,6 +147,7 @@ int rflag; /* Random ports flag */
|
||
|
char *sflag; /* Source Address */
|
||
|
int tflag; /* Telnet Emulation */
|
||
|
int uflag; /* UDP - Default to TCP */
|
||
|
+int dccpflag; /* DCCP - Default to TCP */
|
||
|
int vflag; /* Verbosity */
|
||
|
int xflag; /* Socks proxy */
|
||
|
int zflag; /* Port Scan Flag */
|
||
|
@@ -219,6 +220,7 @@ ssize_t drainbuf(int, unsigned char *, s
|
||
|
ssize_t fillbuf(int, unsigned char *, size_t *);
|
||
|
# endif
|
||
|
|
||
|
+char *proto_name(int uflag, int dccpflag);
|
||
|
static int connect_with_timeout(int fd, const struct sockaddr *sa,
|
||
|
socklen_t salen, int ctimeout);
|
||
|
|
||
|
@@ -252,9 +254,9 @@ main(int argc, char *argv[])
|
||
|
|
||
|
while ((ch = getopt(argc, argv,
|
||
|
# if defined(TLS)
|
||
|
- "46C:cDde:FH:hI:i:K:klM:m:NnO:o:P:p:q:R:rSs:T:tUuV:vw:X:x:z")) != -1) {
|
||
|
+ "46C:cDde:FH:hI:i:K:klM:m:NnO:o:P:p:q:R:rSs:T:tUuV:vw:X:x:Zz")) != -1) {
|
||
|
# else
|
||
|
- "46CDdFhI:i:klM:m:NnO:P:p:q:rSs:T:tUuV:vw:X:x:z")) != -1) {
|
||
|
+ "46CDdFhI:i:klM:m:NnO:P:p:q:rSs:T:tUuV:vw:X:x:Zz")) != -1) {
|
||
|
# endif
|
||
|
switch (ch) {
|
||
|
case '4':
|
||
|
@@ -370,6 +372,13 @@ main(int argc, char *argv[])
|
||
|
case 'u':
|
||
|
uflag = 1;
|
||
|
break;
|
||
|
+ case 'Z':
|
||
|
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
|
+ dccpflag = 1;
|
||
|
+# else
|
||
|
+ errx(1, "no DCCP support available");
|
||
|
+# endif
|
||
|
+ break;
|
||
|
case 'V':
|
||
|
# if defined(RT_TABLEID_MAX)
|
||
|
rtableid = (int)strtonum(optarg, 0,
|
||
|
@@ -461,6 +470,12 @@ main(int argc, char *argv[])
|
||
|
|
||
|
/* Cruft to make sure options are clean, and used properly. */
|
||
|
if (argv[0] && !argv[1] && family == AF_UNIX) {
|
||
|
+ if (uflag)
|
||
|
+ errx(1, "cannot use -u and -U");
|
||
|
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
|
+ if (dccpflag)
|
||
|
+ errx(1, "cannot use -Z and -U");
|
||
|
+# endif
|
||
|
host = argv[0];
|
||
|
uport = NULL;
|
||
|
} else if (!argv[0] && lflag) {
|
||
|
@@ -527,8 +542,20 @@ main(int argc, char *argv[])
|
||
|
if (family != AF_UNIX) {
|
||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||
|
hints.ai_family = family;
|
||
|
- hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
|
||
|
- hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
|
||
|
+ if (uflag) {
|
||
|
+ hints.ai_socktype = SOCK_DGRAM;
|
||
|
+ hints.ai_protocol = IPPROTO_UDP;
|
||
|
+ }
|
||
|
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
|
+ else if (dccpflag) {
|
||
|
+ hints.ai_socktype = SOCK_DCCP;
|
||
|
+ hints.ai_protocol = IPPROTO_DCCP;
|
||
|
+ }
|
||
|
+# endif
|
||
|
+ else {
|
||
|
+ hints.ai_socktype = SOCK_STREAM;
|
||
|
+ hints.ai_protocol = IPPROTO_TCP;
|
||
|
+ }
|
||
|
if (nflag)
|
||
|
hints.ai_flags |= AI_NUMERICHOST;
|
||
|
}
|
||
|
@@ -536,7 +563,10 @@ main(int argc, char *argv[])
|
||
|
if (xflag) {
|
||
|
if (uflag)
|
||
|
errx(1, "no proxy support for UDP mode");
|
||
|
-
|
||
|
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
|
+ if (dccpflag)
|
||
|
+ errx(1, "no proxy support for DCCP mode");
|
||
|
+# endif
|
||
|
if (lflag)
|
||
|
errx(1, "no proxy support for listen");
|
||
|
|
||
|
@@ -798,19 +828,20 @@ main(int argc, char *argv[])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ char *proto = proto_name(uflag, dccpflag);
|
||
|
/* Don't look up port if -n. */
|
||
|
if (nflag)
|
||
|
sv = NULL;
|
||
|
else {
|
||
|
sv = getservbyport(
|
||
|
ntohs(atoi(portlist[i])),
|
||
|
- uflag ? "udp" : "tcp");
|
||
|
+ proto);
|
||
|
}
|
||
|
|
||
|
fprintf(stderr,
|
||
|
"Connection to %s %s port [%s/%s] "
|
||
|
"succeeded!\n", host, portlist[i],
|
||
|
- uflag ? "udp" : "tcp",
|
||
|
+ proto,
|
||
|
sv ? sv->s_name : "*");
|
||
|
}
|
||
|
if (Fflag)
|
||
|
@@ -1017,6 +1048,24 @@ unix_listen(char *path)
|
||
|
return (s);
|
||
|
}
|
||
|
|
||
|
+char *proto_name(int uflag, int dccpflag) {
|
||
|
+
|
||
|
+ char *proto = NULL;
|
||
|
+ if (uflag) {
|
||
|
+ proto = "udp";
|
||
|
+ }
|
||
|
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
|
+ else if (dccpflag) {
|
||
|
+ proto = "dccp";
|
||
|
+ }
|
||
|
+# endif
|
||
|
+ else {
|
||
|
+ proto = "tcp";
|
||
|
+ }
|
||
|
+
|
||
|
+ return proto;
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* remote_connect()
|
||
|
* Returns a socket connected to a remote host. Properly binds to a local
|
||
|
@@ -1047,8 +1096,21 @@ remote_connect(const char *host, const c
|
||
|
# endif
|
||
|
memset(&ahints, 0, sizeof(struct addrinfo));
|
||
|
ahints.ai_family = res->ai_family;
|
||
|
- ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
|
||
|
- ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
|
||
|
+ if (uflag) {
|
||
|
+ ahints.ai_socktype = SOCK_DGRAM;
|
||
|
+ ahints.ai_protocol = IPPROTO_UDP;
|
||
|
+
|
||
|
+ }
|
||
|
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
|
+ else if (dccpflag) {
|
||
|
+ hints.ai_socktype = SOCK_DCCP;
|
||
|
+ hints.ai_protocol = IPPROTO_DCCP;
|
||
|
+ }
|
||
|
+# endif
|
||
|
+ else {
|
||
|
+ ahints.ai_socktype = SOCK_STREAM;
|
||
|
+ ahints.ai_protocol = IPPROTO_TCP;
|
||
|
+ }
|
||
|
ahints.ai_flags = AI_PASSIVE;
|
||
|
if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
|
||
|
errx(1, "getaddrinfo: %s", gai_strerror(error));
|
||
|
@@ -1060,15 +1122,16 @@ remote_connect(const char *host, const c
|
||
|
}
|
||
|
|
||
|
set_common_sockopts(s, res->ai_family);
|
||
|
+ char *proto = proto_name(uflag, dccpflag);
|
||
|
|
||
|
if ((error = connect_with_timeout(s, res->ai_addr, res->ai_addrlen, timeout)) == CONNECTION_SUCCESS)
|
||
|
break;
|
||
|
if (vflag && error == CONNECTION_FAILED)
|
||
|
warn("connect to %s port %s (%s) failed", host, port,
|
||
|
- uflag ? "udp" : "tcp");
|
||
|
- else if (vflag && error == CONNECTION_TIMEOUT)
|
||
|
+ proto);
|
||
|
+ else if (vflag && error == CONNECTION_TIMEOUT)
|
||
|
warn("connect to %s port %s (%s) timed out", host, port,
|
||
|
- uflag ? "udp" : "tcp");
|
||
|
+ proto);
|
||
|
|
||
|
save_errno = errno;
|
||
|
close(s);
|
||
|
@@ -1654,7 +1717,8 @@ build_ports(char *p)
|
||
|
int hi, lo, cp;
|
||
|
int x = 0;
|
||
|
|
||
|
- sv = getservbyname(p, uflag ? "udp" : "tcp");
|
||
|
+ char *proto = proto_name(uflag, dccpflag);
|
||
|
+ sv = getservbyname(p, proto);
|
||
|
if (sv) {
|
||
|
if (asprintf(&portlist[0], "%d", ntohs(sv->s_port)) < 0)
|
||
|
err(1, "asprintf");
|
||
|
@@ -1991,6 +2055,7 @@ help(void)
|
||
|
\t-w timeout Timeout for connects and final net reads\n\
|
||
|
\t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
|
||
|
\t-x addr[:port]\tSpecify proxy address and port\n\
|
||
|
+ \t-Z DCCP mode\n\
|
||
|
\t-z Zero-I/O mode [used for scanning]\n\
|
||
|
Port numbers can be individual or ranges: lo-hi [inclusive]\n");
|
||
|
exit(0);
|
||
|
@@ -2000,7 +2065,7 @@ void
|
||
|
usage(int ret)
|
||
|
{
|
||
|
fprintf(stderr,
|
||
|
- "usage: nc [-46CDdFhklNnrStUuvz] [-I length] [-i interval] [-M ttl]\n"
|
||
|
+ "usage: nc [-46CDdFhklNnrStUuvZz] [-I length] [-i interval] [-M ttl]\n"
|
||
|
"\t [-m minttl] [-O length] [-P proxy_username] [-p source_port]\n"
|
||
|
"\t [-q seconds] [-s source] [-T keyword] [-V rtable] [-w timeout] "
|
||
|
"[-X proxy_protocol]\n"
|