diff options
Diffstat (limited to 'contrib/netcat/netcat.c')
-rw-r--r-- | contrib/netcat/netcat.c | 153 |
1 files changed, 99 insertions, 54 deletions
diff --git a/contrib/netcat/netcat.c b/contrib/netcat/netcat.c index 53e55ed..bf586ce 100644 --- a/contrib/netcat/netcat.c +++ b/contrib/netcat/netcat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: netcat.c,v 1.76 2004/12/10 16:51:31 hshoexer Exp $ */ +/* $OpenBSD: netcat.c,v 1.87 2006/02/01 21:33:14 otto Exp $ */ /* * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> * @@ -40,10 +40,12 @@ #include <sys/un.h> #include <netinet/in.h> +#include <netinet/in_systm.h> #ifdef IPSEC #include <netinet6/ipsec.h> #endif #include <netinet/tcp.h> +#include <netinet/ip.h> #include <arpa/telnet.h> #include <err.h> @@ -56,6 +58,8 @@ #include <string.h> #include <unistd.h> #include <fcntl.h> +#include <limits.h> +#include "atomicio.h" #ifndef SUN_LEN #define SUN_LEN(su) \ @@ -69,10 +73,12 @@ int Eflag; /* Use IPsec ESP */ int dflag; /* detached, no stdin */ int iflag; /* Interval Flag */ +int jflag; /* use jumbo frames if we can */ int kflag; /* More than one connect */ int lflag; /* Bind to local port */ int nflag; /* Don't do name look up */ int oflag; /* Once only: stop on EOF */ +char *Pflag; /* Proxy username */ char *pflag; /* Localport flag */ int rflag; /* Random ports flag */ char *sflag; /* Source Address */ @@ -83,23 +89,25 @@ int xflag; /* Socks proxy */ int zflag; /* Port Scan Flag */ int Dflag; /* sodebug */ int Sflag; /* TCP MD5 signature option */ +int Tflag = -1; /* IP Type of Service */ int timeout = -1; int family = AF_UNSPEC; char *portlist[PORT_MAX+1]; -ssize_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t); void atelnet(int, unsigned char *, unsigned int); void build_ports(char *); void help(void); int local_listen(char *, char *, struct addrinfo); void readwrite(int); -int remote_connect(char *, char *, struct addrinfo); -int socks_connect(char *, char *, struct addrinfo, char *, char *, - struct addrinfo, int); +int remote_connect(const char *, const char *, struct addrinfo); +int socks_connect(const char *, const char *, struct addrinfo, + const char *, const char *, struct addrinfo, int, const char *); int udptest(int); int unix_connect(char *); int unix_listen(char *); +void set_common_sockopts(int); +int parse_iptos(char *); void usage(int); #ifdef IPSEC @@ -118,7 +126,7 @@ main(int argc, char *argv[]) socklen_t len; struct sockaddr_storage cliaddr; char *proxy; - char *proxyhost = "", *proxyport = NULL; + const char *proxyhost = "", *proxyport = NULL; struct addrinfo proxyhints; ret = 1; @@ -130,7 +138,8 @@ main(int argc, char *argv[]) endp = NULL; sv = NULL; - while ((ch = getopt(argc, argv, "46e:DEdhi:klnop:rSs:tUuvw:X:x:z")) != -1) { + while ((ch = getopt(argc, argv, + "46e:DEdhi:jklnoP:p:rSs:tT:Uuvw:X:x:z")) != -1) { switch (ch) { case '4': family = AF_INET; @@ -177,6 +186,11 @@ main(int argc, char *argv[]) if (iflag < 0 || *endp != '\0') errx(1, "interval cannot be negative"); break; +#ifdef SO_JUMBO + case 'j': + jflag = 1; + break; +#endif case 'k': kflag = 1; break; @@ -189,6 +203,9 @@ main(int argc, char *argv[]) case 'o': oflag = 1; break; + case 'P': + Pflag = optarg; + break; case 'p': pflag = optarg; break; @@ -229,6 +246,9 @@ main(int argc, char *argv[]) case 'S': Sflag = 1; break; + case 'T': + Tflag = parse_iptos(optarg); + break; default: usage(1); } @@ -319,12 +339,13 @@ main(int argc, char *argv[]) * functions to talk to the caller. */ if (uflag) { - int rv; - char buf[1024]; + int rv, plen; + char buf[8192]; struct sockaddr_storage z; len = sizeof(z); - rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK, + plen = jflag ? 8192 : 1024; + rv = recvfrom(s, buf, plen, MSG_PEEK, (struct sockaddr *)&z, &len); if (rv < 0) err(1, "recvfrom"); @@ -335,6 +356,7 @@ main(int argc, char *argv[]) connfd = s; } else { + len = sizeof(cliaddr); connfd = accept(s, (struct sockaddr *)&cliaddr, &len); } @@ -371,7 +393,8 @@ main(int argc, char *argv[]) if (xflag) s = socks_connect(host, portlist[i], hints, - proxyhost, proxyport, proxyhints, socksv); + proxyhost, proxyport, proxyhints, socksv, + Pflag); else s = remote_connect(host, portlist[i], hints); @@ -485,10 +508,10 @@ unix_listen(char *path) * port or source address if needed. Returns -1 on failure. */ int -remote_connect(char *host, char *port, struct addrinfo hints) +remote_connect(const char *host, const char *port, struct addrinfo hints) { struct addrinfo *res, *res0; - int s, error, x = 1; + int s, error; if ((error = getaddrinfo(host, port, &hints, &res))) errx(1, "getaddrinfo: %s", gai_strerror(error)); @@ -509,13 +532,6 @@ remote_connect(char *host, char *port, struct addrinfo hints) if (sflag || pflag) { struct addrinfo ahints, *ares; - if (!(sflag && pflag)) { - if (!sflag) - sflag = NULL; - else - pflag = NULL; - } - memset(&ahints, 0, sizeof(struct addrinfo)); ahints.ai_family = res0->ai_family; ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; @@ -529,16 +545,8 @@ remote_connect(char *host, char *port, struct addrinfo hints) errx(1, "bind failed: %s", strerror(errno)); freeaddrinfo(ares); } - if (Sflag) { - if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, - &x, sizeof(x)) == -1) - err(1, NULL); - } - if (Dflag) { - if (setsockopt(s, SOL_SOCKET, SO_DEBUG, - &x, sizeof(x)) == -1) - err(1, NULL); - } + + set_common_sockopts(s); if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0) break; @@ -583,7 +591,7 @@ local_listen(char *host, char *port, struct addrinfo hints) res0 = res; do { if ((s = socket(res0->ai_family, res0->ai_socktype, - res0->ai_protocol)) == 0) + res0->ai_protocol)) < 0) continue; ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x)); @@ -595,17 +603,6 @@ local_listen(char *host, char *port, struct addrinfo hints) if (ipsec_policy[1] != NULL) add_ipsec_policy(s, ipsec_policy[1]); #endif - if (Sflag) { - ret = setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, - &x, sizeof(x)); - if (ret == -1) - err(1, NULL); - } - if (Dflag) { - if (setsockopt(s, SOL_SOCKET, SO_DEBUG, - &x, sizeof(x)) == -1) - err(1, NULL); - } if (bind(s, (struct sockaddr *)res0->ai_addr, res0->ai_addrlen) == 0) @@ -633,9 +630,12 @@ void readwrite(int nfd) { struct pollfd pfd[2]; - unsigned char buf[BUFSIZ]; - int wfd = fileno(stdin), n; + unsigned char buf[8192]; + int n, wfd = fileno(stdin); int lfd = fileno(stdout); + int plen; + + plen = jflag ? 8192 : 1024; /* Setup Network FD */ pfd[0].fd = nfd; @@ -658,7 +658,7 @@ readwrite(int nfd) return; if (pfd[0].revents & POLLIN) { - if ((n = read(nfd, buf, sizeof(buf))) < 0) + if ((n = read(nfd, buf, plen)) < 0) return; else if (n == 0) { shutdown(nfd, SHUT_RD); @@ -667,14 +667,13 @@ readwrite(int nfd) } else { if (tflag) atelnet(nfd, buf, n); - if (atomicio((ssize_t (*)(int, void *, size_t))write, - lfd, buf, n) != n) + if (atomicio(vwrite, lfd, buf, n) != n) return; } } if (!dflag && pfd[1].revents & POLLIN) { - if ((n = read(wfd, buf, sizeof(buf))) < 0 || + if ((n = read(wfd, buf, plen)) < 0 || (oflag && n == 0)) { return; } else if (n == 0) { @@ -682,8 +681,7 @@ readwrite(int nfd) pfd[1].fd = -1; pfd[1].events = 0; } else { - if (atomicio((ssize_t (*)(int, void *, size_t))write, - nfd, buf, n) != n) + if (atomicio(vwrite, nfd, buf, n) != n) return; } } @@ -714,9 +712,8 @@ atelnet(int nfd, unsigned char *buf, unsigned int size) p++; obuf[2] = *p; obuf[3] = '\0'; - if (atomicio((ssize_t (*)(int, void *, size_t))write, - nfd, obuf, 3) != 3) - warnx("Write Error!"); + if (atomicio(vwrite, nfd, obuf, 3) != 3) + warn("Write Error!"); obuf[0] = '\0'; } } @@ -808,6 +805,52 @@ udptest(int s) } void +set_common_sockopts(int s) +{ + int x = 1; + + if (Sflag) { + if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, + &x, sizeof(x)) == -1) + err(1, NULL); + } + if (Dflag) { + if (setsockopt(s, SOL_SOCKET, SO_DEBUG, + &x, sizeof(x)) == -1) + err(1, NULL); + } +#ifdef SO_JUMBO + if (jflag) { + if (setsockopt(s, SOL_SOCKET, SO_JUMBO, + &x, sizeof(x)) == -1) + err(1, NULL); + } +#endif + if (Tflag != -1) { + if (setsockopt(s, IPPROTO_IP, IP_TOS, + &Tflag, sizeof(Tflag)) == -1) + err(1, "set IP ToS"); + } +} + +int +parse_iptos(char *s) +{ + int tos = -1; + + if (strcmp(s, "lowdelay") == 0) + return (IPTOS_LOWDELAY); + if (strcmp(s, "throughput") == 0) + return (IPTOS_THROUGHPUT); + if (strcmp(s, "reliability") == 0) + return (IPTOS_RELIABILITY); + + if (sscanf(s, "0x%x", &tos) != 1 || tos < 0 || tos > 0xff) + errx(1, "invalid IP Type of Service"); + return (tos); +} + +void help(void) { usage(0); @@ -827,10 +870,12 @@ help(void) \t-k Keep inbound sockets open for multiple connects\n\ \t-l Listen mode, for inbound connects\n\ \t-n Suppress name/port resolutions\n\ + \t-P proxyuser\tUsername for proxy authentication\n\ \t-p port\t Specify local port for remote connects\n\ \t-r Randomize remote ports\n\ \t-S Enable the TCP MD5 signature option\n\ \t-s addr\t Local source address\n\ + \t-T ToS\t Set IP Type of Service\n\ \t-t Answer TELNET negotiation\n\ \t-U Use UNIX domain socket\n\ \t-u UDP mode\n\ @@ -877,7 +922,7 @@ usage(int ret) #else fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-i interval] [-p source_port]\n"); #endif - fprintf(stderr, "\t [-s source_ip_address] [-w timeout] [-X proxy_version]\n"); + fprintf(stderr, "\t [-s source_ip_address] [-T ToS] [-w timeout] [-X proxy_version]\n"); fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n"); if (ret) exit(1); |