[46009] trunk/dports/net/ucspi-tcp

raimue at macports.org raimue at macports.org
Mon Jan 26 23:48:43 PST 2009


Revision: 46009
          http://trac.macports.org/changeset/46009
Author:   raimue at macports.org
Date:     2009-01-26 23:48:43 -0800 (Mon, 26 Jan 2009)
Log Message:
-----------
net/ucspi-tcp:
New maintainer and new variants, closes #15735

Modified Paths:
--------------
    trunk/dports/net/ucspi-tcp/Portfile

Added Paths:
-----------
    trunk/dports/net/ucspi-tcp/files/
    trunk/dports/net/ucspi-tcp/files/LIMITS.TXT
    trunk/dports/net/ucspi-tcp/files/patch-tcpserver.c.diff

Modified: trunk/dports/net/ucspi-tcp/Portfile
===================================================================
--- trunk/dports/net/ucspi-tcp/Portfile	2009-01-27 07:44:52 UTC (rev 46008)
+++ trunk/dports/net/ucspi-tcp/Portfile	2009-01-27 07:48:43 UTC (rev 46009)
@@ -2,13 +2,15 @@
 
 PortSystem 1.0
 
-name		ucspi-tcp
-version		0.88
-revision	1
-categories	net
-platforms	darwin
-maintainers	nomaintainer
+name			ucspi-tcp
+version			0.88
+revision		2
+categories		net
+platforms		darwin
+maintainers		yahoo.com:compconsultant
+
 description		command-line tools for building TCP client-server applications
+
 long_description	tcpserver waits for incoming connections and, for each \
 			connection, runs a program of your choice. Your program receives \
 			environment variables showing the local and remote host names, IP \
@@ -17,9 +19,26 @@
 			variables as tcpserver.
 
 homepage		http://cr.yp.to/ucspi-tcp.html
-master_sites	http://cr.yp.to/ucspi-tcp/
-checksums		md5 39b619147db54687c4a583a7a94c9163
+master_sites		http://cr.yp.to/ucspi-tcp/
+patch_sites		http://www.fehcom.de/qmail/rblsmtpd:greetdelay
 
+checksums		${distname}${extract.suffix} \
+				md5 39b619147db54687c4a583a7a94c9163 \
+                        	sha1 793b4189795b563085602c030dd8aa0d206ddc0e \
+				rmd160 eb20085ea6ffd5d137a805f7c8768e0312c1f56a \
+			rblsmtpd.c.greetdelay \
+				md5 ce526be5be5c3ba2eab0f3624af9256f \
+				sha1 f52db52bbdee794e2cf0f79d3d5c861e1e2b5e31 \
+				rmd160 68ad0a181c9a4c7d6b40f042ebff4838fe2e29f3
+
+variant greetdelay description {Add configurable delay to discourage Spambots to rblsmtpd} {
+	patchfiles-append	rblsmtpd.c.greetdelay:greetdelay
+}
+
+variant limits description {Ability to limit connections by server} {
+	patchfiles-append	patch-tcpserver.c.diff
+}
+
 configure	{
 	reinplace "s|/usr/local|${destroot}${prefix}|g" ${worksrcpath}/conf-home
 	reinplace "s%/etc/dnsrewrite%${prefix}&%" ${worksrcpath}/dns_rcrw.c
@@ -36,4 +55,5 @@
 	xinstall -m 755 -d ${destroot}${prefix}/share/doc/${name}
 	xinstall -m 644 -W ${worksrcpath} CHANGES README TODO VERSION \
 		${destroot}${prefix}/share/doc/${name}
+	xinstall -W ${filespath} LIMITS.TXT ${destroot}${prefix}/share/doc/${name}/
 }

Added: trunk/dports/net/ucspi-tcp/files/LIMITS.TXT
===================================================================
--- trunk/dports/net/ucspi-tcp/files/LIMITS.TXT	                        (rev 0)
+++ trunk/dports/net/ucspi-tcp/files/LIMITS.TXT	2009-01-27 07:48:43 UTC (rev 46009)
@@ -0,0 +1,140 @@
+This patch (20060126) makes tcpserver from DJB's ucspi-tcp-0.88 package (see
+http://cr.yp.to/ucspi-tcp.html) to modify its behavior if some environment
+variables are present.
+
+The variables can be preset before starting tcpserver (thus acting as
+default for all connections), or, if you use 'tcpserver -x xxx.cdb', they
+can be set (or overridden) from xxx.cdb. If none of the variables are set,
+tcpserver behaves same as non patched version (except for negligible
+performance loss). Any or all variables can be set, as soon as first limit
+is reached the connection is dropped. I'd recommend using .cdb files
+exclusively though, as you can then modify configuration without killing
+tcpserver.
+
+The variables are:
+
+(1) MAXLOAD 
+    maximum 1-minute load average * 100. For example, if you have line
+    :allow,MAXLOAD="350" 
+    in your rules file from which you created .cdb, the connection will be
+    accepted only if load average is below 3.50
+
+    See COMPILING instructions above for info on supported systems.
+  
+(2) MAXCONNIP
+    maximum connections from one IP address. tcpserver's -c flag defines
+    maximum number of allowed connections, but it can be abused if
+    just one host goes wild and eats all the connections - no other host
+    would be able to connect then. If you created your .cdb with:
+    :allow,MAXCONNIP="5"
+    and run tcpserver -c 50, then each IP address would be able to have at 
+    most 5 concurrent connections, while there still could connect 50
+    clients total.
+    0 is valid value and means 'always reject'
+
+(3) MAXCONNC
+
+    maximum connections from whole C-class (256 addresses). Extension of
+    MAXCONNIP, as sometimes the problematic client has a whole farm of
+    client machines with different IP addresses instead of just one IP
+    address, and they all try to connect. It might have been more useful to
+    be able to specify CIDR block than C-class, but I've decided to KISS.
+
+    for example tcpserver -c 200, and .cdb with:
+    :allow,MAXCONNC="15"
+    will allow at most 15 host from any x.y.z.0/24 address block, while
+    still allowing up to 200 total connections.
+    0 is valid value and means 'always reject'
+
+(4) DIEMSG
+    
+    if set and one of the above limits is exceeded, this is the message 
+    to be sent to client (CRLF is always added to the text) before terminating
+    connection. If unset, the connection simply terminates (after 1 sec delay) 
+    if limit is exceeded.
+
+    For example:
+    DIEMSG="421 example.com Service temporarily not available, closing 
+    transmission channel"
+
+(5) DIEMSG_MAXLOAD
+
+    If set, and a connection is denied because the MAXLOAD limit is exceeded,
+    this value will be used instead of DIEMSG.
+
+    For example:
+    DIEMSG_MAXLOAD="421 example.com Server busy, try again later."
+
+(6) DIEMSG_MAXCONNIP
+
+    If set, and a connection is denied because the MAXCONNIP limit is exceeded,
+    this value will be used instead of DIEMSG.
+
+    For example:
+    DIEMSG_MAXCONNIP="421 example.com Too many connections from your IP."
+
+(7) DIEMSG_MAXCONNC
+
+    If set, and a connection is denied because the MAXCONNC limit is exceeded,
+    this value will be used instead of DIEMSG.
+
+    For example:
+    DIEMSG_MAXCONNC="421 example.com Too many connections from your network."
+
+Notes: 
+
+- if a connection is dropped due to some of those variables set, it will be
+  flagged (if you run tcpserver -v) with "MAXLOAD:", "MAXCONNIP:" or
+  "MAXCONNC:" at the end of the "tcpserver: deny" line. If that bothers you
+  (eg. you have a strict log parsers), don't apply that chunk of the patch.
+
+- the idea for this patch came from my previous experience with xinetd, and
+  need to limit incoming bursts of virus/spam SMTP connections, since I was
+  running qmail-scanner to scan incoming and outgoing messages for viruses
+  and spam.
+
+When you make changes, please check that they work as expected. 
+
+Examples (for tcprules created .cdb)
+(a) 192.168.:allow,MAXLOAD="1000"
+    :allow,MAXCONNIP="3"
+
+    this would allow any connection from your local LAN (192.168.*.*
+    addresses) if system load is less than 10.00. non-LAN connections would
+    be accepted only if clients from that IP address have not already opened
+    more than 2 connections (as your connection would be last allowed -- 3rd)
+
+(b) 192.168.:allow
+    5.6.7.8:allow,MAXCONNIP="3"
+    1.2.:allow,MAXLOAD="500",MAXCONNIP="1",MAXCONNC="5"
+    :allow,MAXLOAD="1000",MAXCONNIP="3",DIEMSG="421 example.com unavailable"
+
+    if client connects from 192.168.*.* (ex: your LAN), it is allowed.
+    if it connects from 5.6.7.8 (ex: little abusive customer of yours),
+     it is allowed unless there are already 3active connections from 5.6.7.8
+     to this service
+    if it connects from 1.2.*.* (ex: some problematic networks which caused
+     you grief in the past) it will connect only if load is less than 5.0,
+     there is less than 5 active connections from whole C class
+     (1.2.*.0/24), and if that specific IP address does not already have
+     connection open.
+    in all other cases, the client will be permitted to connect if load is
+     less than 10.00 and client has 2 or less connections open. If load is
+     higher than 10.00 or there are 3 or more connections open from this
+     client, the message "421 example.com unavailable" will be returned to 
+     the client and connection terminated.
+
+
+Any bugs introduced are ours, do not bother DJB with them.
+If you find any, or have neat ideas, or better documentation, or whatever,
+contact me.
+
+the 2006-01-26 version of the patch can be found at:
+http://linux.voyager.hr/ucspi-tcp/
+
+the 2007-12-22 version of the patch can be found at:
+http://qmail.jms1.net/ucspi-tcp/
+
+Enjoy,
+Matija Nalis < mnalis-tcpserver _at_ voyager.hr >
+John Simpson <jms1 at jms1.net> (2007-12-22 version)


Property changes on: trunk/dports/net/ucspi-tcp/files/LIMITS.TXT
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/dports/net/ucspi-tcp/files/patch-tcpserver.c.diff
===================================================================
--- trunk/dports/net/ucspi-tcp/files/patch-tcpserver.c.diff	                        (rev 0)
+++ trunk/dports/net/ucspi-tcp/files/patch-tcpserver.c.diff	2009-01-27 07:48:43 UTC (rev 46009)
@@ -0,0 +1,323 @@
+diff -ruN tcpserver.c.orig tcpserver.c
+--- tcpserver.c.orig	2000-03-18 10:18:42.000000000 -0500
++++ tcpserver.c	2007-12-22 02:41:24.000000000 -0500
+@@ -1,6 +1,14 @@
++#ifdef __dietlibc__
++#define NO_GETLOADAVG
++#endif
++
+ #include <sys/types.h>
+ #include <sys/param.h>
+ #include <netdb.h>
++#include <stdlib.h>
++#ifdef NO_GETLOADAVG
++#include <unistd.h>
++#endif
+ #include "uint16.h"
+ #include "str.h"
+ #include "byte.h"
+@@ -28,6 +36,18 @@
+ #include "sig.h"
+ #include "dns.h"
+ 
++
++#ifdef SOLARIS
++#include <kstat.h>
++static kstat_ctl_t   *kc;
++#ifndef FSCALE
++#define FSHIFT  8               /* bits to right of fixed binary point */
++#define FSCALE  (1<<FSHIFT)
++#endif /* FSCALE */
++
++#define loaddouble(la) ((double)(la) / FSCALE)
++#endif
++
+ int verbosity = 1;
+ int flagkillopts = 1;
+ int flagdelay = 1;
+@@ -59,11 +79,22 @@
+ static stralloc tmp;
+ static stralloc fqdn;
+ static stralloc addresses;
++static stralloc diemsg_buf;
++static stralloc diemsg2_buf;
++static stralloc diemsg3_buf;
++static stralloc diemsg4_buf;
+ 
+ char bspace[16];
+ buffer b;
+ 
+ 
++typedef struct
++{
++  char ip[4];
++  pid_t pid;
++} baby;
++
++baby *child;
+ 
+ /* ---------------------------- child */
+ 
+@@ -72,6 +103,13 @@
+ int flagdeny = 0;
+ int flagallownorules = 0;
+ char *fnrules = 0;
++unsigned long maxload = 0;
++long maxconnip = -1;
++long maxconnc = -1;
++char *diemsg = "";
++char *diemsg2 = "";
++char *diemsg3 = "";
++char *diemsg4 = "";
+ 
+ void drop_nomem(void)
+ {
+@@ -110,6 +148,8 @@
+   strerr_die4sys(111,DROP,"unable to read ",fnrules,": ");
+ }
+ 
++unsigned long limit = 40;
++
+ void found(char *data,unsigned int datalen)
+ {
+   unsigned int next0;
+@@ -125,6 +165,29 @@
+ 	if (data[1 + split] == '=') {
+ 	  data[1 + split] = 0;
+ 	  env(data + 1,data + 1 + split + 1);
++	  if (str_diff(data+1, "MAXLOAD") == 0) scan_ulong(data+1+split+1,&maxload);
++	  if (str_diff(data+1, "MAXCONNIP") == 0) scan_ulong(data+1+split+1,&maxconnip);
++	  if (str_diff(data+1, "MAXCONNC") == 0) scan_ulong(data+1+split+1,&maxconnc);
++	  if (str_diff(data+1, "DIEMSG") == 0) {
++	    if (!stralloc_copys(&diemsg_buf,data+1+split+1)) drop_nomem();
++	    if (!stralloc_0(&diemsg_buf)) drop_nomem();
++	    diemsg = diemsg_buf.s;
++	  }
++	  if (str_diff(data+1, "DIEMSG_MAXLOAD") == 0) {
++	    if (!stralloc_copys(&diemsg2_buf,data+1+split+1)) drop_nomem();
++	    if (!stralloc_0(&diemsg2_buf)) drop_nomem();
++	    diemsg2 = diemsg2_buf.s;
++	  }
++	  if (str_diff(data+1, "DIEMSG_MAXCONNIP") == 0) {
++	    if (!stralloc_copys(&diemsg3_buf,data+1+split+1)) drop_nomem();
++	    if (!stralloc_0(&diemsg3_buf)) drop_nomem();
++	    diemsg3 = diemsg3_buf.s;
++	  }
++	  if (str_diff(data+1, "DIEMSG_MAXCONNC") == 0) {
++	    if (!stralloc_copys(&diemsg4_buf,data+1+split+1)) drop_nomem();
++	    if (!stralloc_0(&diemsg4_buf)) drop_nomem();
++	    diemsg4 = diemsg4_buf.s;
++	  }
+ 	}
+ 	break;
+     }
+@@ -133,9 +196,53 @@
+   }
+ }
+ 
++unsigned long getprocla(void)
++{
++#ifdef SOLARIS
++  kstat_t       *ksp;
++  kstat_named_t *knp;
++  double lavg;
++  kstat_chain_update(kc);
++  ksp = kstat_lookup(kc, "unix", 0, "system_misc");
++  kstat_read(kc,ksp,NULL);
++  knp = kstat_data_lookup(ksp,"avenrun_1min");
++  lavg = loaddouble(knp->value.ui32);
++  return (unsigned long)(lavg * 100);
++#else
++#ifdef NO_GETLOADAVG
++  int lret;
++  int i;
++  unsigned long u1, u2;
++  char *s;
++  static stralloc loadavg_data = {0};
++
++  lret = openreadclose("/proc/loadavg", &loadavg_data, 10);
++  if (lret != -1) {
++    /* /proc/loadavg format is:
++     * 13.08 3.04 1.00 34/170 14190 */
++    s = loadavg_data.s;
++    i = scan_ulong (s, &u1); s+=i;
++    if ((i>0) && (i<5) && (*s == '.')) { /* load should be < 10000 */
++      i = scan_ulong (s+1,&u2);
++      if (i==2) { /* we require two decimal places */
++        return (u1 * 100 + u2);
++      }
++      return (u1 * 100);
++    }
++  }
++#else
++  double result;
++  if (getloadavg(&result, 1) == 1) {
++    return (result * 100);
++  }
++#endif
++#endif
++}
++
+ void doit(int t)
+ {
+   int j;
++  unsigned long curload = 0;
+ 
+   remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0;
+ 
+@@ -211,6 +318,26 @@
+     }
+   }
+ 
++  if (maxload) {
++    curload = getprocla();
++    if (curload > maxload) flagdeny = 2;
++  }
++  
++  if (!flagdeny && (maxconnip != -1 || maxconnc != -1)) {
++  	unsigned long u;
++  	long c1=0, cc=0;
++  	for (u=0; u < limit; u++) if (child[u].pid != 0) { 
++  		if ((child[u].ip[0] == remoteip[0]) &&
++  		    (child[u].ip[1] == remoteip[1]) &&
++  		    (child[u].ip[2] == remoteip[2]) ) {
++  		    cc++;
++  		    if (child[u].ip[3] == remoteip[3]) c1++;
++  		}
++  	}
++	if (maxconnc != -1 && (cc >= maxconnc)) flagdeny = 4;
++	if (maxconnip != -1 && (c1 >= maxconnip)) flagdeny = 3;
++  }
++
+   if (verbosity >= 2) {
+     strnum[fmt_ulong(strnum,getpid())] = 0;
+     if (!stralloc_copys(&tmp,"tcpserver: ")) drop_nomem();
+@@ -223,11 +350,38 @@
+     cats(":"); safecats(remoteipstr);
+     cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s);
+     cats(":"); safecats(remoteportstr);
++    if (flagdeny == 2) {
++    	char curloadstr[FMT_ULONG];
++    	curloadstr[fmt_ulong(curloadstr,curload)] = 0;
++    	cats(" "); safecats ("MAXLOAD"); cats(":"); safecats(curloadstr);
++    }
++    if (flagdeny == 3) {
++    	char maxconstr[FMT_ULONG];
++    	maxconstr[fmt_ulong(maxconstr,maxconnip)] = 0;
++    	cats(" "); safecats ("MAXCONNIP"); cats(":"); safecats(maxconstr);
++    }
++    if (flagdeny == 4) {
++    	char maxconstr[FMT_ULONG];
++    	maxconstr[fmt_ulong(maxconstr,maxconnc)] = 0;
++    	cats(" "); safecats ("MAXCONNC"); cats(":"); safecats(maxconstr);
++    }
+     cats("\n");
+     buffer_putflush(buffer_2,tmp.s,tmp.len);
+   }
+ 
+-  if (flagdeny) _exit(100);
++  if (flagdeny) {
++    if ((flagdeny==2) && *diemsg2) diemsg = diemsg2;
++    if ((flagdeny==3) && *diemsg3) diemsg = diemsg3;
++    if ((flagdeny==4) && *diemsg4) diemsg = diemsg4;
++    if (*diemsg) {
++      buffer_init(&b,write,t,bspace,sizeof bspace);
++      buffer_puts(&b,diemsg);
++      if (buffer_putsflush(&b,"\r\n") == -1)
++        strerr_die2sys(111,DROP,"unable to print diemsg: ");
++    }
++    sleep(1);
++    _exit(100);
++  }
+ }
+ 
+ 
+@@ -253,7 +407,6 @@
+   _exit(100);
+ }
+ 
+-unsigned long limit = 40;
+ unsigned long numchildren = 0;
+ 
+ int flag1 = 0;
+@@ -278,6 +431,7 @@
+ {
+   int wstat;
+   int pid;
++  unsigned long u;
+  
+   while ((pid = wait_nohang(&wstat)) > 0) {
+     if (verbosity >= 2) {
+@@ -286,6 +440,8 @@
+       strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0);
+     }
+     if (numchildren) --numchildren; printstatus();
++    for (u=0; u < limit; u++) if (child[u].pid == pid) { child[u].pid = 0; break; }
++    if (u == limit) strerr_die1x(111,"tcpserver: ERROR: dead child not found?!"); /* never happens */
+   }
+ }
+ 
+@@ -299,6 +455,7 @@
+   unsigned long u;
+   int s;
+   int t;
++  pid_t pid;
+  
+   while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof)
+     switch(opt) {
+@@ -332,6 +489,14 @@
+   argc -= optind;
+   argv += optind;
+ 
++  x = env_get("MAXLOAD"); if (x) scan_ulong(x,&maxload);
++  x = env_get("MAXCONNIP"); if (x) scan_ulong(x,&maxconnip);
++  x = env_get("MAXCONNC"); if (x) scan_ulong(x,&maxconnc);
++  x = env_get("DIEMSG"); if (x) diemsg = x;
++  x = env_get("DIEMSG_MAXLOAD"); if (x) diemsg2 = x;
++  x = env_get("DIEMSG_MAXCONNIP"); if (x) diemsg3 = x;
++  x = env_get("DIEMSG_MAXCONNC"); if (x) diemsg4 = x;
++  
+   if (!verbosity)
+     buffer_2->fd = -1;
+  
+@@ -352,6 +517,10 @@
+   }
+ 
+   if (!*argv) usage();
++  
++  child = calloc(sizeof(baby),limit);
++  if (!child)
++    strerr_die2x(111,FATAL,"out of memory for MAXCONNIP tracking");
+  
+   sig_block(sig_child);
+   sig_catch(sig_child,sigchld);
+@@ -393,6 +562,9 @@
+  
+   close(0);
+   close(1);
++  #ifdef SOLARIS
++  kc = kstat_open();
++  #endif  
+   printstatus();
+  
+   for (;;) {
+@@ -405,7 +577,7 @@
+     if (t == -1) continue;
+     ++numchildren; printstatus();
+  
+-    switch(fork()) {
++    switch(pid=fork()) {
+       case 0:
+         close(s);
+         doit(t);
+@@ -420,6 +592,10 @@
+       case -1:
+         strerr_warn2(DROP,"unable to fork: ",&strerr_sys);
+         --numchildren; printstatus();
++        break;
++      default:
++        for (u=0; u < limit; u++) if (child[u].pid == 0) { byte_copy(child[u].ip,4,remoteip); child[u].pid = pid; break; }
++	if (u == limit) strerr_die1x(111,"tcpserver: ERROR: no empty space for new child?!"); /* never happens */
+     }
+     close(t);
+   }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20090126/831c4dd4/attachment-0001.html>


More information about the macports-changes mailing list