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 #include #include +#include +#ifdef NO_GETLOADAVG +#include +#endif #include "uint16.h" #include "str.h" #include "byte.h" @@ -28,6 +36,18 @@ #include "sig.h" #include "dns.h" + +#ifdef SOLARIS +#include +static kstat_ctl_t *kc; +#ifndef FSCALE +#define FSHIFT 8 /* bits to right of fixed binary point */ +#define FSCALE (1< 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); }