[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