Date: Wed, 06 Nov 1996 12:03:48 -0800 From: Julian Elischer <julian@whistle.com> To: hackers@freebsd.org Subject: Inetd mod.. comments? Message-ID: <3280EF24.ABD322C@whistle.com>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------2F1CF0FB237C228A31DFF4F5 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit I have some patches to Inetd her that I sent out for comment. the only comment I got was "Gee that's neat!, I need that" but no technical reviews or code checks.. I would like to commit this change but I don't want to do it without a reviewer to put on the commit message.. I include the patch (actually a slightly improved version) again... As I said before this provides us (whistle) with protection against a denial of service attack. reviews please..... --------------2F1CF0FB237C228A31DFF4F5 Content-Type: text/plain; charset=us-ascii; name="inetd.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="inetd.patch" Index: Makefile =================================================================== RCS file: /cvs/freebsd/src/usr.sbin/inetd/Makefile,v retrieving revision 1.3 diff -c -r1.3 Makefile *** 1.3 1996/01/01 08:42:22 --- Makefile 1996/11/06 19:02:22 *************** *** 4,9 **** --- 4,12 ---- MAN8= inetd.8 MLINKS= inetd.8 inetd.conf.5 + COPTS+= -Wall + COPTS+= -DSANITY_CHECK + DPADD+= ${LIBUTIL} LDADD+= -lutil Index: inetd.8 =================================================================== RCS file: /cvs/freebsd/src/usr.sbin/inetd/inetd.8,v retrieving revision 1.9 diff -c -r1.9 inetd.8 *** 1.9 1996/08/09 22:20:23 --- inetd.8 1996/11/06 19:02:22 *************** *** 101,107 **** service name socket type protocol ! wait/nowait user server program server program arguments --- 101,107 ---- service name socket type protocol ! {wait|nowait}[/max-child] user server program server program arguments *************** *** 260,265 **** --- 260,274 ---- requests until a timeout. TCPMUX services must use .Dq nowait . + .Pp + The maximum number of outstanding child processes (or ``threads'') + for a ``nowait'' service may be explicitly specified by appending a + ``/'' followed by the number to the ``nowait'' keyword. Normally + (or if a value of zero is specified) there is no maximum. Otherwise, + once the maximum is reached, further connection attempts will be + queued up until an existing child process exits. This also works + in the case of ``wait'' mode, although a value other than one (the + default) might not make sense in some cases. .Pp The .Em user Index: inetd.c =================================================================== RCS file: /cvs/freebsd/src/usr.sbin/inetd/inetd.c,v retrieving revision 1.15 diff -c -r1.15 inetd.c *** 1.15 1996/11/01 01:42:08 --- inetd.c 1996/11/06 19:02:22 *************** *** 32,45 **** */ #ifndef lint ! static char copyright[] = "@(#) Copyright (c) 1983, 1991, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint /* from: @(#)inetd.c 8.4 (Berkeley) 4/13/94"; */ ! static char inetd_c_rcsid[] = "$Id: inetd.c,v 1.15 1996/11/01 01:42:08 alex Exp $"; #endif /* not lint */ --- 32,45 ---- */ #ifndef lint ! static char copyright[] __attribute__ ((unused)) = "@(#) Copyright (c) 1983, 1991, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint /* from: @(#)inetd.c 8.4 (Berkeley) 4/13/94"; */ ! static char inetd_c_rcsid[] __attribute__ ((unused)) = "$Id: inetd.c,v 1.15 1996/11/01 01:42:08 alex Exp $"; #endif /* not lint */ *************** *** 112,117 **** --- 112,118 ---- #include <netinet/in.h> #include <arpa/inet.h> #include <rpc/rpc.h> + #include <rpc/pmap_clnt.h> #include <errno.h> #include <fcntl.h> *************** *** 124,139 **** #include <syslog.h> #include <unistd.h> #include <libutil.h> #include "pathnames.h" #define TOOMANY 256 /* don't start more than TOOMANY */ #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ #define RETRYTIME (60*10) /* retry after bind or server fail */ #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) - int debug = 0; int log = 0; int nsock, maxsock; --- 125,141 ---- #include <syslog.h> #include <unistd.h> #include <libutil.h> + #include <sysexits.h> #include "pathnames.h" #define TOOMANY 256 /* don't start more than TOOMANY */ #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ #define RETRYTIME (60*10) /* retry after bind or server fail */ + #define MAX_MAXCHLD 32767 /* max allowable max children */ #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) int debug = 0; int log = 0; int nsock, maxsock; *************** *** 149,155 **** char *se_service; /* name of service */ int se_socktype; /* type of socket to use */ char *se_proto; /* protocol used */ ! short se_wait; /* single threaded server */ short se_checked; /* looked at during merge */ char *se_user; /* user name to run as */ struct biltin *se_bi; /* if built-in, description */ --- 151,159 ---- char *se_service; /* name of service */ int se_socktype; /* type of socket to use */ char *se_proto; /* protocol used */ ! short se_maxchild; /* max number of children */ ! short se_numchild; /* current number of children */ ! short *se_pids; /* array of child pids */ short se_checked; /* looked at during merge */ char *se_user; /* user name to run as */ struct biltin *se_bi; /* if built-in, description */ *************** *** 159,165 **** int se_fd; /* open descriptor */ int se_type; /* type */ struct sockaddr_in se_ctrladdr;/* bound address */ ! int se_rpc; /* ==1 if RPC service */ int se_rpc_prog; /* RPC program number */ u_int se_rpc_lowvers; /* RPC low version */ u_int se_rpc_highvers; /* RPC high version */ --- 163,170 ---- int se_fd; /* open descriptor */ int se_type; /* type */ struct sockaddr_in se_ctrladdr;/* bound address */ ! u_char se_accept; /* i.e., wait/nowait mode */ ! u_char se_rpc; /* ==1 if RPC service */ int se_rpc_prog; /* RPC program number */ u_int se_rpc_lowvers; /* RPC low version */ u_int se_rpc_highvers; /* RPC high version */ *************** *** 195,201 **** --- 200,209 ---- char *newstr __P((char *)); char *nextline __P((FILE *)); void print_service __P((char *, struct servtab *)); + void addchild __P((struct servtab *, int)); void reapchild __P((int)); + void enable __P((struct servtab *)); + void disable __P((struct servtab *)); void retry __P((int)); int setconfig __P((void)); void setup __P((struct servtab *)); *************** *** 209,215 **** char *bi_service; /* internally provided service name */ int bi_socktype; /* type of socket supported */ short bi_fork; /* 1 if should fork before call */ ! short bi_wait; /* 1 if should wait for child */ void (*bi_fn)(); /* function which performs it */ } biltins[] = { /* Echo received data */ --- 217,223 ---- char *bi_service; /* internally provided service name */ int bi_socktype; /* type of socket supported */ short bi_fork; /* 1 if should fork before call */ ! short bi_maxchild; /* max number of children (default) */ void (*bi_fn)(); /* function which performs it */ } biltins[] = { /* Echo received data */ *************** *** 298,304 **** if (!inet_aton(optarg, &bind_address)) { syslog(LOG_ERR, "-a %s: invalid IP address", optarg); ! exit(1); } break; case 'p': --- 306,312 ---- if (!inet_aton(optarg, &bind_address)) { syslog(LOG_ERR, "-a %s: invalid IP address", optarg); ! exit(EX_USAGE); } break; case 'p': *************** *** 309,315 **** syslog(LOG_ERR, "usage: inetd [-dl] [-a address] [-R rate]" " [-p pidfile] [conf-file]"); ! exit(1); } argc -= optind; argv += optind; --- 317,323 ---- syslog(LOG_ERR, "usage: inetd [-dl] [-a address] [-R rate]" " [-p pidfile] [conf-file]"); ! exit(EX_USAGE); } argc -= optind; argv += optind; *************** *** 383,389 **** if (debug) fprintf(stderr, "someone wants %s\n", sep->se_service); ! if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { ctrl = accept(sep->se_fd, (struct sockaddr *)0, (int *)0); if (debug) --- 391,397 ---- if (debug) fprintf(stderr, "someone wants %s\n", sep->se_service); ! if (sep->se_accept && sep->se_socktype == SOCK_STREAM) { ctrl = accept(sep->se_fd, (struct sockaddr *)0, (int *)0); if (debug) *************** *** 395,401 **** sep->se_service); continue; } ! if(log) { i = sizeof peer; if(getpeername(ctrl, (struct sockaddr *) &peer, &i)) { --- 403,409 ---- sep->se_service); continue; } ! if (log) { i = sizeof peer; if(getpeername(ctrl, (struct sockaddr *) &peer, &i)) { *************** *** 456,475 **** } if (pid < 0) { syslog(LOG_ERR, "fork: %m"); ! if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) close(ctrl); sigsetmask(0L); sleep(1); continue; } ! if (pid && sep->se_wait) { ! sep->se_wait = pid; ! if (sep->se_fd >= 0) { ! FD_CLR(sep->se_fd, &allsock); ! nsock--; ! } ! } sigsetmask(0L); if (pid == 0) { if (dofork) { --- 464,478 ---- } if (pid < 0) { syslog(LOG_ERR, "fork: %m"); ! if (sep->se_accept && sep->se_socktype == SOCK_STREAM) close(ctrl); sigsetmask(0L); sleep(1); continue; } ! if (pid) ! addchild(sep, pid); sigsetmask(0L); if (pid == 0) { if (dofork) { *************** *** 478,488 **** maxsock); for (tmpint = maxsock; tmpint > 2; tmpint--) if (tmpint != ctrl) ! close(tmpint); } ! if (sep->se_bi) (*sep->se_bi->bi_fn)(ctrl, sep); ! else { if (debug) fprintf(stderr, "%d execl %s\n", getpid(), sep->se_server); --- 481,492 ---- maxsock); for (tmpint = maxsock; tmpint > 2; tmpint--) if (tmpint != ctrl) ! (void) close(tmpint); } ! if (sep->se_bi) { (*sep->se_bi->bi_fn)(ctrl, sep); ! /* NOTREACHED */ ! } else { if (debug) fprintf(stderr, "%d execl %s\n", getpid(), sep->se_server); *************** *** 497,522 **** sep->se_user); if (sep->se_socktype != SOCK_STREAM) recv(0, buf, sizeof (buf), 0); ! _exit(1); } if (setsid() < 0) { syslog(LOG_ERR, "%s: can't setsid(): %m", sep->se_service); ! /* _exit(1); not fatal yet */ } if (pwd->pw_uid) { if (setlogin(sep->se_user) < 0) { syslog(LOG_ERR, "%s: can't setlogin(%s): %m", sep->se_service, sep->se_user); ! /* _exit(1); not fatal yet */ } if (setgid(pwd->pw_gid) < 0) { syslog(LOG_ERR, "%s: can't set gid %d: %m", sep->se_service, pwd->pw_gid); ! _exit(1); } (void) initgroups(pwd->pw_name, pwd->pw_gid); --- 501,526 ---- sep->se_user); if (sep->se_socktype != SOCK_STREAM) recv(0, buf, sizeof (buf), 0); ! _exit(EX_NOUSER); } if (setsid() < 0) { syslog(LOG_ERR, "%s: can't setsid(): %m", sep->se_service); ! /* _exit(EX_OSERR); not fatal yet */ } if (pwd->pw_uid) { if (setlogin(sep->se_user) < 0) { syslog(LOG_ERR, "%s: can't setlogin(%s): %m", sep->se_service, sep->se_user); ! /* _exit(EX_OSERR); not yet */ } if (setgid(pwd->pw_gid) < 0) { syslog(LOG_ERR, "%s: can't set gid %d: %m", sep->se_service, pwd->pw_gid); ! _exit(EX_OSERR); } (void) initgroups(pwd->pw_name, pwd->pw_gid); *************** *** 524,530 **** syslog(LOG_ERR, "%s: can't set uid %d: %m", sep->se_service, pwd->pw_uid); ! _exit(1); } } execv(sep->se_server, sep->se_argv); --- 528,534 ---- syslog(LOG_ERR, "%s: can't set uid %d: %m", sep->se_service, pwd->pw_uid); ! _exit(EX_OSERR); } } execv(sep->se_server, sep->se_argv); *************** *** 532,551 **** recv(0, buf, sizeof (buf), 0); syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server); ! _exit(1); } } ! if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) close(ctrl); } } } void reapchild(signo) int signo; { ! int status; pid_t pid; struct servtab *sep; --- 536,581 ---- recv(0, buf, sizeof (buf), 0); syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server); ! _exit(EX_OSERR); } } ! if (sep->se_accept && sep->se_socktype == SOCK_STREAM) close(ctrl); } } } + /* + * Record a new child pid for this service. If we've reached the + * limit on children, then stop accepting incoming requests. + */ + + void + addchild(struct servtab *sep, pid_t pid) + { + #ifdef SANITY_CHECK + if (sep->se_numchild >= sep->se_maxchild) { + syslog(LOG_ERR, "%s: %d >= %d", + __FUNCTION__, sep->se_numchild, sep->se_maxchild); + exit(EX_SOFTWARE); + } + #endif + if (sep->se_maxchild == 0) + return; + sep->se_pids[sep->se_numchild++] = pid; + if (sep->se_numchild == sep->se_maxchild) + disable(sep); + } + + /* + * Some child process has exited. See if it's on somebody's list. + */ + void reapchild(signo) int signo; { ! int k, status; pid_t pid; struct servtab *sep; *************** *** 556,574 **** if (debug) fprintf(stderr, "%d reaped, status %#x\n", pid, status); ! for (sep = servtab; sep; sep = sep->se_next) ! if (sep->se_wait == pid) { ! if (status) ! syslog(LOG_WARNING, ! "%s: exit status 0x%x", ! sep->se_server, status); ! if (debug) ! fprintf(stderr, "restored %s, fd %d\n", ! sep->se_service, sep->se_fd); ! FD_SET(sep->se_fd, &allsock); ! nsock++; ! sep->se_wait = 1; ! } } } --- 586,606 ---- if (debug) fprintf(stderr, "%d reaped, status %#x\n", pid, status); ! for (sep = servtab; sep; sep = sep->se_next) { ! for (k = 0; k < sep->se_numchild; k++) ! if (sep->se_pids[k] == pid) ! break; ! if (k == sep->se_numchild) ! continue; ! if (sep->se_numchild == sep->se_maxchild) ! enable(sep); ! sep->se_pids[k] = sep->se_pids[--sep->se_numchild]; ! if (status) ! syslog(LOG_WARNING, ! "%s[%d]: exit status 0x%x", ! sep->se_server, pid, status); ! break; ! } } } *************** *** 576,582 **** config(signo) int signo; { ! struct servtab *sep, *cp, **sepp; struct passwd *pwd; long omask; --- 608,614 ---- config(signo) int signo; { ! struct servtab *sep, *new, **sepp; struct passwd *pwd; long omask; *************** *** 586,628 **** } for (sep = servtab; sep; sep = sep->se_next) sep->se_checked = 0; ! while (cp = getconfigent()) { ! if ((pwd = getpwnam(cp->se_user)) == NULL) { syslog(LOG_ERR, "%s/%s: No such user '%s', service ignored", ! cp->se_service, cp->se_proto, cp->se_user); continue; } for (sep = servtab; sep; sep = sep->se_next) ! if (strcmp(sep->se_service, cp->se_service) == 0 && ! strcmp(sep->se_proto, cp->se_proto) == 0) break; if (sep != 0) { int i; omask = sigblock(SIGBLOCK); ! /* ! * sep->se_wait may be holding the pid of a daemon ! * that we're waiting for. If so, don't overwrite ! * it unless the config file explicitly says don't ! * wait. ! */ ! if (cp->se_bi == 0 && ! (sep->se_wait == 1 || cp->se_wait == 0)) ! sep->se_wait = cp->se_wait; ! #define SWAP(a, b) { char *c = a; a = b; b = c; } ! if (cp->se_user) ! SWAP(sep->se_user, cp->se_user); ! if (cp->se_server) ! SWAP(sep->se_server, cp->se_server); for (i = 0; i < MAXARGV; i++) ! SWAP(sep->se_argv[i], cp->se_argv[i]); sigsetmask(omask); ! freeconfig(cp); if (debug) print_service("REDO", sep); } else { ! sep = enter(cp); if (debug) print_service("ADD ", sep); } --- 618,674 ---- } for (sep = servtab; sep; sep = sep->se_next) sep->se_checked = 0; ! while ((new = getconfigent())) { ! if ((pwd = getpwnam(new->se_user)) == NULL) { syslog(LOG_ERR, "%s/%s: No such user '%s', service ignored", ! new->se_service, new->se_proto, new->se_user); continue; } for (sep = servtab; sep; sep = sep->se_next) ! if (strcmp(sep->se_service, new->se_service) == 0 && ! strcmp(sep->se_proto, new->se_proto) == 0) break; if (sep != 0) { int i; + #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; } omask = sigblock(SIGBLOCK); ! /* copy over outstanding child pids */ ! if (sep->se_maxchild && new->se_maxchild) { ! new->se_numchild = sep->se_numchild; ! if (new->se_numchild > new->se_maxchild) ! new->se_numchild = new->se_maxchild; ! memcpy(new->se_pids, sep->se_pids, ! new->se_numchild * sizeof(*new->se_pids)); ! } ! SWAP(sep->se_pids, new->se_pids); ! sep->se_maxchild = new->se_maxchild; ! sep->se_numchild = new->se_numchild; ! /* might need to turn on or off service now */ ! if (sep->se_fd >= 0) { ! if (sep->se_maxchild ! && sep->se_numchild == sep->se_maxchild) { ! if (FD_ISSET(sep->se_fd, &allsock)) ! disable(sep); ! } else { ! if (!FD_ISSET(sep->se_fd, &allsock)) ! enable(sep); ! } ! } ! sep->se_accept = new->se_accept; ! if (new->se_user) ! SWAP(sep->se_user, new->se_user); ! if (new->se_server) ! SWAP(sep->se_server, new->se_server); for (i = 0; i < MAXARGV; i++) ! SWAP(sep->se_argv[i], new->se_argv[i]); sigsetmask(omask); ! freeconfig(new); if (debug) print_service("REDO", sep); } else { ! sep = enter(new); if (debug) print_service("ADD ", sep); } *************** *** 673,679 **** */ omask = sigblock(SIGBLOCK); sepp = &servtab; ! while (sep = *sepp) { if (sep->se_checked) { sepp = &sep->se_next; continue; --- 719,725 ---- */ omask = sigblock(SIGBLOCK); sepp = &servtab; ! while ((sep = *sepp)) { if (sep->se_checked) { sepp = &sep->se_next; continue; *************** *** 727,733 **** timingout = 0; for (sep = servtab; sep; sep = sep->se_next) ! if (sep->se_fd == -1) setup(sep); } --- 773,779 ---- timingout = 0; for (sep = servtab; sep; sep = sep->se_next) ! if (sep->se_fd == -1 && !ISMUX(sep)) setup(sep); } *************** *** 796,805 **** } if (sep->se_socktype == SOCK_STREAM) listen(sep->se_fd, 64); ! FD_SET(sep->se_fd, &allsock); ! nsock++; ! if (sep->se_fd > maxsock) ! maxsock = sep->se_fd; if (debug) { fprintf(stderr, "registered %s on %d\n", sep->se_server, sep->se_fd); --- 842,848 ---- } if (sep->se_socktype == SOCK_STREAM) listen(sep->se_fd, 64); ! enable(sep); if (debug) { fprintf(stderr, "registered %s on %d\n", sep->se_server, sep->se_fd); *************** *** 814,831 **** struct servtab *sep; { if (sep->se_fd >= 0) { ! nsock--; ! FD_CLR(sep->se_fd, &allsock); (void) close(sep->se_fd); sep->se_fd = -1; } sep->se_count = 0; ! /* ! * Don't keep the pid of this running deamon: when reapchild() ! * reaps this pid, it would erroneously increment nsock. ! */ ! if (sep->se_wait > 1) ! sep->se_wait = 1; } struct servtab * --- 857,869 ---- struct servtab *sep; { if (sep->se_fd >= 0) { ! if (FD_ISSET(sep->se_fd, &allsock)) ! disable(sep); (void) close(sep->se_fd); sep->se_fd = -1; } sep->se_count = 0; ! sep->se_numchild = 0; /* forget about any existing children */ } struct servtab * *************** *** 838,844 **** sep = (struct servtab *)malloc(sizeof (*sep)); if (sep == (struct servtab *)0) { syslog(LOG_ERR, "Out of memory."); ! exit(-1); } *sep = *cp; sep->se_fd = -1; --- 876,882 ---- sep = (struct servtab *)malloc(sizeof (*sep)); if (sep == (struct servtab *)0) { syslog(LOG_ERR, "Out of memory."); ! exit(EX_OSERR); } *sep = *cp; sep->se_fd = -1; *************** *** 849,854 **** --- 887,954 ---- return (sep); } + void + enable(struct servtab *sep) + { + if (debug) + fprintf(stderr, + "enabling %s, fd %d", sep->se_service, sep->se_fd); + #ifdef SANITY_CHECK + if (sep->se_fd < 0) { + syslog(LOG_ERR, + "%s: %s: bad fd", __FUNCTION__, sep->se_service); + exit(EX_SOFTWARE); + } + if (ISMUX(sep)) { + syslog(LOG_ERR, + "%s: %s: is mux", __FUNCTION__, sep->se_service); + exit(EX_SOFTWARE); + } + if (FD_ISSET(sep->se_fd, &allsock)) { + syslog(LOG_ERR, + "%s: %s: not off", __FUNCTION__, sep->se_service); + exit(EX_SOFTWARE); + } + #endif + FD_SET(sep->se_fd, &allsock); + nsock++; + if (sep->se_fd > maxsock) + maxsock = sep->se_fd; + } + + void + disable(struct servtab *sep) + { + if (debug) + fprintf(stderr, + "disabling %s, fd %d", sep->se_service, sep->se_fd); + #ifdef SANITY_CHECK + if (sep->se_fd < 0) { + syslog(LOG_ERR, + "%s: %s: bad fd", __FUNCTION__, sep->se_service); + exit(EX_SOFTWARE); + } + if (ISMUX(sep)) { + syslog(LOG_ERR, + "%s: %s: is mux", __FUNCTION__, sep->se_service); + exit(EX_SOFTWARE); + } + if (!FD_ISSET(sep->se_fd, &allsock)) { + syslog(LOG_ERR, + "%s: %s: not on", __FUNCTION__, sep->se_service); + exit(EX_SOFTWARE); + } + if (nsock == 0) { + syslog(LOG_ERR, "%s: nsock=0", __FUNCTION__); + exit(EX_SOFTWARE); + } + #endif + FD_CLR(sep->se_fd, &allsock); + nsock--; + if (sep->se_fd == maxsock) + maxsock--; + } + FILE *fconfig = NULL; struct servtab serv; char line[LINE_MAX]; *************** *** 879,885 **** { struct servtab *sep = &serv; int argc; ! char *cp, *arg; char *versp; static char TCPMUX_TOKEN[] = "tcpmux/"; #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) --- 979,985 ---- { struct servtab *sep = &serv; int argc; ! char *cp, *arg, *s; char *versp; static char TCPMUX_TOKEN[] = "tcpmux/"; #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) *************** *** 959,972 **** } } arg = sskip(&cp); ! sep->se_wait = strcmp(arg, "wait") == 0; if (ISMUX(sep)) { /* ! * Silently enforce "nowait" for TCPMUX services since ! * they don't have an assigned port to listen on. */ ! sep->se_wait = 0; ! if (strcmp(sep->se_proto, "tcp")) { syslog(LOG_ERR, "%s: bad protocol for tcpmux service %s", --- 1059,1094 ---- } } arg = sskip(&cp); ! if (!strncmp(arg, "wait", 4)) ! sep->se_accept = 0; ! else if (!strncmp(arg, "nowait", 6)) ! sep->se_accept = 1; ! else { ! syslog(LOG_ERR, ! "%s: bad wait/nowait for service %s", ! CONFIG, sep->se_service); ! goto more; ! } ! sep->se_maxchild = -1; ! if ((s = strchr(arg, '/')) != NULL) { ! char *eptr; ! u_long val; ! ! val = strtoul(s + 1, &eptr, 10); ! if (eptr == s + 1 || *eptr || val > MAX_MAXCHLD) { ! syslog(LOG_ERR, ! "%s: bad max-child for service %s", ! CONFIG, sep->se_service); ! goto more; ! } ! sep->se_maxchild = val; ! } if (ISMUX(sep)) { /* ! * Silently enforce "nowait" mode for TCPMUX services ! * since they don't have an assigned port to listen on. */ ! sep->se_accept = 1; if (strcmp(sep->se_proto, "tcp")) { syslog(LOG_ERR, "%s: bad protocol for tcpmux service %s", *************** *** 994,1007 **** sep->se_service); goto more; } sep->se_bi = bi; - sep->se_wait = bi->bi_wait; } else sep->se_bi = NULL; argc = 0; for (arg = skip(&cp); cp; arg = skip(&cp)) ! if (argc < MAXARGV) sep->se_argv[argc++] = newstr(arg); while (argc <= MAXARGV) sep->se_argv[argc++] = NULL; return (sep); --- 1116,1147 ---- sep->se_service); goto more; } + sep->se_accept = 1; /* force accept mode for built-ins */ sep->se_bi = bi; } else sep->se_bi = NULL; + if (sep->se_maxchild < 0) /* apply default max-children */ + if (sep->se_bi) + sep->se_maxchild = sep->se_bi->bi_maxchild; + else + sep->se_maxchild = sep->se_accept ? 0 : 1; + if (sep->se_maxchild) { + sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids)); + if (sep->se_pids == NULL) { + syslog(LOG_ERR, "Out of memory."); + exit(EX_OSERR); + } + } argc = 0; for (arg = skip(&cp); cp; arg = skip(&cp)) ! if (argc < MAXARGV) { sep->se_argv[argc++] = newstr(arg); + } else { + syslog(LOG_ERR, + "%s: too many arguments for service %s", + CONFIG, sep->se_service); + goto more; + } while (argc <= MAXARGV) sep->se_argv[argc++] = NULL; return (sep); *************** *** 1021,1026 **** --- 1161,1168 ---- free(cp->se_user); if (cp->se_server) free(cp->se_server); + if (cp->se_pids) + free(cp->se_pids); for (i = 0; i < MAXARGV; i++) if (cp->se_argv[i]) free(cp->se_argv[i]); *************** *** 1040,1046 **** cp = skip(cpp); if (cp == NULL) { syslog(LOG_ERR, "%s: syntax error", CONFIG); ! exit(-1); } return (cp); } --- 1182,1188 ---- cp = skip(cpp); if (cp == NULL) { syslog(LOG_ERR, "%s: syntax error", CONFIG); ! exit(EX_DATAERR); } return (cp); } *************** *** 1062,1068 **** c = getc(fconfig); (void) ungetc(c, fconfig); if (c == ' ' || c == '\t') ! if (cp = nextline(fconfig)) goto again; *cpp = (char *)0; return ((char *)0); --- 1204,1210 ---- c = getc(fconfig); (void) ungetc(c, fconfig); if (c == ' ' || c == '\t') ! if ((cp = nextline(fconfig))) goto again; *cpp = (char *)0; return ((char *)0); *************** *** 1100,1109 **** newstr(cp) char *cp; { ! if (cp = strdup(cp ? cp : "")) return (cp); syslog(LOG_ERR, "strdup: %m"); ! exit(-1); } #ifdef OLD_SETPROCTITLE --- 1242,1251 ---- newstr(cp) char *cp; { ! if ((cp = strdup(cp ? cp : ""))) return (cp); syslog(LOG_ERR, "strdup: %m"); ! exit(EX_OSERR); } #ifdef OLD_SETPROCTITLE *************** *** 1439,1456 **** char *action; struct servtab *sep; { ! if(sep->se_rpc) ! fprintf(stderr, ! "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n", ! action, sep->se_service, sep->se_proto, ! sep->se_wait, sep->se_user, (int)sep->se_bi, ! sep->se_server); ! else ! fprintf(stderr, ! "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n", ! action, sep->se_service, sep->se_proto, ! sep->se_wait, sep->se_user, (int)sep->se_bi, ! sep->se_server); } /* --- 1581,1591 ---- char *action; struct servtab *sep; { ! fprintf(stderr, ! "%s: %s proto=%s accept=%d max=%d user=%s builtin=%x server=%s\n", ! action, sep->se_service, sep->se_proto, ! sep->se_accept, sep->se_maxchild, sep->se_user, ! (int)sep->se_bi, sep->se_server); } /* --------------2F1CF0FB237C228A31DFF4F5--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3280EF24.ABD322C>