aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/inetd.c66
1 files changed, 55 insertions, 11 deletions
diff --git a/networking/inetd.c b/networking/inetd.c
index 873fd9528..fc6847bb5 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -357,10 +357,26 @@ struct BUG_G_too_big {
357 config_filename = "/etc/inetd.conf"; \ 357 config_filename = "/etc/inetd.conf"; \
358} while (0) 358} while (0)
359 359
360#if 1
361# define dbg(...) ((void)0)
362#else
363# define dbg(...) \
364do { \
365 int dbg_fd = open("inetd_debug.log", O_WRONLY | O_CREAT | O_APPEND, 0666); \
366 if (dbg_fd >= 0) { \
367 fdprintf(dbg_fd, "%d: ", getpid()); \
368 fdprintf(dbg_fd, __VA_ARGS__); \
369 close(dbg_fd); \
370 } \
371} while (0)
372#endif
373
360static void maybe_close(int fd) 374static void maybe_close(int fd)
361{ 375{
362 if (fd >= 0) 376 if (fd >= 0) {
363 close(fd); 377 close(fd);
378 dbg("closed fd:%d\n", fd);
379 }
364} 380}
365 381
366// TODO: move to libbb? 382// TODO: move to libbb?
@@ -464,7 +480,9 @@ static void remove_fd_from_set(int fd)
464{ 480{
465 if (fd >= 0) { 481 if (fd >= 0) {
466 FD_CLR(fd, &allsock); 482 FD_CLR(fd, &allsock);
483 dbg("stopped listening on fd:%d\n", fd);
467 maxsock = -1; 484 maxsock = -1;
485 dbg("maxsock:%d\n", maxsock);
468 } 486 }
469} 487}
470 488
@@ -472,8 +490,10 @@ static void add_fd_to_set(int fd)
472{ 490{
473 if (fd >= 0) { 491 if (fd >= 0) {
474 FD_SET(fd, &allsock); 492 FD_SET(fd, &allsock);
493 dbg("started listening on fd:%d\n", fd);
475 if (maxsock >= 0 && fd > maxsock) { 494 if (maxsock >= 0 && fd > maxsock) {
476 prev_maxsock = maxsock = fd; 495 prev_maxsock = maxsock = fd;
496 dbg("maxsock:%d\n", maxsock);
477 if ((rlim_t)fd > rlim_ofile_cur - FD_MARGIN) 497 if ((rlim_t)fd > rlim_ofile_cur - FD_MARGIN)
478 bump_nofile(); 498 bump_nofile();
479 } 499 }
@@ -492,6 +512,7 @@ static void recalculate_maxsock(void)
492 maxsock = fd; 512 maxsock = fd;
493 fd++; 513 fd++;
494 } 514 }
515 dbg("recalculated maxsock:%d\n", maxsock);
495 prev_maxsock = maxsock; 516 prev_maxsock = maxsock;
496 if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN) 517 if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN)
497 bump_nofile(); 518 bump_nofile();
@@ -549,8 +570,13 @@ static void prepare_socket_fd(servtab_t *sep)
549 rearm_alarm(); 570 rearm_alarm();
550 return; 571 return;
551 } 572 }
552 if (sep->se_socktype == SOCK_STREAM) 573
574 if (sep->se_socktype == SOCK_STREAM) {
553 listen(fd, global_queuelen); 575 listen(fd, global_queuelen);
576 dbg("new sep->se_fd:%d (stream)\n", fd);
577 } else {
578 dbg("new sep->se_fd:%d (!stream)\n", fd);
579 }
554 580
555 add_fd_to_set(fd); 581 add_fd_to_set(fd);
556 sep->se_fd = fd; 582 sep->se_fd = fd;
@@ -1012,7 +1038,7 @@ static void reread_config_file(int sig UNUSED_PARAM)
1012 * new config file doesnt have them. */ 1038 * new config file doesnt have them. */
1013 block_CHLD_HUP_ALRM(&omask); 1039 block_CHLD_HUP_ALRM(&omask);
1014 sepp = &serv_list; 1040 sepp = &serv_list;
1015 while ((sep = *sepp)) { 1041 while ((sep = *sepp) != NULL) {
1016 if (sep->se_checked) { 1042 if (sep->se_checked) {
1017 sepp = &sep->se_next; 1043 sepp = &sep->se_next;
1018 continue; 1044 continue;
@@ -1206,11 +1232,13 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1206 } 1232 }
1207 continue; 1233 continue;
1208 } 1234 }
1235 dbg("ready_fd_cnt:%d\n", ready_fd_cnt);
1209 1236
1210 for (sep = serv_list; ready_fd_cnt && sep; sep = sep->se_next) { 1237 for (sep = serv_list; ready_fd_cnt && sep; sep = sep->se_next) {
1211 if (sep->se_fd == -1 || !FD_ISSET(sep->se_fd, &readable)) 1238 if (sep->se_fd == -1 || !FD_ISSET(sep->se_fd, &readable))
1212 continue; 1239 continue;
1213 1240
1241 dbg("ready fd:%d\n", sep->se_fd);
1214 ready_fd_cnt--; 1242 ready_fd_cnt--;
1215 ctrl = sep->se_fd; 1243 ctrl = sep->se_fd;
1216 accepted_fd = -1; 1244 accepted_fd = -1;
@@ -1218,6 +1246,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1218 if (!sep->se_wait) { 1246 if (!sep->se_wait) {
1219 if (sep->se_socktype == SOCK_STREAM) { 1247 if (sep->se_socktype == SOCK_STREAM) {
1220 ctrl = accepted_fd = accept(sep->se_fd, NULL, NULL); 1248 ctrl = accepted_fd = accept(sep->se_fd, NULL, NULL);
1249 dbg("accepted_fd:%d\n", accepted_fd);
1221 if (ctrl < 0) { 1250 if (ctrl < 0) {
1222 if (errno != EINTR) 1251 if (errno != EINTR)
1223 bb_perror_msg("accept (for %s)", sep->se_service); 1252 bb_perror_msg("accept (for %s)", sep->se_service);
@@ -1238,19 +1267,22 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1238 * (can create many copies of same child, etc). 1267 * (can create many copies of same child, etc).
1239 * Parent must create and use new socket instead. */ 1268 * Parent must create and use new socket instead. */
1240 new_udp_fd = socket(sep->se_family, SOCK_DGRAM, 0); 1269 new_udp_fd = socket(sep->se_family, SOCK_DGRAM, 0);
1270 dbg("new_udp_fd:%d\n", new_udp_fd);
1241 if (new_udp_fd < 0) { /* error: eat packet, forget about it */ 1271 if (new_udp_fd < 0) { /* error: eat packet, forget about it */
1242 udp_err: 1272 udp_err:
1243 recv(sep->se_fd, line, LINE_SIZE, MSG_DONTWAIT); 1273 recv(sep->se_fd, line, LINE_SIZE, MSG_DONTWAIT);
1244 continue; 1274 continue;
1245 } 1275 }
1246 setsockopt_reuseaddr(new_udp_fd); 1276 setsockopt_reuseaddr(new_udp_fd);
1247 /* TODO: better do bind after vfork in parent, 1277 /* TODO: better do bind after fork in parent,
1248 * so that we don't have two wildcard bound sockets 1278 * so that we don't have two wildcard bound sockets
1249 * even for a brief moment? */ 1279 * even for a brief moment? */
1250 if (bind(new_udp_fd, &sep->se_lsa->u.sa, sep->se_lsa->len) < 0) { 1280 if (bind(new_udp_fd, &sep->se_lsa->u.sa, sep->se_lsa->len) < 0) {
1281 dbg("bind(new_udp_fd) failed\n");
1251 close(new_udp_fd); 1282 close(new_udp_fd);
1252 goto udp_err; 1283 goto udp_err;
1253 } 1284 }
1285 dbg("bind(new_udp_fd) succeeded\n");
1254 } 1286 }
1255 } 1287 }
1256 1288
@@ -1278,6 +1310,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1278 sep->se_count = 0; 1310 sep->se_count = 0;
1279 rearm_alarm(); /* will revive it in RETRYTIME sec */ 1311 rearm_alarm(); /* will revive it in RETRYTIME sec */
1280 restore_sigmask(&omask); 1312 restore_sigmask(&omask);
1313 maybe_close(new_udp_fd);
1281 maybe_close(accepted_fd); 1314 maybe_close(accepted_fd);
1282 continue; /* -> check next fd in fd set */ 1315 continue; /* -> check next fd in fd set */
1283 } 1316 }
@@ -1298,17 +1331,18 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1298 bb_perror_msg("vfork"+1); 1331 bb_perror_msg("vfork"+1);
1299 sleep(1); 1332 sleep(1);
1300 restore_sigmask(&omask); 1333 restore_sigmask(&omask);
1334 maybe_close(new_udp_fd);
1301 maybe_close(accepted_fd); 1335 maybe_close(accepted_fd);
1302 continue; /* -> check next fd in fd set */ 1336 continue; /* -> check next fd in fd set */
1303 } 1337 }
1304 if (pid == 0) 1338 if (pid == 0)
1305 pid--; /* -1: "we did fork and we are child" */ 1339 pid--; /* -1: "we did fork and we are child" */
1306 } 1340 }
1307 /* if pid == 0 here, we never forked */ 1341 /* if pid == 0 here, we didn't fork */
1308 1342
1309 if (pid > 0) { /* parent */ 1343 if (pid > 0) { /* parent */
1310 if (sep->se_wait) { 1344 if (sep->se_wait) {
1311 /* tcp wait: we passed listening socket to child, 1345 /* wait: we passed socket to child,
1312 * will wait for child to terminate */ 1346 * will wait for child to terminate */
1313 sep->se_wait = pid; 1347 sep->se_wait = pid;
1314 remove_fd_from_set(sep->se_fd); 1348 remove_fd_from_set(sep->se_fd);
@@ -1317,17 +1351,19 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1317 /* udp nowait: child connected the socket, 1351 /* udp nowait: child connected the socket,
1318 * we created and will use new, unconnected one */ 1352 * we created and will use new, unconnected one */
1319 xmove_fd(new_udp_fd, sep->se_fd); 1353 xmove_fd(new_udp_fd, sep->se_fd);
1354 dbg("moved new_udp_fd:%d to sep->se_fd:%d\n", new_udp_fd, sep->se_fd);
1320 } 1355 }
1321 restore_sigmask(&omask); 1356 restore_sigmask(&omask);
1322 maybe_close(accepted_fd); 1357 maybe_close(accepted_fd);
1323 continue; /* -> check next fd in fd set */ 1358 continue; /* -> check next fd in fd set */
1324 } 1359 }
1325 1360
1326 /* we are either child or didn't vfork at all */ 1361 /* we are either child or didn't fork at all */
1327#ifdef INETD_BUILTINS_ENABLED 1362#ifdef INETD_BUILTINS_ENABLED
1328 if (sep->se_builtin) { 1363 if (sep->se_builtin) {
1329 if (pid) { /* "pid" is -1: we did vfork */ 1364 if (pid) { /* "pid" is -1: we did fork */
1330 close(sep->se_fd); /* listening socket */ 1365 close(sep->se_fd); /* listening socket */
1366 dbg("closed sep->se_fd:%d\n", sep->se_fd);
1331 logmode = LOGMODE_NONE; /* make xwrite etc silent */ 1367 logmode = LOGMODE_NONE; /* make xwrite etc silent */
1332 } 1368 }
1333 restore_sigmask(&omask); 1369 restore_sigmask(&omask);
@@ -1335,7 +1371,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1335 sep->se_builtin->bi_stream_fn(ctrl, sep); 1371 sep->se_builtin->bi_stream_fn(ctrl, sep);
1336 else 1372 else
1337 sep->se_builtin->bi_dgram_fn(ctrl, sep); 1373 sep->se_builtin->bi_dgram_fn(ctrl, sep);
1338 if (pid) /* we did vfork */ 1374 if (pid) /* we did fork */
1339 _exit(EXIT_FAILURE); 1375 _exit(EXIT_FAILURE);
1340 maybe_close(accepted_fd); 1376 maybe_close(accepted_fd);
1341 continue; /* -> check next fd in fd set */ 1377 continue; /* -> check next fd in fd set */
@@ -1345,9 +1381,14 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1345 setsid(); 1381 setsid();
1346 /* "nowait" udp */ 1382 /* "nowait" udp */
1347 if (new_udp_fd >= 0) { 1383 if (new_udp_fd >= 0) {
1348 len_and_sockaddr *lsa = xzalloc_lsa(sep->se_family); 1384 len_and_sockaddr *lsa;
1385 int r;
1386
1387 close(new_udp_fd);
1388 dbg("closed new_udp_fd:%d\n", new_udp_fd);
1389 lsa = xzalloc_lsa(sep->se_family);
1349 /* peek at the packet and remember peer addr */ 1390 /* peek at the packet and remember peer addr */
1350 int r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT, 1391 r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT,
1351 &lsa->u.sa, &lsa->len); 1392 &lsa->u.sa, &lsa->len);
1352 if (r < 0) 1393 if (r < 0)
1353 goto do_exit1; 1394 goto do_exit1;
@@ -1355,6 +1396,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1355 * only packets from this peer will be recv'ed, 1396 * only packets from this peer will be recv'ed,
1356 * and bare write()/send() will work on it */ 1397 * and bare write()/send() will work on it */
1357 connect(ctrl, &lsa->u.sa, lsa->len); 1398 connect(ctrl, &lsa->u.sa, lsa->len);
1399 dbg("connected ctrl:%d to remote peer\n", ctrl);
1358 free(lsa); 1400 free(lsa);
1359 } 1401 }
1360 /* prepare env and exec program */ 1402 /* prepare env and exec program */
@@ -1391,6 +1433,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1391 */ 1433 */
1392 xmove_fd(ctrl, STDIN_FILENO); 1434 xmove_fd(ctrl, STDIN_FILENO);
1393 xdup2(STDIN_FILENO, STDOUT_FILENO); 1435 xdup2(STDIN_FILENO, STDOUT_FILENO);
1436 dbg("moved ctrl:%d to fd 0,1[,2]\n", ctrl);
1394 /* manpages of inetd I managed to find either say 1437 /* manpages of inetd I managed to find either say
1395 * that stderr is also redirected to the network, 1438 * that stderr is also redirected to the network,
1396 * or do not talk about redirection at all (!) */ 1439 * or do not talk about redirection at all (!) */
@@ -1403,6 +1446,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
1403 maybe_close(sep2->se_fd); 1446 maybe_close(sep2->se_fd);
1404 sigaction_set(SIGPIPE, &saved_pipe_handler); 1447 sigaction_set(SIGPIPE, &saved_pipe_handler);
1405 restore_sigmask(&omask); 1448 restore_sigmask(&omask);
1449 dbg("execing:'%s'\n", sep->se_program);
1406 BB_EXECVP(sep->se_program, sep->se_argv); 1450 BB_EXECVP(sep->se_program, sep->se_argv);
1407 bb_perror_msg("can't execute '%s'", sep->se_program); 1451 bb_perror_msg("can't execute '%s'", sep->se_program);
1408 do_exit1: 1452 do_exit1: