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#include "libbb.h"
33
34#include <linux/types.h>
35#include <linux/netfilter_ipv4.h>
36
37
38#include "tcpudp_perhost.h"
39
40#ifdef SSLSVD
41#include "matrixSsl.h"
42#include "ssl_io.h"
43#endif
44
45struct globals {
46 unsigned verbose;
47 unsigned max_per_host;
48 unsigned cur_per_host;
49 unsigned cnum;
50 unsigned cmax;
51 char **env_cur;
52 char *env_var[1];
53} FIX_ALIASING;
54#define G (*(struct globals*)&bb_common_bufsiz1)
55#define verbose (G.verbose )
56#define max_per_host (G.max_per_host)
57#define cur_per_host (G.cur_per_host)
58#define cnum (G.cnum )
59#define cmax (G.cmax )
60#define env_cur (G.env_cur )
61#define env_var (G.env_var )
62#define INIT_G() do { \
63 cmax = 30; \
64 env_cur = &env_var[0]; \
65} while (0)
66
67
68
69static void xsetenv_plain(const char *n, const char *v)
70{
71 char *var = xasprintf("%s=%s", n, v);
72 *env_cur++ = var;
73 putenv(var);
74}
75
76static void xsetenv_proto(const char *proto, const char *n, const char *v)
77{
78 char *var = xasprintf("%s%s=%s", proto, n, v);
79 *env_cur++ = var;
80 putenv(var);
81}
82
83static void undo_xsetenv(void)
84{
85 char **pp = env_cur = &env_var[0];
86 while (*pp) {
87 char *var = *pp;
88 bb_unsetenv_and_free(var);
89 *pp++ = NULL;
90 }
91}
92
93static void sig_term_handler(int sig)
94{
95 if (verbose)
96 bb_error_msg("got signal %u, exit", sig);
97 kill_myself_with_sig(sig);
98}
99
100
101
102static void print_waitstat(unsigned pid, int wstat)
103{
104 unsigned e = 0;
105 const char *cause = "?exit";
106
107 if (WIFEXITED(wstat)) {
108 cause++;
109 e = WEXITSTATUS(wstat);
110 } else if (WIFSIGNALED(wstat)) {
111 cause = "signal";
112 e = WTERMSIG(wstat);
113 }
114 bb_error_msg("end %d %s %d", pid, cause, e);
115}
116
117
118enum {
119 OPT_c = (1 << 0),
120 OPT_C = (1 << 1),
121 OPT_i = (1 << 2),
122 OPT_x = (1 << 3),
123 OPT_u = (1 << 4),
124 OPT_l = (1 << 5),
125 OPT_E = (1 << 6),
126 OPT_b = (1 << 7),
127 OPT_h = (1 << 8),
128 OPT_p = (1 << 9),
129 OPT_t = (1 << 10),
130 OPT_v = (1 << 11),
131 OPT_V = (1 << 12),
132 OPT_U = (1 << 13),
133 OPT_slash = (1 << 14),
134 OPT_Z = (1 << 15),
135 OPT_K = (1 << 16),
136};
137
138static void connection_status(void)
139{
140
141 if (cmax > 1)
142 bb_error_msg("status %u/%u", cnum, cmax);
143}
144
145static void sig_child_handler(int sig UNUSED_PARAM)
146{
147 int wstat;
148 pid_t pid;
149
150 while ((pid = wait_any_nohang(&wstat)) > 0) {
151 if (max_per_host)
152 ipsvd_perhost_remove(pid);
153 if (cnum)
154 cnum--;
155 if (verbose)
156 print_waitstat(pid, wstat);
157 }
158 if (verbose)
159 connection_status();
160}
161
162int tcpudpsvd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
163int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv)
164{
165 char *str_C, *str_t;
166 char *user;
167 struct hcc *hccp;
168 const char *instructs;
169 char *msg_per_host = NULL;
170 unsigned len_per_host = len_per_host;
171#ifndef SSLSVD
172 struct bb_uidgid_t ugid;
173#endif
174 bool tcp;
175 uint16_t local_port;
176 char *preset_local_hostname = NULL;
177 char *remote_hostname = remote_hostname;
178 char *remote_addr = remote_addr;
179 len_and_sockaddr *lsa;
180 len_and_sockaddr local, remote;
181 socklen_t sa_len;
182 int pid;
183 int sock;
184 int conn;
185 unsigned backlog = 20;
186 unsigned opts;
187
188 INIT_G();
189
190 tcp = (applet_name[0] == 't');
191
192
193 opt_complementary = "-3:i--i:ph:vv:b+:c+";
194#ifdef SSLSVD
195 opts = getopt32(argv, "+c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:",
196 &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname,
197 &backlog, &str_t, &ssluser, &root, &cert, &key, &verbose
198 );
199#else
200
201 opts = getopt32(argv, "+c:C:i:x:u:l:Eb:hpt:v",
202 &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname,
203 &backlog, &str_t, &verbose
204 );
205#endif
206 if (opts & OPT_C) {
207 max_per_host = bb_strtou(str_C, &str_C, 10);
208 if (str_C[0]) {
209 if (str_C[0] != ':')
210 bb_show_usage();
211 msg_per_host = str_C + 1;
212 len_per_host = strlen(msg_per_host);
213 }
214 }
215 if (max_per_host > cmax)
216 max_per_host = cmax;
217 if (opts & OPT_u) {
218 xget_uidgid(&ugid, user);
219 }
220#ifdef SSLSVD
221 if (opts & OPT_U) ssluser = optarg;
222 if (opts & OPT_slash) root = optarg;
223 if (opts & OPT_Z) cert = optarg;
224 if (opts & OPT_K) key = optarg;
225#endif
226 argv += optind;
227 if (!argv[0][0] || LONE_CHAR(argv[0], '0'))
228 argv[0] = (char*)"0.0.0.0";
229
230
231 if (!tcp)
232 max_per_host = 0;
233
234 bb_sanitize_stdio();
235
236#ifdef SSLSVD
237 sslser = user;
238 client = 0;
239 if ((getuid() == 0) && !(opts & OPT_u)) {
240 xfunc_exitcode = 100;
241 bb_error_msg_and_die(bb_msg_you_must_be_root);
242 }
243 if (opts & OPT_u)
244 if (!uidgid_get(&sslugid, ssluser, 1)) {
245 if (errno) {
246 bb_perror_msg_and_die("can't get user/group: %s", ssluser);
247 }
248 bb_error_msg_and_die("unknown user/group %s", ssluser);
249 }
250 if (!cert) cert = "./cert.pem";
251 if (!key) key = cert;
252 if (matrixSslOpen() < 0)
253 fatal("can't initialize ssl");
254 if (matrixSslReadKeys(&keys, cert, key, 0, ca) < 0) {
255 if (client)
256 fatal("can't read cert, key, or ca file");
257 fatal("can't read cert or key file");
258 }
259 if (matrixSslNewSession(&ssl, keys, 0, SSL_FLAGS_SERVER) < 0)
260 fatal("can't create ssl session");
261#endif
262
263 sig_block(SIGCHLD);
264 signal(SIGCHLD, sig_child_handler);
265 bb_signals(BB_FATAL_SIGS, sig_term_handler);
266 signal(SIGPIPE, SIG_IGN);
267
268 if (max_per_host)
269 ipsvd_perhost_init(cmax);
270
271 local_port = bb_lookup_port(argv[1], tcp ? "tcp" : "udp", 0);
272 lsa = xhost2sockaddr(argv[0], local_port);
273 argv += 2;
274
275 sock = xsocket(lsa->u.sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
276 setsockopt_reuseaddr(sock);
277 sa_len = lsa->len;
278 xbind(sock, &lsa->u.sa, sa_len);
279 if (tcp) {
280 xlisten(sock, backlog);
281 close_on_exec_on(sock);
282 } else {
283 socket_want_pktinfo(sock);
284 }
285
286
287#ifndef SSLSVD
288 if (opts & OPT_u) {
289
290 xsetgid(ugid.gid);
291 xsetuid(ugid.uid);
292 }
293#endif
294
295 if (verbose) {
296 char *addr = xmalloc_sockaddr2dotted(&lsa->u.sa);
297 if (opts & OPT_u)
298 bb_error_msg("listening on %s, starting, uid %u, gid %u", addr,
299 (unsigned)ugid.uid, (unsigned)ugid.gid);
300 else
301 bb_error_msg("listening on %s, starting", addr);
302 free(addr);
303 }
304
305
306
307 again:
308 hccp = NULL;
309
310 while (cnum >= cmax)
311 wait_for_any_sig();
312
313
314 again1:
315 close(0);
316 again2:
317 sig_unblock(SIGCHLD);
318 local.len = remote.len = sa_len;
319 if (tcp) {
320 conn = accept(sock, &remote.u.sa, &remote.len);
321 } else {
322
323
324 local = *lsa;
325 conn = recv_from_to(sock, NULL, 0, MSG_PEEK,
326 &remote.u.sa, &local.u.sa, sa_len);
327 }
328 sig_block(SIGCHLD);
329 if (conn < 0) {
330 if (errno != EINTR)
331 bb_perror_msg(tcp ? "accept" : "recv");
332 goto again2;
333 }
334 xmove_fd(tcp ? conn : sock, 0);
335
336 if (max_per_host) {
337
338
339 remote_addr = xmalloc_sockaddr2dotted_noport(&remote.u.sa);
340 cur_per_host = ipsvd_perhost_add(remote_addr, max_per_host, &hccp);
341 if (cur_per_host > max_per_host) {
342
343
344 free(remote_addr);
345 if (msg_per_host) {
346
347 send(0, msg_per_host, len_per_host, MSG_DONTWAIT);
348 }
349 goto again1;
350 }
351
352 }
353
354 if (!tcp) {
355
356
357
358
359
360
361
362 sock = xsocket(lsa->u.sa.sa_family, SOCK_DGRAM, 0);
363 setsockopt_reuseaddr(sock);
364
365
366
367 xconnect(0, &remote.u.sa, sa_len);
368
369
370
371
372 xbind(sock, &lsa->u.sa, sa_len);
373 socket_want_pktinfo(sock);
374
375
376
377
378
379
380#if 0
381
382
383
384
385
386 close(0);
387 set_nport(localp, htons(local_port));
388 xmove_fd(xsocket(localp->u.sa.sa_family, SOCK_DGRAM, 0), 0);
389 setsockopt_reuseaddr(0);
390 xbind(0, &localp->u.sa, localp->len);
391#endif
392 }
393
394 pid = vfork();
395 if (pid == -1) {
396 bb_perror_msg("vfork");
397 goto again;
398 }
399
400 if (pid != 0) {
401
402 cnum++;
403 if (verbose)
404 connection_status();
405 if (hccp)
406 hccp->pid = pid;
407
408 undo_xsetenv();
409 goto again;
410 }
411
412
413
414 {
415 char *local_hostname = local_hostname;
416 char *local_addr = NULL;
417 char *free_me0 = NULL;
418 char *free_me1 = NULL;
419 char *free_me2 = NULL;
420
421 if (verbose || !(opts & OPT_E)) {
422 if (!max_per_host)
423 free_me0 = remote_addr = xmalloc_sockaddr2dotted(&remote.u.sa);
424 if (opts & OPT_h) {
425 free_me1 = remote_hostname = xmalloc_sockaddr2host_noport(&remote.u.sa);
426 if (!remote_hostname) {
427 bb_error_msg("can't look up hostname for %s", remote_addr);
428 remote_hostname = remote_addr;
429 }
430 }
431
432
433
434 if (tcp)
435 getsockname(0, &local.u.sa, &local.len);
436
437 local_addr = xmalloc_sockaddr2dotted(&local.u.sa);
438 if (opts & OPT_h) {
439 local_hostname = preset_local_hostname;
440 if (!local_hostname) {
441 free_me2 = local_hostname = xmalloc_sockaddr2host_noport(&local.u.sa);
442 if (!local_hostname)
443 bb_error_msg_and_die("can't look up hostname for %s", local_addr);
444 }
445
446 }
447 }
448 if (verbose) {
449 pid = getpid();
450 if (max_per_host) {
451 bb_error_msg("concurrency %s %u/%u",
452 remote_addr,
453 cur_per_host, max_per_host);
454 }
455 bb_error_msg((opts & OPT_h)
456 ? "start %u %s-%s (%s-%s)"
457 : "start %u %s-%s",
458 pid,
459 local_addr, remote_addr,
460 local_hostname, remote_hostname);
461 }
462
463 if (!(opts & OPT_E)) {
464
465 const char *proto = tcp ? "TCP" : "UDP";
466
467
468
469
470
471 if (tcp && getsockopt(0, SOL_IP, SO_ORIGINAL_DST, &local.u.sa, &local.len) == 0) {
472 char *addr = xmalloc_sockaddr2dotted(&local.u.sa);
473 xsetenv_plain("TCPORIGDSTADDR", addr);
474 free(addr);
475 }
476 xsetenv_plain("PROTO", proto);
477 xsetenv_proto(proto, "LOCALADDR", local_addr);
478 xsetenv_proto(proto, "REMOTEADDR", remote_addr);
479 if (opts & OPT_h) {
480 xsetenv_proto(proto, "LOCALHOST", local_hostname);
481 xsetenv_proto(proto, "REMOTEHOST", remote_hostname);
482 }
483
484
485 if (cur_per_host > 0)
486 xsetenv_plain("TCPCONCURRENCY", utoa(cur_per_host));
487 }
488 free(local_addr);
489 free(free_me0);
490 free(free_me1);
491 free(free_me2);
492 }
493
494 xdup2(0, 1);
495
496 signal(SIGPIPE, SIG_DFL);
497
498
499 sig_unblock(SIGCHLD);
500
501#ifdef SSLSVD
502 strcpy(id, utoa(pid));
503 ssl_io(0, argv);
504 bb_perror_msg_and_die("can't execute '%s'", argv[0]);
505#else
506 BB_EXECVP_or_die(argv);
507#endif
508}
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605