[CODE] tcpserver完整的patch

可不是我一个人的,呵呵!首先是 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.c
Index: tcpserver.c
===================================================================
RCS file: /home/cvs/ucspi-tcp/tcpserver.c,v
retrieving revision 1.1
diff -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: /
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值