[CODE] tcpserver完整的patch

来源:互联网 发布:余弦相似算法 编辑:程序博客网 时间:2024/05/17 06:11

可不是我一个人的,呵呵!首先是 Balazs Nagy 和他的 ucspi-tcp-0.88-periplimit.6.patch ; 然后是 qftang 和他的 frequencylimit 的 patch, 偶只是把这些弄到一起哦!

patch: ucspi-tcp-0.88-periplimit.6-frequencylimit.1.patch.txt

cvs diff -u -r1.1 tcpserver.cIndex: tcpserver.c===================================================================RCS file: /home/cvs/ucspi-tcp/tcpserver.c,vretrieving revision 1.1diff -u -r1.1 tcpserver.c--- tcpserver.c 11 Jul 2004 09:09:21 -0000      1.1+++ tcpserver.c 18 Aug 2004 09:24:52 -0000@@ -2,6 +2,7 @@ #include <sys/param.h> #include <netdb.h> #include "uint16.h"+#include "uint32.h" #include "str.h" #include "byte.h" #include "fmt.h"@@ -27,6 +28,7 @@ #include "rules.h" #include "sig.h" #include "dns.h"+#include <stdio.h>  int verbosity = 1; int flagkillopts = 1;@@ -235,6 +237,7 @@ /* ---------------------------- parent */  #define FATAL "tcpserver: fatal: "+#define MAX_IP_TIME 4096  void usage(void) {@@ -242,6 +245,8 @@ tcpserver: usage: tcpserver / [ -1UXpPhHrRoOdDqQv ] / [ -c limit ] /+[ -s perip limit ] /+[ -f max connection per ip in one minite ] / [ -x rules.cdb ] / [ -B banner ] / [ -g gid ] /@@ -254,13 +259,165 @@ }  unsigned long limit = 40;+unsigned long periplimit = 0; unsigned long numchildren = 0;+unsigned long max_freq = 20;++typedef struct+{+  pid_t pid;+  int offset;+} connections;++typedef struct+{+  uint32 ipaddr;+  unsigned long num;+} ipchildren;++typedef struct freeip_t+{+  char ip[4];+  uint32 ipaddr;+  unsigned long num;+  struct freeip_t *next;+} freeip;++typedef struct+{+  uint32 ipaddr;+  unsigned long time; +} iptime;+++connections *children;+ipchildren *numipchildren;+freeip *freeiplist = NULL;+iptime iptimebuf[MAX_IP_TIME];  int flag1 = 0; unsigned long backlog = 20; unsigned long uid = 0; unsigned long gid = 0; +void initfreeip(void)+{+    freeip *tail = NULL;+    freeip *new  = NULL;+    char tempip[4];+    uint32 tempaddr;+    char buf[BUFSIZ] = {0};+    FILE *fp;++    if (!(tail = (freeip *)malloc(sizeof(freeip))))+        strerr_die2x(111,FATAL,"out of memory");++    uint32_unpack(localip, &tail->ipaddr);+    tail->num  = 100;+    tail->next = NULL;+    freeiplist = tail;++    if (!(new = (freeip *)malloc(sizeof(freeip))))+        strerr_die2x(111,FATAL,"out of memory");++    if (ip4_scan("127.0.0.1", tempip)) {+        uint32_unpack(tempip, &new->ipaddr);+        new->num   = 100;+        new->next  = NULL;+        tail->next = new;+        tail       = tail->next;+    }++    fp = fopen("/var/qmail/control/freeip", "r");+    if (!fp) {+        strerr_die2x(111,FATAL,"can not read control file: /var/qmail/control/freeip");+    }++    while (fgets(buf, BUFSIZ, fp)) {+        if (ip4_scan(buf, tempip)) {+            uint32_unpack(tempip, &tempaddr);+            if (isfreeip(tempaddr)) +                continue;++            if (!(new = (freeip *)malloc(sizeof(freeip))))+                strerr_die2x(111,FATAL,"out of memory");++            new->ipaddr = tempaddr;+            new->num    = 100;+            new->next   = NULL;+            tail->next  = new;+            tail        = tail->next;+        }+    }+}++void dumpfreeip(void)+{+    freeip *temp = freeiplist;+    char tempip[4];+    char ipstr[IP4_FMT];+    char buf[256] = {0};+    do {+        uint32_pack(tempip, temp->ipaddr);+        ipstr[ip4_fmt(ipstr, tempip)] = 0;+        sprintf (buf, "freeip: %s, num: %d/n", ipstr, temp->num);+        write(2, buf, strlen(buf));+        temp = temp->next;+    } while (temp);+}++int isfreeip(uint32 ipaddr)+{+    freeip *temp = freeiplist;+    int isfree = 0;++    do {+        if (temp->ipaddr == ipaddr) {+            isfree = 1;+            temp   = NULL;+            break;+        }+        temp = temp->next;+    } while (temp);+    return isfree;+}++void freefreeip(void)+{+}++int isoverfrequency(uint32 ipaddr)+{+  iptime *empty_iptime = NULL;+  iptime *piptime = NULL;+  time_t now = time(0);+  int j;+  int count = 0;+  int emp_pos = 0;++  for(j=0; j<MAX_IP_TIME; j++) {+    piptime = &iptimebuf[j];+    if(!empty_iptime) {+      if( !piptime->ipaddr || piptime->time < (now - 60)) {+        empty_iptime = piptime;+        emp_pos = j;+      }+    }+    if(piptime->ipaddr == ipaddr && piptime->time > (now - 60)) {+      count ++;+      if(empty_iptime && count >= max_freq)+        break;+    }+  }++  if (!empty_iptime) empty_iptime = &iptimebuf[0];+      +  empty_iptime->ipaddr = ipaddr;+  empty_iptime->time = now;+      +  return (count >= max_freq) ? 1 : 0;+}+ void printstatus(void) {   if (verbosity < 2) return;@@ -278,6 +435,7 @@ {   int wstat;   int pid;+  int i;     while ((pid = wait_nohang(&wstat)) > 0) {     if (verbosity >= 2) {@@ -286,6 +444,12 @@       strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0);     }     if (numchildren) --numchildren; printstatus();+    for (i=0;i<limit;++i)+      if (children[i].pid == pid) {+        children[i].pid=0;+        numipchildren[children[i].offset].num--;+        break;+      }   } } @@ -300,10 +464,12 @@   int s;   int t;  -  while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof)+  while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:s:f:pPoO")) != opteof)     switch(opt) {       case 'b': scan_ulong(optarg,&backlog); break;       case 'c': scan_ulong(optarg,&limit); break;+      case 's': scan_ulong(optarg,&periplimit); break;+      case 'f': scan_ulong(optarg,&max_freq);break;       case 'X': flagallownorules = 1; break;       case 'x': fnrules = optarg; break;       case 'B': banner = optarg; break;@@ -334,6 +500,11 @@    if (!verbosity)     buffer_2->fd = -1;++  if (!periplimit)+    periplimit = limit;+  if (limit<periplimit)+    strerr_die2x(111,FATAL,"periplimit must be smaller than or equal to connection limit");     hostname = *argv++;   if (!hostname) usage();@@ -358,6 +529,13 @@   sig_catch(sig_term,sigterm);   sig_ignore(sig_pipe);  +  if (!(numipchildren = (ipchildren*)malloc(sizeof(ipchildren)*limit)))+    strerr_die2x(111,FATAL,"out of memory");+  byte_zero(numipchildren,sizeof(ipchildren)*limit);+  if (!(children = (connections*)malloc(sizeof(connections)*limit)))+    strerr_die2x(111,FATAL,"out of memory");+  byte_zero(children,sizeof(connections)*limit);+  byte_zero(iptimebuf,sizeof(iptime)*MAX_IP_TIME);    if (!stralloc_copys(&tmp,hostname))     strerr_die2x(111,FATAL,"out of memory");   if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1)@@ -390,12 +568,23 @@     buffer_puts(&b,"/n");     buffer_flush(&b);   }++  initfreeip();++  dumpfreeip();     close(0);   close(1);   printstatus();     for (;;) {+    uint32 ipaddr;+    pid_t pid;+    int i;+    int lastempty = 0;+    int freechild = 0;+    ipchildren *ipcount;+     while (numchildren >= limit) sig_pause();      sig_unblock(sig_child);@@ -403,9 +592,53 @@     sig_block(sig_child);      if (t == -1) continue;++    for (i=0;i<limit;++i) {+      if (children[i].pid == 0) {+        freechild = i;+        break;+      }+    }+    uint32_unpack(remoteip,&ipaddr);+    for (i=0;i<limit;++i) {+      ipcount = &numipchildren[i];+      if (!ipcount->ipaddr || !ipcount->num)+        lastempty = i;+      else if (ipcount->ipaddr == ipaddr) {+        ++ipcount->num;+        break;+      }+    }+    if (i == limit) {+      if (lastempty) {+        i = lastempty;+        ipcount = &numipchildren[i];+        ipcount->ipaddr = ipaddr;+        ipcount->num = 1;+      } else+        /* never reached */+        strerr_die2x(111,DROP,"internal problem");+    }+    //if (ipcount->num > periplimit) {+    if (!isfreeip(ipaddr) && (ipcount->num > periplimit)) {+      remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0;+      strerr_warn3(DROP, "per ip limit reached for ", remoteipstr, 0);+      close(t);+      --ipcount->num;+      continue;+    }+     +    if (isoverfrequency(ipaddr)) {+      remoteipstr[ip4_fmt(remoteipstr, remoteip)] = 0;+      strerr_warn3(DROP, "frequency limit reached for ", remoteipstr, 0);+      close(t);+      continue;+    }+    +     ++numchildren; printstatus();  -    switch(fork()) {+    switch(pid = fork()) {       case 0:         close(s);         doit(t);@@ -420,6 +653,10 @@       case -1:         strerr_warn2(DROP,"unable to fork: ",&strerr_sys);         --numchildren; printstatus();+        break;+      default:+       children[freechild].pid = pid;+       children[freechild].offset = i;     }     close(t);   }

patch: Makefile

diff -u -r1.2 -r1.3--- Makefile    19 Jul 2004 09:12:09 -0000      1.2+++ Makefile    9 Aug 2004 08:06:06 -0000       1.3@@ -757,7 +757,7 @@ alloc.h buffer.h error.h strerr.h sgetopt.h subgetopt.h pathexec.h / socket.h uint16.h ndelay.h remoteinfo.h stralloc.h uint16.h rules.h / stralloc.h sig.h dns.h stralloc.h iopause.h taia.h tai.h uint64.h /-taia.h+taia.h uint32.h        ./compile tcpserver.c  time.a: /
原创粉丝点击