xref: /aosp_15_r20/external/toybox/toys/net/netcat.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
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