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 | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- socks.c | 46 +++++++++++++++---------------- 4 files changed, 122 insertions(+), 41 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 d83cb5c..67cc19f 100644 --- a/nc.1 +++ b/nc.1 @@ -169,9 +169,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 @@ -193,6 +190,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 6358539..30591de 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 @@ -54,6 +94,8 @@ #include #include #include +#include +#include #include "atomicio.h" #ifndef SUN_LEN @@ -130,7 +172,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]; @@ -211,10 +253,14 @@ main(int argc, char *argv[]) uflag = 1; break; case 'V': +# if defined(RT_TABLEID_MAX) rtableid = (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; @@ -249,7 +295,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; @@ -276,6 +326,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); @@ -287,14 +346,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) { @@ -303,8 +355,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; } } @@ -598,16 +650,20 @@ remote_connect(const char *host, const char *port, struct addrinfo hints) res0->ai_protocol)) < 0) continue; +# if defined(RT_TABLEID_MAX) if (rtableid >= 0 && (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; @@ -707,13 +763,21 @@ local_listen(char *host, char *port, struct addrinfo hints) res0->ai_protocol)) < 0) continue; +# if defined(RT_TABLEID_MAX) if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, 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, res0->ai_family); @@ -1134,11 +1198,13 @@ set_common_sockopts(int s, int af) { 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) @@ -1201,6 +1267,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 }, @@ -1247,6 +1314,9 @@ report_connect(const struct sockaddr *sa, socklen_t salen) 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\ @@ -1278,7 +1348,7 @@ 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 @@ -1286,7 +1356,7 @@ usage(int ret) { fprintf(stderr, "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n" - "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\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 1b06e0e..57e4316 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 (%zu/6)", cnt); + err(1, "read failed (%zu/6)", (size_t)cnt); break; case SOCKS_IPV6: cnt = atomicio(read, proxyfd, buf + 4, 18); if (cnt != 18) - err(1, "read failed (%zu/18)", cnt); + err(1, "read failed (%zu/18)", (size_t)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(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 (%zu/2)", cnt); /* 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; } --