This patch is based on db2b1d9a8d4644ef892f47d84606ee96598d23fb of http://anonscm.debian.org/cgit/collab-maint/netcat-openbsd.git From: Aron Xu Date: Mon, 13 Feb 2012 15:59:31 +0800 Subject: port to linux with libsd --- Makefile | 17 ++++++++-- nc.1 | 4 +-- netcat.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------- socks.c | 46 +++++++++++++-------------- 4 files changed, 130 insertions(+), 42 deletions(-) diff --git a/Makefile b/Makefile index 150f829..96a6587 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,19 @@ -# $OpenBSD: Makefile,v 1.6 2001/09/02 18:45:41 jakob Exp $ +# $OpenBSD: Makefile,v 1.6 2001/09/02 18:45:41 jakob Exp $ PROG= nc SRCS= netcat.c atomicio.c socks.c -.include +LIBS= `pkg-config --libs libbsd` -lresolv +OBJS= $(SRCS:.c=.o) +CFLAGS= -g -O2 +LDFLAGS= -Wl,--no-add-needed + +all: nc +nc: $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o nc + +$(OBJS): %.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJS) nc diff --git a/nc.1 b/nc.1 index 75d1437..b7014a2 100644 --- a/nc.1 +++ b/nc.1 @@ -146,9 +146,6 @@ Proxy authentication is only supported for HTTP CONNECT proxies at present. Specifies the source port .Nm should use, subject to privilege restrictions and availability. -It is an error to use this option in conjunction with the -.Fl l -option. .It Fl r Specifies that source and/or destination ports should be chosen randomly instead of sequentially within a range or in the order that the system @@ -170,6 +167,7 @@ Change IPv4 TOS value. may be one of .Ar critical , .Ar inetcontrol , +.Ar lowcost , .Ar lowdelay , .Ar netcontrol , .Ar throughput , diff --git a/netcat.c b/netcat.c index cc4683a..9b2def2 100644 --- a/netcat.c +++ b/netcat.c @@ -42,6 +42,46 @@ #include #include +#ifndef IPTOS_LOWDELAY +# define IPTOS_LOWDELAY 0x10 +# define IPTOS_THROUGHPUT 0x08 +# define IPTOS_RELIABILITY 0x04 +# define IPTOS_LOWCOST 0x02 +# define IPTOS_MINCOST IPTOS_LOWCOST +#endif /* IPTOS_LOWDELAY */ + +# ifndef IPTOS_DSCP_AF11 +# define IPTOS_DSCP_AF11 0x28 +# define IPTOS_DSCP_AF12 0x30 +# define IPTOS_DSCP_AF13 0x38 +# define IPTOS_DSCP_AF21 0x48 +# define IPTOS_DSCP_AF22 0x50 +# define IPTOS_DSCP_AF23 0x58 +# define IPTOS_DSCP_AF31 0x68 +# define IPTOS_DSCP_AF32 0x70 +# define IPTOS_DSCP_AF33 0x78 +# define IPTOS_DSCP_AF41 0x88 +# define IPTOS_DSCP_AF42 0x90 +# define IPTOS_DSCP_AF43 0x98 +# define IPTOS_DSCP_EF 0xb8 +#endif /* IPTOS_DSCP_AF11 */ + +#ifndef IPTOS_DSCP_CS0 +# define IPTOS_DSCP_CS0 0x00 +# define IPTOS_DSCP_CS1 0x20 +# define IPTOS_DSCP_CS2 0x40 +# define IPTOS_DSCP_CS3 0x60 +# define IPTOS_DSCP_CS4 0x80 +# define IPTOS_DSCP_CS5 0xa0 +# define IPTOS_DSCP_CS6 0xc0 +# define IPTOS_DSCP_CS7 0xe0 +#endif /* IPTOS_DSCP_CS0 */ + +#ifndef IPTOS_DSCP_EF +# define IPTOS_DSCP_EF 0xb8 +#endif /* IPTOS_DSCP_EF */ + + #include #include #include @@ -53,6 +93,8 @@ #include #include #include +#include +#include #include "atomicio.h" #ifndef SUN_LEN @@ -118,7 +160,7 @@ main(int argc, char *argv[]) struct servent *sv; socklen_t len; struct sockaddr_storage cliaddr; - char *proxy; + char *proxy = NULL; const char *errstr, *proxyhost = "", *proxyport = NULL; struct addrinfo proxyhints; char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE]; @@ -164,7 +206,11 @@ main(int argc, char *argv[]) errx(1, "interval %s: %s", errstr, optarg); break; case 'j': +# if defined(SO_JUMBO) jflag = 1; +# else + errx(1, "no jumbo frame support available"); +# endif break; case 'k': kflag = 1; @@ -194,10 +240,14 @@ main(int argc, char *argv[]) uflag = 1; break; case 'V': +# if defined(RT_TABLEID_MAX) rtableid = (unsigned int)strtonum(optarg, 0, RT_TABLEID_MAX, &errstr); if (errstr) errx(1, "rtable %s: %s", errstr, optarg); +# else + errx(1, "no alternate routing table support available"); +# endif break; case 'v': vflag = 1; @@ -232,7 +282,11 @@ main(int argc, char *argv[]) errstr, optarg); break; case 'S': +# if defined(TCP_MD5SIG) Sflag = 1; +# else + errx(1, "no TCP MD5 signature support available"); +# endif break; case 'T': errstr = NULL; @@ -259,6 +313,15 @@ main(int argc, char *argv[]) if (argv[0] && !argv[1] && family == AF_UNIX) { host = argv[0]; uport = NULL; + } else if (!argv[0] && lflag) { + if (sflag) + errx(1, "cannot use -s and -l"); + if (zflag) + errx(1, "cannot use -z and -l"); + if (pflag) + uport=pflag; + } else if (!lflag && kflag) { + errx(1, "cannot use -k without -l"); } else if (argv[0] && !argv[1]) { if (!lflag) usage(1); @@ -270,14 +333,7 @@ main(int argc, char *argv[]) } else usage(1); - if (lflag && sflag) - errx(1, "cannot use -s and -l"); - if (lflag && pflag) - errx(1, "cannot use -p and -l"); - if (lflag && zflag) - errx(1, "cannot use -z and -l"); - if (!lflag && kflag) - errx(1, "must use -l with -k"); + /* Get name of temporary socket for unix datagram client */ if ((family == AF_UNIX) && uflag && !lflag) { @@ -286,8 +342,8 @@ main(int argc, char *argv[]) } else { strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX", UNIX_DG_TMP_SOCKET_SIZE); - if (mktemp(unix_dg_tmp_socket_buf) == NULL) - err(1, "mktemp"); + if (mkstemp(unix_dg_tmp_socket_buf) == -1) + err(1, "mkstemp"); unix_dg_tmp_socket = unix_dg_tmp_socket_buf; } } @@ -563,18 +619,22 @@ remote_connect(const char *host, const char *port, struct addrinfo hints) res0->ai_protocol)) < 0) continue; +# if defined(RT_TABLEID_MAX) if (rtableid) { if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid, sizeof(rtableid)) == -1) err(1, "setsockopt SO_RTABLE"); } +# endif /* Bind to a local port or source address if specified. */ if (sflag || pflag) { struct addrinfo ahints, *ares; +# if defined (SO_BINDANY) /* try SO_BINDANY, but don't insist */ setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on)); +# endif memset(&ahints, 0, sizeof(struct addrinfo)); ahints.ai_family = res0->ai_family; ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; @@ -674,15 +734,23 @@ local_listen(char *host, char *port, struct addrinfo hints) res0->ai_protocol)) < 0) continue; +# if defined(RT_TABLEID_MAX) if (rtableid) { if (setsockopt(s, IPPROTO_IP, SO_RTABLE, &rtableid, sizeof(rtableid)) == -1) err(1, "setsockopt SO_RTABLE"); } +# endif + + ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); + if (ret == -1) + err(1, NULL); +# if defined(SO_REUSEPORT) ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x)); if (ret == -1) err(1, NULL); +# endif set_common_sockopts(s); @@ -886,21 +954,25 @@ set_common_sockopts(int s) { int x = 1; +# if defined(TCP_MD5SIG) if (Sflag) { if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, &x, sizeof(x)) == -1) err(1, NULL); } +# endif if (Dflag) { if (setsockopt(s, SOL_SOCKET, SO_DEBUG, &x, sizeof(x)) == -1) err(1, NULL); } +# if defined(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) @@ -949,6 +1021,7 @@ map_tos(char *s, int *val) { "cs7", IPTOS_DSCP_CS7 }, { "ef", IPTOS_DSCP_EF }, { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, + { "lowcost", IPTOS_LOWCOST }, { "lowdelay", IPTOS_LOWDELAY }, { "netcontrol", IPTOS_PREC_NETCONTROL }, { "reliability", IPTOS_RELIABILITY }, @@ -969,6 +1042,9 @@ map_tos(char *s, int *val) void help(void) { +# if defined(DEBIAN_VERSION) + fprintf(stderr, "OpenBSD netcat (Debian patchlevel " DEBIAN_VERSION ")\n"); +# endif usage(0); fprintf(stderr, "\tCommand Summary:\n\ \t-4 Use IPv4\n\ @@ -978,6 +1054,7 @@ help(void) \t-h This help text\n\ \t-I length TCP receive buffer length\n\ \t-i secs\t Delay interval for lines sent, ports scanned\n\ + \t-j Use jumbo frame\n\ \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\ @@ -998,15 +1075,15 @@ help(void) \t-x addr[:port]\tSpecify proxy address and port\n\ \t-z Zero-I/O mode [used for scanning]\n\ Port numbers can be individual or ranges: lo-hi [inclusive]\n"); - exit(1); + exit(0); } void usage(int ret) { fprintf(stderr, - "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n" - "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n" + "usage: nc [-46DdhjklnrStUuvz] [-I length] [-i interval] [-O length]\n" + "\t [-P proxy_username] [-p source_port] [-s source] [-T toskeyword]\n" "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n" "\t [-x proxy_address[:port]] [destination] [port]\n"); if (ret) diff --git a/socks.c b/socks.c index 71108d5..befd0a9 100644 --- a/socks.c +++ b/socks.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include "atomicio.h" #define SOCKS_PORT "1080" @@ -167,11 +167,11 @@ socks_connect(const char *host, const char *port, buf[2] = SOCKS_NOAUTH; cnt = atomicio(vwrite, proxyfd, buf, 3); if (cnt != 3) - err(1, "write failed (%zu/3)", cnt); + err(1, "write failed (%zu/3)", (size_t)cnt); cnt = atomicio(read, proxyfd, buf, 2); if (cnt != 2) - err(1, "read failed (%zu/3)", cnt); + err(1, "read failed (%zu/3)", (size_t)cnt); if (buf[1] == SOCKS_NOMETHOD) errx(1, "authentication method negotiation failed"); @@ -220,23 +220,23 @@ socks_connect(const char *host, const char *port, cnt = atomicio(vwrite, proxyfd, buf, wlen); if (cnt != wlen) - err(1, "write failed (%zu/%zu)", cnt, wlen); + err(1, "write failed (%zu/%zu)", (size_t)cnt, (size_t)wlen); cnt = atomicio(read, proxyfd, buf, 4); if (cnt != 4) - err(1, "read failed (%zu/4)", cnt); + err(1, "read failed (%zu/4)", (size_t)cnt); if (buf[1] != 0) errx(1, "connection failed, SOCKS error %d", buf[1]); switch (buf[3]) { case SOCKS_IPV4: cnt = atomicio(read, proxyfd, buf + 4, 6); if (cnt != 6) - err(1, "read failed (%d/6)", cnt); + err(1, "read failed (%lu/6)", (unsigned long)cnt); break; case SOCKS_IPV6: cnt = atomicio(read, proxyfd, buf + 4, 18); if (cnt != 18) - err(1, "read failed (%d/18)", cnt); + err(1, "read failed (%lu/18)", (unsigned long)cnt); break; default: errx(1, "connection failed, unsupported address type"); @@ -256,11 +256,11 @@ socks_connect(const char *host, const char *port, cnt = atomicio(vwrite, proxyfd, buf, wlen); if (cnt != wlen) - err(1, "write failed (%zu/%zu)", cnt, wlen); + err(1, "write failed (%zu/%zu)", (size_t)cnt, (size_t)wlen); cnt = atomicio(read, proxyfd, buf, 8); if (cnt != 8) - err(1, "read failed (%zu/8)", cnt); + err(1, "read failed (%zu/8)", (size_t)cnt); if (buf[1] != 90) errx(1, "connection failed, SOCKS error %d", buf[1]); } else if (socksv == -1) { @@ -272,39 +272,39 @@ socks_connect(const char *host, const char *port, /* Try to be sane about numeric IPv6 addresses */ if (strchr(host, ':') != NULL) { - r = snprintf(buf, sizeof(buf), + r = snprintf((char*)buf, sizeof(buf), "CONNECT [%s]:%d HTTP/1.0\r\n", host, ntohs(serverport)); } else { - r = snprintf(buf, sizeof(buf), + r = snprintf((char*)buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n", host, ntohs(serverport)); } if (r == -1 || (size_t)r >= sizeof(buf)) errx(1, "hostname too long"); - r = strlen(buf); + r = strlen((char*)buf); cnt = atomicio(vwrite, proxyfd, buf, r); if (cnt != r) - err(1, "write failed (%zu/%d)", cnt, r); + err(1, "write failed (%zu/%d)", (size_t)cnt, (int)r); if (authretry > 1) { char resp[1024]; proxypass = getproxypass(proxyuser, proxyhost); - r = snprintf(buf, sizeof(buf), "%s:%s", + r = snprintf((char*)buf, sizeof(buf), "%s:%s", proxyuser, proxypass); if (r == -1 || (size_t)r >= sizeof(buf) || - b64_ntop(buf, strlen(buf), resp, + b64_ntop(buf, strlen((char*)buf), resp, sizeof(resp)) == -1) errx(1, "Proxy username/password too long"); - r = snprintf(buf, sizeof(buf), "Proxy-Authorization: " + r = snprintf((char*)buf, sizeof((char*)buf), "Proxy-Authorization: " "Basic %s\r\n", resp); if (r == -1 || (size_t)r >= sizeof(buf)) errx(1, "Proxy auth response too long"); - r = strlen(buf); + r = strlen((char*)buf); if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != r) - err(1, "write failed (%zu/%d)", cnt, r); + err(1, "write failed (%zu/%d)", (size_t)cnt, r); } /* Terminate headers */ @@ -312,22 +312,22 @@ socks_connect(const char *host, const char *port, err(1, "write failed (2/%d)", r); /* Read status reply */ - proxy_read_line(proxyfd, buf, sizeof(buf)); + proxy_read_line(proxyfd, (char*)buf, sizeof(buf)); if (proxyuser != NULL && - strncmp(buf, "HTTP/1.0 407 ", 12) == 0) { + strncmp((char*)buf, "HTTP/1.0 407 ", 12) == 0) { if (authretry > 1) { fprintf(stderr, "Proxy authentication " "failed\n"); } close(proxyfd); goto again; - } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 && - strncmp(buf, "HTTP/1.1 200 ", 12) != 0) + } else if (strncmp((char*)buf, "HTTP/1.0 200 ", 12) != 0 && + strncmp((char*)buf, "HTTP/1.1 200 ", 12) != 0) errx(1, "Proxy error: \"%s\"", buf); /* Headers continue until we hit an empty line */ for (r = 0; r < HTTP_MAXHDRS; r++) { - proxy_read_line(proxyfd, buf, sizeof(buf)); + proxy_read_line(proxyfd, (char*)buf, sizeof(buf)); if (*buf == '\0') break; } --