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>
index | next in thread | raw e-mail
[-- Attachment #1 --]
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.....
[-- Attachment #2 --]
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);
}
/*
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3280EF24.ABD322C>
