last_patch95 from vodz:
[oweals/busybox.git] / networking / inetd.c
1 /*
2  * Copyright (c) 1983,1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * David A. Holland.
7  *
8  * Busybox port by Vladimir Oleynik (C) 2001-2003 <dzo@simtreas.ru>
9  *
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.
14  *
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.
19  *
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
23  *
24  */
25
26 /*
27  * Inetd - Internet super-server
28  *
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
34  * and port.
35  *
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''.
44  *
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.
50  *
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)
58  *
59  * RPC services unsuported
60  *
61  * Comment lines are indicated by a `#' in column 1.
62  */
63
64 /*
65  * Here's the scoop concerning the user.group feature:
66  *
67  * 1) No group listed.
68  *
69  *      a) for root:    NO setuid() or setgid() is done
70  *
71  *      b) nonroot:     setuid()
72  *                      setgid(primary group as found in passwd)
73  *                      initgroups(name, primary group)
74  *
75  * 2) set-group-option on.
76  *
77  *      a) for root:    NO setuid()
78  *                      setgid(specified group)
79  *                      setgroups(1, specified group)
80  *
81  *      b) nonroot:     setuid()
82  *                      setgid(specified group)
83  *                      initgroups(name, specified group)
84  *
85  * All supplementary groups are discarded at startup in case inetd was
86  * run manually.
87  */
88
89 #define __USE_BSD_SIGNAL
90
91 #include "busybox.h"
92
93 #include <sys/param.h>
94 #include <sys/stat.h>
95 #include <sys/ioctl.h>
96 #include <sys/socket.h>
97 #include <sys/un.h>
98 #include <sys/file.h>
99 #include <sys/wait.h>
100 #include <sys/time.h>
101 #include <sys/resource.h>
102
103 #ifndef __linux__
104 #ifndef RLIMIT_NOFILE
105 #define RLIMIT_NOFILE   RLIMIT_OFILE
106 #endif
107 #endif
108
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>
117
118 #include <netinet/in.h>
119 #include <netinet/ip.h>
120 #include <arpa/inet.h>
121
122 #include <errno.h>
123 #include <signal.h>
124 #include <netdb.h>
125 #include <syslog.h>
126 #include <stdio.h>
127 #include <stdlib.h>
128 #include <string.h>
129 #include <getopt.h>
130 #include <unistd.h>
131 #include <stdarg.h>
132 #include <time.h>
133
134 #define _PATH_INETDCONF "/etc/inetd.conf"
135 #define _PATH_INETDPID  "/var/run/inetd.pid"
136
137 #ifndef MIN
138 #define MIN(a, b)       ((a) < (b) ? (a) : (b))
139 #endif
140
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 */
144
145 #ifndef OPEN_MAX
146 #define OPEN_MAX        64
147 #endif
148
149
150 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
151 #define FD_MARGIN       (8)
152 static int     rlim_ofile_cur = OPEN_MAX;
153
154 #ifdef RLIMIT_NOFILE
155 static struct rlimit   rlim_ofile;
156 #endif
157
158 #define INETD_UNSUPPORT_BILTIN 1
159
160 /* Check unsupporting builtin */
161 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
162 #undef INETD_UNSUPPORT_BILTIN
163 #endif
164 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
165 #undef INETD_UNSUPPORT_BILTIN
166 #endif
167 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
168 #undef INETD_UNSUPPORT_BILTIN
169 #endif
170 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
171 #undef INETD_UNSUPPORT_BILTIN
172 #endif
173 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
174 #undef INETD_UNSUPPORT_BILTIN
175 #endif
176
177 static struct  servtab {
178         char    *se_service;            /* name of service */
179         int     se_socktype;            /* type of socket to use */
180         int     se_family;              /* address family */
181         char    *se_proto;              /* protocol used */
182         short   se_wait;                /* single threaded server */
183         short   se_checked;             /* looked at during merge */
184         char    *se_user;               /* user name to run as */
185         char    *se_group;              /* group name to run as */
186 #ifndef INETD_UNSUPPORT_BILTIN
187         const struct  biltin *se_bi;    /* if built-in, description */
188 #endif
189         char    *se_server;             /* server program */
190 #define MAXARGV 20
191         char    *se_argv[MAXARGV+1];    /* program arguments */
192         int     se_fd;                  /* open descriptor */
193         union {
194                 struct  sockaddr se_un_ctrladdr;
195                 struct  sockaddr_in se_un_ctrladdr_in;
196                 struct  sockaddr_un se_un_ctrladdr_un;
197         } se_un;                        /* bound address */
198 #define se_ctrladdr     se_un.se_un_ctrladdr
199 #define se_ctrladdr_in  se_un.se_un_ctrladdr_in
200 #define se_ctrladdr_un  se_un.se_un_ctrladdr_un
201         int     se_ctrladdr_size;
202         int     se_max;                 /* max # of instances of this service */
203         int     se_count;               /* number started since se_time */
204         struct  timeval se_time;        /* start of se_count */
205         struct  servtab *se_next;
206 } *servtab;
207
208 /* Length of socket listen queue. Should be per-service probably. */
209 static int      global_queuelen = 128;
210
211 static int      nsock, maxsock;
212 static fd_set   allsock;
213 static int      timingout;
214 static sigset_t blockmask, emptymask;
215
216
217        /* Echo received data */
218 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
219 static void echo_stream(int, struct servtab *);
220 static void echo_dg(int, struct servtab *);
221 #endif
222         /* Internet /dev/null */
223 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
224 static void discard_stream(int, struct servtab *);
225 static void discard_dg(int, struct servtab *);
226 #endif
227         /* Return 32 bit time since 1900 */
228 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
229 static void machtime_stream(int, struct servtab *);
230 static void machtime_dg(int, struct servtab *);
231 #endif
232         /* Return human-readable time */
233 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
234 static void daytime_stream(int, struct servtab *);
235 static void daytime_dg(int, struct servtab *);
236 #endif
237         /* Familiar character generator */
238 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
239 static void chargen_stream(int, struct servtab *);
240 static void chargen_dg(int, struct servtab *);
241 #endif
242
243 #ifndef INETD_UNSUPPORT_BILTIN
244 struct biltin {
245         const char *bi_service;         /* internally provided service name */
246         int bi_socktype;                /* type of socket supported */
247         short bi_fork;          /* 1 if should fork before call */
248         short bi_wait;          /* 1 if should wait for child */
249         void (*bi_fn)(int, struct servtab *); /* fn which performs it */
250 };
251
252 static const struct biltin biltins[] = {
253 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
254         /* Echo received data */
255         { "echo",               SOCK_STREAM,    1, 0,   echo_stream, },
256         { "echo",               SOCK_DGRAM,     0, 0,   echo_dg, },
257 #endif
258 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
259         /* Internet /dev/null */
260         { "discard",    SOCK_STREAM,    1, 0,   discard_stream, },
261         { "discard",    SOCK_DGRAM,     0, 0,   discard_dg, },
262 #endif
263 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
264         /* Return 32 bit time since 1900 */
265         { "time",               SOCK_STREAM,    0, 0,   machtime_stream, },
266         { "time",               SOCK_DGRAM,     0, 0,   machtime_dg,     },
267 #endif
268 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
269         /* Return human-readable time */
270         { "daytime",    SOCK_STREAM,    0, 0,   daytime_stream, },
271         { "daytime",    SOCK_DGRAM,     0, 0,   daytime_dg,     },
272 #endif
273 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
274         /* Familiar character generator */
275         { "chargen",    SOCK_STREAM,    1, 0,   chargen_stream, },
276         { "chargen",    SOCK_DGRAM,     0, 0,   chargen_dg,     },
277 #endif
278         { NULL, 0, 0, 0, NULL }
279 };
280 #endif  /* INETD_UNSUPPORT_BILTIN */
281
282 #define NUMINT  (sizeof(intab) / sizeof(struct inent))
283 static const char *CONFIG = _PATH_INETDCONF;
284
285 #define BCOPY(s, d, z) memcpy(d, s, z)
286
287 static void
288 syslog_err_and_discard_dg(int se_socktype, const char *msg, ...)
289         __attribute__ ((noreturn, format (printf, 2, 3)));
290
291 static void
292 syslog_err_and_discard_dg(int se_socktype, const char *msg, ...)
293 {
294         char buf[50];
295         va_list p;
296
297         va_start(p, msg);
298         vsyslog(LOG_ERR, msg, p);
299         if (se_socktype != SOCK_STREAM)
300                 recv(0, buf, sizeof (buf), 0);
301         _exit(1);
302 }
303
304 static FILE *fconfig;
305 static char line[256];
306
307 static FILE *
308 setconfig(void)
309 {
310         FILE *f = fconfig;
311
312         if (f != NULL) {
313                 fseek(f, 0L, L_SET);
314         } else {
315                 f = fconfig = fopen(CONFIG, "r");
316                 if(f == NULL)
317                         syslog(LOG_ERR, "%s: %m", CONFIG);
318         }
319         return f;
320 }
321
322 static char *
323 nextline(void)
324 {
325         char *cp;
326         FILE *fd = fconfig;
327
328         if (fgets(line, sizeof (line), fd) == NULL)
329                 return ((char *)0);
330         cp = strchr(line, '\n');
331         if (cp)
332                 *cp = '\0';
333         return (line);
334 }
335
336 static char *
337 skip(char **cpp)
338 {
339         char *cp = *cpp;
340         char *start;
341
342         if (*cpp == NULL)
343                 return ((char *)0);
344
345 again:
346         while (*cp == ' ' || *cp == '\t')
347                 cp++;
348         if (*cp == '\0') {
349                 int c;
350
351                 c = getc(fconfig);
352                 (void) ungetc(c, fconfig);
353                 if (c == ' ' || c == '\t')
354                         if ((cp = nextline()) != NULL)
355                                 goto again;
356                 *cpp = NULL;
357                 return NULL;
358         }
359         start = cp;
360         while (*cp && *cp != ' ' && *cp != '\t')
361                 cp++;
362         if (*cp != '\0')
363                 *cp++ = '\0';
364         *cpp = cp;
365         return (start);
366 }
367
368 static char *
369 newstr(char *cp)
370 {
371         cp = strdup(cp ? cp : "");
372         if (cp)
373                 return(cp);
374
375         syslog_err_and_discard_dg(SOCK_STREAM, "strdup: %m");
376 }
377
378
379 static struct servtab *
380 getconfigent(void)
381 {
382         static struct servtab serv;
383         struct servtab *sep = &serv;
384         int argc;
385         char *cp, *arg;
386
387 more:
388         while ((cp = nextline()) && *cp == '#')
389                 ;
390         if (cp == NULL)
391                 return ((struct servtab *)0);
392         memset((char *)sep, 0, sizeof *sep);
393         sep->se_service = newstr(skip(&cp));
394         arg = skip(&cp);
395         if (arg == NULL)
396                 goto more;
397
398         if (strcmp(arg, "stream") == 0)
399                 sep->se_socktype = SOCK_STREAM;
400         else if (strcmp(arg, "dgram") == 0)
401                 sep->se_socktype = SOCK_DGRAM;
402         else if (strcmp(arg, "rdm") == 0)
403                 sep->se_socktype = SOCK_RDM;
404         else if (strcmp(arg, "seqpacket") == 0)
405                 sep->se_socktype = SOCK_SEQPACKET;
406         else if (strcmp(arg, "raw") == 0)
407                 sep->se_socktype = SOCK_RAW;
408         else
409                 sep->se_socktype = -1;
410
411         sep->se_proto = newstr(skip(&cp));
412         if (strcmp(sep->se_proto, "unix") == 0) {
413                 sep->se_family = AF_UNIX;
414         } else {
415                 sep->se_family = AF_INET;
416                 if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
417                         syslog(LOG_ERR, "%s: rpc services not suported",
418                             sep->se_service);
419                         goto more;
420                 }
421         }
422         arg = skip(&cp);
423         if (arg == NULL)
424                 goto more;
425         {
426                 char    *s = strchr(arg, '.');
427                 if (s) {
428                         *s++ = '\0';
429                         sep->se_max = atoi(s);
430                 } else
431                         sep->se_max = TOOMANY;
432         }
433         sep->se_wait = strcmp(arg, "wait") == 0;
434         sep->se_user = newstr(skip(&cp));
435         sep->se_group = strchr(sep->se_user, '.');
436         if (sep->se_group) {
437                 *sep->se_group++ = '\0';
438         }
439         sep->se_server = newstr(skip(&cp));
440         if (strcmp(sep->se_server, "internal") == 0) {
441 #ifndef INETD_UNSUPPORT_BILTIN
442                 const struct biltin *bi;
443
444                 for (bi = biltins; bi->bi_service; bi++)
445                         if (bi->bi_socktype == sep->se_socktype &&
446                             strcmp(bi->bi_service, sep->se_service) == 0)
447                                 break;
448                 if (bi->bi_service == 0) {
449                         syslog(LOG_ERR, "internal service %s unknown",
450                                 sep->se_service);
451                         goto more;
452                 }
453                 sep->se_bi = bi;
454                 sep->se_wait = bi->bi_wait;
455 #else
456                 syslog(LOG_ERR, "internal service %s unknown",
457                                 sep->se_service);
458                         goto more;
459 #endif
460         } else
461 #ifndef INETD_UNSUPPORT_BILTIN
462                 sep->se_bi = NULL
463 #endif
464                 ;
465         argc = 0;
466         for (arg = skip(&cp); cp; arg = skip(&cp)) {
467                 if (argc < MAXARGV)
468                         sep->se_argv[argc++] = newstr(arg);
469         }
470         while (argc <= MAXARGV)
471                 sep->se_argv[argc++] = NULL;
472         return (sep);
473 }
474
475 static void
476 freeconfig(struct servtab *cp)
477 {
478         int i;
479
480         free(cp->se_service);
481         free(cp->se_proto);
482         free(cp->se_user);
483         /* Note: se_group is part of the newstr'ed se_user */
484         free(cp->se_server);
485         for (i = 0; i < MAXARGV; i++)
486                 free(cp->se_argv[i]);
487 }
488
489 #ifndef INETD_UNSUPPORT_BILTIN
490 static char **Argv;
491 static char *LastArg;
492
493 static void
494 setproctitle(char *a, int s)
495 {
496         size_t size;
497         char *cp;
498         struct sockaddr_in sn;
499         char buf[80];
500
501         cp = Argv[0];
502         size = sizeof(sn);
503         if (getpeername(s, (struct sockaddr *)&sn, &size) == 0)
504                 (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sn.sin_addr));
505         else
506                 (void) sprintf(buf, "-%s", a);
507         strncpy(cp, buf, LastArg - cp);
508         cp += strlen(cp);
509         while (cp < LastArg)
510                 *cp++ = ' ';
511 }
512 #endif  /* INETD_UNSUPPORT_BILTIN */
513
514 static struct servtab *
515 enter(struct servtab *cp)
516 {
517         struct servtab *sep;
518         sigset_t oldmask;
519
520         sep = (struct servtab *)malloc(sizeof (*sep));
521         if (sep == NULL) {
522                 syslog_err_and_discard_dg(SOCK_STREAM, bb_msg_memory_exhausted);
523         }
524         *sep = *cp;
525         sep->se_fd = -1;
526         sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
527         sep->se_next = servtab;
528         servtab = sep;
529         sigprocmask(SIG_SETMASK, &oldmask, NULL);
530         return (sep);
531 }
532
533 static int
534 bump_nofile(void)
535 {
536 #ifdef RLIMIT_NOFILE
537
538 #define FD_CHUNK        32
539
540         struct rlimit rl;
541
542         if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
543                 syslog(LOG_ERR, "getrlimit: %m");
544                 return -1;
545         }
546         rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
547         if (rl.rlim_cur <= rlim_ofile_cur) {
548                 syslog(LOG_ERR,
549 #if _FILE_OFFSET_BITS == 64
550                         "bump_nofile: cannot extend file limit, max = %lld",
551 #else
552                         "bump_nofile: cannot extend file limit, max = %ld",
553 #endif
554                         rl.rlim_cur);
555                 return -1;
556         }
557
558         if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
559                 syslog(LOG_ERR, "setrlimit: %m");
560                 return -1;
561         }
562
563         rlim_ofile_cur = rl.rlim_cur;
564         return 0;
565
566 #else
567         syslog(LOG_ERR, "bump_nofile: cannot extend file limit");
568         return -1;
569 #endif
570 }
571
572
573 static void
574 setup(struct servtab *sep)
575 {
576         int on = 1;
577
578         if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
579                 syslog(LOG_ERR, "%s/%s: socket: %m",
580                     sep->se_service, sep->se_proto);
581                 return;
582         }
583         if (setsockopt(sep->se_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
584                             sizeof(on)) < 0)
585                 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
586         if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) {
587                 syslog(LOG_ERR, "%s/%s: bind: %m",
588                     sep->se_service, sep->se_proto);
589                 (void) close(sep->se_fd);
590                 sep->se_fd = -1;
591                 if (!timingout) {
592                         timingout = 1;
593                         alarm(RETRYTIME);
594                 }
595                 return;
596         }
597         if (sep->se_socktype == SOCK_STREAM)
598                 listen(sep->se_fd, global_queuelen);
599
600         FD_SET(sep->se_fd, &allsock);
601         nsock++;
602         if (sep->se_fd > maxsock) {
603                 maxsock = sep->se_fd;
604                 if (maxsock > rlim_ofile_cur - FD_MARGIN)
605                         bump_nofile();
606         }
607 }
608
609 static void
610 config(int signum)
611 {
612         struct servtab *sep, *cp, **sepp;
613         sigset_t oldmask;
614         unsigned n;
615
616         (void)signum;
617         if (setconfig() == NULL)
618                 return;
619
620         for (sep = servtab; sep; sep = sep->se_next)
621                 sep->se_checked = 0;
622         while ((cp = getconfigent()) != NULL) {
623                 for (sep = servtab; sep; sep = sep->se_next)
624                         if (strcmp(sep->se_service, cp->se_service) == 0 &&
625                             strcmp(sep->se_proto, cp->se_proto) == 0)
626                                 break;
627                 if (sep != 0) {
628                         int i;
629
630 #define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;}
631
632                         sigprocmask(SIG_BLOCK, &emptymask, &oldmask);
633                         /*
634                          * sep->se_wait may be holding the pid of a daemon
635                          * that we're waiting for.  If so, don't overwrite
636                          * it unless the config file explicitly says don't
637                          * wait.
638                          */
639                         if (
640 #ifndef INETD_UNSUPPORT_BILTIN
641                             cp->se_bi == 0 &&
642 #endif
643                             (sep->se_wait == 1 || cp->se_wait == 0))
644                                 sep->se_wait = cp->se_wait;
645                         if (cp->se_max != sep->se_max)
646                                 SWAP(int, cp->se_max, sep->se_max);
647                         if (cp->se_user)
648                                 SWAP(char *, sep->se_user, cp->se_user);
649                         if (cp->se_group)
650                                 SWAP(char *, sep->se_group, cp->se_group);
651                         if (cp->se_server)
652                                 SWAP(char *, sep->se_server, cp->se_server);
653                         for (i = 0; i < MAXARGV; i++)
654                                 SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
655 #undef SWAP
656                         sigprocmask(SIG_SETMASK, &oldmask, NULL);
657                         freeconfig(cp);
658                 } else {
659                         sep = enter(cp);
660                 }
661                 sep->se_checked = 1;
662
663                 switch (sep->se_family) {
664                 case AF_UNIX:
665                         if (sep->se_fd != -1)
666                                 break;
667                         (void)unlink(sep->se_service);
668                         n = strlen(sep->se_service);
669                         if (n > sizeof(sep->se_ctrladdr_un.sun_path) - 1)
670                                 n = sizeof(sep->se_ctrladdr_un.sun_path) - 1;
671                         strncpy(sep->se_ctrladdr_un.sun_path, sep->se_service, n);
672                         sep->se_ctrladdr_un.sun_family = AF_UNIX;
673                         sep->se_ctrladdr_size = n +
674                                         sizeof sep->se_ctrladdr_un.sun_family;
675                         setup(sep);
676                         break;
677                 case AF_INET:
678                         sep->se_ctrladdr_in.sin_family = AF_INET;
679                         sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in;
680                         {
681                                 u_short port = htons(atoi(sep->se_service));
682
683                                 if (!port) {
684                                         struct servent *sp;
685                                         sp = getservbyname(sep->se_service,
686                                                                 sep->se_proto);
687                                         if (sp == 0) {
688                                                 syslog(LOG_ERR,
689                                                     "%s/%s: unknown service",
690                                                     sep->se_service, sep->se_proto);
691                                                 continue;
692                                         }
693                                         port = sp->s_port;
694                                 }
695                                 if (port != sep->se_ctrladdr_in.sin_port) {
696                                         sep->se_ctrladdr_in.sin_port = port;
697                                         if (sep->se_fd != -1) {
698                                                 FD_CLR(sep->se_fd, &allsock);
699                                                 nsock--;
700                                                 (void) close(sep->se_fd);
701                                         }
702                                         sep->se_fd = -1;
703                                 }
704                                 if (sep->se_fd == -1)
705                                         setup(sep);
706                         }
707                 }
708         }
709         if (fconfig) {
710                 (void) fclose(fconfig);
711                 fconfig = NULL;
712         }
713         /*
714          * Purge anything not looked at above.
715          */
716         sigprocmask(SIG_SETMASK, &blockmask, &oldmask);
717         sepp = &servtab;
718         while ((sep = *sepp) != NULL) {
719                 if (sep->se_checked) {
720                         sepp = &sep->se_next;
721                         continue;
722                 }
723                 *sepp = sep->se_next;
724                 if (sep->se_fd != -1) {
725                         FD_CLR(sep->se_fd, &allsock);
726                         nsock--;
727                         (void) close(sep->se_fd);
728                 }
729                 if (sep->se_family == AF_UNIX)
730                         (void)unlink(sep->se_service);
731                 freeconfig(sep);
732                 free((char *)sep);
733         }
734         sigprocmask(SIG_SETMASK, &oldmask, NULL);
735 }
736
737
738
739 static void
740 reapchild(int signum)
741 {
742         int status;
743         int pid;
744         struct servtab *sep;
745
746         (void)signum;
747         for (;;) {
748                 pid = wait3(&status, WNOHANG, (struct rusage *)0);
749                 if (pid <= 0)
750                         break;
751                 for (sep = servtab; sep; sep = sep->se_next)
752                         if (sep->se_wait == pid) {
753                                 if (WIFEXITED(status) && WEXITSTATUS(status))
754                                         syslog(LOG_WARNING,
755                                             "%s: exit status 0x%x",
756                                             sep->se_server, WEXITSTATUS(status));
757                                 else if (WIFSIGNALED(status))
758                                         syslog(LOG_WARNING,
759                                             "%s: exit signal 0x%x",
760                                             sep->se_server, WTERMSIG(status));
761                                 sep->se_wait = 1;
762                                 FD_SET(sep->se_fd, &allsock);
763                                 nsock++;
764                         }
765         }
766 }
767
768 static void
769 retry(int signum)
770 {
771         struct servtab *sep;
772
773         (void)signum;
774         timingout = 0;
775         for (sep = servtab; sep; sep = sep->se_next) {
776                 if (sep->se_fd == -1) {
777                         switch (sep->se_family) {
778                         case AF_UNIX:
779                         case AF_INET:
780                                 setup(sep);
781                                 break;
782                         }
783                 }
784         }
785 }
786
787 static void
788 goaway(int signum)
789 {
790         struct servtab *sep;
791
792         (void)signum;
793         for (sep = servtab; sep; sep = sep->se_next)
794                 if (sep->se_fd != -1 && sep->se_family == AF_UNIX)
795                         (void)unlink(sep->se_service);
796         (void)unlink(_PATH_INETDPID);
797         exit(0);
798 }
799
800
801
802 extern int
803 inetd_main(int argc, char *argv[])
804 {
805         struct servtab *sep;
806         struct passwd *pwd;
807         struct group *grp = NULL;
808         struct sigaction sa;
809         int pid;
810         unsigned long opt;
811         char *sq;
812         gid_t gid;
813
814 #ifdef INETD_UNSUPPORT_BILTIN
815 # define dofork 1
816 #else
817         int dofork;
818         extern char **environ;
819 #endif
820
821         gid = getgid();
822         setgroups(1, &gid);
823
824 #ifndef INETD_UNSUPPORT_BILTIN
825         Argv = argv;
826         if (environ == 0 || *environ == 0)
827                 environ = argv;
828         while (*environ)
829                 environ++;
830         LastArg = environ[-1] + strlen(environ[-1]);
831 #endif
832
833 #if defined(__uClinux__)
834         opt = bb_getopt_ulflags(argc, argv, "q:f", &sq);
835         if (!(opt & 4)) {
836             daemon(0, 0);
837             /* reexec for vfork() do continue parent */
838             vfork_daemon_rexec(argc, argv, "-f");
839         }
840 #else
841         opt = bb_getopt_ulflags(ac, av, "q:", &sq);
842         daemon(0, 0);
843 #endif /* uClinux */
844
845         if(opt & 1) {
846                         global_queuelen = atoi(optarg);
847                         if (global_queuelen < 8) global_queuelen=8;
848                 }
849         argc -= optind;
850         argv += optind;
851
852         if (argc > 0)
853                 CONFIG = argv[0];
854
855         openlog(bb_applet_name, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
856         {
857                 FILE *fp;
858
859                 if ((fp = fopen(_PATH_INETDPID, "w")) != NULL) {
860                         fprintf(fp, "%u\n", getpid());
861                         (void)fclose(fp);
862                 }
863         }
864
865 #ifdef RLIMIT_NOFILE
866         if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
867                 syslog(LOG_ERR, "getrlimit: %m");
868         } else {
869                 rlim_ofile_cur = rlim_ofile.rlim_cur;
870                 if (rlim_ofile_cur == RLIM_INFINITY)    /* ! */
871                         rlim_ofile_cur = OPEN_MAX;
872         }
873 #endif
874
875         config(0);
876
877         sigemptyset(&emptymask);
878         sigemptyset(&blockmask);
879         sigaddset(&blockmask, SIGCHLD);
880         sigaddset(&blockmask, SIGHUP);
881         sigaddset(&blockmask, SIGALRM);
882
883         memset(&sa, 0, sizeof(sa));
884         sa.sa_mask = blockmask;
885         sa.sa_handler = retry;
886         sigaction(SIGALRM, &sa, NULL);
887         sa.sa_handler = config;
888         sigaction(SIGHUP, &sa, NULL);
889         sa.sa_handler = reapchild;
890         sigaction(SIGCHLD, &sa, NULL);
891         sa.sa_handler = goaway;
892         sigaction(SIGTERM, &sa, NULL);
893         sa.sa_handler = goaway;
894         sigaction(SIGINT, &sa,  NULL);
895         sa.sa_handler = SIG_IGN;
896         sigaction(SIGPIPE, &sa, NULL);
897
898         {
899                 /* space for daemons to overwrite environment for ps */
900 #define DUMMYSIZE       100
901                 char dummy[DUMMYSIZE];
902
903                 (void)memset(dummy, 'x', DUMMYSIZE - 1);
904                 dummy[DUMMYSIZE - 1] = '\0';
905
906                 (void)setenv("inetd_dummy", dummy, 1);
907         }
908
909         for (;;) {
910             int n, ctrl;
911             fd_set readable;
912
913             if (nsock == 0) {
914                 sigprocmask(SIG_BLOCK, &blockmask, NULL);
915                 while (nsock == 0)
916                     sigsuspend(&emptymask);
917                 sigprocmask(SIG_SETMASK, &emptymask, NULL);
918             }
919             readable = allsock;
920             if ((n = select(maxsock + 1, &readable, (fd_set *)0,
921                 (fd_set *)0, (struct timeval *)0)) <= 0) {
922                     if (n < 0 && errno != EINTR)
923                         syslog(LOG_WARNING, "select: %m");
924                     sleep(1);
925                     continue;
926             }
927             for (sep = servtab; n && sep; sep = sep->se_next)
928             if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
929                 n--;
930                 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
931                         /* Fixed AGC */
932                         fcntl(sep->se_fd, F_SETFL, O_NDELAY);
933                         /* --------- */
934                         ctrl = accept(sep->se_fd, NULL, NULL);
935                         fcntl(sep->se_fd, F_SETFL, 0);
936                         if (ctrl < 0) {
937                                 if (errno == EINTR || errno == EWOULDBLOCK)
938                                         continue;
939                                 syslog(LOG_WARNING, "accept (for %s): %m",
940                                         sep->se_service);
941                                 continue;
942                         }
943                 } else
944                         ctrl = sep->se_fd;
945                 sigprocmask(SIG_BLOCK, &blockmask, NULL);
946                 pid = 0;
947 #ifndef INETD_UNSUPPORT_BILTIN
948                 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
949 #endif
950                 if (dofork) {
951                         if (sep->se_count++ == 0)
952                             (void)gettimeofday(&sep->se_time,
953                                 (struct timezone *)0);
954                         else if (sep->se_count >= sep->se_max) {
955                                 struct timeval now;
956
957                                 (void)gettimeofday(&now, (struct timezone *)0);
958                                 if (now.tv_sec - sep->se_time.tv_sec >
959                                     CNT_INTVL) {
960                                         sep->se_time = now;
961                                         sep->se_count = 1;
962                                 } else {
963                                         syslog(LOG_ERR,
964                         "%s/%s server failing (looping), service terminated",
965                                             sep->se_service, sep->se_proto);
966                                         FD_CLR(sep->se_fd, &allsock);
967                                         (void) close(sep->se_fd);
968                                         sep->se_fd = -1;
969                                         sep->se_count = 0;
970                                         nsock--;
971                                         sigprocmask(SIG_SETMASK, &emptymask,
972                                                     NULL);
973                                         if (!timingout) {
974                                                 timingout = 1;
975                                                 alarm(RETRYTIME);
976                                         }
977                                         continue;
978                                 }
979                         }
980                         pid = fork();
981                 }
982                 if (pid < 0) {
983                         syslog(LOG_ERR, "fork: %m");
984                         if (sep->se_socktype == SOCK_STREAM)
985                                 close(ctrl);
986                         sigprocmask(SIG_SETMASK, &emptymask, NULL);
987                         sleep(1);
988                         continue;
989                 }
990                 if (pid && sep->se_wait) {
991                         sep->se_wait = pid;
992                         FD_CLR(sep->se_fd, &allsock);
993                         nsock--;
994                 }
995                 sigprocmask(SIG_SETMASK, &emptymask, NULL);
996                 if (pid == 0) {
997 #ifndef INETD_UNSUPPORT_BILTIN
998                         if (sep->se_bi)
999                                 (*sep->se_bi->bi_fn)(ctrl, sep);
1000                         else
1001 #endif
1002                               {
1003                                 if ((pwd = getpwnam(sep->se_user)) == NULL) {
1004                                         syslog_err_and_discard_dg(
1005                                                 sep->se_socktype,
1006                                                 "getpwnam: %s: No such user",
1007                                                 sep->se_user);
1008                                 }
1009                                 if (sep->se_group &&
1010                                     (grp = getgrnam(sep->se_group)) == NULL) {
1011                                         syslog_err_and_discard_dg(
1012                                                 sep->se_socktype,
1013                                                 "getgrnam: %s: No such group",
1014                                                 sep->se_group);
1015                                 }
1016                                 /*
1017                                  * Ok. There are four cases here:
1018                                  *   1. nonroot user, no group specified
1019                                  *   2. nonroot user, some group specified
1020                                  *   3. root user, no group specified
1021                                  *   4. root user, some group specified
1022                                  * In cases 2 and 4 we setgid to the specified
1023                                  * group. In cases 1 and 2 we run initgroups
1024                                  * to run with the groups of the given user.
1025                                  * In case 4 we do setgroups to run with the
1026                                  * given group. In case 3 we do nothing.
1027                                  */
1028                                 if (pwd->pw_uid) {
1029                                         if (sep->se_group)
1030                                                 pwd->pw_gid = grp->gr_gid;
1031                                         setgid((gid_t)pwd->pw_gid);
1032                                         initgroups(pwd->pw_name, pwd->pw_gid);
1033                                         setuid((uid_t)pwd->pw_uid);
1034                                 } else if (sep->se_group) {
1035                                         setgid((gid_t)grp->gr_gid);
1036                                         setgroups(1, &grp->gr_gid);
1037                                 }
1038                                 dup2(ctrl, 0);
1039                                 close(ctrl);
1040                                 dup2(0, 1);
1041                                 dup2(0, 2);
1042 #ifdef RLIMIT_NOFILE
1043                                 if (rlim_ofile.rlim_cur != rlim_ofile_cur) {
1044                                         if (setrlimit(RLIMIT_NOFILE,
1045                                                         &rlim_ofile) < 0)
1046                                                 syslog(LOG_ERR,"setrlimit: %m");
1047                                 }
1048 #endif
1049                                 for (ctrl = rlim_ofile_cur-1; --ctrl > 2; )
1050                                         (void)close(ctrl);
1051
1052                                 memset(&sa, 0, sizeof(sa));
1053                                 sa.sa_handler = SIG_DFL;
1054                                 sigaction(SIGPIPE, &sa, NULL);
1055
1056                                 execv(sep->se_server, sep->se_argv);
1057                                 syslog_err_and_discard_dg(sep->se_socktype,
1058                                         "execv %s: %m", sep->se_server);
1059                         }
1060                 }
1061                 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
1062                         close(ctrl);
1063             }
1064         }
1065 }
1066
1067
1068 /*
1069  * Internet services provided internally by inetd:
1070  */
1071 #define BUFSIZE 4096
1072
1073 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
1074 /* Echo service -- echo data back */
1075 static void
1076 echo_stream(int s, struct servtab *sep)
1077 {
1078         char buffer[BUFSIZE];
1079         int i;
1080
1081         setproctitle(sep->se_service, s);
1082         while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1083             write(s, buffer, i) > 0)
1084                 ;
1085         exit(0);
1086 }
1087
1088 /* Echo service -- echo data back */
1089 static void
1090 echo_dg(int s, struct servtab *sep)
1091 {
1092         char buffer[BUFSIZE];
1093         int i;
1094         size_t size;
1095         struct sockaddr sa;
1096
1097         (void)sep;
1098
1099         size = sizeof(sa);
1100         if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0)
1101                 return;
1102         (void) sendto(s, buffer, i, 0, &sa, sizeof(sa));
1103 }
1104 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO */
1105
1106
1107 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
1108 /* Discard service -- ignore data */
1109 static void
1110 discard_stream(int s, struct servtab *sep)
1111 {
1112         char buffer[BUFSIZE];
1113
1114         setproctitle(sep->se_service, s);
1115         while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1116                         errno == EINTR)
1117                 ;
1118         exit(0);
1119 }
1120
1121 /* Discard service -- ignore data */
1122 static void
1123 discard_dg(int s, struct servtab *sep)
1124 {
1125         char buffer[BUFSIZE];
1126         (void)sep;
1127         read(s, buffer, sizeof(buffer));
1128 }
1129 #endif  /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD */
1130
1131
1132 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
1133 #include <ctype.h>
1134 #define LINESIZ 72
1135 static char ring[128];
1136 static char *endring;
1137
1138 static void
1139 initring(void)
1140 {
1141         int i;
1142
1143         endring = ring;
1144
1145         for (i = 0; i <= 128; ++i)
1146                 if (isprint(i))
1147                         *endring++ = i;
1148 }
1149
1150 /* Character generator */
1151 static void
1152 chargen_stream(int s, struct servtab *sep)
1153 {
1154         char *rs;
1155         int len;
1156         char text[LINESIZ+2];
1157
1158         setproctitle(sep->se_service, s);
1159
1160         if (!endring) {
1161                 initring();
1162                 rs = ring;
1163         }
1164
1165         text[LINESIZ] = '\r';
1166         text[LINESIZ + 1] = '\n';
1167         for (rs = ring;;) {
1168                 if ((len = endring - rs) >= LINESIZ)
1169                         BCOPY(rs, text, LINESIZ);
1170                 else {
1171                         BCOPY(rs, text, len);
1172                         BCOPY(ring, text + len, LINESIZ - len);
1173                 }
1174                 if (++rs == endring)
1175                         rs = ring;
1176                 if (write(s, text, sizeof(text)) != sizeof(text))
1177                         break;
1178         }
1179         exit(0);
1180 }
1181
1182 /* Character generator */
1183 static void
1184 chargen_dg(int s, struct servtab *sep)
1185 {
1186         struct sockaddr sa;
1187         static char *rs;
1188         size_t len, size;
1189         char text[LINESIZ+2];
1190
1191         (void)sep;
1192
1193         if (endring == 0) {
1194                 initring();
1195                 rs = ring;
1196         }
1197
1198         size = sizeof(sa);
1199         if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0)
1200                 return;
1201
1202         if ((len = endring - rs) >= LINESIZ)
1203                 BCOPY(rs, text, LINESIZ);
1204         else {
1205                 BCOPY(rs, text, len);
1206                 BCOPY(ring, text + len, LINESIZ - len);
1207         }
1208         if (++rs == endring)
1209                 rs = ring;
1210         text[LINESIZ] = '\r';
1211         text[LINESIZ + 1] = '\n';
1212         (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
1213 }
1214 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN */
1215
1216
1217 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
1218 /*
1219  * Return a machine readable date and time, in the form of the
1220  * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
1221  * returns the number of seconds since midnight, Jan 1, 1970,
1222  * we must add 2208988800 seconds to this figure to make up for
1223  * some seventy years Bell Labs was asleep.
1224  */
1225
1226 static long
1227 machtime(void)
1228 {
1229         struct timeval tv;
1230
1231         if (gettimeofday(&tv, (struct timezone *)0) < 0) {
1232                 fprintf(stderr, "Unable to get time of day\n");
1233                 return (0L);
1234         }
1235         return (htonl((long)tv.tv_sec + 2208988800UL));
1236 }
1237
1238 static void
1239 machtime_stream(int s, struct servtab *sep)
1240 {
1241         long result;
1242         (void)sep;
1243
1244         result = machtime();
1245         write(s, (char *) &result, sizeof(result));
1246 }
1247
1248 static void
1249 machtime_dg(int s, struct servtab *sep)
1250 {
1251         long result;
1252         struct sockaddr sa;
1253         size_t size;
1254         (void)sep;
1255
1256         size = sizeof(sa);
1257         if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0)
1258                 return;
1259         result = machtime();
1260         (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa));
1261 }
1262 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME */
1263
1264
1265 #ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
1266 /* Return human-readable time of day */
1267 static int
1268 human_readable_time_sprintf(char *buffer)
1269 {
1270         time_t clocc = time(NULL);
1271
1272         return sprintf(buffer, "%.24s\r\n", ctime(&clocc));
1273 }
1274
1275 static void
1276 daytime_stream(int s, struct servtab *sep)
1277 {
1278         char buffer[256];
1279         size_t st = human_readable_time_sprintf(buffer);
1280
1281         (void)sep;
1282
1283         write(s, buffer, st);
1284 }
1285
1286 /* Return human-readable time of day */
1287 static void
1288 daytime_dg(int s, struct servtab *sep)
1289 {
1290         char buffer[256];
1291         struct sockaddr sa;
1292         size_t size;
1293
1294         (void)sep;
1295
1296         size = sizeof(sa);
1297         if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0)
1298                 return;
1299         size = human_readable_time_sprintf(buffer);
1300         sendto(s, buffer, size, 0, &sa, sizeof(sa));
1301 }
1302 #endif /* CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME */