1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#define FOR_netcat
47#include "toys.h"
48
49GLOBALS(
50 char *filename;
51 long quit_delay;
52 char *source_address;
53 long port;
54 long idle;
55 long wait;
56)
57
58static void timeout(int signum)
59{
60 if (TT.wait) error_exit("Timeout");
61
62 exit(0);
63}
64
65static void set_alarm(int seconds)
66{
67 xsignal(SIGALRM, seconds ? timeout : SIG_DFL);
68 alarm(seconds);
69}
70
71
72static void lookup_name(char *name, uint32_t *result)
73{
74 struct hostent *hostbyname;
75
76 hostbyname = gethostbyname(name);
77 if (!hostbyname) error_exit("no host '%s'", name);
78 *result = *(uint32_t *)*hostbyname->h_addr_list;
79}
80
81
82static void lookup_port(char *str, uint16_t *port)
83{
84 *port = SWAP_BE16(atoi(str));
85}
86
87void netcat_main(void)
88{
89 struct sockaddr_in *address = (void *)toybuf;
90 int sockfd=-1, in1 = 0, in2 = 0, out1 = 1, out2 = 1;
91 pid_t child;
92
93
94 TT.idle = TT.idle ? TT.idle*1000 : -1;
95 TT.quit_delay = TT.quit_delay ? TT.quit_delay*1000 : -1;
96
97 set_alarm(TT.wait);
98
99
100
101 if ((toys.optflags&FLAG_f) ? toys.optc :
102 (!(toys.optflags&(FLAG_l|FLAG_L)) && toys.optc!=2))
103 help_exit("bad argument count");
104
105 if (TT.filename) in1 = out2 = xopen(TT.filename, O_RDWR);
106 else {
107
108 sockfd = xsocket(AF_INET, SOCK_STREAM, 0);
109 fcntl(sockfd, F_SETFD, FD_CLOEXEC);
110 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &out1, sizeof(out1));
111 address->sin_family = AF_INET;
112 if (TT.source_address || TT.port) {
113 address->sin_port = SWAP_BE16(TT.port);
114 if (TT.source_address)
115 lookup_name(TT.source_address, (uint32_t *)&(address->sin_addr));
116 if (bind(sockfd, (struct sockaddr *)address, sizeof(*address)))
117 perror_exit("bind");
118 }
119
120
121
122 if (!CFG_NETCAT_LISTEN || !(toys.optflags&(FLAG_L|FLAG_l))) {
123
124 lookup_name(*toys.optargs, (uint32_t *)&(address->sin_addr));
125 lookup_port(toys.optargs[1], &(address->sin_port));
126
127 if (connect(sockfd, (struct sockaddr *)address, sizeof(*address))<0)
128 perror_exit("connect");
129
130
131 set_alarm(0);
132
133 in1 = out2 = sockfd;
134
135 pollinate(in1, in2, out1, out2, TT.idle, TT.quit_delay);
136 } else {
137
138 socklen_t len = sizeof(*address);
139
140 if (listen(sockfd, 5)) error_exit("listen");
141 if (!TT.port) {
142 getsockname(sockfd, (struct sockaddr *)address, &len);
143 printf("%d\n", SWAP_BE16(address->sin_port));
144 fflush(stdout);
145
146
147 if (CFG_TOYBOX_FORK && toys.optc && xfork()) goto cleanup;
148 }
149
150 do {
151 child = 0;
152 len = sizeof(*address);
153 in1 = out2 = accept(sockfd, (struct sockaddr *)address, &len);
154
155 if (in1<0) perror_exit("accept");
156
157
158
159
160
161
162
163
164 set_alarm(0);
165
166 if (toys.optc) {
167
168
169
170
171
172
173
174
175
176 if (toys.optflags&FLAG_L) {
177 toys.stacktop = 0;
178 child = vfork();
179 }
180 if (child<0) error_msg("vfork failed\n");
181 else {
182 if (child) {
183 close(in1);
184 continue;
185 }
186 dup2(in1, 0);
187 dup2(in1, 1);
188 if (toys.optflags&FLAG_L) dup2(in1, 2);
189 if (in1>2) close(in1);
190 xexec(toys.optargs);
191 }
192 }
193
194 pollinate(in1, in2, out1, out2, TT.idle, TT.quit_delay);
195 close(in1);
196 } while (!(toys.optflags&FLAG_l));
197 }
198 }
199
200cleanup:
201 if (CFG_TOYBOX_FREE) {
202 close(in1);
203 close(sockfd);
204 }
205}
206