mirror of
https://github.com/sheumann/hush.git
synced 2025-01-11 08:29:54 +00:00
inetd: close new udp fd in "udp nowait" case
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
d2fe2ba08d
commit
223b9417b3
@ -357,10 +357,26 @@ struct BUG_G_too_big {
|
|||||||
config_filename = "/etc/inetd.conf"; \
|
config_filename = "/etc/inetd.conf"; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
# define dbg(...) ((void)0)
|
||||||
|
#else
|
||||||
|
# define dbg(...) \
|
||||||
|
do { \
|
||||||
|
int dbg_fd = open("inetd_debug.log", O_WRONLY | O_CREAT | O_APPEND, 0666); \
|
||||||
|
if (dbg_fd >= 0) { \
|
||||||
|
fdprintf(dbg_fd, "%d: ", getpid()); \
|
||||||
|
fdprintf(dbg_fd, __VA_ARGS__); \
|
||||||
|
close(dbg_fd); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
static void maybe_close(int fd)
|
static void maybe_close(int fd)
|
||||||
{
|
{
|
||||||
if (fd >= 0)
|
if (fd >= 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
|
dbg("closed fd:%d\n", fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move to libbb?
|
// TODO: move to libbb?
|
||||||
@ -464,7 +480,9 @@ static void remove_fd_from_set(int fd)
|
|||||||
{
|
{
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
FD_CLR(fd, &allsock);
|
FD_CLR(fd, &allsock);
|
||||||
|
dbg("stopped listening on fd:%d\n", fd);
|
||||||
maxsock = -1;
|
maxsock = -1;
|
||||||
|
dbg("maxsock:%d\n", maxsock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,8 +490,10 @@ static void add_fd_to_set(int fd)
|
|||||||
{
|
{
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
FD_SET(fd, &allsock);
|
FD_SET(fd, &allsock);
|
||||||
|
dbg("started listening on fd:%d\n", fd);
|
||||||
if (maxsock >= 0 && fd > maxsock) {
|
if (maxsock >= 0 && fd > maxsock) {
|
||||||
prev_maxsock = maxsock = fd;
|
prev_maxsock = maxsock = fd;
|
||||||
|
dbg("maxsock:%d\n", maxsock);
|
||||||
if ((rlim_t)fd > rlim_ofile_cur - FD_MARGIN)
|
if ((rlim_t)fd > rlim_ofile_cur - FD_MARGIN)
|
||||||
bump_nofile();
|
bump_nofile();
|
||||||
}
|
}
|
||||||
@ -492,6 +512,7 @@ static void recalculate_maxsock(void)
|
|||||||
maxsock = fd;
|
maxsock = fd;
|
||||||
fd++;
|
fd++;
|
||||||
}
|
}
|
||||||
|
dbg("recalculated maxsock:%d\n", maxsock);
|
||||||
prev_maxsock = maxsock;
|
prev_maxsock = maxsock;
|
||||||
if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN)
|
if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN)
|
||||||
bump_nofile();
|
bump_nofile();
|
||||||
@ -549,8 +570,13 @@ static void prepare_socket_fd(servtab_t *sep)
|
|||||||
rearm_alarm();
|
rearm_alarm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sep->se_socktype == SOCK_STREAM)
|
|
||||||
|
if (sep->se_socktype == SOCK_STREAM) {
|
||||||
listen(fd, global_queuelen);
|
listen(fd, global_queuelen);
|
||||||
|
dbg("new sep->se_fd:%d (stream)\n", fd);
|
||||||
|
} else {
|
||||||
|
dbg("new sep->se_fd:%d (!stream)\n", fd);
|
||||||
|
}
|
||||||
|
|
||||||
add_fd_to_set(fd);
|
add_fd_to_set(fd);
|
||||||
sep->se_fd = fd;
|
sep->se_fd = fd;
|
||||||
@ -1012,7 +1038,7 @@ static void reread_config_file(int sig UNUSED_PARAM)
|
|||||||
* new config file doesnt have them. */
|
* new config file doesnt have them. */
|
||||||
block_CHLD_HUP_ALRM(&omask);
|
block_CHLD_HUP_ALRM(&omask);
|
||||||
sepp = &serv_list;
|
sepp = &serv_list;
|
||||||
while ((sep = *sepp)) {
|
while ((sep = *sepp) != NULL) {
|
||||||
if (sep->se_checked) {
|
if (sep->se_checked) {
|
||||||
sepp = &sep->se_next;
|
sepp = &sep->se_next;
|
||||||
continue;
|
continue;
|
||||||
@ -1206,11 +1232,13 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
dbg("ready_fd_cnt:%d\n", ready_fd_cnt);
|
||||||
|
|
||||||
for (sep = serv_list; ready_fd_cnt && sep; sep = sep->se_next) {
|
for (sep = serv_list; ready_fd_cnt && sep; sep = sep->se_next) {
|
||||||
if (sep->se_fd == -1 || !FD_ISSET(sep->se_fd, &readable))
|
if (sep->se_fd == -1 || !FD_ISSET(sep->se_fd, &readable))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
dbg("ready fd:%d\n", sep->se_fd);
|
||||||
ready_fd_cnt--;
|
ready_fd_cnt--;
|
||||||
ctrl = sep->se_fd;
|
ctrl = sep->se_fd;
|
||||||
accepted_fd = -1;
|
accepted_fd = -1;
|
||||||
@ -1218,6 +1246,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
if (!sep->se_wait) {
|
if (!sep->se_wait) {
|
||||||
if (sep->se_socktype == SOCK_STREAM) {
|
if (sep->se_socktype == SOCK_STREAM) {
|
||||||
ctrl = accepted_fd = accept(sep->se_fd, NULL, NULL);
|
ctrl = accepted_fd = accept(sep->se_fd, NULL, NULL);
|
||||||
|
dbg("accepted_fd:%d\n", accepted_fd);
|
||||||
if (ctrl < 0) {
|
if (ctrl < 0) {
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
bb_perror_msg("accept (for %s)", sep->se_service);
|
bb_perror_msg("accept (for %s)", sep->se_service);
|
||||||
@ -1238,19 +1267,22 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
* (can create many copies of same child, etc).
|
* (can create many copies of same child, etc).
|
||||||
* Parent must create and use new socket instead. */
|
* Parent must create and use new socket instead. */
|
||||||
new_udp_fd = socket(sep->se_family, SOCK_DGRAM, 0);
|
new_udp_fd = socket(sep->se_family, SOCK_DGRAM, 0);
|
||||||
|
dbg("new_udp_fd:%d\n", new_udp_fd);
|
||||||
if (new_udp_fd < 0) { /* error: eat packet, forget about it */
|
if (new_udp_fd < 0) { /* error: eat packet, forget about it */
|
||||||
udp_err:
|
udp_err:
|
||||||
recv(sep->se_fd, line, LINE_SIZE, MSG_DONTWAIT);
|
recv(sep->se_fd, line, LINE_SIZE, MSG_DONTWAIT);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
setsockopt_reuseaddr(new_udp_fd);
|
setsockopt_reuseaddr(new_udp_fd);
|
||||||
/* TODO: better do bind after vfork in parent,
|
/* TODO: better do bind after fork in parent,
|
||||||
* so that we don't have two wildcard bound sockets
|
* so that we don't have two wildcard bound sockets
|
||||||
* even for a brief moment? */
|
* even for a brief moment? */
|
||||||
if (bind(new_udp_fd, &sep->se_lsa->u.sa, sep->se_lsa->len) < 0) {
|
if (bind(new_udp_fd, &sep->se_lsa->u.sa, sep->se_lsa->len) < 0) {
|
||||||
|
dbg("bind(new_udp_fd) failed\n");
|
||||||
close(new_udp_fd);
|
close(new_udp_fd);
|
||||||
goto udp_err;
|
goto udp_err;
|
||||||
}
|
}
|
||||||
|
dbg("bind(new_udp_fd) succeeded\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1278,6 +1310,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
sep->se_count = 0;
|
sep->se_count = 0;
|
||||||
rearm_alarm(); /* will revive it in RETRYTIME sec */
|
rearm_alarm(); /* will revive it in RETRYTIME sec */
|
||||||
restore_sigmask(&omask);
|
restore_sigmask(&omask);
|
||||||
|
maybe_close(new_udp_fd);
|
||||||
maybe_close(accepted_fd);
|
maybe_close(accepted_fd);
|
||||||
continue; /* -> check next fd in fd set */
|
continue; /* -> check next fd in fd set */
|
||||||
}
|
}
|
||||||
@ -1298,17 +1331,18 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
bb_perror_msg("vfork"+1);
|
bb_perror_msg("vfork"+1);
|
||||||
sleep(1);
|
sleep(1);
|
||||||
restore_sigmask(&omask);
|
restore_sigmask(&omask);
|
||||||
|
maybe_close(new_udp_fd);
|
||||||
maybe_close(accepted_fd);
|
maybe_close(accepted_fd);
|
||||||
continue; /* -> check next fd in fd set */
|
continue; /* -> check next fd in fd set */
|
||||||
}
|
}
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
pid--; /* -1: "we did fork and we are child" */
|
pid--; /* -1: "we did fork and we are child" */
|
||||||
}
|
}
|
||||||
/* if pid == 0 here, we never forked */
|
/* if pid == 0 here, we didn't fork */
|
||||||
|
|
||||||
if (pid > 0) { /* parent */
|
if (pid > 0) { /* parent */
|
||||||
if (sep->se_wait) {
|
if (sep->se_wait) {
|
||||||
/* tcp wait: we passed listening socket to child,
|
/* wait: we passed socket to child,
|
||||||
* will wait for child to terminate */
|
* will wait for child to terminate */
|
||||||
sep->se_wait = pid;
|
sep->se_wait = pid;
|
||||||
remove_fd_from_set(sep->se_fd);
|
remove_fd_from_set(sep->se_fd);
|
||||||
@ -1317,17 +1351,19 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
/* udp nowait: child connected the socket,
|
/* udp nowait: child connected the socket,
|
||||||
* we created and will use new, unconnected one */
|
* we created and will use new, unconnected one */
|
||||||
xmove_fd(new_udp_fd, sep->se_fd);
|
xmove_fd(new_udp_fd, sep->se_fd);
|
||||||
|
dbg("moved new_udp_fd:%d to sep->se_fd:%d\n", new_udp_fd, sep->se_fd);
|
||||||
}
|
}
|
||||||
restore_sigmask(&omask);
|
restore_sigmask(&omask);
|
||||||
maybe_close(accepted_fd);
|
maybe_close(accepted_fd);
|
||||||
continue; /* -> check next fd in fd set */
|
continue; /* -> check next fd in fd set */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we are either child or didn't vfork at all */
|
/* we are either child or didn't fork at all */
|
||||||
#ifdef INETD_BUILTINS_ENABLED
|
#ifdef INETD_BUILTINS_ENABLED
|
||||||
if (sep->se_builtin) {
|
if (sep->se_builtin) {
|
||||||
if (pid) { /* "pid" is -1: we did vfork */
|
if (pid) { /* "pid" is -1: we did fork */
|
||||||
close(sep->se_fd); /* listening socket */
|
close(sep->se_fd); /* listening socket */
|
||||||
|
dbg("closed sep->se_fd:%d\n", sep->se_fd);
|
||||||
logmode = LOGMODE_NONE; /* make xwrite etc silent */
|
logmode = LOGMODE_NONE; /* make xwrite etc silent */
|
||||||
}
|
}
|
||||||
restore_sigmask(&omask);
|
restore_sigmask(&omask);
|
||||||
@ -1335,7 +1371,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
sep->se_builtin->bi_stream_fn(ctrl, sep);
|
sep->se_builtin->bi_stream_fn(ctrl, sep);
|
||||||
else
|
else
|
||||||
sep->se_builtin->bi_dgram_fn(ctrl, sep);
|
sep->se_builtin->bi_dgram_fn(ctrl, sep);
|
||||||
if (pid) /* we did vfork */
|
if (pid) /* we did fork */
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
maybe_close(accepted_fd);
|
maybe_close(accepted_fd);
|
||||||
continue; /* -> check next fd in fd set */
|
continue; /* -> check next fd in fd set */
|
||||||
@ -1345,9 +1381,14 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
setsid();
|
setsid();
|
||||||
/* "nowait" udp */
|
/* "nowait" udp */
|
||||||
if (new_udp_fd >= 0) {
|
if (new_udp_fd >= 0) {
|
||||||
len_and_sockaddr *lsa = xzalloc_lsa(sep->se_family);
|
len_and_sockaddr *lsa;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
close(new_udp_fd);
|
||||||
|
dbg("closed new_udp_fd:%d\n", new_udp_fd);
|
||||||
|
lsa = xzalloc_lsa(sep->se_family);
|
||||||
/* peek at the packet and remember peer addr */
|
/* peek at the packet and remember peer addr */
|
||||||
int r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT,
|
r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT,
|
||||||
&lsa->u.sa, &lsa->len);
|
&lsa->u.sa, &lsa->len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto do_exit1;
|
goto do_exit1;
|
||||||
@ -1355,6 +1396,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
* only packets from this peer will be recv'ed,
|
* only packets from this peer will be recv'ed,
|
||||||
* and bare write()/send() will work on it */
|
* and bare write()/send() will work on it */
|
||||||
connect(ctrl, &lsa->u.sa, lsa->len);
|
connect(ctrl, &lsa->u.sa, lsa->len);
|
||||||
|
dbg("connected ctrl:%d to remote peer\n", ctrl);
|
||||||
free(lsa);
|
free(lsa);
|
||||||
}
|
}
|
||||||
/* prepare env and exec program */
|
/* prepare env and exec program */
|
||||||
@ -1391,6 +1433,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
*/
|
*/
|
||||||
xmove_fd(ctrl, STDIN_FILENO);
|
xmove_fd(ctrl, STDIN_FILENO);
|
||||||
xdup2(STDIN_FILENO, STDOUT_FILENO);
|
xdup2(STDIN_FILENO, STDOUT_FILENO);
|
||||||
|
dbg("moved ctrl:%d to fd 0,1[,2]\n", ctrl);
|
||||||
/* manpages of inetd I managed to find either say
|
/* manpages of inetd I managed to find either say
|
||||||
* that stderr is also redirected to the network,
|
* that stderr is also redirected to the network,
|
||||||
* or do not talk about redirection at all (!) */
|
* or do not talk about redirection at all (!) */
|
||||||
@ -1403,6 +1446,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
maybe_close(sep2->se_fd);
|
maybe_close(sep2->se_fd);
|
||||||
sigaction_set(SIGPIPE, &saved_pipe_handler);
|
sigaction_set(SIGPIPE, &saved_pipe_handler);
|
||||||
restore_sigmask(&omask);
|
restore_sigmask(&omask);
|
||||||
|
dbg("execing:'%s'\n", sep->se_program);
|
||||||
BB_EXECVP(sep->se_program, sep->se_argv);
|
BB_EXECVP(sep->se_program, sep->se_argv);
|
||||||
bb_perror_msg("can't execute '%s'", sep->se_program);
|
bb_perror_msg("can't execute '%s'", sep->se_program);
|
||||||
do_exit1:
|
do_exit1:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user