From dchapes@golden.net  Thu Nov 20 11:58:32 1997
Received: from ymris.ddm.on.ca (cisco7-156.cas.golden.net [207.216.76.156])
          by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id LAA01842
          for <FreeBSD-gnats-submit@freebsd.org>; Thu, 20 Nov 1997 11:58:29 -0800 (PST)
          (envelope-from dchapes@golden.net)
Received: from squigy.ddm.on.ca (squigy.ddm.on.ca [209.47.139.138])
	by ymris.ddm.on.ca (8.8.7/8.8.7) with ESMTP id OAA04959
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 20 Nov 1997 14:58:19 -0500 (EST)
Received: (from dchapes@localhost)
	by squigy.ddm.on.ca (8.8.7/8.8.7) id OAA02139;
	Thu, 20 Nov 1997 14:58:18 -0500 (EST)
Message-Id: <199711201958.OAA02139@squigy.ddm.on.ca>
Date: Thu, 20 Nov 1997 14:58:18 -0500 (EST)
From: dchapes@golden.net
Reply-To: dchapes@golden.net
To: FreeBSD-gnats-submit@freebsd.org
Subject: patch to ftpd, new option to limit number of ftpd sessions
X-Send-Pr-Version: 3.2

>Number:         5109
>Category:       bin
>Synopsis:       patch to ftpd, new option to limit number of ftpd sessions
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Nov 20 12:00:04 PST 1997
>Closed-Date:    Mon Mar 29 18:07:30 PST 1999
>Last-Modified:  Mon Mar 29 18:10:35 PST 1999
>Originator:     Dave Chapeskie
>Release:        FreeBSD 2.2-STABLE i386
>Organization:
DDM Consulting
>Environment:
>Description:

FreeBSD's ftpd(8) has no way to limit the number of ftp clients
allowed at one time so I spent a few minutes to add and test a new
"-C maxchildren" option to ftpd to do this (when used with the
existing -D option).

It would be nice if someone with commit privileges could commit this.

The following patch is relative to FreeBSD-2.2.5 (actually 2.2-STABLE
shortly after 2.2.5) but should apply to -current as well.

>How-To-Repeat:
>Fix:
	
Index: ftpd.8
===================================================================
RCS file: /cvs/FreeBSD/src/libexec/ftpd/ftpd.8,v
retrieving revision 1.9.2.8
diff -u -r1.9.2.8 ftpd.8
--- ftpd.8	1997/05/10 19:48:12	1.9.2.8
+++ ftpd.8	1997/11/20 19:18:13
@@ -50,6 +50,7 @@
 .Op Fl t Ar timeout
 .Op Fl a Ar address
 .Op Fl p Ar file
+.Op Fl C Ar maxchildren
 .Sh DESCRIPTION
 .Nm Ftpd
 is the
@@ -137,6 +138,16 @@
 .Ar file .
 .It Fl A
 Allow only anonymous ftp access
+.It Fl C
+When
+.Fl D
+is specified, limit the number of concurrent ftp sessions to
+.Ar maxchildren .
+If the file
+.Pa /etc/ftptoomany
+exists,
+.Nm
+displays it before exiting.
 .El
 .Pp
 The file
@@ -429,6 +440,8 @@
 Welcome notice.
 .It Pa /etc/ftpmotd
 Welcome notice after login.
+.It Pa /etc/ftptoomany
+Displayed when there are too many ftp sessions.
 .It Pa /etc/nologin
 Displayed and access refused.
 .It Pa /var/log/ftpd
Index: ftpd.c
===================================================================
RCS file: /cvs/FreeBSD/src/libexec/ftpd/ftpd.c,v
retrieving revision 1.25.2.11
diff -u -r1.25.2.11 ftpd.c
--- ftpd.c	1997/09/05 12:45:29	1.25.2.11
+++ ftpd.c	1997/11/20 19:28:59
@@ -128,6 +128,8 @@
 int	debug;
 int	timeout = 900;    /* timeout after 15 minutes of inactivity */
 int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
+int	maxchildren = 0;
+int	children = 0;
 int	logging;
 int	restricted_data_ports = 1;
 int	paranoid = 1;	  /* be extra careful about security */
@@ -287,7 +289,7 @@
 
 
 	bind_address.s_addr = htonl(INADDR_ANY);
-	while ((ch = getopt(argc, argv, "AdlDSURt:T:u:va:p:")) != -1) {
+	while ((ch = getopt(argc, argv, "AdlDSURt:T:u:va:p:C:")) != -1) {
 		switch (ch) {
 		case 'D':
 			daemon_mode++;
@@ -353,6 +355,10 @@
 			debug = 1;
 			break;
 
+		case 'C':
+			maxchildren = atoi(optarg);
+			break;
+
 		default:
 			warnx("unknown flag -%c ignored", optopt);
 			break;
@@ -441,6 +447,7 @@
 		while (1) {
 			addrlen = sizeof(his_addr);
 			fd = accept(ctl_sock, (struct sockaddr *)&his_addr, &addrlen);
+			children++;
 			if (fork() == 0) {
 				/* child */
 				(void) dup2(fd, 0);
@@ -518,6 +525,23 @@
 		reply(530, "System not available.");
 		exit(0);
 	}
+
+	/* If there are too many ftpd's */
+	if (maxchildren && children > maxchildren) {
+		if ((fd = fopen(_PATH_FTPTOOMANY,"r")) != NULL) {
+			while (fgets(line, sizeof(line), fd) != NULL) {
+				if ((cp = strchr(line, '\n')) != NULL)
+					*cp = '\0';
+				lreply(530, "%s", line);
+			}
+			(void) fflush(stdout);
+			(void) fclose(fd);
+		} else {
+			reply(530, "Too many ftp users, try again later.");
+		}
+		exit(0);
+	}
+
 #ifdef VIRTUAL_HOSTING
 	if ((fd = fopen(thishost->welcome, "r")) != NULL) {
 #else
@@ -537,6 +561,14 @@
 		fatal("Ran out of memory.");
 	(void) gethostname(hostname, MAXHOSTNAMELEN);
 #endif
+	if (daemon_mode) {
+		if (maxchildren) {
+			lreply(220, "There are currently %d users out of "
+				"%d possible.", children, maxchildren);
+		} else {
+			lreply(220, "There are currently %d users.", children);
+		}
+	}
 	reply(220, "%s FTP server (%s) ready.", hostname, version);
 	(void) setjmp(errcatch);
 	for (;;)
@@ -2222,7 +2254,9 @@
 reapchild(signo)
 	int signo;
 {
-	while (wait3(NULL, WNOHANG, NULL) > 0);
+	while (wait3(NULL, WNOHANG, NULL) > 0) {
+		children--;
+	}
 }
 
 #ifdef OLD_SETPROCTITLE
Index: pathnames.h
===================================================================
RCS file: /cvs/FreeBSD/src/libexec/ftpd/pathnames.h,v
retrieving revision 1.6.2.2
diff -u -r1.6.2.2 pathnames.h
--- pathnames.h	1997/04/29 12:55:33	1.6.2.2
+++ pathnames.h	1997/11/20 18:40:15
@@ -42,3 +42,4 @@
 #define	_PATH_FTPHOSTS		"/etc/ftphosts"
 #define	_PATH_FTPDSTATFILE	"/var/log/ftpd"
 #define	_PATH_LS		"/bin/ls"
+#define	_PATH_FTPTOOMANY	"/etc/ftptoomany"
>Release-Note:
>Audit-Trail:

From: j@uriah.heep.sax.de (J Wunsch)
To: dchapes@golden.net
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: bin/5109: patch to ftpd, new option to limit number of ftpd sessions
Date: Sun, 23 Nov 1997 13:42:37 +0100

 As dchapes@golden.net wrote:
 
 > FreeBSD's ftpd(8) has no way to limit the number of ftp clients
 > allowed at one time so I spent a few minutes to add and test a new
 > "-C maxchildren" option to ftpd to do this (when used with the
 > existing -D option).
 
 Instead of inventing a bunch of commandline options for each resource
 limit, did you consider using login.conf, and making ftpd using the
 user "ftp"'s login class for anonymous access (and i think that's what
 you actually want)?  This would IMHO constitute a better approach.
 
 -- 
 cheers, J"org
 
 joerg_wunsch@uriah.heep.sax.de -- http://www.sax.de/~joerg/ -- NIC: JW11-RIPE
 Never trust an operating system you don't have sources for. ;-)

From: Dave Chapeskie <dchapes@golden.net>
To: Joerg Wunsch <joerg_wunsch@uriah.heep.sax.de>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: bin/5109: patch to ftpd, new option to limit number of ftpd sessions
Date: Sun, 23 Nov 1997 12:28:23 -0500

 On Sun, Nov 23, 1997 at 01:42:37PM +0100, J Wunsch wrote:
 > Instead of inventing a bunch of commandline options for each resource
 > limit,
 
 I only needed this one.  :-)
 
 > did you consider using login.conf, and making ftpd using the user
 > "ftp"'s login class for anonymous access (and i think that's what you
 > actually want)?  This would IMHO constitute a better approach.
 
 Do you mean just setting maxproc and letting the fork fail?  If so that's
 evil cause the client gets no useful information on why the connection
 failed.
 
 At any rate, I did my change in 5 minutes and it works for me.  If you
 want to spend more time to do something better go ahead.  If you think
 my change is an ugly hack then don't commit it (and add a more detailed
 description of what you mean to the gnats PR so the next person that
 wants this can do it "right").
 
 Cheers,
 -- 
 Dave Chapeskie, DDM Consulting
 E-Mail: dchapes@ddm.on.ca
State-Changed-From-To: open->closed 
State-Changed-By: sheldonh 
State-Changed-When: Mon Mar 29 18:07:30 PST 1999 
State-Changed-Why:  
inetd's max-child feature makes this hack unnecessary. 
>Unformatted:
