2 * Copyright (c) 1983,1991 The Regents of the University of California.
5 * This code is derived from software contributed to Berkeley by
8 * Busybox port by Vladimir Oleynik (C) 2001-2003 <dzo@simtreas.ru>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Inetd - Internet super-server
29 * This program invokes all internet services as needed.
30 * connection-oriented services are invoked each time a
31 * connection is made, by creating a process. This process
32 * is passed the connection as file descriptor 0 and is
33 * expected to do a getpeername to find out the source host
36 * Datagram oriented services are invoked when a datagram
37 * arrives; a process is created and passed a pending message
38 * on file descriptor 0. Datagram servers may either connect
39 * to their peer, freeing up the original socket for inetd
40 * to receive further messages on, or ``take over the socket'',
41 * processing all arriving datagrams and, eventually, timing
42 * out. The first type of server is said to be ``multi-threaded'';
43 * the second type of server ``single-threaded''.
45 * Inetd uses a configuration file which is read at startup
46 * and, possibly, at some later time in response to a hangup signal.
47 * The configuration file is ``free format'' with fields given in the
48 * order shown below. Continuation lines for an entry must being with
49 * a space or tab. All fields must be present in each entry.
51 * service name must be in /etc/services
52 * socket type stream/dgram/raw/rdm/seqpacket
53 * protocol must be in /etc/protocols
54 * wait/nowait[.max] single-threaded/multi-threaded, max #
55 * user[.group] user/group to run daemon as
56 * server program full path name
57 * server program arguments maximum of MAXARGS (20)
59 * RPC services unsuported
61 * Comment lines are indicated by a `#' in column 1.
65 * Here's the scoop concerning the user.group feature:
69 * a) for root: NO setuid() or setgid() is done
71 * b) nonroot: setuid()
72 * setgid(primary group as found in passwd)
73 * initgroups(name, primary group)
75 * 2) set-group-option on.
77 * a) for root: NO setuid()
78 * setgid(specified group)
79 * setgroups(1, specified group)
81 * b) nonroot: setuid()
82 * setgid(specified group)
83 * initgroups(name, specified group)
85 * All supplementary groups are discarded at startup in case inetd was
89 #define __USE_BSD_SIGNAL
93 #include <sys/param.h>
95 #include <sys/ioctl.h>
96 #include <sys/socket.h>
100 #include <sys/time.h>
101 #include <sys/resource.h>
104 #ifndef RLIMIT_NOFILE
105 #define RLIMIT_NOFILE RLIMIT_OFILE
109 #include <sys/param.h>
110 #include <sys/stat.h>
111 #include <sys/ioctl.h>
112 #include <sys/socket.h>
113 #include <sys/file.h>
114 #include <sys/wait.h>
115 #include <sys/time.h>
116 #include <sys/resource.h>
118 #include <netinet/in.h>
119 #include <netinet/ip.h>
120 #include <arpa/inet.h>
138 #define _PATH_INETDCONF "/etc/inetd.conf"
139 #define _PATH_INETDPID "/var/run/inetd.pid"
141 #define TOOMANY 40 /* don't start more than TOOMANY */
142 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
143 #define RETRYTIME (60*10) /* retry after bind or server fail */
146 #define se_ctrladdr se_un.se_un_ctrladdr
147 #define se_ctrladdr_in se_un.se_un_ctrladdr_in
148 #define se_ctrladdr_un se_un.se_un_ctrladdr_un
150 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
151 #define FD_MARGIN (8)
153 /* Check unsupporting builtin */
154 #if defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO || \
155 defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD || \
156 defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME || \
157 defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME || \
158 defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
159 # define INETD_FEATURE_ENABLED
162 static struct servtab {
163 char *se_service; /* name of service */
164 int se_socktype; /* type of socket to use */
165 int se_family; /* address family */
166 char *se_proto; /* protocol used */
167 short se_wait; /* single threaded server */
168 short se_checked; /* looked at during merge */
169 char *se_user; /* user name to run as */
170 char *se_group; /* group name to run as */
171 #ifdef INETD_FEATURE_ENABLED
172 const struct biltin *se_bi; /* if built-in, description */
174 char *se_server; /* server program */
175 char *se_argv[MAXARGV+1]; /* program arguments */
176 int se_fd; /* open descriptor */
178 struct sockaddr se_un_ctrladdr;
179 struct sockaddr_in se_un_ctrladdr_in;
180 struct sockaddr_un se_un_ctrladdr_un;
181 } se_un; /* bound address */
182 int se_ctrladdr_size;
183 int se_max; /* max # of instances of this service */
184 int se_count; /* number started since se_time */
185 struct timeval se_time; /* start of se_count */
186 struct servtab *se_next;
189 #ifdef INETD_FEATURE_ENABLED
191 const char *bi_service; /* internally provided service name */
192 int bi_socktype; /* type of socket supported */
193 short bi_fork; /* 1 if should fork before call */
194 short bi_wait; /* 1 if should wait for child */
195 void (*bi_fn)(int, struct servtab *); /* fn which performs it */
198 /* Echo received data */
199 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
200 static void echo_stream(int, struct servtab *);
201 static void echo_dg(int, struct servtab *);
203 /* Internet /dev/null */
204 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
205 static void discard_stream(int, struct servtab *);
206 static void discard_dg(int, struct servtab *);
208 /* Return 32 bit time since 1900 */
209 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
210 static void machtime_stream(int, struct servtab *);
211 static void machtime_dg(int, struct servtab *);
213 /* Return human-readable time */
214 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
215 static void daytime_stream(int, struct servtab *);
216 static void daytime_dg(int, struct servtab *);
218 /* Familiar character generator */
219 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
220 static void chargen_stream(int, struct servtab *);
221 static void chargen_dg(int, struct servtab *);
224 static const struct biltin biltins[] = {
225 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
226 /* Echo received data */
227 { "echo", SOCK_STREAM, 1, 0, echo_stream, },
228 { "echo", SOCK_DGRAM, 0, 0, echo_dg, },
230 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
231 /* Internet /dev/null */
232 { "discard", SOCK_STREAM, 1, 0, discard_stream, },
233 { "discard", SOCK_DGRAM, 0, 0, discard_dg, },
235 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
236 /* Return 32 bit time since 1900 */
237 { "time", SOCK_STREAM, 0, 0, machtime_stream, },
238 { "time", SOCK_DGRAM, 0, 0, machtime_dg, },
240 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
241 /* Return human-readable time */
242 { "daytime", SOCK_STREAM, 0, 0, daytime_stream, },
243 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg, },
245 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
246 /* Familiar character generator */
247 { "chargen", SOCK_STREAM, 1, 0, chargen_stream, },
248 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg, },
250 { NULL, 0, 0, 0, NULL }
252 #endif /* INETD_FEATURE_ENABLED */
255 static struct rlimit rlim_ofile;
258 /* Length of socket listen queue. Should be per-service probably. */
259 static int global_queuelen = 128;
261 static FILE *fconfig;
262 static sigset_t blockmask;
263 static sigset_t emptymask;
264 static fd_set allsock;
267 static int timingout;
268 static int rlim_ofile_cur = OPEN_MAX;
269 static const char *CONFIG = _PATH_INETDCONF;
272 syslog_err_and_discard_dg(int se_socktype, const char *msg, ...)
273 __attribute__ ((noreturn, format (printf, 2, 3)));
276 syslog_err_and_discard_dg(int se_socktype, const char *msg, ...)
282 vsyslog(LOG_ERR, msg, p);
283 if (se_socktype != SOCK_STREAM)
284 recv(0, buf, sizeof (buf), 0);
288 static struct servtab *getconfigent(void)
290 static struct servtab serv;
291 struct servtab *sep = &serv;
295 char *cp_ptr_ptr = NULL;
299 cp = bb_get_chomped_line_from_file(fconfig);
304 if ((cp == NULL) || (*cp == '#')) {
307 printf("line is %s\n", cp);
309 cp_ptr = strtok_r(cp, " \t", &cp_ptr_ptr);
310 if (cp_ptr == NULL) {
315 sep->se_service = bb_xstrdup(cp_ptr);
317 cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
318 if (cp_ptr == NULL) {
323 if (strcmp(cp_ptr, "stream") == 0)
324 sep->se_socktype = SOCK_STREAM;
325 else if (strcmp(cp_ptr, "dgram") == 0)
326 sep->se_socktype = SOCK_DGRAM;
327 else if (strcmp(cp_ptr, "rdm") == 0)
328 sep->se_socktype = SOCK_RDM;
329 else if (strcmp(cp_ptr, "seqpacket") == 0)
330 sep->se_socktype = SOCK_SEQPACKET;
331 else if (strcmp(cp_ptr, "raw") == 0)
332 sep->se_socktype = SOCK_RAW;
334 sep->se_socktype = -1;
336 cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
337 if (cp_ptr == NULL) {
342 if (strcmp(cp_ptr, "unix") == 0) {
343 sep->se_family = AF_UNIX;
345 if (strncmp(cp_ptr, "rpc/", 4) == 0) {
346 syslog(LOG_ERR, "%s: rpc services not suported",
350 sep->se_family = AF_INET;
352 sep->se_proto = bb_xstrdup(cp_ptr);
354 cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
355 if (cp_ptr == NULL) {
361 char *s = strchr(cp_ptr, '.');
364 sep->se_max = atoi(s);
366 sep->se_max = TOOMANY;
368 sep->se_wait = strcmp(cp_ptr, "wait") == 0;
370 cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
371 if (cp_ptr == NULL) {
377 char *cp_ptr2 = strchr(cp_ptr, '.');
380 sep->se_group = bb_xstrdup(cp_ptr2);
383 sep->se_user = bb_xstrdup(cp_ptr);
385 cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
386 if (cp_ptr == NULL) {
391 if (strcmp(cp_ptr, "internal") == 0) {
392 #ifdef INETD_FEATURE_ENABLED
393 const struct biltin *bi;
395 for (bi = biltins; bi->bi_service; bi++) {
396 if ((bi->bi_socktype == sep->se_socktype) &&
397 (strcmp(bi->bi_service, sep->se_service) == 0)) {
401 if (bi->bi_service == 0) {
402 syslog(LOG_ERR, "internal service %s unknown", sep->se_service);
406 sep->se_wait = bi->bi_wait;
408 syslog(LOG_ERR, "internal service %s unknown", cp_ptr);
412 #ifdef INETD_FEATURE_ENABLED
417 sep->se_server = bb_xstrdup(cp_ptr);
420 while ((cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr)) != NULL) {
421 if (argc < MAXARGV) {
422 sep->se_argv[argc++] = cp_ptr;
425 while (argc <= MAXARGV) {
426 sep->se_argv[argc++] = NULL;
429 //free(cp); // BUG: cp is the argv[] container; we must not free it here!
433 static void freeconfig(struct servtab *cp)
437 free(cp->se_service);
440 /* Note: se_group is part of the newstr'ed se_user */
442 for (i = 0; i < MAXARGV; i++)
443 free(cp->se_argv[i]);
446 #ifdef INETD_FEATURE_ENABLED
448 static char *LastArg;
450 static void setproctitle(char *a, int s)
454 struct sockaddr_in sn;
459 if (getpeername(s, (struct sockaddr *)&sn, &size) == 0)
460 (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sn.sin_addr));
462 (void) sprintf(buf, "-%s", a);
463 strncpy(cp, buf, LastArg - cp);
468 #endif /* INETD_FEATURE_ENABLED */
471 static void setup(struct servtab *sep)
475 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
476 syslog(LOG_ERR, "%s/%s: socket: %m",
477 sep->se_service, sep->se_proto);
480 if (setsockopt(sep->se_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
482 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
483 if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) {
484 syslog(LOG_ERR, "%s/%s: bind: %m",
485 sep->se_service, sep->se_proto);
486 (void) close(sep->se_fd);
494 if (sep->se_socktype == SOCK_STREAM)
495 listen(sep->se_fd, global_queuelen);
497 FD_SET(sep->se_fd, &allsock);
499 if (sep->se_fd > maxsock) {
500 maxsock = sep->se_fd;
501 if (maxsock > rlim_ofile_cur - FD_MARGIN) {
506 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
507 syslog(LOG_ERR, "getrlimit: %m");
510 rl.rlim_cur = rl.rlim_max < (rl.rlim_cur + FD_CHUNK) ? rl.rlim_max : (rl.rlim_cur + FD_CHUNK);
511 if (rl.rlim_cur <= rlim_ofile_cur) {
513 # if _FILE_OFFSET_BITS == 64
514 "bump_nofile: cannot extend file limit, max = %lld",
516 "bump_nofile: cannot extend file limit, max = %ld",
522 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
523 syslog(LOG_ERR, "setrlimit: %m");
527 rlim_ofile_cur = rl.rlim_cur;
530 syslog(LOG_ERR, "bump_nofile: cannot extend file limit");
532 #endif /* RLIMIT_NOFILE */
537 static void config(int signum)
539 struct servtab *sep, *cp, **sepp;
545 if (fconfig != NULL) {
546 fseek(fconfig, 0L, L_SET);
548 fconfig = fopen(CONFIG, "r");
549 if (fconfig == NULL) {
550 syslog(LOG_ERR, "%s: %m", CONFIG);
555 for (sep = servtab; sep; sep = sep->se_next)
557 while ((cp = getconfigent()) != NULL) {
558 for (sep = servtab; sep; sep = sep->se_next)
559 if (strcmp(sep->se_service, cp->se_service) == 0 &&
560 strcmp(sep->se_proto, cp->se_proto) == 0)
565 #define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;}
567 sigprocmask(SIG_BLOCK, &emptymask, &oldmask);
569 * sep->se_wait may be holding the pid of a daemon
570 * that we're waiting for. If so, don't overwrite
571 * it unless the config file explicitly says don't
575 #ifdef INETD_FEATURE_ENABLED
578 (sep->se_wait == 1 || cp->se_wait == 0))
579 sep->se_wait = cp->se_wait;
580 if (cp->se_max != sep->se_max)
581 SWAP(int, cp->se_max, sep->se_max);
583 SWAP(char *, sep->se_user, cp->se_user);
585 SWAP(char *, sep->se_group, cp->se_group);
587 SWAP(char *, sep->se_server, cp->se_server);
588 for (i = 0; i < MAXARGV; i++)
589 SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
591 sigprocmask(SIG_SETMASK, &oldmask, NULL);
592 // This freeconfig() is probably a bug, since it will try and free()
593 // each of the argv[] values, which are really just pointers
594 // into the middle of a single line buffer for the config file.
595 //freeconfig(cp); // BUG?
597 sep = (struct servtab *)xmalloc(sizeof (*sep));
600 sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
601 sep->se_next = servtab;
603 sigprocmask(SIG_SETMASK, &oldmask, NULL);
607 switch (sep->se_family) {
609 if (sep->se_fd != -1)
611 (void)unlink(sep->se_service);
612 n = strlen(sep->se_service);
613 if (n > sizeof(sep->se_ctrladdr_un.sun_path) - 1)
614 n = sizeof(sep->se_ctrladdr_un.sun_path) - 1;
615 strncpy(sep->se_ctrladdr_un.sun_path, sep->se_service, n);
616 sep->se_ctrladdr_un.sun_family = AF_UNIX;
617 sep->se_ctrladdr_size = n +
618 sizeof sep->se_ctrladdr_un.sun_family;
622 sep->se_ctrladdr_in.sin_family = AF_INET;
623 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in;
625 u_short port = bb_lookup_port(sep->se_service, sep->se_proto, 0);
629 "%s/%s: unknown service",
630 sep->se_service, sep->se_proto);
633 if (port != sep->se_ctrladdr_in.sin_port) {
634 sep->se_ctrladdr_in.sin_port = port;
635 if (sep->se_fd != -1) {
636 FD_CLR(sep->se_fd, &allsock);
638 (void) close(sep->se_fd);
642 if (sep->se_fd == -1)
648 (void) fclose(fconfig);
652 * Purge anything not looked at above.
654 sigprocmask(SIG_SETMASK, &blockmask, &oldmask);
656 while ((sep = *sepp) != NULL) {
657 if (sep->se_checked) {
658 sepp = &sep->se_next;
661 *sepp = sep->se_next;
662 if (sep->se_fd != -1) {
663 FD_CLR(sep->se_fd, &allsock);
665 (void) close(sep->se_fd);
667 if (sep->se_family == AF_UNIX)
668 (void)unlink(sep->se_service);
672 sigprocmask(SIG_SETMASK, &oldmask, NULL);
677 static void reapchild(int signum)
685 pid = wait3(&status, WNOHANG, (struct rusage *)0);
688 for (sep = servtab; sep; sep = sep->se_next)
689 if (sep->se_wait == pid) {
690 if (WIFEXITED(status) && WEXITSTATUS(status))
692 "%s: exit status 0x%x",
693 sep->se_server, WEXITSTATUS(status));
694 else if (WIFSIGNALED(status))
696 "%s: exit signal 0x%x",
697 sep->se_server, WTERMSIG(status));
699 FD_SET(sep->se_fd, &allsock);
705 static void retry(int signum)
711 for (sep = servtab; sep; sep = sep->se_next) {
712 if (sep->se_fd == -1) {
713 switch (sep->se_family) {
723 static void goaway(int signum)
728 for (sep = servtab; sep; sep = sep->se_next)
729 if (sep->se_fd != -1 && sep->se_family == AF_UNIX)
730 (void)unlink(sep->se_service);
731 (void)unlink(_PATH_INETDPID);
737 extern int inetd_main(int argc, char *argv[])
740 struct group *grp = NULL;
747 #ifdef INETD_FEATURE_ENABLED
748 extern char **environ;
754 #ifdef INETD_FEATURE_ENABLED
756 if (environ == 0 || *environ == 0)
760 LastArg = environ[-1] + strlen(environ[-1]);
763 #if defined(__uClinux__)
764 opt = bb_getopt_ulflags(argc, argv, "q:f", &sq);
767 /* reexec for vfork() do continue parent */
768 vfork_daemon_rexec(argc, argv, "-f");
771 opt = bb_getopt_ulflags(argc, argv, "q:", &sq);
776 global_queuelen = atoi(optarg);
777 if (global_queuelen < 8) global_queuelen=8;
785 openlog(bb_applet_name, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
789 if ((fp = fopen(_PATH_INETDPID, "w")) != NULL) {
790 fprintf(fp, "%u\n", getpid());
796 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
797 syslog(LOG_ERR, "getrlimit: %m");
799 rlim_ofile_cur = rlim_ofile.rlim_cur;
800 if (rlim_ofile_cur == RLIM_INFINITY) /* ! */
801 rlim_ofile_cur = OPEN_MAX;
807 sigemptyset(&emptymask);
808 sigemptyset(&blockmask);
809 sigaddset(&blockmask, SIGCHLD);
810 sigaddset(&blockmask, SIGHUP);
811 sigaddset(&blockmask, SIGALRM);
813 memset(&sa, 0, sizeof(sa));
814 sa.sa_mask = blockmask;
815 sa.sa_handler = retry;
816 sigaction(SIGALRM, &sa, NULL);
817 sa.sa_handler = config;
818 sigaction(SIGHUP, &sa, NULL);
819 sa.sa_handler = reapchild;
820 sigaction(SIGCHLD, &sa, NULL);
821 sa.sa_handler = goaway;
822 sigaction(SIGTERM, &sa, NULL);
823 sa.sa_handler = goaway;
824 sigaction(SIGINT, &sa, NULL);
825 sa.sa_handler = SIG_IGN;
826 sigaction(SIGPIPE, &sa, NULL);
829 /* space for daemons to overwrite environment for ps */
830 #define DUMMYSIZE 100
831 char dummy[DUMMYSIZE];
833 (void)memset(dummy, 'x', DUMMYSIZE - 1);
834 dummy[DUMMYSIZE - 1] = '\0';
836 (void)setenv("inetd_dummy", dummy, 1);
844 sigprocmask(SIG_BLOCK, &blockmask, NULL);
846 sigsuspend(&emptymask);
847 sigprocmask(SIG_SETMASK, &emptymask, NULL);
850 if ((n = select(maxsock + 1, &readable, (fd_set *)0,
851 (fd_set *)0, (struct timeval *)0)) <= 0) {
852 if (n < 0 && errno != EINTR)
853 syslog(LOG_WARNING, "select: %m");
857 for (sep = servtab; n && sep; sep = sep->se_next)
858 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
860 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
862 fcntl(sep->se_fd, F_SETFL, O_NDELAY);
864 ctrl = accept(sep->se_fd, NULL, NULL);
865 fcntl(sep->se_fd, F_SETFL, 0);
867 if (errno == EINTR || errno == EWOULDBLOCK)
869 syslog(LOG_WARNING, "accept (for %s): %m",
875 sigprocmask(SIG_BLOCK, &blockmask, NULL);
877 #ifdef INETD_FEATURE_ENABLED
878 if (sep->se_bi == 0 || sep->se_bi->bi_fork)
881 if (sep->se_count++ == 0)
882 (void)gettimeofday(&sep->se_time, (struct timezone *)0);
883 else if (sep->se_count >= sep->se_max) {
886 (void)gettimeofday(&now, (struct timezone *)0);
887 if (now.tv_sec - sep->se_time.tv_sec >
893 "%s/%s server failing (looping), service terminated",
894 sep->se_service, sep->se_proto);
895 FD_CLR(sep->se_fd, &allsock);
896 (void) close(sep->se_fd);
900 sigprocmask(SIG_SETMASK, &emptymask,
911 syslog(LOG_ERR, "fork: %m");
912 if (sep->se_socktype == SOCK_STREAM)
914 sigprocmask(SIG_SETMASK, &emptymask, NULL);
918 if (pid && sep->se_wait) {
920 FD_CLR(sep->se_fd, &allsock);
924 sigprocmask(SIG_SETMASK, &emptymask, NULL);
926 #ifdef INETD_FEATURE_ENABLED
928 (*sep->se_bi->bi_fn)(ctrl, sep);
932 struct passwd *pwd = getpwnam(sep->se_user);
934 syslog_err_and_discard_dg(
936 "getpwnam: %s: No such user",
940 (grp = getgrnam(sep->se_group)) == NULL) {
941 syslog_err_and_discard_dg(
943 "getgrnam: %s: No such group",
947 * Ok. There are four cases here:
948 * 1. nonroot user, no group specified
949 * 2. nonroot user, some group specified
950 * 3. root user, no group specified
951 * 4. root user, some group specified
952 * In cases 2 and 4 we setgid to the specified
953 * group. In cases 1 and 2 we run initgroups
954 * to run with the groups of the given user.
955 * In case 4 we do setgroups to run with the
956 * given group. In case 3 we do nothing.
960 pwd->pw_gid = grp->gr_gid;
961 setgid((gid_t)pwd->pw_gid);
962 initgroups(pwd->pw_name, pwd->pw_gid);
963 setuid((uid_t)pwd->pw_uid);
964 } else if (sep->se_group) {
965 setgid((gid_t)grp->gr_gid);
966 setgroups(1, &grp->gr_gid);
973 if (rlim_ofile.rlim_cur != rlim_ofile_cur) {
974 if (setrlimit(RLIMIT_NOFILE,
976 syslog(LOG_ERR,"setrlimit: %m");
979 for (ctrl = rlim_ofile_cur-1; --ctrl > 2; )
982 memset(&sa, 0, sizeof(sa));
983 sa.sa_handler = SIG_DFL;
984 sigaction(SIGPIPE, &sa, NULL);
986 execv(sep->se_server, sep->se_argv);
987 syslog_err_and_discard_dg(sep->se_socktype,
988 "execv %s: %m", sep->se_server);
991 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
999 * Internet services provided internally by inetd:
1001 #define BUFSIZE 4096
1003 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
1004 /* Echo service -- echo data back */
1005 static void echo_stream(int s, struct servtab *sep)
1007 char buffer[BUFSIZE];
1010 setproctitle(sep->se_service, s);
1011 while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1012 write(s, buffer, i) > 0)
1017 /* Echo service -- echo data back */
1018 static void echo_dg(int s, struct servtab *sep)
1020 char buffer[BUFSIZE];
1028 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0)
1030 (void) sendto(s, buffer, i, 0, &sa, sizeof(sa));
1032 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO */
1035 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
1036 /* Discard service -- ignore data */
1037 static void discard_stream(int s, struct servtab *sep)
1039 char buffer[BUFSIZE];
1041 setproctitle(sep->se_service, s);
1042 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1048 /* Discard service -- ignore data */
1049 static void discard_dg(int s, struct servtab *sep)
1051 char buffer[BUFSIZE];
1053 read(s, buffer, sizeof(buffer));
1055 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD */
1058 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
1061 static char ring[128];
1062 static char *endring;
1064 static void initring(void)
1070 for (i = 0; i <= 128; ++i)
1075 /* Character generator */
1076 static void chargen_stream(int s, struct servtab *sep)
1080 char text[LINESIZ+2];
1082 setproctitle(sep->se_service, s);
1089 text[LINESIZ] = '\r';
1090 text[LINESIZ + 1] = '\n';
1092 if ((len = endring - rs) >= LINESIZ)
1093 memcpy(rs, text, LINESIZ);
1095 memcpy(rs, text, len);
1096 memcpy(ring, text + len, LINESIZ - len);
1098 if (++rs == endring)
1100 if (write(s, text, sizeof(text)) != sizeof(text))
1106 /* Character generator */
1107 static void chargen_dg(int s, struct servtab *sep)
1112 char text[LINESIZ+2];
1122 if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0)
1125 if ((len = endring - rs) >= LINESIZ)
1126 memcpy(rs, text, LINESIZ);
1128 memcpy(rs, text, len);
1129 memcpy(ring, text + len, LINESIZ - len);
1131 if (++rs == endring)
1133 text[LINESIZ] = '\r';
1134 text[LINESIZ + 1] = '\n';
1135 (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
1137 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN */
1140 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
1142 * Return a machine readable date and time, in the form of the
1143 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday
1144 * returns the number of seconds since midnight, Jan 1, 1970,
1145 * we must add 2208988800 seconds to this figure to make up for
1146 * some seventy years Bell Labs was asleep.
1149 static long machtime(void)
1153 if (gettimeofday(&tv, (struct timezone *)0) < 0) {
1154 fprintf(stderr, "Unable to get time of day\n");
1157 return (htonl((long)tv.tv_sec + 2208988800UL));
1160 static void machtime_stream(int s, struct servtab *sep)
1165 result = machtime();
1166 write(s, (char *) &result, sizeof(result));
1169 static void machtime_dg(int s, struct servtab *sep)
1177 if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0)
1179 result = machtime();
1180 (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa));
1182 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME */
1185 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
1186 /* Return human-readable time of day */
1187 static int human_readable_time_sprintf(char *buffer)
1189 time_t clocc = time(NULL);
1191 return sprintf(buffer, "%.24s\r\n", ctime(&clocc));
1194 static void daytime_stream(int s, struct servtab *sep)
1197 size_t st = human_readable_time_sprintf(buffer);
1201 write(s, buffer, st);
1204 /* Return human-readable time of day */
1205 static void daytime_dg(int s, struct servtab *sep)
1214 if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0)
1216 size = human_readable_time_sprintf(buffer);
1217 sendto(s, buffer, size, 0, &sa, sizeof(sa));
1219 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME */