diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-12 23:13:50 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-12 23:13:50 +0000 |
commit | 4cf1d08fc2e50f9abda999d468c5e972ff4995c2 (patch) | |
tree | 58dd8efdd7d0f0990d30d8b5f5f53cf2ee35d444 | |
parent | 4e6d5117b839cef41cd3919966f95bf25d24d8d9 (diff) | |
download | busybox-w32-4cf1d08fc2e50f9abda999d468c5e972ff4995c2.tar.gz busybox-w32-4cf1d08fc2e50f9abda999d468c5e972ff4995c2.tar.bz2 busybox-w32-4cf1d08fc2e50f9abda999d468c5e972ff4995c2.zip |
nc: remove a bit of bloat
inetd: more NOMMU fixes
rx: shrink
devfsd: minor shrink
vlock: shrink
tcpudp: narrow down window where we have no wildcard socket
parse_one_line 1015 1102 +87
init_ring - 53 +53
xzalloc_lsa - 48 +48
read_byte 51 50 -1
rearm_alarm 28 25 -3
nc_main 1028 1000 -28
initring 53 - -53
vlock_main 583 496 -87
reread_config_file 1089 991 -98
rx_main 1046 912 -134
------------------------------------------------------------------------------
(add/remove: 2/1 grow/shrink: 1/6 up/down: 188/-404) Total: -216 bytes
text data bss dec hex filename
800120 661 7428 808209 c5511 busybox_old
799796 661 7428 807885 c53cd busybox_unstripped
-rw-r--r-- | ipsvd/tcpudp.c | 12 | ||||
-rw-r--r-- | libbb/signals.c | 7 | ||||
-rw-r--r-- | loginutils/vlock.c | 84 | ||||
-rw-r--r-- | miscutils/devfsd.c | 9 | ||||
-rw-r--r-- | miscutils/rx.c | 232 | ||||
-rw-r--r-- | networking/inetd.c | 258 | ||||
-rw-r--r-- | networking/nc_bloaty.c | 7 |
7 files changed, 308 insertions, 301 deletions
diff --git a/ipsvd/tcpudp.c b/ipsvd/tcpudp.c index cb57e598a..8b4ae88f4 100644 --- a/ipsvd/tcpudp.c +++ b/ipsvd/tcpudp.c | |||
@@ -339,16 +339,17 @@ int tcpudpsvd_main(int argc, char **argv) | |||
339 | * 1) we have to do it before fork() | 339 | * 1) we have to do it before fork() |
340 | * 2) order is important - is it right now? */ | 340 | * 2) order is important - is it right now? */ |
341 | 341 | ||
342 | /* Make plain write/send work for this socket by supplying default | 342 | /* Open new non-connected UDP socket for further clients... */ |
343 | sock = xsocket(lsa->u.sa.sa_family, SOCK_DGRAM, 0); | ||
344 | setsockopt_reuseaddr(sock); | ||
345 | /* Make plain write/send work for old socket by supplying default | ||
343 | * destination address. This also restricts incoming packets | 346 | * destination address. This also restricts incoming packets |
344 | * to ones coming from this remote IP. */ | 347 | * to ones coming from this remote IP. */ |
345 | xconnect(0, &remote.u.sa, sa_len); | 348 | xconnect(0, &remote.u.sa, sa_len); |
346 | /* hole? at this point we have no wildcard udp socket... | 349 | /* hole? at this point we have no wildcard udp socket... |
347 | * can this cause clients to get "port unreachable" icmp? | 350 | * can this cause clients to get "port unreachable" icmp? |
348 | * Yup, time window is very small, but it exists (is it?) */ | 351 | * Yup, time window is very small, but it exists (is it?) */ |
349 | /* Open new non-connected UDP socket for further clients */ | 352 | /* ..."open new socket", continued */ |
350 | sock = xsocket(lsa->u.sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); | ||
351 | setsockopt_reuseaddr(sock); | ||
352 | xbind(sock, &lsa->u.sa, sa_len); | 353 | xbind(sock, &lsa->u.sa, sa_len); |
353 | socket_want_pktinfo(sock); | 354 | socket_want_pktinfo(sock); |
354 | 355 | ||
@@ -377,7 +378,6 @@ int tcpudpsvd_main(int argc, char **argv) | |||
377 | goto again; | 378 | goto again; |
378 | } | 379 | } |
379 | 380 | ||
380 | |||
381 | if (pid != 0) { | 381 | if (pid != 0) { |
382 | /* parent */ | 382 | /* parent */ |
383 | cnum++; | 383 | cnum++; |
@@ -467,7 +467,7 @@ int tcpudpsvd_main(int argc, char **argv) | |||
467 | 467 | ||
468 | argv += 2; | 468 | argv += 2; |
469 | #ifdef SSLSVD | 469 | #ifdef SSLSVD |
470 | strcpy(id, utoa(pid); | 470 | strcpy(id, utoa(pid)); |
471 | ssl_io(0, argv); | 471 | ssl_io(0, argv); |
472 | #else | 472 | #else |
473 | BB_EXECVP(argv[0], argv); | 473 | BB_EXECVP(argv[0], argv); |
diff --git a/libbb/signals.c b/libbb/signals.c index 1929cb88e..a327e87c8 100644 --- a/libbb/signals.c +++ b/libbb/signals.c | |||
@@ -82,13 +82,8 @@ void sig_pause(void) | |||
82 | /* Assuming the sig is fatal */ | 82 | /* Assuming the sig is fatal */ |
83 | void kill_myself_with_sig(int sig) | 83 | void kill_myself_with_sig(int sig) |
84 | { | 84 | { |
85 | sigset_t set; | ||
86 | |||
87 | signal(sig, SIG_DFL); | 85 | signal(sig, SIG_DFL); |
88 | 86 | sig_unblock(sig); | |
89 | sigemptyset(&set); | ||
90 | sigaddset(&set, sig); | ||
91 | sigprocmask(SIG_UNBLOCK, &set, NULL); | ||
92 | raise(sig); | 87 | raise(sig); |
93 | _exit(1); /* Should not reach it */ | 88 | _exit(1); /* Should not reach it */ |
94 | } | 89 | } |
diff --git a/loginutils/vlock.c b/loginutils/vlock.c index 6e928e239..846733ea8 100644 --- a/loginutils/vlock.c +++ b/loginutils/vlock.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | |||
3 | /* | 2 | /* |
4 | * vlock implementation for busybox | 3 | * vlock implementation for busybox |
5 | * | 4 | * |
@@ -16,27 +15,25 @@ | |||
16 | /* Fixed by Erik Andersen to do passwords the tinylogin way... | 15 | /* Fixed by Erik Andersen to do passwords the tinylogin way... |
17 | * It now works with md5, sha1, etc passwords. */ | 16 | * It now works with md5, sha1, etc passwords. */ |
18 | 17 | ||
19 | #include "libbb.h" | ||
20 | #include <sys/vt.h> | 18 | #include <sys/vt.h> |
21 | 19 | #include "libbb.h" | |
22 | enum { vfd = 3 }; | ||
23 | |||
24 | /* static unsigned long o_lock_all; */ | ||
25 | 20 | ||
26 | static void release_vt(int signo) | 21 | static void release_vt(int signo) |
27 | { | 22 | { |
28 | ioctl(vfd, VT_RELDISP, (unsigned long) !option_mask32 /*!o_lock_all*/); | 23 | /* If -a, param is 0, which means: |
24 | * "no, kernel, we don't allow console switch away from us!" */ | ||
25 | ioctl(STDIN_FILENO, VT_RELDISP, (unsigned long) !option_mask32); | ||
29 | } | 26 | } |
30 | 27 | ||
31 | static void acquire_vt(int signo) | 28 | static void acquire_vt(int signo) |
32 | { | 29 | { |
33 | ioctl(vfd, VT_RELDISP, VT_ACKACQ); | 30 | /* ACK to kernel that switch to console is successful */ |
31 | ioctl(STDIN_FILENO, VT_RELDISP, VT_ACKACQ); | ||
34 | } | 32 | } |
35 | 33 | ||
36 | int vlock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 34 | int vlock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
37 | int vlock_main(int argc, char **argv) | 35 | int vlock_main(int argc, char **argv) |
38 | { | 36 | { |
39 | sigset_t sig; | ||
40 | struct sigaction sa; | 37 | struct sigaction sa; |
41 | struct vt_mode vtm; | 38 | struct vt_mode vtm; |
42 | struct termios term; | 39 | struct termios term; |
@@ -48,49 +45,48 @@ int vlock_main(int argc, char **argv) | |||
48 | uid = getuid(); | 45 | uid = getuid(); |
49 | pw = getpwuid(uid); | 46 | pw = getpwuid(uid); |
50 | if (pw == NULL) | 47 | if (pw == NULL) |
51 | bb_error_msg_and_die("unknown uid %d", uid); | 48 | bb_error_msg_and_die("unknown uid %d", (int)uid); |
52 | 49 | ||
53 | if (argc > 2) { | 50 | opt_complementary = "=0"; /* no params! */ |
54 | bb_show_usage(); | 51 | getopt32(argv, "a"); |
55 | } | 52 | |
56 | 53 | /* Ignore some signals so that we don't get killed by them */ | |
57 | /*o_lock_all = */getopt32(argv, "a"); | 54 | bb_signals(0 |
58 | 55 | + (1 << SIGTSTP) | |
59 | /* Avoid using statics - use constant fd */ | 56 | + (1 << SIGTTIN) |
60 | xmove_fd(xopen(CURRENT_TTY, O_RDWR), vfd); | 57 | + (1 << SIGTTOU) |
61 | xioctl(vfd, VT_GETMODE, &vtm); | 58 | + (1 << SIGHUP ) |
62 | 59 | + (1 << SIGCHLD) /* paranoia :) */ | |
63 | /* mask a bunch of signals */ | 60 | + (1 << SIGQUIT) |
64 | sigprocmask(SIG_SETMASK, NULL, &sig); | 61 | + (1 << SIGINT ) |
65 | sigdelset(&sig, SIGUSR1); | 62 | , SIG_IGN); |
66 | sigdelset(&sig, SIGUSR2); | 63 | |
67 | sigaddset(&sig, SIGTSTP); | 64 | /* We will use SIGUSRx for console switch control: */ |
68 | sigaddset(&sig, SIGTTIN); | 65 | /* 1: set handlers */ |
69 | sigaddset(&sig, SIGTTOU); | 66 | sigemptyset(&sa.sa_mask); |
70 | sigaddset(&sig, SIGHUP); | ||
71 | sigaddset(&sig, SIGCHLD); | ||
72 | sigaddset(&sig, SIGQUIT); | ||
73 | sigaddset(&sig, SIGINT); | ||
74 | |||
75 | sigemptyset(&(sa.sa_mask)); | ||
76 | sa.sa_flags = SA_RESTART; | 67 | sa.sa_flags = SA_RESTART; |
77 | sa.sa_handler = release_vt; | 68 | sa.sa_handler = release_vt; |
78 | sigaction(SIGUSR1, &sa, NULL); | 69 | sigaction(SIGUSR1, &sa, NULL); |
79 | sa.sa_handler = acquire_vt; | 70 | sa.sa_handler = acquire_vt; |
80 | sigaction(SIGUSR2, &sa, NULL); | 71 | sigaction(SIGUSR2, &sa, NULL); |
81 | 72 | /* 2: unmask them */ | |
82 | /* need to handle some signals so that we don't get killed by them */ | 73 | sigprocmask(SIG_SETMASK, NULL, &sa.sa_mask); |
83 | sa.sa_handler = SIG_IGN; | 74 | sigdelset(&sa.sa_mask, SIGUSR1); |
84 | sigaction(SIGHUP, &sa, NULL); | 75 | sigdelset(&sa.sa_mask, SIGUSR2); |
85 | sigaction(SIGQUIT, &sa, NULL); | 76 | sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL); |
86 | sigaction(SIGINT, &sa, NULL); | 77 | |
87 | sigaction(SIGTSTP, &sa, NULL); | 78 | /* Revert stdin/out to our controlling tty |
88 | 79 | * (or die if we have none) */ | |
80 | xmove_fd(xopen(CURRENT_TTY, O_RDWR), STDIN_FILENO); | ||
81 | xdup2(STDIN_FILENO, STDOUT_FILENO); | ||
82 | |||
83 | xioctl(STDIN_FILENO, VT_GETMODE, &vtm); | ||
89 | ovtm = vtm; | 84 | ovtm = vtm; |
85 | /* "console switches are controlled by us, not kernel!" */ | ||
90 | vtm.mode = VT_PROCESS; | 86 | vtm.mode = VT_PROCESS; |
91 | vtm.relsig = SIGUSR1; | 87 | vtm.relsig = SIGUSR1; |
92 | vtm.acqsig = SIGUSR2; | 88 | vtm.acqsig = SIGUSR2; |
93 | ioctl(vfd, VT_SETMODE, &vtm); | 89 | ioctl(STDIN_FILENO, VT_SETMODE, &vtm); |
94 | 90 | ||
95 | tcgetattr(STDIN_FILENO, &oterm); | 91 | tcgetattr(STDIN_FILENO, &oterm); |
96 | term = oterm; | 92 | term = oterm; |
@@ -111,7 +107,7 @@ int vlock_main(int argc, char **argv) | |||
111 | puts("Password incorrect"); | 107 | puts("Password incorrect"); |
112 | } while (1); | 108 | } while (1); |
113 | 109 | ||
114 | ioctl(vfd, VT_SETMODE, &ovtm); | 110 | ioctl(STDIN_FILENO, VT_SETMODE, &ovtm); |
115 | tcsetattr(STDIN_FILENO, TCSANOW, &oterm); | 111 | tcsetattr(STDIN_FILENO, TCSANOW, &oterm); |
116 | fflush_stdout_and_exit(0); | 112 | fflush_stdout_and_exit(0); |
117 | } | 113 | } |
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index 286f00fd8..50c8203cb 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c | |||
@@ -386,15 +386,14 @@ int devfsd_main(int argc, char **argv) | |||
386 | /* Tell kernel we are special(i.e. we get to see hidden entries) */ | 386 | /* Tell kernel we are special(i.e. we get to see hidden entries) */ |
387 | xioctl(fd, DEVFSDIOC_SET_EVENT_MASK, 0); | 387 | xioctl(fd, DEVFSDIOC_SET_EVENT_MASK, 0); |
388 | 388 | ||
389 | /* Set up SIGHUP and SIGUSR1 handlers */ | ||
389 | sigemptyset(&new_action.sa_mask); | 390 | sigemptyset(&new_action.sa_mask); |
390 | new_action.sa_flags = 0; | 391 | new_action.sa_flags = 0; |
391 | |||
392 | /* Set up SIGHUP and SIGUSR1 handlers */ | ||
393 | new_action.sa_handler = signal_handler; | 392 | new_action.sa_handler = signal_handler; |
394 | if (sigaction(SIGHUP, &new_action, NULL) != 0 || sigaction(SIGUSR1, &new_action, NULL) != 0) | 393 | sigaction(SIGHUP, &new_action, NULL); |
395 | bb_error_msg_and_die("sigaction"); | 394 | sigaction(SIGUSR1, &new_action, NULL); |
396 | 395 | ||
397 | printf("%s v%s started for %s\n",applet_name, DEVFSD_VERSION, mount_point); | 396 | printf("%s v%s started for %s\n", applet_name, DEVFSD_VERSION, mount_point); |
398 | 397 | ||
399 | /* Set umask so that mknod(2), open(2) and mkdir(2) have complete control over permissions */ | 398 | /* Set umask so that mknod(2), open(2) and mkdir(2) have complete control over permissions */ |
400 | umask(0); | 399 | umask(0); |
diff --git a/miscutils/rx.c b/miscutils/rx.c index 8ccea4974..9a8fcaa20 100644 --- a/miscutils/rx.c +++ b/miscutils/rx.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 16 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
17 | * | 17 | * |
18 | * This was originally written for blob and then adapted for busybox. | 18 | * This was originally written for blob and then adapted for busybox. |
19 | * | ||
20 | */ | 19 | */ |
21 | 20 | ||
22 | #include "libbb.h" | 21 | #include "libbb.h" |
@@ -29,66 +28,59 @@ | |||
29 | #define BS 0x08 | 28 | #define BS 0x08 |
30 | 29 | ||
31 | /* | 30 | /* |
32 | |||
33 | Cf: | 31 | Cf: |
34 | |||
35 | http://www.textfiles.com/apple/xmodem | 32 | http://www.textfiles.com/apple/xmodem |
36 | http://www.phys.washington.edu/~belonis/xmodem/docxmodem.txt | 33 | http://www.phys.washington.edu/~belonis/xmodem/docxmodem.txt |
37 | http://www.phys.washington.edu/~belonis/xmodem/docymodem.txt | 34 | http://www.phys.washington.edu/~belonis/xmodem/docymodem.txt |
38 | http://www.phys.washington.edu/~belonis/xmodem/modmprot.col | 35 | http://www.phys.washington.edu/~belonis/xmodem/modmprot.col |
39 | |||
40 | */ | 36 | */ |
41 | 37 | ||
42 | #define TIMEOUT 1 | 38 | #define TIMEOUT 1 |
43 | #define TIMEOUT_LONG 10 | 39 | #define TIMEOUT_LONG 10 |
44 | #define MAXERRORS 10 | 40 | #define MAXERRORS 10 |
45 | 41 | ||
46 | static int read_byte(int fd, unsigned timeout) | 42 | #define read_fd STDIN_FILENO |
43 | #define write_fd STDOUT_FILENO | ||
44 | |||
45 | static int read_byte(unsigned timeout) | ||
47 | { | 46 | { |
48 | char buf[1]; | 47 | char buf[1]; |
49 | int n; | 48 | int n; |
50 | 49 | ||
51 | alarm(timeout); | 50 | alarm(timeout); |
52 | 51 | /* NOT safe_read! We want ALRM to interrupt us */ | |
53 | n = read(fd, &buf, 1); | 52 | n = read(read_fd, buf, 1); |
54 | |||
55 | alarm(0); | 53 | alarm(0); |
56 | |||
57 | if (n == 1) | 54 | if (n == 1) |
58 | return buf[0] & 0xff; | 55 | return (unsigned char)buf[0]; |
59 | else | 56 | return -1; |
60 | return -1; | ||
61 | } | 57 | } |
62 | 58 | ||
63 | static int receive(char *error_buf, size_t error_buf_size, | 59 | static int receive(/*int read_fd, */int file_fd) |
64 | int ttyfd, int filefd) | ||
65 | { | 60 | { |
66 | char blockBuf[1024]; | 61 | unsigned char blockBuf[1024]; |
67 | unsigned int errors = 0; | 62 | unsigned errors = 0; |
68 | unsigned int wantBlockNo = 1; | 63 | unsigned wantBlockNo = 1; |
69 | unsigned int length = 0; | 64 | unsigned length = 0; |
70 | int docrc = 1; | 65 | int do_crc = 1; |
71 | char nak = 'C'; | 66 | char nak = 'C'; |
72 | unsigned int timeout = TIMEOUT_LONG; | 67 | unsigned timeout = TIMEOUT_LONG; |
73 | |||
74 | #define note_error(fmt,args...) \ | ||
75 | snprintf(error_buf, error_buf_size, fmt,##args) | ||
76 | 68 | ||
77 | /* Flush pending input */ | 69 | /* Flush pending input */ |
78 | tcflush(ttyfd, TCIFLUSH); | 70 | tcflush(read_fd, TCIFLUSH); |
79 | 71 | ||
80 | /* Ask for CRC; if we get errors, we will go with checksum */ | 72 | /* Ask for CRC; if we get errors, we will go with checksum */ |
81 | write(ttyfd, &nak, 1); | 73 | full_write(write_fd, &nak, 1); |
82 | 74 | ||
83 | for (;;) { | 75 | for (;;) { |
84 | int blockBegin; | 76 | int blockBegin; |
85 | int blockNo, blockNoOnesCompl; | 77 | int blockNo, blockNoOnesCompl; |
86 | int blockLength; | 78 | int blockLength; |
87 | int cksum = 0; | 79 | int cksum_crc; /* cksum OR crc */ |
88 | int crcHi = 0; | 80 | int expected; |
89 | int crcLo = 0; | 81 | int i,j; |
90 | 82 | ||
91 | blockBegin = read_byte(ttyfd, timeout); | 83 | blockBegin = read_byte(timeout); |
92 | if (blockBegin < 0) | 84 | if (blockBegin < 0) |
93 | goto timeout; | 85 | goto timeout; |
94 | 86 | ||
@@ -102,52 +94,47 @@ static int receive(char *error_buf, size_t error_buf_size, | |||
102 | 94 | ||
103 | case EOT: | 95 | case EOT: |
104 | nak = ACK; | 96 | nak = ACK; |
105 | write(ttyfd, &nak, 1); | 97 | full_write(write_fd, &nak, 1); |
106 | goto done; | 98 | return length; |
107 | 99 | ||
108 | default: | 100 | default: |
109 | goto error; | 101 | goto error; |
110 | } | 102 | } |
111 | 103 | ||
112 | /* block no */ | 104 | /* block no */ |
113 | blockNo = read_byte(ttyfd, TIMEOUT); | 105 | blockNo = read_byte(TIMEOUT); |
114 | if (blockNo < 0) | 106 | if (blockNo < 0) |
115 | goto timeout; | 107 | goto timeout; |
116 | 108 | ||
117 | /* block no one's compliment */ | 109 | /* block no one's compliment */ |
118 | blockNoOnesCompl = read_byte(ttyfd, TIMEOUT); | 110 | blockNoOnesCompl = read_byte(TIMEOUT); |
119 | if (blockNoOnesCompl < 0) | 111 | if (blockNoOnesCompl < 0) |
120 | goto timeout; | 112 | goto timeout; |
121 | 113 | ||
122 | if (blockNo != (255 - blockNoOnesCompl)) { | 114 | if (blockNo != (255 - blockNoOnesCompl)) { |
123 | note_error("bad block ones compl"); | 115 | bb_error_msg("bad block ones compl"); |
124 | goto error; | 116 | goto error; |
125 | } | 117 | } |
126 | 118 | ||
127 | blockLength = (blockBegin == SOH) ? 128 : 1024; | 119 | blockLength = (blockBegin == SOH) ? 128 : 1024; |
128 | 120 | ||
129 | { | 121 | for (i = 0; i < blockLength; i++) { |
130 | int i; | 122 | int cc = read_byte(TIMEOUT); |
131 | 123 | if (cc < 0) | |
132 | for (i = 0; i < blockLength; i++) { | 124 | goto timeout; |
133 | int cc = read_byte(ttyfd, TIMEOUT); | 125 | blockBuf[i] = cc; |
134 | if (cc < 0) | ||
135 | goto timeout; | ||
136 | blockBuf[i] = cc; | ||
137 | } | ||
138 | } | 126 | } |
139 | 127 | ||
140 | if (docrc) { | 128 | if (do_crc) { |
141 | crcHi = read_byte(ttyfd, TIMEOUT); | 129 | cksum_crc = read_byte(TIMEOUT); |
142 | if (crcHi < 0) | 130 | if (cksum_crc < 0) |
143 | goto timeout; | 131 | goto timeout; |
144 | 132 | cksum_crc = (cksum_crc << 8) | read_byte(TIMEOUT); | |
145 | crcLo = read_byte(ttyfd, TIMEOUT); | 133 | if (cksum_crc < 0) |
146 | if (crcLo < 0) | ||
147 | goto timeout; | 134 | goto timeout; |
148 | } else { | 135 | } else { |
149 | cksum = read_byte(ttyfd, TIMEOUT); | 136 | cksum_crc = read_byte(TIMEOUT); |
150 | if (cksum < 0) | 137 | if (cksum_crc < 0) |
151 | goto timeout; | 138 | goto timeout; |
152 | } | 139 | } |
153 | 140 | ||
@@ -156,93 +143,74 @@ static int receive(char *error_buf, size_t error_buf_size, | |||
156 | /* this also ignores the initial block 0 which is */ | 143 | /* this also ignores the initial block 0 which is */ |
157 | /* meta data. */ | 144 | /* meta data. */ |
158 | goto next; | 145 | goto next; |
159 | } else if (blockNo != (wantBlockNo & 0xff)) { | 146 | } |
160 | note_error("unexpected block no, 0x%08x, expecting 0x%08x", blockNo, wantBlockNo); | 147 | if (blockNo != (wantBlockNo & 0xff)) { |
148 | bb_error_msg("unexpected block no, 0x%08x, expecting 0x%08x", blockNo, wantBlockNo); | ||
161 | goto error; | 149 | goto error; |
162 | } | 150 | } |
163 | 151 | ||
164 | if (docrc) { | 152 | expected = 0; |
165 | int crc = 0; | 153 | if (do_crc) { |
166 | int i, j; | ||
167 | int expectedCrcHi; | ||
168 | int expectedCrcLo; | ||
169 | |||
170 | for (i = 0; i < blockLength; i++) { | 154 | for (i = 0; i < blockLength; i++) { |
171 | crc = crc ^ (int) blockBuf[i] << 8; | 155 | expected = expected ^ blockBuf[i] << 8; |
172 | for (j = 0; j < 8; j++) | 156 | for (j = 0; j < 8; j++) { |
173 | if (crc & 0x8000) | 157 | if (expected & 0x8000) |
174 | crc = crc << 1 ^ 0x1021; | 158 | expected = expected << 1 ^ 0x1021; |
175 | else | 159 | else |
176 | crc = crc << 1; | 160 | expected = expected << 1; |
177 | } | 161 | } |
178 | |||
179 | expectedCrcHi = (crc >> 8) & 0xff; | ||
180 | expectedCrcLo = crc & 0xff; | ||
181 | |||
182 | if ((crcHi != expectedCrcHi) || | ||
183 | (crcLo != expectedCrcLo)) { | ||
184 | note_error("crc error, expected 0x%02x 0x%02x, got 0x%02x 0x%02x", expectedCrcHi, expectedCrcLo, crcHi, crcLo); | ||
185 | goto error; | ||
186 | } | 162 | } |
163 | expected &= 0xffff; | ||
187 | } else { | 164 | } else { |
188 | unsigned char expectedCksum = 0; | ||
189 | int i; | ||
190 | |||
191 | for (i = 0; i < blockLength; i++) | 165 | for (i = 0; i < blockLength; i++) |
192 | expectedCksum += blockBuf[i]; | 166 | expected += blockBuf[i]; |
193 | 167 | expected &= 0xff; | |
194 | if (cksum != expectedCksum) { | 168 | } |
195 | note_error("checksum error, expected 0x%02x, got 0x%02x", expectedCksum, cksum); | 169 | if (cksum_crc != expected) { |
196 | goto error; | 170 | bb_error_msg(do_crc ? "crc error, expected 0x%04x, got 0x%04x" |
197 | } | 171 | : "checksum error, expected 0x%02x, got 0x%02x", |
172 | expected, cksum_crc); | ||
173 | goto error; | ||
198 | } | 174 | } |
199 | 175 | ||
200 | wantBlockNo++; | 176 | wantBlockNo++; |
201 | length += blockLength; | 177 | length += blockLength; |
202 | 178 | ||
203 | if (full_write(filefd, blockBuf, blockLength) < 0) { | 179 | errno = 0; |
204 | note_error("write to file failed: %m"); | 180 | if (full_write(file_fd, blockBuf, blockLength) != blockLength) { |
181 | bb_perror_msg("can't write to file"); | ||
205 | goto fatal; | 182 | goto fatal; |
206 | } | 183 | } |
207 | 184 | next: | |
208 | next: | ||
209 | errors = 0; | 185 | errors = 0; |
210 | nak = ACK; | 186 | nak = ACK; |
211 | write(ttyfd, &nak, 1); | 187 | full_write(write_fd, &nak, 1); |
212 | continue; | 188 | continue; |
213 | 189 | error: | |
214 | error: | 190 | timeout: |
215 | timeout: | ||
216 | errors++; | 191 | errors++; |
217 | if (errors == MAXERRORS) { | 192 | if (errors == MAXERRORS) { |
218 | /* Abort */ | 193 | /* Abort */ |
219 | 194 | ||
220 | // if using crc, try again w/o crc | 195 | /* if were asking for crc, try again w/o crc */ |
221 | if (nak == 'C') { | 196 | if (nak == 'C') { |
222 | nak = NAK; | 197 | nak = NAK; |
223 | errors = 0; | 198 | errors = 0; |
224 | docrc = 0; | 199 | do_crc = 0; |
225 | goto timeout; | 200 | goto timeout; |
226 | } | 201 | } |
227 | 202 | bb_error_msg("too many errors; giving up"); | |
228 | note_error("too many errors; giving up"); | 203 | fatal: |
229 | 204 | /* 5 CAN followed by 5 BS. Don't try too hard... */ | |
230 | fatal: | 205 | safe_write(write_fd, "\030\030\030\030\030\010\010\010\010\010", 10); |
231 | /* 5 CAN followed by 5 BS */ | ||
232 | write(ttyfd, "\030\030\030\030\030\010\010\010\010\010", 10); | ||
233 | return -1; | 206 | return -1; |
234 | } | 207 | } |
235 | 208 | ||
236 | /* Flush pending input */ | 209 | /* Flush pending input */ |
237 | tcflush(ttyfd, TCIFLUSH); | 210 | tcflush(read_fd, TCIFLUSH); |
238 | |||
239 | write(ttyfd, &nak, 1); | ||
240 | } | ||
241 | |||
242 | done: | ||
243 | return length; | ||
244 | 211 | ||
245 | #undef note_error | 212 | full_write(write_fd, &nak, 1); |
213 | } /* for (;;) */ | ||
246 | } | 214 | } |
247 | 215 | ||
248 | static void sigalrm_handler(int ATTRIBUTE_UNUSED signum) | 216 | static void sigalrm_handler(int ATTRIBUTE_UNUSED signum) |
@@ -252,40 +220,38 @@ static void sigalrm_handler(int ATTRIBUTE_UNUSED signum) | |||
252 | int rx_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 220 | int rx_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
253 | int rx_main(int argc, char **argv) | 221 | int rx_main(int argc, char **argv) |
254 | { | 222 | { |
255 | char *fn; | ||
256 | int ttyfd, filefd; | ||
257 | struct termios tty, orig_tty; | ||
258 | struct sigaction act; | 223 | struct sigaction act; |
224 | struct termios tty, orig_tty; | ||
225 | int termios_err; | ||
226 | int file_fd; | ||
259 | int n; | 227 | int n; |
260 | char error_buf[256]; | ||
261 | 228 | ||
262 | if (argc != 2) | 229 | if (argc != 2) |
263 | bb_show_usage(); | 230 | bb_show_usage(); |
264 | 231 | ||
265 | fn = argv[1]; | 232 | /* Disabled by vda: |
266 | ttyfd = xopen(CURRENT_TTY, O_RDWR); | 233 | * why we can't receive from stdin? Why we *require* |
267 | filefd = xopen(fn, O_RDWR|O_CREAT|O_TRUNC); | 234 | * controlling tty?? */ |
268 | 235 | /*read_fd = xopen(CURRENT_TTY, O_RDWR);*/ | |
269 | if (tcgetattr(ttyfd, &tty) < 0) | 236 | file_fd = xopen(argv[1], O_RDWR|O_CREAT|O_TRUNC); |
270 | bb_perror_msg_and_die("tcgetattr"); | 237 | |
271 | 238 | termios_err = tcgetattr(read_fd, &tty); | |
272 | orig_tty = tty; | 239 | if (termios_err == 0) { |
273 | 240 | orig_tty = tty; | |
274 | cfmakeraw(&tty); | 241 | cfmakeraw(&tty); |
275 | tcsetattr(ttyfd, TCSAFLUSH, &tty); | 242 | tcsetattr(read_fd, TCSAFLUSH, &tty); |
243 | } | ||
276 | 244 | ||
245 | /* No SA_RESTART: we want ALRM to interrupt read() */ | ||
277 | memset(&act, 0, sizeof(act)); | 246 | memset(&act, 0, sizeof(act)); |
278 | act.sa_handler = sigalrm_handler; | 247 | act.sa_handler = sigalrm_handler; |
279 | sigaction(SIGALRM, &act, 0); | 248 | sigaction(SIGALRM, &act, NULL); |
280 | |||
281 | n = receive(error_buf, sizeof(error_buf), ttyfd, filefd); | ||
282 | |||
283 | close(filefd); | ||
284 | |||
285 | tcsetattr(ttyfd, TCSAFLUSH, &orig_tty); | ||
286 | 249 | ||
287 | if (n < 0) | 250 | n = receive(file_fd); |
288 | bb_error_msg_and_die("\nreceive failed:\n %s", error_buf); | ||
289 | 251 | ||
290 | fflush_stdout_and_exit(EXIT_SUCCESS); | 252 | if (termios_err == 0) |
253 | tcsetattr(read_fd, TCSAFLUSH, &orig_tty); | ||
254 | if (ENABLE_FEATURE_CLEAN_UP) | ||
255 | close(file_fd); | ||
256 | fflush_stdout_and_exit(n >= 0); | ||
291 | } | 257 | } |
diff --git a/networking/inetd.c b/networking/inetd.c index 8a4c9fbf6..463c7cfcf 100644 --- a/networking/inetd.c +++ b/networking/inetd.c | |||
@@ -3,6 +3,7 @@ | |||
3 | /* $OpenBSD: inetd.c,v 1.79 2001/01/30 08:30:57 deraadt Exp $ */ | 3 | /* $OpenBSD: inetd.c,v 1.79 2001/01/30 08:30:57 deraadt Exp $ */ |
4 | /* $NetBSD: inetd.c,v 1.11 1996/02/22 11:14:41 mycroft Exp $ */ | 4 | /* $NetBSD: inetd.c,v 1.11 1996/02/22 11:14:41 mycroft Exp $ */ |
5 | /* Busybox port by Vladimir Oleynik (C) 2001-2005 <dzo@simtreas.ru> */ | 5 | /* Busybox port by Vladimir Oleynik (C) 2001-2005 <dzo@simtreas.ru> */ |
6 | /* IPv6 support, many bug fixes by Denys Vlasenko (c) 2008 */ | ||
6 | /* | 7 | /* |
7 | * Copyright (c) 1983,1991 The Regents of the University of California. | 8 | * Copyright (c) 1983,1991 The Regents of the University of California. |
8 | * All rights reserved. | 9 | * All rights reserved. |
@@ -38,21 +39,17 @@ | |||
38 | 39 | ||
39 | /* Inetd - Internet super-server | 40 | /* Inetd - Internet super-server |
40 | * | 41 | * |
41 | * This program invokes all internet services as needed. | 42 | * This program invokes configured services when a connection |
42 | * connection-oriented services are invoked each time a | 43 | * from a peer is established or a datagram arrives. |
44 | * Connection-oriented services are invoked each time a | ||
43 | * connection is made, by creating a process. This process | 45 | * connection is made, by creating a process. This process |
44 | * is passed the connection as file descriptor 0 and is | 46 | * is passed the connection as file descriptor 0 and is |
45 | * expected to do a getpeername to find out the source host | 47 | * expected to do a getpeername to find out peer's host |
46 | * and port. | 48 | * and port. |
47 | * | ||
48 | * Datagram oriented services are invoked when a datagram | 49 | * Datagram oriented services are invoked when a datagram |
49 | * arrives; a process is created and passed a pending message | 50 | * arrives; a process is created and passed a pending message |
50 | * on file descriptor 0. Datagram servers may either connect | 51 | * on file descriptor 0. peer's address can be obtained |
51 | * to their peer, freeing up the original socket for inetd | 52 | * using recvfrom. |
52 | * to receive further messages on, or "take over the socket", | ||
53 | * processing all arriving datagrams and, eventually, timing | ||
54 | * out. The first type of server is said to be "multi-threaded"; | ||
55 | * the second type of server "single-threaded". | ||
56 | * | 53 | * |
57 | * Inetd uses a configuration file which is read at startup | 54 | * Inetd uses a configuration file which is read at startup |
58 | * and, possibly, at some later time in response to a hangup signal. | 55 | * and, possibly, at some later time in response to a hangup signal. |
@@ -60,28 +57,28 @@ | |||
60 | * order shown below. Continuation lines for an entry must begin with | 57 | * order shown below. Continuation lines for an entry must begin with |
61 | * a space or tab. All fields must be present in each entry. | 58 | * a space or tab. All fields must be present in each entry. |
62 | * | 59 | * |
63 | * service name must be in /etc/services | 60 | * service_name must be in /etc/services |
64 | * socket type stream/dgram/raw/rdm/seqpacket | 61 | * socket_type stream/dgram/raw/rdm/seqpacket |
65 | * protocol must be in /etc/protocols | 62 | * protocol must be in /etc/protocols |
66 | * (usually "tcp" or "udp") | 63 | * (usually "tcp" or "udp") |
67 | * wait/nowait[.max] single-threaded/multi-threaded, max # | 64 | * wait/nowait[.max] single-threaded/multi-threaded, max # |
68 | * user[.group] or user[:group] user/group to run daemon as | 65 | * user[.group] or user[:group] user/group to run daemon as |
69 | * server program full path name | 66 | * server_program full path name |
70 | * server program arguments maximum of MAXARGS (20) | 67 | * server_program_arguments maximum of MAXARGS (20) |
71 | * | 68 | * |
72 | * For RPC services | 69 | * For RPC services |
73 | * service name/version must be in /etc/rpc | 70 | * service_name/version must be in /etc/rpc |
74 | * socket type stream/dgram/raw/rdm/seqpacket | 71 | * socket_type stream/dgram/raw/rdm/seqpacket |
75 | * rpc/protocol "rpc/tcp" etc | 72 | * rpc/protocol "rpc/tcp" etc |
76 | * wait/nowait[.max] single-threaded/multi-threaded | 73 | * wait/nowait[.max] single-threaded/multi-threaded |
77 | * user[.group] or user[:group] user to run daemon as | 74 | * user[.group] or user[:group] user to run daemon as |
78 | * server program full path name | 75 | * server_program full path name |
79 | * server program arguments maximum of MAXARGS (20) | 76 | * server_program_arguments maximum of MAXARGS (20) |
80 | * | 77 | * |
81 | * For non-RPC services, the "service name" can be of the form | 78 | * For non-RPC services, the "service name" can be of the form |
82 | * hostaddress:servicename, in which case the hostaddress is used | 79 | * hostaddress:servicename, in which case the hostaddress is used |
83 | * as the host portion of the address to listen on. If hostaddress | 80 | * as the host portion of the address to listen on. If hostaddress |
84 | * consists of a single `*' character, INADDR_ANY is used. | 81 | * consists of a single '*' character, INADDR_ANY is used. |
85 | * | 82 | * |
86 | * A line can also consist of just | 83 | * A line can also consist of just |
87 | * hostaddress: | 84 | * hostaddress: |
@@ -102,7 +99,7 @@ | |||
102 | * one line for any given RPC service, even if the host-address | 99 | * one line for any given RPC service, even if the host-address |
103 | * specifiers are different. | 100 | * specifiers are different. |
104 | * | 101 | * |
105 | * Comment lines are indicated by a `#' in column 1. | 102 | * Comment lines are indicated by a '#' in column 1. |
106 | */ | 103 | */ |
107 | 104 | ||
108 | /* inetd rules for passing file descriptors to children | 105 | /* inetd rules for passing file descriptors to children |
@@ -133,6 +130,8 @@ | |||
133 | * tening service socket, and must accept at least one connection request | 130 | * tening service socket, and must accept at least one connection request |
134 | * before exiting. Such a server would normally accept and process incoming | 131 | * before exiting. Such a server would normally accept and process incoming |
135 | * connection requests until a timeout. | 132 | * connection requests until a timeout. |
133 | * | ||
134 | * In short: "stream" can be "wait" or "nowait"; "dgram" must be "wait". | ||
136 | */ | 135 | */ |
137 | 136 | ||
138 | /* Here's the scoop concerning the user[:group] feature: | 137 | /* Here's the scoop concerning the user[:group] feature: |
@@ -152,26 +151,27 @@ | |||
152 | 151 | ||
153 | #include <syslog.h> | 152 | #include <syslog.h> |
154 | #include <sys/un.h> | 153 | #include <sys/un.h> |
154 | |||
155 | #include "libbb.h" | 155 | #include "libbb.h" |
156 | 156 | ||
157 | #if ENABLE_FEATURE_INETD_RPC | ||
158 | #include <rpc/rpc.h> | ||
159 | #include <rpc/pmap_clnt.h> | ||
160 | #endif | ||
161 | |||
157 | #if !BB_MMU | 162 | #if !BB_MMU |
158 | /* stream versions of these builtins are forking, | 163 | /* stream version of chargen is forking but not execing, |
159 | * can't do that (easily) on NOMMU */ | 164 | * can't do that (easily) on NOMMU */ |
160 | #undef ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD | ||
161 | #define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD 0 | ||
162 | #undef ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 165 | #undef ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
163 | #define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN 0 | 166 | #define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN 0 |
164 | #endif | 167 | #endif |
165 | 168 | ||
166 | #if ENABLE_FEATURE_INETD_RPC | ||
167 | #include <rpc/rpc.h> | ||
168 | #include <rpc/pmap_clnt.h> | ||
169 | #endif | ||
170 | |||
171 | #define _PATH_INETDPID "/var/run/inetd.pid" | 169 | #define _PATH_INETDPID "/var/run/inetd.pid" |
172 | 170 | ||
173 | #define CNT_INTERVAL 60 /* servers in CNT_INTERVAL sec. */ | 171 | #define CNT_INTERVAL 60 /* servers in CNT_INTERVAL sec. */ |
174 | #define RETRYTIME (60*10) /* retry after bind or server fail */ | 172 | #define RETRYTIME 60 /* retry after bind or server fail */ |
173 | |||
174 | // TODO: explain, or get rid of setrlimit games | ||
175 | 175 | ||
176 | #ifndef RLIMIT_NOFILE | 176 | #ifndef RLIMIT_NOFILE |
177 | #define RLIMIT_NOFILE RLIMIT_OFILE | 177 | #define RLIMIT_NOFILE RLIMIT_OFILE |
@@ -209,20 +209,21 @@ typedef struct servtab_t { | |||
209 | #else | 209 | #else |
210 | #define is_rpc_service(sep) 0 | 210 | #define is_rpc_service(sep) 0 |
211 | #endif | 211 | #endif |
212 | pid_t se_wait; /* 0:"nowait", 1:"wait" */ | 212 | pid_t se_wait; /* 0:"nowait", 1:"wait", >1:"wait" */ |
213 | /* and waiting for this pid */ | ||
213 | socktype_t se_socktype; /* SOCK_STREAM/DGRAM/RDM/... */ | 214 | socktype_t se_socktype; /* SOCK_STREAM/DGRAM/RDM/... */ |
214 | family_t se_family; /* AF_UNIX/INET[6] */ | 215 | family_t se_family; /* AF_UNIX/INET[6] */ |
215 | smallint se_proto_no; /* almost "getprotobyname(se_proto)" */ | 216 | /* se_proto_no is used by RPC code only... hmm */ |
217 | smallint se_proto_no; /* IPPROTO_TCP/UDP, n/a for AF_UNIX */ | ||
216 | smallint se_checked; /* looked at during merge */ | 218 | smallint se_checked; /* looked at during merge */ |
219 | unsigned se_max; /* allowed instances per minute */ | ||
220 | unsigned se_count; /* number started since se_time */ | ||
221 | unsigned se_time; /* whem we started counting */ | ||
217 | char *se_user; /* user name to run as */ | 222 | char *se_user; /* user name to run as */ |
218 | char *se_group; /* group name to run as, can be NULL */ | 223 | char *se_group; /* group name to run as, can be NULL */ |
219 | #ifdef INETD_BUILTINS_ENABLED | 224 | #ifdef INETD_BUILTINS_ENABLED |
220 | const struct builtin *se_builtin; /* if built-in, description */ | 225 | const struct builtin *se_builtin; /* if built-in, description */ |
221 | #endif | 226 | #endif |
222 | // TODO: wrong algorithm!!! | ||
223 | unsigned se_max; /* max # of instances of this service */ | ||
224 | unsigned se_count; /* number started since se_time */ | ||
225 | unsigned se_time; /* start of se_count */ | ||
226 | struct servtab_t *se_next; | 227 | struct servtab_t *se_next; |
227 | len_and_sockaddr *se_lsa; | 228 | len_and_sockaddr *se_lsa; |
228 | char *se_program; /* server program */ | 229 | char *se_program; /* server program */ |
@@ -231,60 +232,54 @@ typedef struct servtab_t { | |||
231 | } servtab_t; | 232 | } servtab_t; |
232 | 233 | ||
233 | #ifdef INETD_BUILTINS_ENABLED | 234 | #ifdef INETD_BUILTINS_ENABLED |
234 | /* Echo received data */ | 235 | /* Echo received data */ |
235 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO | 236 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO |
236 | static void echo_stream(int, servtab_t *); | 237 | static void echo_stream(int, servtab_t *); |
237 | static void echo_dg(int, servtab_t *); | 238 | static void echo_dg(int, servtab_t *); |
238 | #endif | 239 | #endif |
239 | /* Internet /dev/null */ | 240 | /* Internet /dev/null */ |
240 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD | 241 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD |
241 | static void discard_stream(int, servtab_t *); | 242 | static void discard_stream(int, servtab_t *); |
242 | static void discard_dg(int, servtab_t *); | 243 | static void discard_dg(int, servtab_t *); |
243 | #endif | 244 | #endif |
244 | /* Return 32 bit time since 1900 */ | 245 | /* Return 32 bit time since 1900 */ |
245 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME | 246 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME |
246 | static void machtime_stream(int, servtab_t *); | 247 | static void machtime_stream(int, servtab_t *); |
247 | static void machtime_dg(int, servtab_t *); | 248 | static void machtime_dg(int, servtab_t *); |
248 | #endif | 249 | #endif |
249 | /* Return human-readable time */ | 250 | /* Return human-readable time */ |
250 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME | 251 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME |
251 | static void daytime_stream(int, servtab_t *); | 252 | static void daytime_stream(int, servtab_t *); |
252 | static void daytime_dg(int, servtab_t *); | 253 | static void daytime_dg(int, servtab_t *); |
253 | #endif | 254 | #endif |
254 | /* Familiar character generator */ | 255 | /* Familiar character generator */ |
255 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 256 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
256 | static void chargen_stream(int, servtab_t *); | 257 | static void chargen_stream(int, servtab_t *); |
257 | static void chargen_dg(int, servtab_t *); | 258 | static void chargen_dg(int, servtab_t *); |
258 | #endif | 259 | #endif |
259 | 260 | ||
260 | struct builtin { | 261 | struct builtin { |
261 | const char *bi_service; /* internally provided service name */ | 262 | /* NB: not necessarily NUL terminated */ |
262 | uint8_t bi_fork; /* 1 if stream fn should run in child */ | 263 | char bi_service7[7]; /* internally provided service name */ |
263 | /* All builtins are "nowait" */ | 264 | uint8_t bi_fork; /* 1 if stream fn should run in child */ |
264 | /* uint8_t bi_wait; */ /* 1 if should wait for child */ | ||
265 | void (*bi_stream_fn)(int, servtab_t *); | 265 | void (*bi_stream_fn)(int, servtab_t *); |
266 | void (*bi_dgram_fn)(int, servtab_t *); | 266 | void (*bi_dgram_fn)(int, servtab_t *); |
267 | }; | 267 | }; |
268 | 268 | ||
269 | static const struct builtin builtins[] = { | 269 | static const struct builtin builtins[] = { |
270 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO | 270 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO |
271 | /* Echo received data */ | ||
272 | { "echo", 1, echo_stream, echo_dg }, | 271 | { "echo", 1, echo_stream, echo_dg }, |
273 | #endif | 272 | #endif |
274 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD | 273 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD |
275 | /* Internet /dev/null */ | ||
276 | { "discard", 1, discard_stream, discard_dg }, | 274 | { "discard", 1, discard_stream, discard_dg }, |
277 | #endif | 275 | #endif |
278 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 276 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
279 | /* Familiar character generator */ | ||
280 | { "chargen", 1, chargen_stream, chargen_dg }, | 277 | { "chargen", 1, chargen_stream, chargen_dg }, |
281 | #endif | 278 | #endif |
282 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME | 279 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME |
283 | /* Return 32 bit time since 1900 */ | ||
284 | { "time", 0, machtime_stream, machtime_dg }, | 280 | { "time", 0, machtime_stream, machtime_dg }, |
285 | #endif | 281 | #endif |
286 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME | 282 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME |
287 | /* Return human-readable time */ | ||
288 | { "daytime", 0, daytime_stream, daytime_dg }, | 283 | { "daytime", 0, daytime_stream, daytime_dg }, |
289 | #endif | 284 | #endif |
290 | }; | 285 | }; |
@@ -305,8 +300,8 @@ struct globals { | |||
305 | FILE *fconfig; | 300 | FILE *fconfig; |
306 | char *default_local_hostname; | 301 | char *default_local_hostname; |
307 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 302 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
308 | char *endring; | 303 | char *end_ring; |
309 | char *ringpos; | 304 | char *ring_pos; |
310 | char ring[128]; | 305 | char ring[128]; |
311 | #endif | 306 | #endif |
312 | fd_set allsock; | 307 | fd_set allsock; |
@@ -333,8 +328,8 @@ struct BUG_G_too_big { | |||
333 | #define default_local_hostname (G.default_local_hostname) | 328 | #define default_local_hostname (G.default_local_hostname) |
334 | #define first_ps_byte (G.first_ps_byte ) | 329 | #define first_ps_byte (G.first_ps_byte ) |
335 | #define last_ps_byte (G.last_ps_byte ) | 330 | #define last_ps_byte (G.last_ps_byte ) |
336 | #define endring (G.endring ) | 331 | #define end_ring (G.end_ring ) |
337 | #define ringpos (G.ringpos ) | 332 | #define ring_pos (G.ring_pos ) |
338 | #define ring (G.ring ) | 333 | #define ring (G.ring ) |
339 | #define allsock (G.allsock ) | 334 | #define allsock (G.allsock ) |
340 | #define line (G.line ) | 335 | #define line (G.line ) |
@@ -357,6 +352,8 @@ static len_and_sockaddr *xzalloc_lsa(int family) | |||
357 | int sz; | 352 | int sz; |
358 | 353 | ||
359 | sz = sizeof(struct sockaddr_in); | 354 | sz = sizeof(struct sockaddr_in); |
355 | if (family == AF_UNIX) | ||
356 | sz = sizeof(struct sockaddr_un); | ||
360 | #if ENABLE_FEATURE_IPV6 | 357 | #if ENABLE_FEATURE_IPV6 |
361 | if (family == AF_INET6) | 358 | if (family == AF_INET6) |
362 | sz = sizeof(struct sockaddr_in6); | 359 | sz = sizeof(struct sockaddr_in6); |
@@ -367,7 +364,6 @@ static len_and_sockaddr *xzalloc_lsa(int family) | |||
367 | return lsa; | 364 | return lsa; |
368 | } | 365 | } |
369 | 366 | ||
370 | |||
371 | static void rearm_alarm(void) | 367 | static void rearm_alarm(void) |
372 | { | 368 | { |
373 | if (!alarm_armed) { | 369 | if (!alarm_armed) { |
@@ -660,10 +656,8 @@ static NOINLINE servtab_t *parse_one_line(void) | |||
660 | } | 656 | } |
661 | 657 | ||
662 | arg = next_word(&cp); | 658 | arg = next_word(&cp); |
663 | if (arg == NULL) { | 659 | if (arg == NULL) /* a blank line. */ |
664 | /* A blank line. */ | ||
665 | goto more; | 660 | goto more; |
666 | } | ||
667 | 661 | ||
668 | /* [host:]service socktype proto wait user[:group] prog [args] */ | 662 | /* [host:]service socktype proto wait user[:group] prog [args] */ |
669 | /* Check for "host:...." line */ | 663 | /* Check for "host:...." line */ |
@@ -764,9 +758,9 @@ static NOINLINE servtab_t *parse_one_line(void) | |||
764 | } | 758 | } |
765 | /* we don't really need getprotobyname()! */ | 759 | /* we don't really need getprotobyname()! */ |
766 | if (strcmp(arg, "tcp") == 0) | 760 | if (strcmp(arg, "tcp") == 0) |
767 | sep->se_proto_no = 6; | 761 | sep->se_proto_no = IPPROTO_TCP; /* = 6 */ |
768 | if (strcmp(arg, "udp") == 0) | 762 | if (strcmp(arg, "udp") == 0) |
769 | sep->se_proto_no = 17; | 763 | sep->se_proto_no = IPPROTO_UDP; /* = 17 */ |
770 | if (six) | 764 | if (six) |
771 | *six = '6'; | 765 | *six = '6'; |
772 | if (!sep->se_proto_no) /* not tcp/udp?? */ | 766 | if (!sep->se_proto_no) /* not tcp/udp?? */ |
@@ -785,7 +779,11 @@ static NOINLINE servtab_t *parse_one_line(void) | |||
785 | if (errno) | 779 | if (errno) |
786 | goto parse_err; | 780 | goto parse_err; |
787 | } | 781 | } |
788 | sep->se_wait = (strcmp(arg, "wait") == 0); | 782 | sep->se_wait = (arg[0] != 'n' || arg[1] != 'o'); |
783 | if (!sep->se_wait) /* "no" seen */ | ||
784 | arg += 2; | ||
785 | if (strcmp(arg, "wait") != 0) | ||
786 | goto parse_err; | ||
789 | 787 | ||
790 | /* user[:group] prog [args] */ | 788 | /* user[:group] prog [args] */ |
791 | sep->se_user = xstrdup(next_word(&cp)); | 789 | sep->se_user = xstrdup(next_word(&cp)); |
@@ -804,48 +802,56 @@ static NOINLINE servtab_t *parse_one_line(void) | |||
804 | if (sep->se_program == NULL) | 802 | if (sep->se_program == NULL) |
805 | goto parse_err; | 803 | goto parse_err; |
806 | #ifdef INETD_BUILTINS_ENABLED | 804 | #ifdef INETD_BUILTINS_ENABLED |
807 | /* sep->se_builtin = NULL; - done by new_servtab() */ | ||
808 | if (strcmp(sep->se_program, "internal") == 0 | 805 | if (strcmp(sep->se_program, "internal") == 0 |
806 | && strlen(sep->se_service) <= 7 | ||
809 | && (sep->se_socktype == SOCK_STREAM | 807 | && (sep->se_socktype == SOCK_STREAM |
810 | || sep->se_socktype == SOCK_DGRAM) | 808 | || sep->se_socktype == SOCK_DGRAM) |
811 | ) { | 809 | ) { |
812 | int i; | 810 | int i; |
813 | for (i = 0; i < ARRAY_SIZE(builtins); i++) | 811 | for (i = 0; i < ARRAY_SIZE(builtins); i++) |
814 | if (strcmp(builtins[i].bi_service, sep->se_service) == 0) | 812 | if (strncmp(builtins[i].bi_service7, sep->se_service, 7) == 0) |
815 | goto found_bi; | 813 | goto found_bi; |
816 | bb_error_msg("unknown internal service %s", sep->se_service); | 814 | bb_error_msg("unknown internal service %s", sep->se_service); |
817 | goto parse_err; | 815 | goto parse_err; |
818 | found_bi: | 816 | found_bi: |
819 | sep->se_builtin = &builtins[i]; | 817 | sep->se_builtin = &builtins[i]; |
820 | sep->se_wait = 0; /* = builtins[i].bi_wait; - always 0 */ | 818 | /* stream builtins must be "nowait", dgram must be "wait" */ |
819 | if (sep->se_wait != (sep->se_socktype == SOCK_DGRAM)) | ||
820 | goto parse_err; | ||
821 | } | 821 | } |
822 | #endif | 822 | #endif |
823 | argc = 0; | 823 | argc = 0; |
824 | while ((arg = next_word(&cp)) != NULL && argc < MAXARGV) { | 824 | while ((arg = next_word(&cp)) != NULL && argc < MAXARGV) |
825 | sep->se_argv[argc++] = xstrdup(arg); | 825 | sep->se_argv[argc++] = xstrdup(arg); |
826 | |||
827 | /* catch mixups. "<service> stream udp ..." == wtf */ | ||
828 | if (sep->se_socktype == SOCK_STREAM) { | ||
829 | if (sep->se_proto_no == IPPROTO_UDP) | ||
830 | goto parse_err; | ||
831 | } | ||
832 | if (sep->se_socktype == SOCK_DGRAM) { | ||
833 | if (sep->se_proto_no == IPPROTO_TCP) | ||
834 | goto parse_err; | ||
835 | /* "udp nowait" is a small fork bomb :) */ | ||
836 | if (!sep->se_wait) | ||
837 | goto parse_err; | ||
826 | } | 838 | } |
827 | /* while (argc <= MAXARGV) */ | 839 | |
828 | /* sep->se_argv[argc++] = NULL; - done by new_servtab() */ | 840 | /* check if the hostname specifier is a comma separated list |
829 | 841 | * of hostnames. we'll make new entries for each address. */ | |
830 | /* | ||
831 | * Now that we've processed the entire line, check if the hostname | ||
832 | * specifier was a comma separated list of hostnames. If so | ||
833 | * we'll make new entries for each address. | ||
834 | */ | ||
835 | while ((hostdelim = strrchr(sep->se_local_hostname, ',')) != NULL) { | 842 | while ((hostdelim = strrchr(sep->se_local_hostname, ',')) != NULL) { |
836 | nsep = dup_servtab(sep); | 843 | nsep = dup_servtab(sep); |
837 | /* | 844 | /* NUL terminate the hostname field of the existing entry, |
838 | * NUL terminate the hostname field of the existing entry, | 845 | * and make a dup for the new entry. */ |
839 | * and make a dup for the new entry. | ||
840 | */ | ||
841 | *hostdelim++ = '\0'; | 846 | *hostdelim++ = '\0'; |
842 | nsep->se_local_hostname = xstrdup(hostdelim); | 847 | nsep->se_local_hostname = xstrdup(hostdelim); |
843 | nsep->se_next = sep->se_next; | 848 | nsep->se_next = sep->se_next; |
844 | sep->se_next = nsep; | 849 | sep->se_next = nsep; |
845 | } | 850 | } |
846 | 851 | ||
847 | /* Was doing it here: */ | 852 | /* was doing it here: */ |
848 | /* DNS resolution, create copies for each IP address */ | 853 | /* DNS resolution, create copies for each IP address */ |
854 | /* IPv6-ization destroyed it :( */ | ||
849 | 855 | ||
850 | return sep; | 856 | return sep; |
851 | } | 857 | } |
@@ -947,15 +953,9 @@ static void reread_config_file(int sig ATTRIBUTE_UNUSED) | |||
947 | switch (sep->se_family) { | 953 | switch (sep->se_family) { |
948 | struct sockaddr_un *sun; | 954 | struct sockaddr_un *sun; |
949 | case AF_UNIX: | 955 | case AF_UNIX: |
950 | /* we have poor infrastructure for AF_UNIX... */ | 956 | lsa = xzalloc_lsa(AF_UNIX); |
951 | n = strlen(sep->se_service); | ||
952 | if (n > sizeof(sun->sun_path) - 1) | ||
953 | n = sizeof(sun->sun_path) - 1; | ||
954 | lsa = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_un)); | ||
955 | lsa->len = sizeof(struct sockaddr_un); | ||
956 | sun = (struct sockaddr_un*)&lsa->u.sa; | 957 | sun = (struct sockaddr_un*)&lsa->u.sa; |
957 | sun->sun_family = AF_UNIX; | 958 | safe_strncpy(sun->sun_path, sep->se_service, sizeof(sun->sun_path)); |
958 | strncpy(sun->sun_path, sep->se_service, n); | ||
959 | break; | 959 | break; |
960 | 960 | ||
961 | default: /* case AF_INET, case AF_INET6 */ | 961 | default: /* case AF_INET, case AF_INET6 */ |
@@ -1259,8 +1259,8 @@ int inetd_main(int argc, char **argv) | |||
1259 | sep->se_count = 0; | 1259 | sep->se_count = 0; |
1260 | } | 1260 | } |
1261 | } | 1261 | } |
1262 | /* on NOMMU, streamed echo, chargen and discard | 1262 | /* on NOMMU, streamed chargen |
1263 | * builtins wouldn't work, but they are | 1263 | * builtin wouldn't work, but it is |
1264 | * not allowed on NOMMU (ifdefed out) */ | 1264 | * not allowed on NOMMU (ifdefed out) */ |
1265 | #ifdef INETD_BUILTINS_ENABLED | 1265 | #ifdef INETD_BUILTINS_ENABLED |
1266 | if (BB_MMU && sep->se_builtin) | 1266 | if (BB_MMU && sep->se_builtin) |
@@ -1311,8 +1311,42 @@ int inetd_main(int argc, char **argv) | |||
1311 | continue; /* -> check next fd in fd set */ | 1311 | continue; /* -> check next fd in fd set */ |
1312 | } | 1312 | } |
1313 | #endif | 1313 | #endif |
1314 | /* child. prepare env and exec program */ | 1314 | /* child */ |
1315 | setsid(); | 1315 | setsid(); |
1316 | #if 0 | ||
1317 | /* This does not work. | ||
1318 | * Actually, it _almost_ works. The idea behind it is: child | ||
1319 | * can peek at (already received and buffered by kernel) UDP packet, | ||
1320 | * and perform connect() on the socket so that it is linked only | ||
1321 | * to this peer. But this also affects parent, because descriptors | ||
1322 | * are shared after fork() a-la dup(). When parent returns to | ||
1323 | * select(), it will see this descriptor attached to the peer (!) | ||
1324 | * and likely still readable, will act on it and mess things up | ||
1325 | * (can create many copies of same child, etc). | ||
1326 | * If child will create new socket instead, then bind() and | ||
1327 | * connect() it to peer's address, descriptor aliasing problem | ||
1328 | * is solved, but first packet cannot be "transferred" to the new | ||
1329 | * socket. It is not a problem if child can account for this, | ||
1330 | * but our child will exec - and exec'ed program does not know | ||
1331 | * about this "lost packet" problem! Pity... */ | ||
1332 | /* "nowait" udp[6]. Hmmm... */ | ||
1333 | if (!sep->se_wait | ||
1334 | && sep->se_socktype == SOCK_DGRAM | ||
1335 | && sep->se_family != AF_UNIX | ||
1336 | ) { | ||
1337 | len_and_sockaddr *lsa = xzalloc_lsa(sep->se_family); | ||
1338 | /* peek at the packet and remember peer addr */ | ||
1339 | int r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT, | ||
1340 | &lsa->u.sa, &lsa->len); | ||
1341 | if (r >= 0) | ||
1342 | /* make this socket "connected" to peer addr: | ||
1343 | * only packets from this peer will be recv'ed, | ||
1344 | * and bare write()/send() will work on it */ | ||
1345 | connect(ctrl, &lsa->u.sa, lsa->len); | ||
1346 | free(lsa); | ||
1347 | } | ||
1348 | #endif | ||
1349 | /* prepare env and exec program */ | ||
1316 | pwd = getpwnam(sep->se_user); | 1350 | pwd = getpwnam(sep->se_user); |
1317 | if (pwd == NULL) { | 1351 | if (pwd == NULL) { |
1318 | bb_error_msg("%s: no such user", sep->se_user); | 1352 | bb_error_msg("%s: no such user", sep->se_user); |
@@ -1342,8 +1376,8 @@ int inetd_main(int argc, char **argv) | |||
1342 | bb_perror_msg("setrlimit"); | 1376 | bb_perror_msg("setrlimit"); |
1343 | closelog(); | 1377 | closelog(); |
1344 | xmove_fd(ctrl, 0); | 1378 | xmove_fd(ctrl, 0); |
1345 | dup2(0, 1); | 1379 | xdup2(0, 1); |
1346 | dup2(0, 2); | 1380 | xdup2(0, 2); |
1347 | /* NB: among others, this loop closes listening socket | 1381 | /* NB: among others, this loop closes listening socket |
1348 | * for nowait stream children */ | 1382 | * for nowait stream children */ |
1349 | for (sep2 = serv_list; sep2; sep2 = sep2->se_next) | 1383 | for (sep2 = serv_list; sep2; sep2 = sep2->se_next) |
@@ -1378,6 +1412,8 @@ static void echo_stream(int s, servtab_t *sep ATTRIBUTE_UNUSED) | |||
1378 | } | 1412 | } |
1379 | #else | 1413 | #else |
1380 | static const char *const args[] = { "cat", NULL }; | 1414 | static const char *const args[] = { "cat", NULL }; |
1415 | /* no error messages */ | ||
1416 | xmove_fd(xopen("/dev/null", O_WRONLY), STDERR_FILENO); | ||
1381 | BB_EXECVP("cat", (char**)args); | 1417 | BB_EXECVP("cat", (char**)args); |
1382 | _exit(1); | 1418 | _exit(1); |
1383 | #endif | 1419 | #endif |
@@ -1404,8 +1440,16 @@ static void echo_dg(int s, servtab_t *sep) | |||
1404 | /* ARGSUSED */ | 1440 | /* ARGSUSED */ |
1405 | static void discard_stream(int s, servtab_t *sep ATTRIBUTE_UNUSED) | 1441 | static void discard_stream(int s, servtab_t *sep ATTRIBUTE_UNUSED) |
1406 | { | 1442 | { |
1443 | #if BB_MMU | ||
1407 | while (safe_read(s, line, LINE_SIZE) > 0) | 1444 | while (safe_read(s, line, LINE_SIZE) > 0) |
1408 | continue; | 1445 | continue; |
1446 | #else | ||
1447 | static const char *const args[] = { "dd", "of=/dev/null", NULL }; | ||
1448 | /* no error messages */ | ||
1449 | xmove_fd(xopen("/dev/null", O_WRONLY), STDERR_FILENO); | ||
1450 | BB_EXECVP("dd", (char**)args); | ||
1451 | _exit(1); | ||
1452 | #endif | ||
1409 | } | 1453 | } |
1410 | /* ARGSUSED */ | 1454 | /* ARGSUSED */ |
1411 | static void discard_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) | 1455 | static void discard_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) |
@@ -1418,14 +1462,14 @@ static void discard_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) | |||
1418 | 1462 | ||
1419 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 1463 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
1420 | #define LINESIZ 72 | 1464 | #define LINESIZ 72 |
1421 | static void initring(void) | 1465 | static void init_ring(void) |
1422 | { | 1466 | { |
1423 | int i; | 1467 | int i; |
1424 | 1468 | ||
1425 | endring = ring; | 1469 | end_ring = ring; |
1426 | for (i = 0; i <= 128; ++i) | 1470 | for (i = 0; i <= 128; ++i) |
1427 | if (isprint(i)) | 1471 | if (isprint(i)) |
1428 | *endring++ = i; | 1472 | *end_ring++ = i; |
1429 | } | 1473 | } |
1430 | /* Character generator. MMU arches only. */ | 1474 | /* Character generator. MMU arches only. */ |
1431 | /* ARGSUSED */ | 1475 | /* ARGSUSED */ |
@@ -1435,8 +1479,8 @@ static void chargen_stream(int s, servtab_t *sep) | |||
1435 | int len; | 1479 | int len; |
1436 | char text[LINESIZ + 2]; | 1480 | char text[LINESIZ + 2]; |
1437 | 1481 | ||
1438 | if (!endring) { | 1482 | if (!end_ring) { |
1439 | initring(); | 1483 | init_ring(); |
1440 | rs = ring; | 1484 | rs = ring; |
1441 | } | 1485 | } |
1442 | 1486 | ||
@@ -1444,14 +1488,14 @@ static void chargen_stream(int s, servtab_t *sep) | |||
1444 | text[LINESIZ + 1] = '\n'; | 1488 | text[LINESIZ + 1] = '\n'; |
1445 | rs = ring; | 1489 | rs = ring; |
1446 | for (;;) { | 1490 | for (;;) { |
1447 | len = endring - rs; | 1491 | len = end_ring - rs; |
1448 | if (len >= LINESIZ) | 1492 | if (len >= LINESIZ) |
1449 | memmove(text, rs, LINESIZ); | 1493 | memmove(text, rs, LINESIZ); |
1450 | else { | 1494 | else { |
1451 | memmove(text, rs, len); | 1495 | memmove(text, rs, len); |
1452 | memmove(text + len, ring, LINESIZ - len); | 1496 | memmove(text + len, ring, LINESIZ - len); |
1453 | } | 1497 | } |
1454 | if (++rs == endring) | 1498 | if (++rs == end_ring) |
1455 | rs = ring; | 1499 | rs = ring; |
1456 | xwrite(s, text, sizeof(text)); | 1500 | xwrite(s, text, sizeof(text)); |
1457 | } | 1501 | } |
@@ -1469,20 +1513,20 @@ static void chargen_dg(int s, servtab_t *sep) | |||
1469 | if (recvfrom(s, text, sizeof(text), MSG_DONTWAIT, &lsa->u.sa, &lsa->len) < 0) | 1513 | if (recvfrom(s, text, sizeof(text), MSG_DONTWAIT, &lsa->u.sa, &lsa->len) < 0) |
1470 | return; | 1514 | return; |
1471 | 1515 | ||
1472 | if (!endring) { | 1516 | if (!end_ring) { |
1473 | initring(); | 1517 | init_ring(); |
1474 | ringpos = ring; | 1518 | ring_pos = ring; |
1475 | } | 1519 | } |
1476 | 1520 | ||
1477 | len = endring - ringpos; | 1521 | len = end_ring - ring_pos; |
1478 | if (len >= LINESIZ) | 1522 | if (len >= LINESIZ) |
1479 | memmove(text, ringpos, LINESIZ); | 1523 | memmove(text, ring_pos, LINESIZ); |
1480 | else { | 1524 | else { |
1481 | memmove(text, ringpos, len); | 1525 | memmove(text, ring_pos, len); |
1482 | memmove(text + len, ring, LINESIZ - len); | 1526 | memmove(text + len, ring, LINESIZ - len); |
1483 | } | 1527 | } |
1484 | if (++ringpos == endring) | 1528 | if (++ring_pos == end_ring) |
1485 | ringpos = ring; | 1529 | ring_pos = ring; |
1486 | text[LINESIZ] = '\r'; | 1530 | text[LINESIZ] = '\r'; |
1487 | text[LINESIZ + 1] = '\n'; | 1531 | text[LINESIZ + 1] = '\n'; |
1488 | sendto(s, text, sizeof(text), 0, &lsa->u.sa, lsa->len); | 1532 | sendto(s, text, sizeof(text), 0, &lsa->u.sa, lsa->len); |
@@ -1498,7 +1542,7 @@ static void chargen_dg(int s, servtab_t *sep) | |||
1498 | * we must add 2208988800 seconds to this figure to make up for | 1542 | * we must add 2208988800 seconds to this figure to make up for |
1499 | * some seventy years Bell Labs was asleep. | 1543 | * some seventy years Bell Labs was asleep. |
1500 | */ | 1544 | */ |
1501 | static unsigned machtime(void) | 1545 | static uint32_t machtime(void) |
1502 | { | 1546 | { |
1503 | struct timeval tv; | 1547 | struct timeval tv; |
1504 | 1548 | ||
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 2ee833e3f..ce4829584 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
@@ -751,6 +751,11 @@ int nc_main(int argc, char **argv) | |||
751 | if (option_mask32 & OPT_s) { /* local address */ | 751 | if (option_mask32 & OPT_s) { /* local address */ |
752 | /* if o_lport is still 0, then we will use random port */ | 752 | /* if o_lport is still 0, then we will use random port */ |
753 | ouraddr = xhost2sockaddr(str_s, o_lport); | 753 | ouraddr = xhost2sockaddr(str_s, o_lport); |
754 | #ifdef BLOAT | ||
755 | /* prevent spurious "UDP listen needs !0 port" */ | ||
756 | o_lport = get_nport(ouraddr); | ||
757 | o_lport = ntohs(o_lport); | ||
758 | #endif | ||
754 | x = xsocket(ouraddr->u.sa.sa_family, x, 0); | 759 | x = xsocket(ouraddr->u.sa.sa_family, x, 0); |
755 | } else { | 760 | } else { |
756 | /* We try IPv6, then IPv4, unless addr family is | 761 | /* We try IPv6, then IPv4, unless addr family is |
@@ -771,12 +776,14 @@ int nc_main(int argc, char **argv) | |||
771 | setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf); | 776 | setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf); |
772 | #endif | 777 | #endif |
773 | 778 | ||
779 | #ifdef BLOAT | ||
774 | if (OPT_l && (option_mask32 & (OPT_u|OPT_l)) == (OPT_u|OPT_l)) { | 780 | if (OPT_l && (option_mask32 & (OPT_u|OPT_l)) == (OPT_u|OPT_l)) { |
775 | /* apparently UDP can listen ON "port 0", | 781 | /* apparently UDP can listen ON "port 0", |
776 | but that's not useful */ | 782 | but that's not useful */ |
777 | if (!o_lport) | 783 | if (!o_lport) |
778 | bb_error_msg_and_die("UDP listen needs nonzero -p port"); | 784 | bb_error_msg_and_die("UDP listen needs nonzero -p port"); |
779 | } | 785 | } |
786 | #endif | ||
780 | 787 | ||
781 | FD_SET(0, &ding1); /* stdin *is* initially open */ | 788 | FD_SET(0, &ding1); /* stdin *is* initially open */ |
782 | if (proggie) { | 789 | if (proggie) { |