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 unsupported
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
96 #define RLIMIT_NOFILE RLIMIT_OFILE
100 #include <sys/file.h>
101 #include <sys/ioctl.h>
102 #include <sys/param.h>
103 #include <sys/resource.h>
104 #include <sys/socket.h>
105 #include <sys/stat.h>
106 #include <sys/time.h>
108 #include <sys/wait.h>
110 #include <netinet/in.h>
111 #include <netinet/ip.h>
112 #include <arpa/inet.h>
130 #define _PATH_INETDCONF "/etc/inetd.conf"
131 #define _PATH_INETDPID "/var/run/inetd.pid"
133 #define TOOMANY 40 /* don't start more than TOOMANY */
134 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
135 #define RETRYTIME (60*10) /* retry after bind or server fail */
138 #define se_ctrladdr se_un.se_un_ctrladdr
139 #define se_ctrladdr_in se_un.se_un_ctrladdr_in
140 #define se_ctrladdr_un se_un.se_un_ctrladdr_un
142 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
143 #define FD_MARGIN (8)
145 /* Check unsupporting builtin */
146 #if defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO || \
147 defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD || \
148 defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME || \
149 defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME || \
150 defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
151 # define INETD_FEATURE_ENABLED
154 typedef struct servtab_s {
155 char *se_service; /* name of service */
156 int se_socktype; /* type of socket to use */
157 int se_family; /* address family */
158 char *se_proto; /* protocol used */
159 short se_wait; /* single threaded server */
160 short se_checked; /* looked at during merge */
161 char *se_user; /* user name to run as */
162 char *se_group; /* group name to run as */
163 #ifdef INETD_FEATURE_ENABLED
164 const struct biltin *se_bi; /* if built-in, description */
166 char *se_server; /* server program */
167 char *se_argv[MAXARGV+1]; /* program arguments */
168 int se_fd; /* open descriptor */
170 struct sockaddr se_un_ctrladdr;
171 struct sockaddr_in se_un_ctrladdr_in;
172 struct sockaddr_un se_un_ctrladdr_un;
173 } se_un; /* bound address */
174 int se_ctrladdr_size;
175 int se_max; /* max # of instances of this service */
176 int se_count; /* number started since se_time */
177 struct timeval se_time; /* start of se_count */
178 struct servtab_s *se_next;
181 static servtab_t *servtab;
183 #ifdef INETD_FEATURE_ENABLED
185 const char *bi_service; /* internally provided service name */
186 int bi_socktype; /* type of socket supported */
187 short bi_fork; /* 1 if should fork before call */
188 short bi_wait; /* 1 if should wait for child */
189 void (*bi_fn)(int, servtab_t *); /* fn which performs it */
192 /* Echo received data */
193 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
194 static void echo_stream(int, servtab_t *);
195 static void echo_dg(int, servtab_t *);
197 /* Internet /dev/null */
198 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
199 static void discard_stream(int, servtab_t *);
200 static void discard_dg(int, servtab_t *);
202 /* Return 32 bit time since 1900 */
203 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
204 static void machtime_stream(int, servtab_t *);
205 static void machtime_dg(int, servtab_t *);
207 /* Return human-readable time */
208 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
209 static void daytime_stream(int, servtab_t *);
210 static void daytime_dg(int, servtab_t *);
212 /* Familiar character generator */
213 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
214 static void chargen_stream(int, servtab_t *);
215 static void chargen_dg(int, servtab_t *);
218 static const struct biltin biltins[] = {
219 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
220 /* Echo received data */
221 { "echo", SOCK_STREAM, 1, 0, echo_stream, },
222 { "echo", SOCK_DGRAM, 0, 0, echo_dg, },
224 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
225 /* Internet /dev/null */
226 { "discard", SOCK_STREAM, 1, 0, discard_stream, },
227 { "discard", SOCK_DGRAM, 0, 0, discard_dg, },
229 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
230 /* Return 32 bit time since 1900 */
231 { "time", SOCK_STREAM, 0, 0, machtime_stream, },
232 { "time", SOCK_DGRAM, 0, 0, machtime_dg, },
234 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
235 /* Return human-readable time */
236 { "daytime", SOCK_STREAM, 0, 0, daytime_stream, },
237 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg, },
239 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
240 /* Familiar character generator */
241 { "chargen", SOCK_STREAM, 1, 0, chargen_stream, },
242 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg, },
244 { NULL, 0, 0, 0, NULL }
246 #endif /* INETD_FEATURE_ENABLED */
249 static struct rlimit rlim_ofile;
252 /* Length of socket listen queue. Should be per-service probably. */
253 static int global_queuelen = 128;
255 static FILE *fconfig;
256 static sigset_t blockmask;
257 static sigset_t emptymask;
258 static fd_set allsock;
261 static int timingout;
262 static int rlim_ofile_cur = OPEN_MAX;
263 static const char *CONFIG = _PATH_INETDCONF;
266 syslog_err_and_discard_dg(int se_socktype, const char *msg, ...)
267 __attribute__ ((noreturn, format (printf, 2, 3)));
270 syslog_err_and_discard_dg(int se_socktype, const char *msg, ...)
276 vsyslog(LOG_ERR, msg, p);
277 if (se_socktype != SOCK_STREAM)
278 recv(0, buf, sizeof (buf), 0);
282 static char * inetd_strdup(const char *s)
284 char *ms = strdup(s);
287 syslog_err_and_discard_dg(SOCK_STREAM, "strdup: %m");
292 static servtab_t *getconfigent(void)
294 static servtab_t serv;
295 servtab_t *sep = &serv;
299 char *cp_ptr_ptr = NULL;
303 cp = bb_get_chomped_line_from_file(fconfig);
308 if ((cp == NULL) || (*cp == '#')) {
311 /* make bind 0.0.0.0 and other zero default */
312 memset((char *)sep, 0, sizeof *sep);
314 cp_ptr = strtok_r(cp, " \t", &cp_ptr_ptr);
315 if (cp_ptr == NULL) {
319 sep->se_service = inetd_strdup(cp_ptr);
321 cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
322 if (cp_ptr == NULL) {
326 if (strcmp(cp_ptr, "stream") == 0)
327 sep->se_socktype = SOCK_STREAM;
328 else if (strcmp(cp_ptr, "dgram") == 0)
329 sep->se_socktype = SOCK_DGRAM;
330 else if (strcmp(cp_ptr, "rdm") == 0)
331 sep->se_socktype = SOCK_RDM;
332 else if (strcmp(cp_ptr, "seqpacket") == 0)
333 sep->se_socktype = SOCK_SEQPACKET;
334 else if (strcmp(cp_ptr, "raw") == 0)
335 sep->se_socktype = SOCK_RAW;
337 sep->se_socktype = -1;
339 cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
340 if (cp_ptr == NULL) {
344 if (strcmp(cp_ptr, "unix") == 0) {
345 sep->se_family = AF_UNIX;
347 if (strncmp(cp_ptr, "rpc/", 4) == 0) {
348 syslog(LOG_ERR, "%s: rpc services not supported",
352 sep->se_family = AF_INET;
354 sep->se_proto = inetd_strdup(cp_ptr);
356 cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
357 if (cp_ptr == NULL) {
362 char *s = strchr(cp_ptr, '.');
365 sep->se_max = atoi(s);
367 sep->se_max = TOOMANY;
369 sep->se_wait = strcmp(cp_ptr, "wait") == 0;
371 cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
372 if (cp_ptr == NULL) {
377 sep->se_user = inetd_strdup(cp_ptr);
379 char *cp_ptr2 = strchr(sep->se_user, '.');
384 sep->se_group = cp_ptr2;
387 cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
388 if (cp_ptr == NULL) {
392 if (strcmp(cp_ptr, "internal") == 0) {
393 #ifdef INETD_FEATURE_ENABLED
394 const struct biltin *bi;
396 for (bi = biltins; bi->bi_service; bi++) {
397 if ((bi->bi_socktype == sep->se_socktype) &&
398 (strcmp(bi->bi_service, sep->se_service) == 0)) {
402 if (bi->bi_service == 0) {
403 syslog(LOG_ERR, "internal service %s unknown", sep->se_service);
407 sep->se_wait = bi->bi_wait;
409 syslog(LOG_ERR, "internal service %s unknown", cp_ptr);
413 #ifdef INETD_FEATURE_ENABLED
418 sep->se_server = inetd_strdup(cp_ptr);
421 while ((cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr)) != NULL) {
422 if (argc < MAXARGV) {
423 sep->se_argv[argc++] = inetd_strdup(cp_ptr);
431 static void freeconfig(servtab_t *cp)
435 free(cp->se_service);
438 /* Note: se_group is part of the newstr'ed se_user */
440 for (i = 0; i < MAXARGV; i++)
441 free(cp->se_argv[i]);
444 #ifdef INETD_FEATURE_ENABLED
446 static char *LastArg;
448 static void setproctitle(char *a, int s)
452 struct sockaddr_in sn;
457 if (getpeername(s, (struct sockaddr *)&sn, &size) == 0)
458 (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sn.sin_addr));
460 (void) sprintf(buf, "-%s", a);
461 strncpy(cp, buf, LastArg - cp);
466 #endif /* INETD_FEATURE_ENABLED */
469 static void setup(servtab_t *sep)
473 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
474 syslog(LOG_ERR, "%s/%s: socket: %m",
475 sep->se_service, sep->se_proto);
478 if (setsockopt(sep->se_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
480 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
481 if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) {
482 syslog(LOG_ERR, "%s/%s: bind: %m",
483 sep->se_service, sep->se_proto);
484 (void) close(sep->se_fd);
492 if (sep->se_socktype == SOCK_STREAM)
493 listen(sep->se_fd, global_queuelen);
495 FD_SET(sep->se_fd, &allsock);
497 if (sep->se_fd > maxsock) {
498 maxsock = sep->se_fd;
499 if (maxsock > rlim_ofile_cur - FD_MARGIN) {
504 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
505 syslog(LOG_ERR, "getrlimit: %m");
508 rl.rlim_cur = rl.rlim_max < (rl.rlim_cur + FD_CHUNK) ? rl.rlim_max : (rl.rlim_cur + FD_CHUNK);
509 if (rl.rlim_cur <= rlim_ofile_cur) {
511 # if _FILE_OFFSET_BITS == 64
512 "bump_nofile: cannot extend file limit, max = %lld",
514 "bump_nofile: cannot extend file limit, max = %ld",
520 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
521 syslog(LOG_ERR, "setrlimit: %m");
525 rlim_ofile_cur = rl.rlim_cur;
528 syslog(LOG_ERR, "bump_nofile: cannot extend file limit");
530 #endif /* RLIMIT_NOFILE */
535 static void config(int signum)
537 servtab_t *sep, *cp, **sepp;
543 if (fconfig != NULL) {
544 fseek(fconfig, 0L, L_SET);
546 fconfig = fopen(CONFIG, "r");
547 if (fconfig == NULL) {
548 syslog(LOG_ERR, "%s: %m", CONFIG);
553 for (sep = servtab; sep; sep = sep->se_next)
555 while ((cp = getconfigent()) != NULL) {
556 for (sep = servtab; sep; sep = sep->se_next)
557 if (strcmp(sep->se_service, cp->se_service) == 0 &&
558 strcmp(sep->se_proto, cp->se_proto) == 0)
563 #define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;}
565 sigprocmask(SIG_BLOCK, &emptymask, &oldmask);
567 * sep->se_wait may be holding the pid of a daemon
568 * that we're waiting for. If so, don't overwrite
569 * it unless the config file explicitly says don't
573 #ifdef INETD_FEATURE_ENABLED
576 (sep->se_wait == 1 || cp->se_wait == 0))
577 sep->se_wait = cp->se_wait;
578 if (cp->se_max != sep->se_max)
579 SWAP(int, cp->se_max, sep->se_max);
581 SWAP(char *, sep->se_user, cp->se_user);
583 SWAP(char *, sep->se_group, cp->se_group);
585 SWAP(char *, sep->se_server, cp->se_server);
586 for (i = 0; i < MAXARGV; i++)
587 SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
589 sigprocmask(SIG_SETMASK, &oldmask, NULL);
590 // This freeconfig() is probably a bug, since it will try and free()
591 // each of the argv[] values, which are really just pointers
592 // into the middle of a single line buffer for the config file.
593 //freeconfig(cp); // BUG?
595 sep = (servtab_t *)xmalloc(sizeof (*sep));
598 sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
599 sep->se_next = servtab;
601 sigprocmask(SIG_SETMASK, &oldmask, NULL);
605 switch (sep->se_family) {
607 if (sep->se_fd != -1)
609 (void)unlink(sep->se_service);
610 n = strlen(sep->se_service);
611 if (n > sizeof(sep->se_ctrladdr_un.sun_path) - 1)
612 n = sizeof(sep->se_ctrladdr_un.sun_path) - 1;
613 strncpy(sep->se_ctrladdr_un.sun_path, sep->se_service, n);
614 sep->se_ctrladdr_un.sun_family = AF_UNIX;
615 sep->se_ctrladdr_size = n +
616 sizeof sep->se_ctrladdr_un.sun_family;
620 sep->se_ctrladdr_in.sin_family = AF_INET;
621 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in;
623 u_short port = bb_lookup_port(sep->se_service, sep->se_proto, 0);
627 "%s/%s: unknown service",
628 sep->se_service, sep->se_proto);
631 if (port != sep->se_ctrladdr_in.sin_port) {
632 sep->se_ctrladdr_in.sin_port = port;
633 if (sep->se_fd != -1) {
634 FD_CLR(sep->se_fd, &allsock);
636 (void) close(sep->se_fd);
640 if (sep->se_fd == -1)
646 (void) fclose(fconfig);
650 * Purge anything not looked at above.
652 sigprocmask(SIG_SETMASK, &blockmask, &oldmask);
654 while ((sep = *sepp) != NULL) {
655 if (sep->se_checked) {
656 sepp = &sep->se_next;
659 *sepp = sep->se_next;
660 if (sep->se_fd != -1) {
661 FD_CLR(sep->se_fd, &allsock);
663 (void) close(sep->se_fd);
665 if (sep->se_family == AF_UNIX)
666 (void)unlink(sep->se_service);
670 sigprocmask(SIG_SETMASK, &oldmask, NULL);
675 static void reapchild(int signum)
683 pid = wait3(&status, WNOHANG, (struct rusage *)0);
686 for (sep = servtab; sep; sep = sep->se_next)
687 if (sep->se_wait == pid) {
688 if (WIFEXITED(status) && WEXITSTATUS(status))
690 "%s: exit status 0x%x",
691 sep->se_server, WEXITSTATUS(status));
692 else if (WIFSIGNALED(status))
694 "%s: exit signal 0x%x",
695 sep->se_server, WTERMSIG(status));
697 FD_SET(sep->se_fd, &allsock);
703 static void retry(int signum)
709 for (sep = servtab; sep; sep = sep->se_next) {
710 if (sep->se_fd == -1) {
711 switch (sep->se_family) {
721 static void goaway(int signum)
726 for (sep = servtab; sep; sep = sep->se_next)
727 if (sep->se_fd != -1 && sep->se_family == AF_UNIX)
728 (void)unlink(sep->se_service);
729 (void)unlink(_PATH_INETDPID);
735 extern int inetd_main(int argc, char *argv[])
738 struct group *grp = NULL;
745 #ifdef INETD_FEATURE_ENABLED
746 extern char **environ;
752 #ifdef INETD_FEATURE_ENABLED
754 if (environ == 0 || *environ == 0)
758 LastArg = environ[-1] + strlen(environ[-1]);
761 #if defined(__uClinux__)
762 opt = bb_getopt_ulflags(argc, argv, "q:f", &sq);
765 /* reexec for vfork() do continue parent */
766 vfork_daemon_rexec(argc, argv, "-f");
769 opt = bb_getopt_ulflags(argc, argv, "q:", &sq);
774 global_queuelen = atoi(sq);
775 if (global_queuelen < 8) global_queuelen=8;
783 openlog(bb_applet_name, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
787 if ((fp = fopen(_PATH_INETDPID, "w")) != NULL) {
788 fprintf(fp, "%u\n", getpid());
794 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
795 syslog(LOG_ERR, "getrlimit: %m");
797 rlim_ofile_cur = rlim_ofile.rlim_cur;
798 if (rlim_ofile_cur == RLIM_INFINITY) /* ! */
799 rlim_ofile_cur = OPEN_MAX;
805 sigemptyset(&emptymask);
806 sigemptyset(&blockmask);
807 sigaddset(&blockmask, SIGCHLD);
808 sigaddset(&blockmask, SIGHUP);
809 sigaddset(&blockmask, SIGALRM);
811 memset(&sa, 0, sizeof(sa));
812 sa.sa_mask = blockmask;
813 sa.sa_handler = retry;
814 sigaction(SIGALRM, &sa, NULL);
815 sa.sa_handler = config;
816 sigaction(SIGHUP, &sa, NULL);
817 sa.sa_handler = reapchild;
818 sigaction(SIGCHLD, &sa, NULL);
819 sa.sa_handler = goaway;
820 sigaction(SIGTERM, &sa, NULL);
821 sa.sa_handler = goaway;
822 sigaction(SIGINT, &sa, NULL);
823 sa.sa_handler = SIG_IGN;
824 sigaction(SIGPIPE, &sa, NULL);
827 /* space for daemons to overwrite environment for ps */
828 #define DUMMYSIZE 100
829 char dummy[DUMMYSIZE];
831 (void)memset(dummy, 'x', DUMMYSIZE - 1);
832 dummy[DUMMYSIZE - 1] = '\0';
834 (void)setenv("inetd_dummy", dummy, 1);
843 sigprocmask(SIG_BLOCK, &blockmask, NULL);
845 sigsuspend(&emptymask);
847 sigprocmask(SIG_SETMASK, &emptymask, NULL);
850 n = select(maxsock + 1, &readable, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
852 if (n < 0 && errno != EINTR) {
853 syslog(LOG_WARNING, "select: %m");
858 for (sep = servtab; n && sep; sep = sep->se_next) {
859 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
861 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
863 fcntl(sep->se_fd, F_SETFL, O_NDELAY);
865 ctrl = accept(sep->se_fd, NULL, NULL);
866 fcntl(sep->se_fd, F_SETFL, 0);
868 if (errno == EINTR || errno == EWOULDBLOCK) {
871 syslog(LOG_WARNING, "accept (for %s): %m",
878 sigprocmask(SIG_BLOCK, &blockmask, NULL);
880 #ifdef INETD_FEATURE_ENABLED
881 if (sep->se_bi == 0 || sep->se_bi->bi_fork)
884 if (sep->se_count++ == 0) {
885 gettimeofday(&sep->se_time, (struct timezone *)0);
887 else if (sep->se_count >= sep->se_max) {
890 gettimeofday(&now, (struct timezone *)0);
891 if (now.tv_sec - sep->se_time.tv_sec > CNT_INTVL) {
896 "%s/%s server failing (looping), service terminated",
897 sep->se_service, sep->se_proto);
898 FD_CLR(sep->se_fd, &allsock);
903 sigprocmask(SIG_SETMASK, &emptymask, NULL);
913 syslog(LOG_ERR, "fork: %m");
914 if (sep->se_socktype == SOCK_STREAM) {
917 sigprocmask(SIG_SETMASK, &emptymask, NULL);
921 if (pid && sep->se_wait) {
923 FD_CLR(sep->se_fd, &allsock);
927 sigprocmask(SIG_SETMASK, &emptymask, NULL);
929 #ifdef INETD_FEATURE_ENABLED
931 (*sep->se_bi->bi_fn)(ctrl, sep);
935 struct passwd *pwd = getpwnam(sep->se_user);
937 syslog_err_and_discard_dg(
939 "getpwnam: %s: No such user",
942 if (sep->se_group && (grp = getgrnam(sep->se_group)) == NULL) {
943 syslog_err_and_discard_dg(sep->se_socktype,
944 "getgrnam: %s: No such group", sep->se_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;
962 setgid((gid_t)pwd->pw_gid);
963 initgroups(pwd->pw_name, pwd->pw_gid);
964 setuid((uid_t)pwd->pw_uid);
965 } else if (sep->se_group) {
966 setgid((gid_t)grp->gr_gid);
967 setgroups(1, &grp->gr_gid);
974 if (rlim_ofile.rlim_cur != rlim_ofile_cur) {
975 if (setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
976 syslog(LOG_ERR,"setrlimit: %m");
980 for (ctrl = rlim_ofile_cur-1; --ctrl > 2; ) {
983 memset(&sa, 0, sizeof(sa));
984 sa.sa_handler = SIG_DFL;
985 sigaction(SIGPIPE, &sa, NULL);
987 execv(sep->se_server, sep->se_argv);
988 syslog_err_and_discard_dg(sep->se_socktype, "execv %s: %m", sep->se_server);
991 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
1001 * Internet services provided internally by inetd:
1003 #define BUFSIZE 4096
1005 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
1006 /* Echo service -- echo data back */
1007 static void echo_stream(int s, servtab_t *sep)
1009 char buffer[BUFSIZE];
1012 setproctitle(sep->se_service, s);
1013 while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1014 write(s, buffer, i) > 0)
1019 /* Echo service -- echo data back */
1020 static void echo_dg(int s, servtab_t *sep)
1022 char buffer[BUFSIZE];
1030 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0)
1032 (void) sendto(s, buffer, i, 0, &sa, sizeof(sa));
1034 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO */
1037 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
1038 /* Discard service -- ignore data */
1039 static void discard_stream(int s, servtab_t *sep)
1041 char buffer[BUFSIZE];
1043 setproctitle(sep->se_service, s);
1044 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1050 /* Discard service -- ignore data */
1051 static void discard_dg(int s, servtab_t *sep)
1053 char buffer[BUFSIZE];
1055 read(s, buffer, sizeof(buffer));
1057 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD */
1060 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
1063 static char ring[128];
1064 static char *endring;
1066 static void initring(void)
1072 for (i = 0; i <= 128; ++i)
1077 /* Character generator */
1078 static void chargen_stream(int s, servtab_t *sep)
1082 char text[LINESIZ+2];
1084 setproctitle(sep->se_service, s);
1091 text[LINESIZ] = '\r';
1092 text[LINESIZ + 1] = '\n';
1094 if ((len = endring - rs) >= LINESIZ)
1095 memcpy(rs, text, LINESIZ);
1097 memcpy(rs, text, len);
1098 memcpy(ring, text + len, LINESIZ - len);
1100 if (++rs == endring)
1102 if (write(s, text, sizeof(text)) != sizeof(text))
1108 /* Character generator */
1109 static void chargen_dg(int s, servtab_t *sep)
1114 char text[LINESIZ+2];
1124 if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0)
1127 if ((len = endring - rs) >= LINESIZ)
1128 memcpy(rs, text, LINESIZ);
1130 memcpy(rs, text, len);
1131 memcpy(ring, text + len, LINESIZ - len);
1133 if (++rs == endring)
1135 text[LINESIZ] = '\r';
1136 text[LINESIZ + 1] = '\n';
1137 (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
1139 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN */
1142 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
1144 * Return a machine readable date and time, in the form of the
1145 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday
1146 * returns the number of seconds since midnight, Jan 1, 1970,
1147 * we must add 2208988800 seconds to this figure to make up for
1148 * some seventy years Bell Labs was asleep.
1151 static long machtime(void)
1155 if (gettimeofday(&tv, (struct timezone *)0) < 0) {
1156 fprintf(stderr, "Unable to get time of day\n");
1159 return (htonl((long)tv.tv_sec + 2208988800UL));
1162 static void machtime_stream(int s, servtab_t *sep)
1167 result = machtime();
1168 write(s, (char *) &result, sizeof(result));
1171 static void machtime_dg(int s, servtab_t *sep)
1179 if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0)
1181 result = machtime();
1182 (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa));
1184 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME */
1187 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
1188 /* Return human-readable time of day */
1189 static int human_readable_time_sprintf(char *buffer)
1191 time_t clocc = time(NULL);
1193 return sprintf(buffer, "%.24s\r\n", ctime(&clocc));
1196 static void daytime_stream(int s, servtab_t *sep)
1199 size_t st = human_readable_time_sprintf(buffer);
1203 write(s, buffer, st);
1206 /* Return human-readable time of day */
1207 static void daytime_dg(int s, servtab_t *sep)
1216 if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0)
1218 size = human_readable_time_sprintf(buffer);
1219 sendto(s, buffer, size, 0, &sa, sizeof(sa));
1221 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME */