diff options
-rw-r--r-- | networking/inetd.c | 207 |
1 files changed, 130 insertions, 77 deletions
diff --git a/networking/inetd.c b/networking/inetd.c index e4e9f95b0..b3a00cfa5 100644 --- a/networking/inetd.c +++ b/networking/inetd.c | |||
@@ -190,9 +190,6 @@ extern char **environ; | |||
190 | 190 | ||
191 | /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ | 191 | /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ |
192 | #define FD_MARGIN 8 | 192 | #define FD_MARGIN 8 |
193 | static rlim_t rlim_ofile_cur = OPEN_MAX; | ||
194 | static struct rlimit rlim_ofile; | ||
195 | |||
196 | 193 | ||
197 | /* Check unsupporting builtin */ | 194 | /* Check unsupporting builtin */ |
198 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \ | 195 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \ |
@@ -209,11 +206,24 @@ static struct rlimit rlim_ofile; | |||
209 | # define INETD_SETPROCTITLE | 206 | # define INETD_SETPROCTITLE |
210 | #endif | 207 | #endif |
211 | 208 | ||
212 | typedef struct servtab { | 209 | typedef int8_t socktype_t; |
210 | typedef int8_t family_t; | ||
211 | struct BUG_too_small { | ||
212 | char BUG_socktype_t_too_small[(0 | ||
213 | | SOCK_STREAM | ||
214 | | SOCK_DGRAM | ||
215 | | SOCK_RDM | ||
216 | | SOCK_SEQPACKET | ||
217 | | SOCK_RAW) <= 127 ? 1 : -1]; | ||
218 | char BUG_family_t_too_small[(0 | ||
219 | | AF_INET | ||
220 | | AF_INET6 | ||
221 | | AF_UNIX) <= 127 ? 1 : -1]; | ||
222 | }; | ||
223 | |||
224 | typedef struct servtab_t { | ||
213 | char *se_hostaddr; /* host address to listen on */ | 225 | char *se_hostaddr; /* host address to listen on */ |
214 | char *se_service; /* name of service */ | 226 | char *se_service; /* name of service */ |
215 | int se_socktype; /* type of socket to use */ | ||
216 | int se_family; /* address family */ | ||
217 | char *se_proto; /* protocol used */ | 227 | char *se_proto; /* protocol used */ |
218 | #if ENABLE_FEATURE_INETD_RPC | 228 | #if ENABLE_FEATURE_INETD_RPC |
219 | int se_rpcprog; /* rpc program number */ | 229 | int se_rpcprog; /* rpc program number */ |
@@ -224,7 +234,9 @@ typedef struct servtab { | |||
224 | #define isrpcservice(sep) 0 | 234 | #define isrpcservice(sep) 0 |
225 | #endif | 235 | #endif |
226 | pid_t se_wait; /* single threaded server */ | 236 | pid_t se_wait; /* single threaded server */ |
227 | short se_checked; /* looked at during merge */ | 237 | socktype_t se_socktype; /* type of socket to use */ |
238 | family_t se_family; /* address family */ | ||
239 | smallint se_checked; /* looked at during merge */ | ||
228 | char *se_user; /* user name to run as */ | 240 | char *se_user; /* user name to run as */ |
229 | char *se_group; /* group name to run as */ | 241 | char *se_group; /* group name to run as */ |
230 | #ifdef INETD_FEATURE_ENABLED | 242 | #ifdef INETD_FEATURE_ENABLED |
@@ -250,17 +262,16 @@ typedef struct servtab { | |||
250 | int se_max; /* max # of instances of this service */ | 262 | int se_max; /* max # of instances of this service */ |
251 | int se_count; /* number started since se_time */ | 263 | int se_count; /* number started since se_time */ |
252 | struct timeval se_time; /* start of se_count */ | 264 | struct timeval se_time; /* start of se_count */ |
253 | struct servtab *se_next; | 265 | struct servtab_t *se_next; |
254 | } servtab_t; | 266 | } servtab_t; |
255 | 267 | ||
256 | static servtab_t *servtab; | ||
257 | |||
258 | #ifdef INETD_FEATURE_ENABLED | 268 | #ifdef INETD_FEATURE_ENABLED |
259 | struct builtin { | 269 | struct builtin { |
260 | const char *bi_service; /* internally provided service name */ | 270 | const char *bi_service; /* internally provided service name */ |
261 | int bi_socktype; /* type of socket supported */ | 271 | socktype_t bi_socktype; /* type of socket supported */ |
262 | short bi_fork; /* 1 if should fork before call */ | 272 | uint8_t bi_fork; /* 1 if should fork before call */ |
263 | short bi_wait; /* 1 if should wait for child */ | 273 | // Commented since it is always 0 |
274 | // uint8_t bi_wait; /* 1 if should wait for child */ | ||
264 | void (*bi_fn) (int, servtab_t *); | 275 | void (*bi_fn) (int, servtab_t *); |
265 | }; | 276 | }; |
266 | 277 | ||
@@ -293,45 +304,90 @@ static void chargen_dg(int, servtab_t *); | |||
293 | static const struct builtin builtins[] = { | 304 | static const struct builtin builtins[] = { |
294 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO | 305 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO |
295 | /* Echo received data */ | 306 | /* Echo received data */ |
296 | {"echo", SOCK_STREAM, 1, 0, echo_stream,}, | 307 | {"echo", SOCK_STREAM, 1, echo_stream,}, |
297 | {"echo", SOCK_DGRAM, 0, 0, echo_dg,}, | 308 | {"echo", SOCK_DGRAM, 0, echo_dg,}, |
298 | #endif | 309 | #endif |
299 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD | 310 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD |
300 | /* Internet /dev/null */ | 311 | /* Internet /dev/null */ |
301 | {"discard", SOCK_STREAM, 1, 0, discard_stream,}, | 312 | {"discard", SOCK_STREAM, 1, discard_stream,}, |
302 | {"discard", SOCK_DGRAM, 0, 0, discard_dg,}, | 313 | {"discard", SOCK_DGRAM, 0, discard_dg,}, |
303 | #endif | 314 | #endif |
304 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME | 315 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME |
305 | /* Return 32 bit time since 1900 */ | 316 | /* Return 32 bit time since 1900 */ |
306 | {"time", SOCK_STREAM, 0, 0, machtime_stream,}, | 317 | {"time", SOCK_STREAM, 0, machtime_stream,}, |
307 | {"time", SOCK_DGRAM, 0, 0, machtime_dg,}, | 318 | {"time", SOCK_DGRAM, 0, machtime_dg,}, |
308 | #endif | 319 | #endif |
309 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME | 320 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME |
310 | /* Return human-readable time */ | 321 | /* Return human-readable time */ |
311 | {"daytime", SOCK_STREAM, 0, 0, daytime_stream,}, | 322 | {"daytime", SOCK_STREAM, 0, daytime_stream,}, |
312 | {"daytime", SOCK_DGRAM, 0, 0, daytime_dg,}, | 323 | {"daytime", SOCK_DGRAM, 0, daytime_dg,}, |
313 | #endif | 324 | #endif |
314 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 325 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
315 | /* Familiar character generator */ | 326 | /* Familiar character generator */ |
316 | {"chargen", SOCK_STREAM, 1, 0, chargen_stream,}, | 327 | {"chargen", SOCK_STREAM, 1, chargen_stream,}, |
317 | {"chargen", SOCK_DGRAM, 0, 0, chargen_dg,}, | 328 | {"chargen", SOCK_DGRAM, 0, chargen_dg,}, |
318 | #endif | 329 | #endif |
319 | {NULL, 0, 0, 0, NULL} | 330 | { /* zero filled */ } |
320 | }; | 331 | }; |
321 | #endif /* INETD_FEATURE_ENABLED */ | 332 | #endif /* INETD_FEATURE_ENABLED */ |
322 | 333 | ||
323 | static int global_queuelen = 128; | 334 | struct globals { |
324 | static int nsock, maxsock; | 335 | rlim_t rlim_ofile_cur; |
325 | static fd_set allsock; | 336 | struct rlimit rlim_ofile; |
326 | static int toomany; | 337 | servtab_t *servtab; |
327 | static int timingout; | 338 | int global_queuelen; |
328 | static struct servent *sp; | 339 | int nsock; |
329 | static uid_t uid; | 340 | int maxsock; |
330 | 341 | int toomany; | |
331 | static const char *config_filename = "/etc/inetd.conf"; | 342 | int timingout; |
332 | 343 | struct servent *sp; | |
333 | static FILE *fconfig; | 344 | uid_t uid; |
334 | static char *defhost; | 345 | const char *config_filename; |
346 | FILE *fconfig; | ||
347 | char *defhost; | ||
348 | #ifdef INETD_SETPROCTITLE | ||
349 | char **Argv; | ||
350 | char *LastArg; | ||
351 | #endif | ||
352 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | ||
353 | char *endring; | ||
354 | char *ringpos; | ||
355 | char ring[128]; | ||
356 | #endif | ||
357 | fd_set allsock; | ||
358 | /* Used only in nextline() */ | ||
359 | char line[80]; /* at least 80, see LINE_SIZE */ | ||
360 | }; | ||
361 | #define G (*(struct globals*)&bb_common_bufsiz1) | ||
362 | enum { LINE_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line) }; | ||
363 | struct BUG_G_too_big { | ||
364 | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; | ||
365 | }; | ||
366 | #define rlim_ofile_cur (G.rlim_ofile_cur ) | ||
367 | #define rlim_ofile (G.rlim_ofile ) | ||
368 | #define servtab (G.servtab ) | ||
369 | #define global_queuelen (G.global_queuelen) | ||
370 | #define nsock (G.nsock ) | ||
371 | #define maxsock (G.maxsock ) | ||
372 | #define toomany (G.toomany ) | ||
373 | #define timingout (G.timingout ) | ||
374 | #define sp (G.sp ) | ||
375 | #define uid (G.uid ) | ||
376 | #define config_filename (G.config_filename) | ||
377 | #define fconfig (G.fconfig ) | ||
378 | #define defhost (G.defhost ) | ||
379 | #define Argv (G.Argv ) | ||
380 | #define LastArg (G.LastArg ) | ||
381 | #define endring (G.endring ) | ||
382 | #define ringpos (G.ringpos ) | ||
383 | #define ring (G.ring ) | ||
384 | #define allsock (G.allsock ) | ||
385 | #define line (G.line ) | ||
386 | #define INIT_G() do { \ | ||
387 | rlim_ofile_cur = OPEN_MAX; \ | ||
388 | global_queuelen = 128; \ | ||
389 | config_filename = "/etc/inetd.conf"; \ | ||
390 | } while (0) | ||
335 | 391 | ||
336 | /* xstrdup(NULL) returns NULL, but this one | 392 | /* xstrdup(NULL) returns NULL, but this one |
337 | * will return newly-allocated "" if called with NULL arg | 393 | * will return newly-allocated "" if called with NULL arg |
@@ -510,12 +566,10 @@ static void setup(servtab_t *sep) | |||
510 | 566 | ||
511 | static char *nextline(void) | 567 | static char *nextline(void) |
512 | { | 568 | { |
513 | #define line bb_common_bufsiz1 | ||
514 | |||
515 | char *cp; | 569 | char *cp; |
516 | FILE *fd = fconfig; | 570 | FILE *fd = fconfig; |
517 | 571 | ||
518 | if (fgets(line, sizeof(line), fd) == NULL) | 572 | if (fgets(line, LINE_SIZE, fd) == NULL) |
519 | return NULL; | 573 | return NULL; |
520 | cp = strchr(line, '\n'); | 574 | cp = strchr(line, '\n'); |
521 | if (cp) | 575 | if (cp) |
@@ -740,15 +794,15 @@ static servtab_t *getconfigent(void) | |||
740 | const struct builtin *bi; | 794 | const struct builtin *bi; |
741 | 795 | ||
742 | for (bi = builtins; bi->bi_service; bi++) | 796 | for (bi = builtins; bi->bi_service; bi++) |
743 | if (bi->bi_socktype == sep->se_socktype && | 797 | if (bi->bi_socktype == sep->se_socktype |
744 | strcmp(bi->bi_service, sep->se_service) == 0) | 798 | && strcmp(bi->bi_service, sep->se_service) == 0) |
745 | break; | 799 | break; |
746 | if (bi->bi_service == 0) { | 800 | if (bi->bi_service == 0) { |
747 | bb_error_msg("internal service %s unknown", sep->se_service); | 801 | bb_error_msg("internal service %s unknown", sep->se_service); |
748 | goto more; | 802 | goto more; |
749 | } | 803 | } |
750 | sep->se_bi = bi; | 804 | sep->se_bi = bi; |
751 | sep->se_wait = bi->bi_wait; | 805 | sep->se_wait = 0; /* = bi->bi_wait; - always 0 */ |
752 | #else | 806 | #else |
753 | bb_perror_msg("internal service %s unknown", sep->se_service); | 807 | bb_perror_msg("internal service %s unknown", sep->se_service); |
754 | goto more; | 808 | goto more; |
@@ -792,36 +846,36 @@ static servtab_t *getconfigent(void) | |||
792 | if (LONE_CHAR(nsep->se_hostaddr, '*')) | 846 | if (LONE_CHAR(nsep->se_hostaddr, '*')) |
793 | nsep->se_ctrladdr_in.sin_addr.s_addr = INADDR_ANY; | 847 | nsep->se_ctrladdr_in.sin_addr.s_addr = INADDR_ANY; |
794 | else if (!inet_aton(nsep->se_hostaddr, &nsep->se_ctrladdr_in.sin_addr)) { | 848 | else if (!inet_aton(nsep->se_hostaddr, &nsep->se_ctrladdr_in.sin_addr)) { |
849 | int i; | ||
795 | struct hostent *hp; | 850 | struct hostent *hp; |
796 | 851 | ||
797 | hp = gethostbyname(nsep->se_hostaddr); | 852 | hp = gethostbyname(nsep->se_hostaddr); |
798 | if (hp == 0) { | 853 | if (hp == NULL) { |
799 | bb_error_msg("%s: unknown host", nsep->se_hostaddr); | 854 | bb_error_msg("%s: unknown host", nsep->se_hostaddr); |
800 | nsep->se_checked = 0; | 855 | nsep->se_checked = 0; |
801 | goto skip; | 856 | goto skip; |
802 | } else if (hp->h_addrtype != AF_INET) { | 857 | } |
858 | if (hp->h_addrtype != AF_INET) { | ||
803 | bb_error_msg("%s: address isn't an Internet " | 859 | bb_error_msg("%s: address isn't an Internet " |
804 | "address", nsep->se_hostaddr); | 860 | "address", nsep->se_hostaddr); |
805 | nsep->se_checked = 0; | 861 | nsep->se_checked = 0; |
806 | goto skip; | 862 | goto skip; |
807 | } else { | 863 | } |
808 | int i = 1; | 864 | i = 1; |
809 | 865 | memmove(&nsep->se_ctrladdr_in.sin_addr, | |
810 | memmove(&nsep->se_ctrladdr_in.sin_addr, | 866 | hp->h_addr_list[0], sizeof(struct in_addr)); |
811 | hp->h_addr_list[0], sizeof(struct in_addr)); | 867 | while (hp->h_addr_list[i] != NULL) { |
812 | while (hp->h_addr_list[i] != NULL) { | 868 | psep = dupconfig(nsep); |
813 | psep = dupconfig(nsep); | 869 | psep->se_hostaddr = xxstrdup(nsep->se_hostaddr); |
814 | psep->se_hostaddr = xxstrdup(nsep->se_hostaddr); | 870 | psep->se_checked = 1; |
815 | psep->se_checked = 1; | 871 | memmove(&psep->se_ctrladdr_in.sin_addr, |
816 | memmove(&psep->se_ctrladdr_in.sin_addr, | 872 | hp->h_addr_list[i], sizeof(struct in_addr)); |
817 | hp->h_addr_list[i], sizeof(struct in_addr)); | 873 | psep->se_ctrladdr_size = sizeof(psep->se_ctrladdr_in); |
818 | psep->se_ctrladdr_size = sizeof(psep->se_ctrladdr_in); | 874 | i++; |
819 | i++; | 875 | /* Prepend to list, don't want to look up */ |
820 | /* Prepend to list, don't want to look up */ | 876 | /* its hostname again. */ |
821 | /* its hostname again. */ | 877 | psep->se_next = sep; |
822 | psep->se_next = sep; | 878 | sep = psep; |
823 | sep = psep; | ||
824 | } | ||
825 | } | 879 | } |
826 | } | 880 | } |
827 | } | 881 | } |
@@ -1219,8 +1273,6 @@ static void goaway(int sig ATTRIBUTE_UNUSED) | |||
1219 | 1273 | ||
1220 | 1274 | ||
1221 | #ifdef INETD_SETPROCTITLE | 1275 | #ifdef INETD_SETPROCTITLE |
1222 | static char **Argv; | ||
1223 | static char *LastArg; | ||
1224 | 1276 | ||
1225 | static void | 1277 | static void |
1226 | inetd_setproctitle(char *a, int s) | 1278 | inetd_setproctitle(char *a, int s) |
@@ -1262,10 +1314,14 @@ int inetd_main(int argc, char **argv) | |||
1262 | char buf[50]; | 1314 | char buf[50]; |
1263 | char *stoomany; | 1315 | char *stoomany; |
1264 | sigset_t omask, wait_mask; | 1316 | sigset_t omask, wait_mask; |
1265 | |||
1266 | #ifdef INETD_SETPROCTITLE | 1317 | #ifdef INETD_SETPROCTITLE |
1267 | char **envp = environ; | 1318 | char **envp; |
1319 | #endif | ||
1268 | 1320 | ||
1321 | INIT_G(); | ||
1322 | |||
1323 | #ifdef INETD_SETPROCTITLE | ||
1324 | envp = environ; | ||
1269 | Argv = argv; | 1325 | Argv = argv; |
1270 | if (envp == 0 || *envp == 0) | 1326 | if (envp == 0 || *envp == 0) |
1271 | envp = argv; | 1327 | envp = argv; |
@@ -1600,8 +1656,6 @@ discard_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) | |||
1600 | 1656 | ||
1601 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 1657 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
1602 | #define LINESIZ 72 | 1658 | #define LINESIZ 72 |
1603 | static char ring[128]; | ||
1604 | static char *endring; | ||
1605 | 1659 | ||
1606 | static void | 1660 | static void |
1607 | initring(void) | 1661 | initring(void) |
@@ -1609,7 +1663,6 @@ initring(void) | |||
1609 | int i; | 1663 | int i; |
1610 | 1664 | ||
1611 | endring = ring; | 1665 | endring = ring; |
1612 | |||
1613 | for (i = 0; i <= 128; ++i) | 1666 | for (i = 0; i <= 128; ++i) |
1614 | if (isprint(i)) | 1667 | if (isprint(i)) |
1615 | *endring++ = i; | 1668 | *endring++ = i; |
@@ -1657,14 +1710,13 @@ chargen_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) | |||
1657 | { | 1710 | { |
1658 | /* struct sockaddr_storage ss; */ | 1711 | /* struct sockaddr_storage ss; */ |
1659 | struct sockaddr sa; | 1712 | struct sockaddr sa; |
1660 | static char *rs; | ||
1661 | int len; | 1713 | int len; |
1662 | char text[LINESIZ + 2]; | 1714 | char text[LINESIZ + 2]; |
1663 | socklen_t size; | 1715 | socklen_t size; |
1664 | 1716 | ||
1665 | if (endring == 0) { | 1717 | if (!endring) { |
1666 | initring(); | 1718 | initring(); |
1667 | rs = ring; | 1719 | ringpos = ring; |
1668 | } | 1720 | } |
1669 | 1721 | ||
1670 | size = sizeof(sa); | 1722 | size = sizeof(sa); |
@@ -1673,14 +1725,15 @@ chargen_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) | |||
1673 | if (dg_badinput((struct sockaddr_in *) &sa)) | 1725 | if (dg_badinput((struct sockaddr_in *) &sa)) |
1674 | return; | 1726 | return; |
1675 | 1727 | ||
1676 | if ((len = endring - rs) >= LINESIZ) | 1728 | len = endring - ringpos; |
1677 | memmove(text, rs, LINESIZ); | 1729 | if (len >= LINESIZ) |
1730 | memmove(text, ringpos, LINESIZ); | ||
1678 | else { | 1731 | else { |
1679 | memmove(text, rs, len); | 1732 | memmove(text, ringpos, len); |
1680 | memmove(text + len, ring, LINESIZ - len); | 1733 | memmove(text + len, ring, LINESIZ - len); |
1681 | } | 1734 | } |
1682 | if (++rs == endring) | 1735 | if (++ringpos == endring) |
1683 | rs = ring; | 1736 | ringpos = ring; |
1684 | text[LINESIZ] = '\r'; | 1737 | text[LINESIZ] = '\r'; |
1685 | text[LINESIZ + 1] = '\n'; | 1738 | text[LINESIZ + 1] = '\n'; |
1686 | (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); | 1739 | (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); |