[c5c522c] | 1 | From: Aron Xu <aron@debian.org> |
---|
| 2 | Date: Mon, 13 Feb 2012 15:56:51 +0800 |
---|
| 3 | Subject: dccp support |
---|
| 4 | |
---|
| 5 | --- |
---|
| 6 | nc.1 | 4 ++- |
---|
| 7 | netcat.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
---|
| 8 | 2 files changed, 93 insertions(+), 22 deletions(-) |
---|
| 9 | |
---|
| 10 | diff --git a/nc.1 b/nc.1 |
---|
| 11 | index 0d92b74..60e3668 100644 |
---|
| 12 | --- a/nc.1 |
---|
| 13 | +++ b/nc.1 |
---|
| 14 | @@ -34,7 +34,7 @@ |
---|
| 15 | .Sh SYNOPSIS |
---|
| 16 | .Nm nc |
---|
| 17 | .Bk -words |
---|
| 18 | -.Op Fl 46CDdhklnrStUuvz |
---|
| 19 | +.Op Fl 46CDdhklnrStUuvZz |
---|
| 20 | .Op Fl I Ar length |
---|
| 21 | .Op Fl i Ar interval |
---|
| 22 | .Op Fl O Ar length |
---|
| 23 | @@ -257,6 +257,8 @@ If |
---|
| 24 | .Ar port |
---|
| 25 | is not specified, the well-known port for the proxy protocol is used (1080 |
---|
| 26 | for SOCKS, 3128 for HTTPS). |
---|
| 27 | +.It Fl Z |
---|
| 28 | +DCCP mode. |
---|
| 29 | .It Fl z |
---|
| 30 | Specifies that |
---|
| 31 | .Nm |
---|
| 32 | diff --git a/netcat.c b/netcat.c |
---|
| 33 | index eb3453e..56cc15e 100644 |
---|
| 34 | --- a/netcat.c |
---|
| 35 | +++ b/netcat.c |
---|
| 36 | @@ -129,6 +129,7 @@ int rflag; /* Random ports flag */ |
---|
| 37 | char *sflag; /* Source Address */ |
---|
| 38 | int tflag; /* Telnet Emulation */ |
---|
| 39 | int uflag; /* UDP - Default to TCP */ |
---|
| 40 | +int dccpflag; /* DCCP - Default to TCP */ |
---|
| 41 | int vflag; /* Verbosity */ |
---|
| 42 | int xflag; /* Socks proxy */ |
---|
| 43 | int zflag; /* Port Scan Flag */ |
---|
| 44 | @@ -160,6 +161,7 @@ int unix_listen(char *); |
---|
| 45 | void set_common_sockopts(int); |
---|
| 46 | int map_tos(char *, int *); |
---|
| 47 | void usage(int); |
---|
| 48 | +char *proto_name(int uflag, int dccpflag); |
---|
| 49 | |
---|
| 50 | static int connect_with_timeout(int fd, const struct sockaddr *sa, |
---|
| 51 | socklen_t salen, int ctimeout); |
---|
| 52 | @@ -187,7 +189,7 @@ main(int argc, char *argv[]) |
---|
| 53 | sv = NULL; |
---|
| 54 | |
---|
| 55 | while ((ch = getopt(argc, argv, |
---|
| 56 | - "46CDdhI:i:jklnO:P:p:q:rSs:tT:UuV:vw:X:x:z")) != -1) { |
---|
| 57 | + "46CDdhI:i:jklnO:P:p:q:rSs:tT:UuV:vw:X:x:Zz")) != -1) { |
---|
| 58 | switch (ch) { |
---|
| 59 | case '4': |
---|
| 60 | family = AF_INET; |
---|
| 61 | @@ -258,6 +260,13 @@ main(int argc, char *argv[]) |
---|
| 62 | case 'u': |
---|
| 63 | uflag = 1; |
---|
| 64 | break; |
---|
| 65 | + case 'Z': |
---|
| 66 | +# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP) |
---|
| 67 | + dccpflag = 1; |
---|
| 68 | +# else |
---|
| 69 | + errx(1, "no DCCP support available"); |
---|
| 70 | +# endif |
---|
| 71 | + break; |
---|
| 72 | case 'V': |
---|
| 73 | # if defined(RT_TABLEID_MAX) |
---|
| 74 | rtableid = (unsigned int)strtonum(optarg, 0, |
---|
| 75 | @@ -333,6 +342,12 @@ main(int argc, char *argv[]) |
---|
| 76 | |
---|
| 77 | /* Cruft to make sure options are clean, and used properly. */ |
---|
| 78 | if (argv[0] && !argv[1] && family == AF_UNIX) { |
---|
| 79 | + if (uflag) |
---|
| 80 | + errx(1, "cannot use -u and -U"); |
---|
| 81 | +# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP) |
---|
| 82 | + if (dccpflag) |
---|
| 83 | + errx(1, "cannot use -Z and -U"); |
---|
| 84 | +# endif |
---|
| 85 | host = argv[0]; |
---|
| 86 | uport = NULL; |
---|
| 87 | } else if (!argv[0] && lflag) { |
---|
| 88 | @@ -374,8 +389,20 @@ main(int argc, char *argv[]) |
---|
| 89 | if (family != AF_UNIX) { |
---|
| 90 | memset(&hints, 0, sizeof(struct addrinfo)); |
---|
| 91 | hints.ai_family = family; |
---|
| 92 | - hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; |
---|
| 93 | - hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; |
---|
| 94 | + if (uflag) { |
---|
| 95 | + hints.ai_socktype = SOCK_DGRAM; |
---|
| 96 | + hints.ai_protocol = IPPROTO_UDP; |
---|
| 97 | + } |
---|
| 98 | +# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP) |
---|
| 99 | + else if (dccpflag) { |
---|
| 100 | + hints.ai_socktype = SOCK_DCCP; |
---|
| 101 | + hints.ai_protocol = IPPROTO_DCCP; |
---|
| 102 | + } |
---|
| 103 | +# endif |
---|
| 104 | + else { |
---|
| 105 | + hints.ai_socktype = SOCK_STREAM; |
---|
| 106 | + hints.ai_protocol = IPPROTO_TCP; |
---|
| 107 | + } |
---|
| 108 | if (nflag) |
---|
| 109 | hints.ai_flags |= AI_NUMERICHOST; |
---|
| 110 | } |
---|
| 111 | @@ -383,7 +410,10 @@ main(int argc, char *argv[]) |
---|
| 112 | if (xflag) { |
---|
| 113 | if (uflag) |
---|
| 114 | errx(1, "no proxy support for UDP mode"); |
---|
| 115 | - |
---|
| 116 | +# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP) |
---|
| 117 | + if (dccpflag) |
---|
| 118 | + errx(1, "no proxy support for DCCP mode"); |
---|
| 119 | +# endif |
---|
| 120 | if (lflag) |
---|
| 121 | errx(1, "no proxy support for listen"); |
---|
| 122 | |
---|
| 123 | @@ -427,12 +457,12 @@ main(int argc, char *argv[]) |
---|
| 124 | err(1, NULL); |
---|
| 125 | |
---|
| 126 | char* local; |
---|
| 127 | - if (family == AF_INET6 |
---|
| 128 | + if (family == AF_INET6 ) |
---|
| 129 | local = "0.0.0.0"; |
---|
| 130 | else if (family == AF_INET) |
---|
| 131 | local = ":::"; |
---|
| 132 | else |
---|
| 133 | - local = "unknown" |
---|
| 134 | + local = "unknown"; |
---|
| 135 | fprintf(stderr, "Listening on [%s] (family %d, port %d)\n", |
---|
| 136 | host ?: local, |
---|
| 137 | family, |
---|
| 138 | @@ -463,12 +493,13 @@ main(int argc, char *argv[]) |
---|
| 139 | connfd = accept(s, (struct sockaddr *)&cliaddr, |
---|
| 140 | &len); |
---|
| 141 | if(vflag) { |
---|
| 142 | + char *proto = proto_name(uflag, dccpflag); |
---|
| 143 | /* Don't look up port if -n. */ |
---|
| 144 | if (nflag) |
---|
| 145 | sv = NULL; |
---|
| 146 | else |
---|
| 147 | sv = getservbyport(ntohs(atoi(uport)), |
---|
| 148 | - uflag ? "udp" : "tcp"); |
---|
| 149 | + proto); |
---|
| 150 | |
---|
| 151 | if (((struct sockaddr *)&cliaddr)->sa_family == AF_INET) { |
---|
| 152 | char dst[INET_ADDRSTRLEN]; |
---|
| 153 | @@ -476,7 +507,7 @@ main(int argc, char *argv[]) |
---|
| 154 | fprintf(stderr, "Connection from [%s] port %s [%s/%s] accepted (family %d, sport %d)\n", |
---|
| 155 | dst, |
---|
| 156 | uport, |
---|
| 157 | - uflag ? "udp" : "tcp", |
---|
| 158 | + proto, |
---|
| 159 | sv ? sv->s_name : "*", |
---|
| 160 | ((struct sockaddr *)(&cliaddr))->sa_family, |
---|
| 161 | ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); |
---|
| 162 | @@ -487,7 +518,7 @@ main(int argc, char *argv[]) |
---|
| 163 | fprintf(stderr, "Connection from [%s] port %s [%s/%s] accepted (family %d, sport %d)\n", |
---|
| 164 | dst, |
---|
| 165 | uport, |
---|
| 166 | - uflag ? "udp" : "tcp", |
---|
| 167 | + proto, |
---|
| 168 | sv ? sv->s_name : "*", |
---|
| 169 | ((struct sockaddr *)&cliaddr)->sa_family, |
---|
| 170 | ntohs(((struct sockaddr_in6 *)&cliaddr)->sin6_port)); |
---|
| 171 | @@ -495,7 +526,7 @@ main(int argc, char *argv[]) |
---|
| 172 | else { |
---|
| 173 | fprintf(stderr, "Connection from unknown port %s [%s/%s] accepted (family %d, sport %d)\n", |
---|
| 174 | uport, |
---|
| 175 | - uflag ? "udp" : "tcp", |
---|
| 176 | + proto, |
---|
| 177 | sv ? sv->s_name : "*", |
---|
| 178 | ((struct sockaddr *)(&cliaddr))->sa_family, |
---|
| 179 | ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); |
---|
| 180 | @@ -559,19 +590,20 @@ main(int argc, char *argv[]) |
---|
| 181 | } |
---|
| 182 | } |
---|
| 183 | |
---|
| 184 | + char *proto = proto_name(uflag, dccpflag); |
---|
| 185 | /* Don't look up port if -n. */ |
---|
| 186 | if (nflag) |
---|
| 187 | sv = NULL; |
---|
| 188 | else { |
---|
| 189 | sv = getservbyport( |
---|
| 190 | ntohs(atoi(portlist[i])), |
---|
| 191 | - uflag ? "udp" : "tcp"); |
---|
| 192 | + proto); |
---|
| 193 | } |
---|
| 194 | |
---|
| 195 | fprintf(stderr, |
---|
| 196 | "Connection to %s %s port [%s/%s] " |
---|
| 197 | "succeeded!\n", host, portlist[i], |
---|
| 198 | - uflag ? "udp" : "tcp", |
---|
| 199 | + proto, |
---|
| 200 | sv ? sv->s_name : "*"); |
---|
| 201 | } |
---|
| 202 | if (!zflag) |
---|
| 203 | @@ -671,6 +703,24 @@ unix_listen(char *path) |
---|
| 204 | return (s); |
---|
| 205 | } |
---|
| 206 | |
---|
| 207 | +char *proto_name(uflag, dccpflag) { |
---|
| 208 | + |
---|
| 209 | + char *proto = NULL; |
---|
| 210 | + if (uflag) { |
---|
| 211 | + proto = "udp"; |
---|
| 212 | + } |
---|
| 213 | +# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP) |
---|
| 214 | + else if (dccpflag) { |
---|
| 215 | + proto = "dccp"; |
---|
| 216 | + } |
---|
| 217 | +# endif |
---|
| 218 | + else { |
---|
| 219 | + proto = "tcp"; |
---|
| 220 | + } |
---|
| 221 | + |
---|
| 222 | + return proto; |
---|
| 223 | +} |
---|
| 224 | + |
---|
| 225 | /* |
---|
| 226 | * remote_connect() |
---|
| 227 | * Returns a socket connected to a remote host. Properly binds to a local |
---|
| 228 | @@ -709,8 +759,21 @@ remote_connect(const char *host, const char *port, struct addrinfo hints) |
---|
| 229 | # endif |
---|
| 230 | memset(&ahints, 0, sizeof(struct addrinfo)); |
---|
| 231 | ahints.ai_family = res0->ai_family; |
---|
| 232 | - ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; |
---|
| 233 | - ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; |
---|
| 234 | + if (uflag) { |
---|
| 235 | + ahints.ai_socktype = SOCK_DGRAM; |
---|
| 236 | + ahints.ai_protocol = IPPROTO_UDP; |
---|
| 237 | + |
---|
| 238 | + } |
---|
| 239 | +# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP) |
---|
| 240 | + else if (dccpflag) { |
---|
| 241 | + hints.ai_socktype = SOCK_DCCP; |
---|
| 242 | + hints.ai_protocol = IPPROTO_DCCP; |
---|
| 243 | + } |
---|
| 244 | +# endif |
---|
| 245 | + else { |
---|
| 246 | + ahints.ai_socktype = SOCK_STREAM; |
---|
| 247 | + ahints.ai_protocol = IPPROTO_TCP; |
---|
| 248 | + } |
---|
| 249 | ahints.ai_flags = AI_PASSIVE; |
---|
| 250 | if ((error = getaddrinfo(sflag, pflag, &ahints, &ares))) |
---|
| 251 | errx(1, "getaddrinfo: %s", gai_strerror(error)); |
---|
| 252 | @@ -722,15 +785,19 @@ remote_connect(const char *host, const char *port, struct addrinfo hints) |
---|
| 253 | } |
---|
| 254 | |
---|
| 255 | set_common_sockopts(s); |
---|
| 256 | + char *proto = proto_name(uflag, dccpflag); |
---|
| 257 | |
---|
| 258 | - if ((error = connect_with_timeout(s, res0->ai_addr, res0->ai_addrlen, timeout))== CONNECTION_SUCCESS) |
---|
| 259 | + if ((error = connect_with_timeout(s, res0->ai_addr, res0->ai_addrlen, timeout))== CONNECTION_SUCCESS) { |
---|
| 260 | break; |
---|
| 261 | - else if (vflag && error == CONNECTION_FAILED) |
---|
| 262 | + } |
---|
| 263 | + else if (vflag && error == CONNECTION_FAILED) { |
---|
| 264 | warn("connect to %s port %s (%s) failed", host, port, |
---|
| 265 | - uflag ? "udp" : "tcp"); |
---|
| 266 | - else if (vflag && error == CONNECTION_TIMEOUT) |
---|
| 267 | + proto); |
---|
| 268 | + } |
---|
| 269 | + else if (vflag && error == CONNECTION_TIMEOUT) { |
---|
| 270 | warn("connect to %s port %s (%s) timed out", host, port, |
---|
| 271 | - uflag ? "udp" : "tcp"); |
---|
| 272 | + proto); |
---|
| 273 | + } |
---|
| 274 | |
---|
| 275 | close(s); |
---|
| 276 | s = -1; |
---|
| 277 | @@ -1047,7 +1114,8 @@ build_ports(char *p) |
---|
| 278 | int hi, lo, cp; |
---|
| 279 | int x = 0; |
---|
| 280 | |
---|
| 281 | - sv = getservbyname(p, uflag ? "udp" : "tcp"); |
---|
| 282 | + char *proto = proto_name(uflag, dccpflag); |
---|
| 283 | + sv = getservbyname(p, proto); |
---|
| 284 | if (sv) { |
---|
| 285 | portlist[0] = calloc(1, PORT_MAX_LEN); |
---|
| 286 | if (portlist[0] == NULL) |
---|
| 287 | @@ -1252,6 +1320,7 @@ help(void) |
---|
| 288 | \t-w secs\t Timeout for connects and final net reads\n\ |
---|
| 289 | \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\ |
---|
| 290 | \t-x addr[:port]\tSpecify proxy address and port\n\ |
---|
| 291 | + \t-Z DCCP mode\n\ |
---|
| 292 | \t-z Zero-I/O mode [used for scanning]\n\ |
---|
| 293 | Port numbers can be individual or ranges: lo-hi [inclusive]\n"); |
---|
| 294 | exit(0); |
---|
| 295 | @@ -1261,7 +1330,7 @@ void |
---|
| 296 | usage(int ret) |
---|
| 297 | { |
---|
| 298 | fprintf(stderr, |
---|
| 299 | - "usage: nc [-46CDdhjklnrStUuvz] [-I length] [-i interval] [-O length]\n" |
---|
| 300 | + "usage: nc [-46CDdhjklnrStUuvZz] [-I length] [-i interval] [-O length]\n" |
---|
| 301 | "\t [-P proxy_username] [-p source_port] [-q seconds] [-s source]\n" |
---|
| 302 | "\t [-T toskeyword] [-V rtable] [-w timeout] [-X proxy_protocol]\n" |
---|
| 303 | "\t [-x proxy_address[:port]] [destination] [port]\n"); |
---|
| 304 | -- |
---|