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