diff -u -U 2 -r -N -d linux-2.6.0-test11.orig/include/linux/netfilter_ipv4/ipt_ipp2p.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ipp2p.h
--- linux-2.6.0-test11.orig/include/linux/netfilter_ipv4/ipt_ipp2p.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ipp2p.h	2003-12-07 11:44:45.000000000 +0000
@@ -0,0 +1,9 @@
+#ifndef __IPT_IPP2P_H
+#define __IPT_IPP2P_H
+#define IPP2P_VERSION "0.5a"
+
+struct ipt_p2p_info {
+    int cmd;    
+};
+
+#endif //__IPT_IPP2P_H
Binary files linux-2.6.0-test11.orig/net/ipv4/netfilter/.ipt_ipp2p.c.swp and linux-2.6.0-test11/net/ipv4/netfilter/.ipt_ipp2p.c.swp differ
diff -u -U 2 -r -N -d linux-2.6.0-test11.orig/net/ipv4/netfilter/Kconfig linux-2.6.0-test11/net/ipv4/netfilter/Kconfig
--- linux-2.6.0-test11.orig/net/ipv4/netfilter/Kconfig	2003-11-30 20:43:52.000000000 +0000
+++ linux-2.6.0-test11/net/ipv4/netfilter/Kconfig	2003-12-07 12:26:19.000000000 +0000
@@ -256,6 +256,16 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_MATCH_IPP2P
+	tristate "IPP2P match support"
+	depends on IP_NF_IPTABLES
+	help
+	  IPP2P allows you to match certain packets of some popular
+	  peer-to-peer networks. Use it to drop packets or mark them
+	  for further use (with CONNMARK for example).
+	  
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config IP_NF_MATCH_OWNER
 	tristate "Owner match support"
 	depends on IP_NF_IPTABLES
diff -u -U 2 -r -N -d linux-2.6.0-test11.orig/net/ipv4/netfilter/Makefile linux-2.6.0-test11/net/ipv4/netfilter/Makefile
--- linux-2.6.0-test11.orig/net/ipv4/netfilter/Makefile	2003-11-30 20:43:52.000000000 +0000
+++ linux-2.6.0-test11/net/ipv4/netfilter/Makefile	2003-12-07 12:26:19.000000000 +0000
@@ -63,6 +63,7 @@
 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
+obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
 
 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
 
diff -u -U 2 -r -N -d linux-2.6.0-test11.orig/net/ipv4/netfilter/ipt_ipp2p.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_ipp2p.c
--- linux-2.6.0-test11.orig/net/ipv4/netfilter/ipt_ipp2p.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ipp2p.c	2003-12-07 12:13:46.000000000 +0000
@@ -0,0 +1,507 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/ip.h>
+#include <asm/uaccess.h>
+#include <linux/spinlock.h>
+
+#include <linux/netfilter_ipv4/ipt_ipp2p.h>
+
+#define get_u16(X,O)  (*(__u16 *)(X + O))
+
+MODULE_AUTHOR("Eicke Friedrich");
+MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
+MODULE_LICENSE("GPL");
+
+/*Search for appleJuice commands*/
+int
+search_apple (unsigned char *haystack, int packet_len, int head_len)
+{
+    unsigned char *t = haystack;
+    t += head_len;
+    
+    if ((memcmp(t, "ajprot", 6) == 0) && (t[6] == 0x0d) && (t[7] == 0x0a))  return 1;            
+    
+    return 0;
+}
+
+
+/*Search for BitTorrent commands*/
+int
+search_bittorrent (unsigned char *haystack, int head_len)
+{
+
+    unsigned char *t = haystack;
+    if (*(haystack+head_len) != 0x13) return 0; //Bail out of first byte != 0x13
+    
+    t += head_len + 1;
+    
+    if (memcmp(t, "BitTorrent protocol", 19) == 0) return 1;        
+
+    return 0;
+}
+
+
+
+/*check for Kazaa get command*/
+int
+search_kazaa (unsigned char *haystack, int packet_len, int head_len)
+{
+    unsigned char *t = haystack;
+
+    if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;    
+
+    t += head_len;
+    if (memcmp(t, "GET /.hash=", 11) == 0)
+	return 1;
+    else
+	return 0;
+}
+
+
+/*check for gnutella get command*/
+int
+search_gnu (unsigned char *haystack, int packet_len, int head_len)
+{
+    unsigned char *t = haystack;
+
+    if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;    
+
+    t += head_len;
+    if (memcmp(t, "GET /get/", 9) == 0)	return 1;
+    if (memcmp(t, "GET /uri-res/", 13) == 0) return 1; 
+    
+    return 0;
+}
+
+
+/*check for gnutella get commands and other typical data*/
+int
+search_all_gnu (unsigned char *haystack, int packet_len, int head_len)
+{
+    unsigned char *t = haystack;
+    int c;    
+
+    if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;
+
+    t += head_len;
+
+    if (memcmp(t, "GNUTELLA CONNECT/", 17) == 0) return 1;        
+    if (memcmp(t, "GNUTELLA/", 9) == 0) return 1;    
+
+    if ((memcmp(t, "GET /get/", 9) == 0) || (memcmp(t, "GET /uri-res/", 13) == 0))
+    {        
+        c = head_len + 8;
+	t += 8;
+	while (c < packet_len - 22)
+	{
+	    if (t[0] == 0x0d)
+	    {
+		t++;
+		c++;
+		if (t[0] == 0x0a)
+		{
+		    t++;
+		    c++;
+    		    if ( memcmp(t, "X-Gnutella-", 11) == 0 ) return 1;
+		}
+	    }
+	    else
+	    {
+		t++;
+		c++;
+	    }    
+	}
+    }
+    
+    return 0;
+}
+
+
+/*check for KaZaA download commands and other typical data*/
+int
+search_all_kazaa (unsigned char *haystack, int packet_len, int head_len)
+{
+    unsigned char *t = haystack;
+    int c;    
+
+    if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;
+
+    t += head_len;
+    if (memcmp(t, "GIVE ", 5) == 0) return 1;    
+    
+    if (memcmp(t, "GET /.hash=", 11) == 0)
+    {
+        c = head_len + 8;
+	t += 8;
+	while (c < packet_len - 22)
+	{
+	    if (t[0] == 0x0d)
+	    {
+		t++;
+		c++;
+		if (t[0] == 0x0a)
+		{
+		    t++;
+		    c++;
+    		    if ( memcmp(t, "UserAgent:", 10) == 0 ) return 1;
+		}
+	    }
+	    else
+	    {
+		t++;
+		c++;
+	    }    
+	}
+    }
+    
+    return 0;
+}
+
+/*fast check for edonkey file segment transfer command*/
+int
+search_edk (unsigned char *haystack, int head_len)
+{
+    if (*(haystack+head_len) != 0xe3) 
+	return 0;
+    else
+    {
+	if (*(haystack+head_len+5) == 0x47) 
+	    return 1;
+	else 	
+	    return 0;
+    }
+}
+
+
+
+/*intensive but slow search for some edonkey packets incl. size-check*/
+int
+search_all_edk (unsigned char *haystack, int packet_len, int head_len)
+{
+    unsigned char *t = haystack;
+    int cmd;
+    
+//Comment the next lines to turn OFF debug information    
+//debug starts here
+    if (*(haystack+head_len) == 0xc5) //search for additional eMule packets
+    {
+	t += head_len;	
+	cmd = get_u16(t, 1);	
+
+	if (cmd == (packet_len - head_len - 5))
+	{
+	    if (t[5] == 0x01) return 1;	
+	    if (t[5] == 0x02) return 1;		    	    
+	    if (t[5] == 0x60) return 1;
+	    if (t[5] == 0x81) return 1;
+	    if (t[5] == 0x82) return 1;	    
+	    if (t[5] == 0x85) return 1;	    
+	    if (t[5] == 0x86) return 1;
+	    if (t[5] == 0x87) return 1;
+	    if (t[5] == 0x40) return 1;
+//	    printk("IPP2P.search_all_edk: new eMule match: %x %x %x %x %x %x (size %i ok)\n", t[0], t[1], t[2], t[3], t[4], t[5], packet_len);
+	    return 0;
+	}
+	
+/*	if (cmd > packet_len - head_len - 5)
+	{
+	    if (t[cmd+5] == 0xe3)
+	    {
+		printk("IPP2P.search_all_edk: new eMule match with second eDonkey match: %x %x %x %x %x %x (packet: %i)\n", t[0], t[1], t[2], t[3], t[4], t[5], packet_len);
+		return 0;
+	    }
+	    if (t[cmd+5] == 0xc5)
+	    {
+		printk("IPP2P.search_all_edk: new eMule match with second eDonkey match: %x %x %x %x %x %x (packet: %i)\n", t[0], t[1], t[2], t[3], t[4], t[5], packet_len);
+		return 0;
+	    }
+	}*/
+	return 0;
+    }
+//debug ends here    
+
+
+    if (*(haystack+head_len) != 0xe3) 
+	return 0;
+    else
+    {
+	t += head_len;	
+	cmd = get_u16(t, 1);	
+	if (cmd == (packet_len - head_len - 5)) 
+	{
+	    t += 5;
+	    if (t[0] == 0x01) return 1;	//Client: hello or Server:hello
+	    if (t[0] == 0x50) return 1;	//Client: file status
+	    if (t[0] == 0x16) return 1;	//Client: search
+	    if (t[0] == 0x58) return 1;	//Client: file request
+	    if (t[0] == 0x48) return 1;	//???
+	    if (t[0] == 0x54) return 1;	//???	    	    
+	    if (t[0] == 0x47) return 1;	//Client: file segment request
+	    if (t[0] == 0x46) return 1; //Client: download segment	    
+	    if (t[0] == 0x4c) return 1;	//Client: Hello-Answer
+	    if (t[0] == 0x4f) return 1;	//Client: file status request
+	    if (t[0] == 0x59) return 1;	//Client: file request answer
+	    if (t[0] == 0x65) return 1;	//Client: ???
+	    if (t[0] == 0x66) return 1;	//Client: ??? 	    
+	    if (t[0] == 0x51) return 1;	//Client: ??? 	    	    
+	    if (t[0] == 0x52) return 1;	//Client: ??? 	    	        
+	    if (t[0] == 0x4d) return 1;	//Client: ??? 	    
+	    if (t[0] == 0x5c) return 1;	//Client: ??? 	    
+	    if (t[0] == 0x38) return 1;	//Client: ??? 	    
+	    if (t[0] == 0x69) return 1;	//Client: ??? 	    	    
+	    if (t[0] == 0x19) return 1;	//Client: ??? 	    	    
+	    if (t[0] == 0x42) return 1;	//Client: ??? 	    
+	    if (t[0] == 0x34) return 1;	//Client: ???
+	    if (t[0] == 0x94) return 1;	//Client: ???	    
+//Comment the next line to turn OFF debug information	     	    	    	    
+//	    printk("IPP2P.search_all_edk: size (%i) ok, no match (%x)\n", packet_len, t[0]);
+	    return 0;	
+	}
+	else
+	{
+	    if (cmd > packet_len - head_len - 5) 
+	    {
+		if ((t[3] == 0x00) && (t[4] == 0x00))
+		{
+		    if (t[5] == 0x01) return 1;
+		    if (t[5] == 0x4c) return 1;
+		} 
+		return 0;
+		
+	    }	//non edk packet
+	    if (t[cmd+5] == 0xe3) return 1;		//found another edk-command
+	    if (t[cmd+5] == 0xc5) return 1;		//found an emule-command	    
+//Comment the next line to turn OFF debug information
+//	    printk("IPP2P.search_all_edk: size (%i vs %i) WRONG, no second match: %x %x %x %x %x %x  - %x %x %x %x %x %x\n", packet_len, cmd, t[0],
+//	    t[1], t[2], t[3], t[4], t[5], t[cmd+5], t[cmd+6], t[cmd+7], t[cmd+8], t[cmd+9], t[cmd+10]);
+	    return 0;
+	}
+    }
+}
+
+
+/*fast check for Direct Connect send command*/
+int
+search_dc (unsigned char *haystack, int packet_len, int head_len)
+{
+    unsigned char *t = haystack;
+
+    if (*(haystack+head_len) != 0x24 ) 
+	return 0;
+    else
+    {
+	t += head_len + 1;
+        if (memcmp(t, "Send|", 5) == 0)
+	    return 1;
+	else
+	    return 0;
+    }	
+
+}
+
+
+/*intensive but slower check for all direct connect packets*/
+int
+search_all_dc (unsigned char *haystack, int packet_len, int head_len)
+{
+    unsigned char *t = haystack;
+
+    if ((*(haystack + head_len) == 0x24) && (*(haystack + packet_len - 1) == 0x7c)) 
+    {
+    	t += head_len + 1;
+	if (memcmp(t, "Lock ", 5) == 0)	 return 1;	//hub: hello
+	if (memcmp(t, "Key ", 4) == 0)	 return 1;	//client: hello
+	if (memcmp(t, "Hello ", 6) == 0) return 1;	//hub:connected
+	if (memcmp(t, "MyNick ", 7) == 0) return 1;	//client-client: hello
+	if (memcmp(t, "Search ", 7) == 0) return 1;	//client: search
+	if (memcmp(t, "Send", 4) == 0)	 return 1;	//client: start download
+//Comment the next line to turn OFF debug information	
+//	printk("IPP2P.search_all_dc:$ %x%x%x%x%x%x%x%x%x%x |\n",t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9]);
+	return 0;
+    }
+    else
+	return 0;
+	
+
+}
+
+
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      int *hotdrop)
+{
+    const struct ipt_p2p_info *info = matchinfo;
+    unsigned char  *haystack;
+    struct iphdr *ip = skb->nh.iph;
+    int p2p_result = 0;
+    int head_len;
+
+    int hlen = ntohs(ip->tot_len)-(ip->ihl*4);	//hlen = packet-data length    
+    haystack=(char *)ip+(ip->ihl*4);		//haystack = packet data    
+
+
+    if (((*(haystack+13)) & 1) == 1) return 0;  //if FIN bit is set bail out
+    if (((*(haystack+13)) & 2) == 2) return 0;  //if SYN bit is set bail out
+    if (((*(haystack+13)) & 4) == 4) return 0;  //if RST bit is set bail out
+	    
+
+    head_len = (*(haystack+12))/4; //get TCP-Header-Size
+
+    
+    if (((info->cmd & 8) == 8) || ((info->cmd & 4) == 4))	//cmd: kazaa-data || ipp2p-data
+    {
+	if (hlen > 200)
+	{
+	    p2p_result = search_kazaa(haystack, hlen, head_len);
+	    if (p2p_result == 1) return p2p_result;
+	}
+	
+    }
+	
+
+    if (((info->cmd & 2) == 2) || ((info->cmd & 1) == 1))	//cmd: edk || ipp2p
+    {
+	if (hlen > 40)
+	{	
+	    p2p_result = search_all_edk(haystack, hlen, head_len);
+	    if (p2p_result == 1) return p2p_result;	    
+	}
+    }
+    
+    
+    	    
+
+    if (((info->cmd & 16) == 16) || ((info->cmd & 4) == 4))	//cmd: edk-data || ipp2p-data
+    {
+	if (hlen > 60)
+	{	
+	    p2p_result = search_edk(haystack, head_len);
+	    if (p2p_result == 1) return p2p_result;	    	
+	}
+    }
+
+    if (((info->cmd & 32) == 32) || ((info->cmd & 4) == 4))	//cmd: dc-data || ipp2p-data
+    {
+	if (hlen == 26)
+	{
+	    p2p_result = search_dc(haystack, hlen, head_len);
+	    if (p2p_result == 1) return p2p_result;	    
+	}    
+    }
+
+    if (((info->cmd & 64) == 64) || ((info->cmd & 1) == 1))	//cmd: dc || ipp2p
+    {
+	if (hlen > 25)
+	{
+	    p2p_result = search_all_dc(haystack, hlen, head_len);
+	    if (p2p_result == 1) return p2p_result;	    
+	}    
+    }
+    
+    if (((info->cmd & 128) == 128) || ((info->cmd & 4) == 4))	//cmd: gnu-data || ipp2p-data
+    {
+	if (hlen > 40)
+	{
+	    p2p_result = search_gnu(haystack, hlen, head_len);
+	    if (p2p_result == 1) return p2p_result;	    
+	}    
+    }
+    
+    if (((info->cmd & 256) == 256) || ((info->cmd & 1) == 1))	//cmd: gnu || ipp2p
+    {
+	if (hlen > 35)
+	{
+	    p2p_result = search_all_gnu(haystack, hlen, head_len);
+	    if (p2p_result == 1) return p2p_result;	    
+	}    
+    }
+
+
+    if (((info->cmd & 1) == 1) || ((info->cmd & 512) == 512))	//cmd:  ipp2p || kazaa
+    {
+	if (hlen > 35)
+	{
+	    p2p_result = search_all_kazaa(haystack, hlen, head_len);
+	    if (p2p_result == 1) return p2p_result;	    
+	}    
+    }
+
+
+
+    if ((info->cmd & 1024) == 1024)				//cmd:  bit
+    {
+	if (hlen > 40)
+	{
+	    p2p_result = search_bittorrent(haystack, head_len);
+	    if (p2p_result == 1) return p2p_result;	    
+	}    
+    }
+
+
+    if ((info->cmd & 2048) == 2048)				//cmd:  apple
+    {
+	if (hlen > 20)
+	{
+	    p2p_result = search_apple(haystack, hlen, head_len);
+	    if (p2p_result == 1) return p2p_result;	    
+	}    
+    }
+
+
+    return p2p_result;
+}
+								  
+
+
+
+static int
+checkentry(const char *tablename,
+            const struct ipt_ip *ip,
+	    void *matchinfo,
+	    unsigned int matchsize,
+	    unsigned int hook_mask)
+{
+        /* Must specify -p tcp */
+    if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
+	printk("ipp2p: Only works on TCP packets, use -p tcp\n");
+	return 0;
+    }
+							
+
+    return 1;
+}
+									    
+
+
+
+static struct ipt_match ipp2p_match
+= { 
+	.name		= "ipp2p", 
+	.match		= &match, 
+	.checkentry	= &checkentry, 
+	.me		= THIS_MODULE
+};
+
+
+static int __init init(void)
+{
+    return ipt_register_match(&ipp2p_match);
+}
+	
+static void __exit fini(void)
+{
+    ipt_unregister_match(&ipp2p_match);
+}
+	
+module_init(init);
+module_exit(fini);
+
+
