1*cf5a6c84SAndroid Build Coastguard Worker /* netcat.c - Forward stdin/stdout to a file or network connection.
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2007 Rob Landley <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker *
5*cf5a6c84SAndroid Build Coastguard Worker * TODO: genericize for telnet/microcom/tail-f, fix -t with login_tty()
6*cf5a6c84SAndroid Build Coastguard Worker
7*cf5a6c84SAndroid Build Coastguard Worker USE_NETCAT(NEWTOY(netcat, "^tElLw#<1W#<1p#<1>65535q#<1O:o:s:f:46uUnz[!tlL][!Lw][!Lu][!46U][!oO]", TOYFLAG_BIN))
8*cf5a6c84SAndroid Build Coastguard Worker USE_NETCAT(OLDTOY(nc, netcat, TOYFLAG_USR|TOYFLAG_BIN))
9*cf5a6c84SAndroid Build Coastguard Worker
10*cf5a6c84SAndroid Build Coastguard Worker config NETCAT
11*cf5a6c84SAndroid Build Coastguard Worker bool "netcat"
12*cf5a6c84SAndroid Build Coastguard Worker default y
13*cf5a6c84SAndroid Build Coastguard Worker help
14*cf5a6c84SAndroid Build Coastguard Worker usage: netcat [-46ELlntUu] [-pqWw #] [-s addr] [-o FILE] {IPADDR PORTNUM|-f FILENAME|COMMAND...}
15*cf5a6c84SAndroid Build Coastguard Worker
16*cf5a6c84SAndroid Build Coastguard Worker Forward stdin/stdout to a file or network connection.
17*cf5a6c84SAndroid Build Coastguard Worker
18*cf5a6c84SAndroid Build Coastguard Worker -4 Force IPv4
19*cf5a6c84SAndroid Build Coastguard Worker -6 Force IPv6
20*cf5a6c84SAndroid Build Coastguard Worker -E Forward stderr
21*cf5a6c84SAndroid Build Coastguard Worker -f Use FILENAME (ala /dev/ttyS0) instead of network
22*cf5a6c84SAndroid Build Coastguard Worker -L Listen and background each incoming connection (server mode)
23*cf5a6c84SAndroid Build Coastguard Worker -l Listen for one incoming connection, then exit
24*cf5a6c84SAndroid Build Coastguard Worker -n No DNS lookup
25*cf5a6c84SAndroid Build Coastguard Worker -o Hex dump to FILE (show packets, -o- writes hex only to stdout)
26*cf5a6c84SAndroid Build Coastguard Worker -O Hex dump to FILE (streaming mode)
27*cf5a6c84SAndroid Build Coastguard Worker -p Local port number
28*cf5a6c84SAndroid Build Coastguard Worker -q Quit SECONDS after EOF on stdin, even if stdout hasn't closed yet
29*cf5a6c84SAndroid Build Coastguard Worker -s Local source address
30*cf5a6c84SAndroid Build Coastguard Worker -t Allocate tty
31*cf5a6c84SAndroid Build Coastguard Worker -u Use UDP
32*cf5a6c84SAndroid Build Coastguard Worker -U Use a UNIX domain socket
33*cf5a6c84SAndroid Build Coastguard Worker -W SECONDS timeout for more data on an idle connection
34*cf5a6c84SAndroid Build Coastguard Worker -w SECONDS timeout to establish connection
35*cf5a6c84SAndroid Build Coastguard Worker -z zero-I/O mode [used for scanning]
36*cf5a6c84SAndroid Build Coastguard Worker
37*cf5a6c84SAndroid Build Coastguard Worker When listening the COMMAND line is executed as a child process to handle
38*cf5a6c84SAndroid Build Coastguard Worker an incoming connection. With no COMMAND -l forwards the connection
39*cf5a6c84SAndroid Build Coastguard Worker to stdin/stdout. If no -p specified, -l prints the port it bound to and
40*cf5a6c84SAndroid Build Coastguard Worker backgrounds itself (returning immediately).
41*cf5a6c84SAndroid Build Coastguard Worker
42*cf5a6c84SAndroid Build Coastguard Worker For a quick-and-dirty server, try something like:
43*cf5a6c84SAndroid Build Coastguard Worker netcat -s 127.0.0.1 -p 1234 -tL sh -l
44*cf5a6c84SAndroid Build Coastguard Worker
45*cf5a6c84SAndroid Build Coastguard Worker Or use "stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho" with
46*cf5a6c84SAndroid Build Coastguard Worker netcat -f to connect to a serial port.
47*cf5a6c84SAndroid Build Coastguard Worker */
48*cf5a6c84SAndroid Build Coastguard Worker
49*cf5a6c84SAndroid Build Coastguard Worker #define FOR_netcat
50*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
51*cf5a6c84SAndroid Build Coastguard Worker
52*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
53*cf5a6c84SAndroid Build Coastguard Worker char *f, *s, *o, *O;
54*cf5a6c84SAndroid Build Coastguard Worker long q, p, W, w;
55*cf5a6c84SAndroid Build Coastguard Worker
56*cf5a6c84SAndroid Build Coastguard Worker unsigned ofd, olast, opos, ocount[2];
57*cf5a6c84SAndroid Build Coastguard Worker char obuf[16];
58*cf5a6c84SAndroid Build Coastguard Worker )
59*cf5a6c84SAndroid Build Coastguard Worker
timeout(int signum)60*cf5a6c84SAndroid Build Coastguard Worker static void timeout(int signum)
61*cf5a6c84SAndroid Build Coastguard Worker {
62*cf5a6c84SAndroid Build Coastguard Worker if (TT.w) error_exit("Timeout");
63*cf5a6c84SAndroid Build Coastguard Worker xexit();
64*cf5a6c84SAndroid Build Coastguard Worker }
65*cf5a6c84SAndroid Build Coastguard Worker
66*cf5a6c84SAndroid Build Coastguard Worker // open AF_UNIX socket
usock(char * name,int type,int out)67*cf5a6c84SAndroid Build Coastguard Worker static int usock(char *name, int type, int out)
68*cf5a6c84SAndroid Build Coastguard Worker {
69*cf5a6c84SAndroid Build Coastguard Worker int sockfd;
70*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_un sockaddr;
71*cf5a6c84SAndroid Build Coastguard Worker
72*cf5a6c84SAndroid Build Coastguard Worker memset(&sockaddr, 0, sizeof(struct sockaddr_un));
73*cf5a6c84SAndroid Build Coastguard Worker
74*cf5a6c84SAndroid Build Coastguard Worker if (strlen(name) + 1 > sizeof(sockaddr.sun_path))
75*cf5a6c84SAndroid Build Coastguard Worker error_exit("socket path too long %s", name);
76*cf5a6c84SAndroid Build Coastguard Worker strcpy(sockaddr.sun_path, name);
77*cf5a6c84SAndroid Build Coastguard Worker sockaddr.sun_family = AF_UNIX;
78*cf5a6c84SAndroid Build Coastguard Worker
79*cf5a6c84SAndroid Build Coastguard Worker sockfd = xsocket(AF_UNIX, type, 0);
80*cf5a6c84SAndroid Build Coastguard Worker (out?xconnect:xbind)(sockfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
81*cf5a6c84SAndroid Build Coastguard Worker
82*cf5a6c84SAndroid Build Coastguard Worker return sockfd;
83*cf5a6c84SAndroid Build Coastguard Worker }
84*cf5a6c84SAndroid Build Coastguard Worker
85*cf5a6c84SAndroid Build Coastguard Worker // Hex dump accumulated buffer data
oflush(void)86*cf5a6c84SAndroid Build Coastguard Worker void oflush(void)
87*cf5a6c84SAndroid Build Coastguard Worker {
88*cf5a6c84SAndroid Build Coastguard Worker char *s = toybuf;
89*cf5a6c84SAndroid Build Coastguard Worker unsigned *oc = TT.ocount+(TT.olast==1), uu;
90*cf5a6c84SAndroid Build Coastguard Worker
91*cf5a6c84SAndroid Build Coastguard Worker if (!TT.opos) return;
92*cf5a6c84SAndroid Build Coastguard Worker s += sprintf(toybuf, "%c %08x", 60+2*(TT.olast==1), *oc);
93*cf5a6c84SAndroid Build Coastguard Worker for (uu = 0; uu<16; uu++) {
94*cf5a6c84SAndroid Build Coastguard Worker s += sprintf(s, uu<TT.opos ? " %02x" : " ", TT.obuf[uu]);
95*cf5a6c84SAndroid Build Coastguard Worker if (TT.obuf[uu]-32u>95) TT.obuf[uu] = '.';
96*cf5a6c84SAndroid Build Coastguard Worker }
97*cf5a6c84SAndroid Build Coastguard Worker dprintf(TT.ofd, "%s # %.*s\n", toybuf, TT.opos, TT.obuf);
98*cf5a6c84SAndroid Build Coastguard Worker *oc += TT.opos;
99*cf5a6c84SAndroid Build Coastguard Worker TT.opos = 0;
100*cf5a6c84SAndroid Build Coastguard Worker }
101*cf5a6c84SAndroid Build Coastguard Worker
102*cf5a6c84SAndroid Build Coastguard Worker // Write data to output, and hex dump to -o if enabled.
ohexwrite(int fd,void * buf,size_t len)103*cf5a6c84SAndroid Build Coastguard Worker void ohexwrite(int fd, void *buf, size_t len)
104*cf5a6c84SAndroid Build Coastguard Worker {
105*cf5a6c84SAndroid Build Coastguard Worker // Hex dump if -o specified. Output is always to fd 1, input != 1.
106*cf5a6c84SAndroid Build Coastguard Worker if (TT.ofd) {
107*cf5a6c84SAndroid Build Coastguard Worker int i = 0, j;
108*cf5a6c84SAndroid Build Coastguard Worker
109*cf5a6c84SAndroid Build Coastguard Worker if (TT.olast != fd) oflush();
110*cf5a6c84SAndroid Build Coastguard Worker TT.olast = fd;
111*cf5a6c84SAndroid Build Coastguard Worker
112*cf5a6c84SAndroid Build Coastguard Worker while (i<len) {
113*cf5a6c84SAndroid Build Coastguard Worker j = minof(16-TT.opos, len-i);
114*cf5a6c84SAndroid Build Coastguard Worker memcpy(TT.obuf+TT.opos, buf+i, j);
115*cf5a6c84SAndroid Build Coastguard Worker TT.opos += j;
116*cf5a6c84SAndroid Build Coastguard Worker i += j;
117*cf5a6c84SAndroid Build Coastguard Worker if (TT.opos==16 || !TT.O) oflush();
118*cf5a6c84SAndroid Build Coastguard Worker }
119*cf5a6c84SAndroid Build Coastguard Worker
120*cf5a6c84SAndroid Build Coastguard Worker // Don't write data to stdout when -o goes to stdout.
121*cf5a6c84SAndroid Build Coastguard Worker if (TT.ofd==1 && fd==1) return;
122*cf5a6c84SAndroid Build Coastguard Worker }
123*cf5a6c84SAndroid Build Coastguard Worker
124*cf5a6c84SAndroid Build Coastguard Worker // Pass along raw data
125*cf5a6c84SAndroid Build Coastguard Worker xwrite(fd, buf, len);
126*cf5a6c84SAndroid Build Coastguard Worker }
127*cf5a6c84SAndroid Build Coastguard Worker
netcat_main(void)128*cf5a6c84SAndroid Build Coastguard Worker void netcat_main(void)
129*cf5a6c84SAndroid Build Coastguard Worker {
130*cf5a6c84SAndroid Build Coastguard Worker int sockfd = -1, in1 = 0, in2 = 0, out1 = 1, out2 = 1, family = AF_UNSPEC,
131*cf5a6c84SAndroid Build Coastguard Worker type = FLAG(u) ? SOCK_DGRAM : SOCK_STREAM;
132*cf5a6c84SAndroid Build Coastguard Worker socklen_t len;
133*cf5a6c84SAndroid Build Coastguard Worker pid_t child;
134*cf5a6c84SAndroid Build Coastguard Worker
135*cf5a6c84SAndroid Build Coastguard Worker // -o - disables normal writes to stdout, just gives hex dump.
136*cf5a6c84SAndroid Build Coastguard Worker if (TT.O) TT.o = TT.O;
137*cf5a6c84SAndroid Build Coastguard Worker if (TT.o) {
138*cf5a6c84SAndroid Build Coastguard Worker if (!strcmp(TT.o, "-")) TT.ofd = 1;
139*cf5a6c84SAndroid Build Coastguard Worker else TT.ofd = xcreate(TT.o, O_CREAT|O_TRUNC|O_WRONLY, 0666);
140*cf5a6c84SAndroid Build Coastguard Worker sigatexit(oflush);
141*cf5a6c84SAndroid Build Coastguard Worker }
142*cf5a6c84SAndroid Build Coastguard Worker
143*cf5a6c84SAndroid Build Coastguard Worker // Adjust idle and quit_delay to ms or -1 for no timeout
144*cf5a6c84SAndroid Build Coastguard Worker TT.W = TT.W ? TT.W*1000 : -1;
145*cf5a6c84SAndroid Build Coastguard Worker TT.q = TT.q ? TT.q*1000 : -1;
146*cf5a6c84SAndroid Build Coastguard Worker
147*cf5a6c84SAndroid Build Coastguard Worker xsignal(SIGCHLD, SIG_IGN);
148*cf5a6c84SAndroid Build Coastguard Worker if (TT.w) {
149*cf5a6c84SAndroid Build Coastguard Worker xsignal(SIGALRM, timeout);
150*cf5a6c84SAndroid Build Coastguard Worker alarm(TT.w);
151*cf5a6c84SAndroid Build Coastguard Worker }
152*cf5a6c84SAndroid Build Coastguard Worker
153*cf5a6c84SAndroid Build Coastguard Worker // The argument parsing logic can't make "<2" conditional on other
154*cf5a6c84SAndroid Build Coastguard Worker // arguments like -f and -l, so do it by hand here.
155*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(f) ? toys.optc : (!FLAG(l) && !FLAG(L) && toys.optc!=2-FLAG(U)))
156*cf5a6c84SAndroid Build Coastguard Worker help_exit("bad argument count");
157*cf5a6c84SAndroid Build Coastguard Worker
158*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(4)) family = AF_INET;
159*cf5a6c84SAndroid Build Coastguard Worker else if (FLAG(6)) family = AF_INET6;
160*cf5a6c84SAndroid Build Coastguard Worker else if (FLAG(U)) family = AF_UNIX;
161*cf5a6c84SAndroid Build Coastguard Worker
162*cf5a6c84SAndroid Build Coastguard Worker if (TT.f) {
163*cf5a6c84SAndroid Build Coastguard Worker in1 = out2 = xopen(TT.f, O_RDWR);
164*cf5a6c84SAndroid Build Coastguard Worker alarm(0);
165*cf5a6c84SAndroid Build Coastguard Worker pollinate(in1, in2, out1, out2, ohexwrite, TT.W, TT.q);
166*cf5a6c84SAndroid Build Coastguard Worker } else {
167*cf5a6c84SAndroid Build Coastguard Worker // Setup socket
168*cf5a6c84SAndroid Build Coastguard Worker if (!FLAG(l) && !FLAG(L)) {
169*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(U)) sockfd = usock(toys.optargs[0], type, 1);
170*cf5a6c84SAndroid Build Coastguard Worker else sockfd = xconnectany(xgetaddrinfo(toys.optargs[0], toys.optargs[1],
171*cf5a6c84SAndroid Build Coastguard Worker family, type, 0, AI_NUMERICHOST*FLAG(n)));
172*cf5a6c84SAndroid Build Coastguard Worker
173*cf5a6c84SAndroid Build Coastguard Worker // Do not perform any I/O in zero mode
174*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(z)) goto cleanup;
175*cf5a6c84SAndroid Build Coastguard Worker
176*cf5a6c84SAndroid Build Coastguard Worker // We have a connection. Disarm timeout and start poll/send loop.
177*cf5a6c84SAndroid Build Coastguard Worker alarm(0);
178*cf5a6c84SAndroid Build Coastguard Worker in1 = out2 = sockfd;
179*cf5a6c84SAndroid Build Coastguard Worker pollinate(in1, in2, out1, out2, ohexwrite, TT.W, TT.q);
180*cf5a6c84SAndroid Build Coastguard Worker } else {
181*cf5a6c84SAndroid Build Coastguard Worker // Listen for incoming connections
182*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(U)) {
183*cf5a6c84SAndroid Build Coastguard Worker if (!FLAG(s)) error_exit("-s must be provided if using -U with -L/-l");
184*cf5a6c84SAndroid Build Coastguard Worker sockfd = usock(TT.s, type, 0);
185*cf5a6c84SAndroid Build Coastguard Worker } else {
186*cf5a6c84SAndroid Build Coastguard Worker sprintf(toybuf, "%ld", TT.p);
187*cf5a6c84SAndroid Build Coastguard Worker sockfd = xbindany(xgetaddrinfo(TT.s, toybuf, family, type, 0, 0));
188*cf5a6c84SAndroid Build Coastguard Worker }
189*cf5a6c84SAndroid Build Coastguard Worker
190*cf5a6c84SAndroid Build Coastguard Worker if (!FLAG(u) && listen(sockfd, 5)) perror_exit("listen");
191*cf5a6c84SAndroid Build Coastguard Worker if (!TT.p && !FLAG(U)) {
192*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr* address = (void*)toybuf;
193*cf5a6c84SAndroid Build Coastguard Worker short port_be;
194*cf5a6c84SAndroid Build Coastguard Worker
195*cf5a6c84SAndroid Build Coastguard Worker len = sizeof(struct sockaddr_storage);
196*cf5a6c84SAndroid Build Coastguard Worker getsockname(sockfd, address, &len);
197*cf5a6c84SAndroid Build Coastguard Worker if (address->sa_family == AF_INET)
198*cf5a6c84SAndroid Build Coastguard Worker port_be = ((struct sockaddr_in*)address)->sin_port;
199*cf5a6c84SAndroid Build Coastguard Worker else if (address->sa_family == AF_INET6)
200*cf5a6c84SAndroid Build Coastguard Worker port_be = ((struct sockaddr_in6*)address)->sin6_port;
201*cf5a6c84SAndroid Build Coastguard Worker else perror_exit("getsockname: bad family");
202*cf5a6c84SAndroid Build Coastguard Worker
203*cf5a6c84SAndroid Build Coastguard Worker dprintf(1, "%d\n", SWAP_BE16(port_be));
204*cf5a6c84SAndroid Build Coastguard Worker // Return immediately if no -p and -Ll has arguments, so wrapper
205*cf5a6c84SAndroid Build Coastguard Worker // script can use port number.
206*cf5a6c84SAndroid Build Coastguard Worker if (CFG_TOYBOX_FORK && toys.optc && xfork()) goto cleanup;
207*cf5a6c84SAndroid Build Coastguard Worker }
208*cf5a6c84SAndroid Build Coastguard Worker
209*cf5a6c84SAndroid Build Coastguard Worker do {
210*cf5a6c84SAndroid Build Coastguard Worker len = sizeof(struct sockaddr_storage);
211*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(u)) {
212*cf5a6c84SAndroid Build Coastguard Worker if (-1 == recvfrom(in1 = dup(sockfd), &child, 1, MSG_PEEK,
213*cf5a6c84SAndroid Build Coastguard Worker (void *)toybuf, &len)) perror_exit("recvfrom");
214*cf5a6c84SAndroid Build Coastguard Worker } else if ((in1 = accept(sockfd, 0, 0))<0) perror_exit("accept");
215*cf5a6c84SAndroid Build Coastguard Worker out2 = in1;
216*cf5a6c84SAndroid Build Coastguard Worker child = 0;
217*cf5a6c84SAndroid Build Coastguard Worker
218*cf5a6c84SAndroid Build Coastguard Worker // We have a connection. Disarm timeout.
219*cf5a6c84SAndroid Build Coastguard Worker alarm(0);
220*cf5a6c84SAndroid Build Coastguard Worker
221*cf5a6c84SAndroid Build Coastguard Worker // Fork a child as necessary. Parent cleans up and continues here.
222*cf5a6c84SAndroid Build Coastguard Worker if (toys.optc && FLAG(L)) NOEXIT(child = XVFORK());
223*cf5a6c84SAndroid Build Coastguard Worker if (child) {
224*cf5a6c84SAndroid Build Coastguard Worker close(in1);
225*cf5a6c84SAndroid Build Coastguard Worker continue;
226*cf5a6c84SAndroid Build Coastguard Worker }
227*cf5a6c84SAndroid Build Coastguard Worker
228*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(u))
229*cf5a6c84SAndroid Build Coastguard Worker xconnect(in1, (void *)toybuf, sizeof(struct sockaddr_storage));
230*cf5a6c84SAndroid Build Coastguard Worker
231*cf5a6c84SAndroid Build Coastguard Worker // Cleanup and redirect for exec
232*cf5a6c84SAndroid Build Coastguard Worker if (toys.optc) {
233*cf5a6c84SAndroid Build Coastguard Worker // Do we need a tty?
234*cf5a6c84SAndroid Build Coastguard Worker // TODO nommu and -t only affects server mode...
235*cf5a6c84SAndroid Build Coastguard Worker // if (FLAG(t)) child = forkpty(&fdout, NULL, NULL, NULL);
236*cf5a6c84SAndroid Build Coastguard Worker
237*cf5a6c84SAndroid Build Coastguard Worker close(sockfd);
238*cf5a6c84SAndroid Build Coastguard Worker dup2(in1, 0);
239*cf5a6c84SAndroid Build Coastguard Worker dup2(in1, 1);
240*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(E)) dup2(in1, 2);
241*cf5a6c84SAndroid Build Coastguard Worker if (in1>2) close(in1);
242*cf5a6c84SAndroid Build Coastguard Worker xexec(toys.optargs);
243*cf5a6c84SAndroid Build Coastguard Worker
244*cf5a6c84SAndroid Build Coastguard Worker // Copy stdin/out
245*cf5a6c84SAndroid Build Coastguard Worker } else {
246*cf5a6c84SAndroid Build Coastguard Worker pollinate(in1, in2, out1, out2, ohexwrite, TT.W, TT.q);
247*cf5a6c84SAndroid Build Coastguard Worker close(in1);
248*cf5a6c84SAndroid Build Coastguard Worker }
249*cf5a6c84SAndroid Build Coastguard Worker } while (FLAG(L));
250*cf5a6c84SAndroid Build Coastguard Worker }
251*cf5a6c84SAndroid Build Coastguard Worker }
252*cf5a6c84SAndroid Build Coastguard Worker
253*cf5a6c84SAndroid Build Coastguard Worker cleanup:
254*cf5a6c84SAndroid Build Coastguard Worker if (CFG_TOYBOX_FREE) {
255*cf5a6c84SAndroid Build Coastguard Worker close(in1);
256*cf5a6c84SAndroid Build Coastguard Worker close(sockfd);
257*cf5a6c84SAndroid Build Coastguard Worker }
258*cf5a6c84SAndroid Build Coastguard Worker }
259