1diff -uNr linux.orig/include/linux/netfilter_ipv4/ipt_fuzzy.h linux/include/linux/netfilter_ipv4/ipt_fuzzy.h 2--- linux.orig/include/linux/netfilter_ipv4/ipt_fuzzy.h Wed Dec 31 21:00:00 1969 3+++ linux/include/linux/netfilter_ipv4/ipt_fuzzy.h Fri Aug 23 20:47:16 2002 4@@ -0,0 +1,21 @@ 5+#ifndef _IPT_FUZZY_H 6+#define _IPT_FUZZY_H 7+ 8+#include <linux/param.h> 9+#include <linux/types.h> 10+ 11+#define MAXFUZZYRATE 10000000 12+#define MINFUZZYRATE 3 13+ 14+struct ipt_fuzzy_info { 15+ u_int32_t minimum_rate; 16+ u_int32_t maximum_rate; 17+ u_int32_t packets_total; 18+ u_int32_t bytes_total; 19+ u_int32_t previous_time; 20+ u_int32_t present_time; 21+ u_int32_t mean_rate; 22+ u_int8_t acceptance_rate; 23+}; 24+ 25+#endif /*_IPT_FUZZY_H*/ 26diff -uNr linux.orig/net/ipv4/netfilter/ipt_fuzzy.c linux/net/ipv4/netfilter/ipt_fuzzy.c 27--- linux.orig/net/ipv4/netfilter/ipt_fuzzy.c Wed Dec 31 21:00:00 1969 28+++ linux/net/ipv4/netfilter/ipt_fuzzy.c Fri Aug 23 20:47:16 2002 29@@ -0,0 +1,190 @@ 30+/* 31+ * This module implements a simple TSK FLC 32+ * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims 33+ * to limit , in an adaptive and flexible way , the packet rate crossing 34+ * a given stream . It serves as an initial and very simple (but effective) 35+ * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks. 36+ * As a matter of fact , Fuzzy Logic can help us to insert any "behavior" 37+ * into our code in a precise , adaptive and efficient manner. 38+ * The goal is very similar to that of "limit" match , but using techniques of 39+ * Fuzzy Control , that allow us to shape the transfer functions precisely , 40+ * avoiding over and undershoots - and stuff like that . 41+ * 42+ * 43+ * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version. 44+ * 2002-08-17 : Changed to eliminate floating point operations . 45+ * 2002-08-23 : Coding style changes . 46+*/ 47+ 48+#include <linux/module.h> 49+#include <linux/skbuff.h> 50+#include <linux/ip.h> 51+#include <linux/random.h> 52+#include <net/tcp.h> 53+#include <linux/spinlock.h> 54+#include <linux/netfilter_ipv4/ip_tables.h> 55+#include <linux/netfilter_ipv4/ipt_fuzzy.h> 56+ 57+/* 58+ Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH 59+ Expressed in percentage 60+*/ 61+ 62+#define PAR_LOW 0.01 63+#define PAR_HIGH 1 64+ 65+static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ; 66+ 67+MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>"); 68+MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module"); 69+MODULE_LICENSE("GPL"); 70+ 71+static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi) 72+{ 73+ if (tx >= maxi) return 100; 74+ 75+ if (tx <= mini) return 0; 76+ 77+ return ( (100*(tx-mini)) / (maxi-mini) ) ; 78+} 79+ 80+static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi) 81+{ 82+ if (tx <= mini) return 100; 83+ 84+ if (tx >= maxi) return 0; 85+ 86+ return ( (100*( maxi - tx )) / ( maxi - mini ) ) ; 87+ 88+} 89+ 90+static int 91+ipt_fuzzy_match(const struct sk_buff *pskb, 92+ const struct net_device *in, 93+ const struct net_device *out, 94+ const void *matchinfo, 95+ int offset, 96+ const void *hdr, 97+ u_int16_t datalen, 98+ int *hotdrop) 99+{ 100+ /* From userspace */ 101+ 102+ struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo; 103+ 104+ u_int8_t random_number; 105+ unsigned long amount ; 106+ u_int8_t howhigh , howlow ; 107+ 108+ 109+ spin_lock_bh(&fuzzy_lock) ; /* Rise the lock */ 110+ 111+ info->bytes_total += pskb->len ; 112+ info->packets_total++ ; 113+ 114+ info->present_time = jiffies ; 115+ 116+ if ( info->present_time >= info->previous_time ) 117+ amount = info->present_time - info->previous_time ; 118+ else { 119+ /* There was a transition : I choose to re-sample 120+ and keep the old acceptance rate... 121+ */ 122+ 123+ amount = 0 ; 124+ info->previous_time = info->present_time ; 125+ info->bytes_total = info->packets_total = 0; 126+ }; 127+ 128+ if ( amount > HZ/10 ) /* More than 100 ms elapsed ... */ 129+ { 130+ 131+ info->mean_rate = (u_int32_t) ( ( HZ * info->packets_total ) \ 132+ / amount ) ; 133+ 134+ info->previous_time = info->present_time ; 135+ info->bytes_total = info->packets_total = 0 ; 136+ 137+ howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate); 138+ howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate); 139+ 140+ info->acceptance_rate = (u_int8_t) \ 141+ ( PAR_LOW*howhigh + PAR_HIGH*howlow ) ; 142+ 143+ /* In fact , the above defuzzification would require a denominator 144+ proportional to (howhigh+howlow) but , in this particular case , 145+ that expression is constant . 146+ An imediate consequence is that it isn't necessary to call 147+ both mf_high and mf_low - but to keep things understandable , 148+ I did so . 149+ */ 150+ 151+ } 152+ 153+ spin_unlock_bh(&fuzzy_lock) ; /* Release the lock */ 154+ 155+ 156+ if ( info->acceptance_rate < 100 ) 157+ { 158+ get_random_bytes((void *)(&random_number), 1); 159+ 160+ /* If within the acceptance , it can pass => don't match */ 161+ if ( random_number <= 2.55 * info->acceptance_rate ) 162+ return 0 ; 163+ else 164+ return 1; /* It can't pass ( It matches ) */ 165+ } ; 166+ 167+ return 0; /* acceptance_rate == 100 % => Everything passes ... */ 168+ 169+} 170+ 171+static int 172+ipt_fuzzy_checkentry(const char *tablename, 173+ const struct ipt_ip *e, 174+ void *matchinfo, 175+ unsigned int matchsize, 176+ unsigned int hook_mask) 177+{ 178+ 179+ const struct ipt_fuzzy_info *info = matchinfo; 180+ 181+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) { 182+ printk("ipt_fuzzy: matchsize %u != %u\n", matchsize, 183+ IPT_ALIGN(sizeof(struct ipt_fuzzy_info))); 184+ return 0; 185+ } 186+ 187+if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE) 188+ || (info->minimum_rate >= info->maximum_rate )) 189+ { 190+ printk("ipt_fuzzy: BAD limits , please verify !!!\n"); 191+ return 0; 192+ } 193+ 194+ return 1; 195+} 196+ 197+static struct ipt_match ipt_fuzzy_reg = { 198+ {NULL, NULL}, 199+ "fuzzy", 200+ ipt_fuzzy_match, 201+ ipt_fuzzy_checkentry, 202+ NULL, 203+ THIS_MODULE }; 204+ 205+static int __init init(void) 206+{ 207+ if (ipt_register_match(&ipt_fuzzy_reg)) 208+ return -EINVAL; 209+ 210+ return 0; 211+} 212+ 213+static void __exit fini(void) 214+{ 215+ ipt_unregister_match(&ipt_fuzzy_reg); 216+} 217+ 218+module_init(init); 219+module_exit(fini); 220