1 diff -uNr linux-2.6.4-rc1/include/linux.orig/netfilter_ipv4/ipt_ipp2p.h linux-2.6.4-rc1/include/linux/netfilter_ipv4/ipt_ipp2p.h
2 --- linux-2.6.4-rc1/include/linux.orig/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.4-rc1/include/linux/netfilter_ipv4/ipt_ipp2p.h 2004-03-03 04:06:59.299251608 +0100
7 +#define IPP2P_VERSION "0.5a"
13 +#endif //__IPT_IPP2P_H
14 diff -uNr linux-2.6.4-rc1/net/ipv4.orig/netfilter/ipt_ipp2p.c linux-2.6.4-rc1/net/ipv4/netfilter/ipt_ipp2p.c
15 --- linux-2.6.4-rc1/net/ipv4.orig/netfilter/ipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
16 +++ linux-2.6.4-rc1/net/ipv4/netfilter/ipt_ipp2p.c 2004-03-03 04:06:59.311249784 +0100
18 +#include <linux/kernel.h>
19 +#include <linux/module.h>
20 +#include <linux/skbuff.h>
21 +#include <linux/netfilter_ipv4.h>
22 +#include <linux/netfilter_ipv4/ip_tables.h>
23 +#include <linux/ip.h>
24 +#include <asm/uaccess.h>
25 +#include <linux/spinlock.h>
27 +#include <linux/netfilter_ipv4/ipt_ipp2p.h>
29 +#define get_u16(X,O) (*(__u16 *)(X + O))
31 +MODULE_AUTHOR("Eicke Friedrich");
32 +MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
33 +MODULE_LICENSE("GPL");
35 +/*Search for appleJuice commands*/
37 +search_apple (unsigned char *haystack, int packet_len, int head_len)
39 + unsigned char *t = haystack;
42 + if ((memcmp(t, "ajprot", 6) == 0) && (t[6] == 0x0d) && (t[7] == 0x0a)) return 1;
48 +/*Search for BitTorrent commands*/
50 +search_bittorrent (unsigned char *haystack, int head_len)
53 + unsigned char *t = haystack;
54 + if (*(haystack+head_len) != 0x13) return 0; //Bail out of first byte != 0x13
58 + if (memcmp(t, "BitTorrent protocol", 19) == 0) return 1;
65 +/*check for Kazaa get command*/
67 +search_kazaa (unsigned char *haystack, int packet_len, int head_len)
69 + unsigned char *t = haystack;
71 + if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;
74 + if (memcmp(t, "GET /.hash=", 11) == 0)
81 +/*check for gnutella get command*/
83 +search_gnu (unsigned char *haystack, int packet_len, int head_len)
85 + unsigned char *t = haystack;
87 + if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;
90 + if (memcmp(t, "GET /get/", 9) == 0) return 1;
91 + if (memcmp(t, "GET /uri-res/", 13) == 0) return 1;
97 +/*check for gnutella get commands and other typical data*/
99 +search_all_gnu (unsigned char *haystack, int packet_len, int head_len)
101 + unsigned char *t = haystack;
104 + if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;
108 + if (memcmp(t, "GNUTELLA CONNECT/", 17) == 0) return 1;
109 + if (memcmp(t, "GNUTELLA/", 9) == 0) return 1;
111 + if ((memcmp(t, "GET /get/", 9) == 0) || (memcmp(t, "GET /uri-res/", 13) == 0))
115 + while (c < packet_len - 22)
125 + if ( memcmp(t, "X-Gnutella-", 11) == 0 ) return 1;
140 +/*check for KaZaA download commands and other typical data*/
142 +search_all_kazaa (unsigned char *haystack, int packet_len, int head_len)
144 + unsigned char *t = haystack;
147 + if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;
150 + if (memcmp(t, "GIVE ", 5) == 0) return 1;
152 + if (memcmp(t, "GET /.hash=", 11) == 0)
156 + while (c < packet_len - 22)
166 + if ( memcmp(t, "UserAgent:", 10) == 0 ) return 1;
180 +/*fast check for edonkey file segment transfer command*/
182 +search_edk (unsigned char *haystack, int head_len)
184 + if (*(haystack+head_len) != 0xe3)
188 + if (*(haystack+head_len+5) == 0x47)
197 +/*intensive but slow search for some edonkey packets incl. size-check*/
199 +search_all_edk (unsigned char *haystack, int packet_len, int head_len)
201 + unsigned char *t = haystack;
204 +//Comment the next lines to turn OFF debug information
206 + if (*(haystack+head_len) == 0xc5) //search for additional eMule packets
209 + cmd = get_u16(t, 1);
211 + if (cmd == (packet_len - head_len - 5))
213 + if (t[5] == 0x01) return 1;
214 + if (t[5] == 0x02) return 1;
215 + if (t[5] == 0x60) return 1;
216 + if (t[5] == 0x81) return 1;
217 + if (t[5] == 0x82) return 1;
218 + if (t[5] == 0x85) return 1;
219 + if (t[5] == 0x86) return 1;
220 + if (t[5] == 0x87) return 1;
221 + if (t[5] == 0x40) return 1;
222 +// 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);
226 +/* if (cmd > packet_len - head_len - 5)
228 + if (t[cmd+5] == 0xe3)
230 + 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);
233 + if (t[cmd+5] == 0xc5)
235 + 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);
244 + if (*(haystack+head_len) != 0xe3)
249 + cmd = get_u16(t, 1);
250 + if (cmd == (packet_len - head_len - 5))
253 + if (t[0] == 0x01) return 1; //Client: hello or Server:hello
254 + if (t[0] == 0x50) return 1; //Client: file status
255 + if (t[0] == 0x16) return 1; //Client: search
256 + if (t[0] == 0x58) return 1; //Client: file request
257 + if (t[0] == 0x48) return 1; //???
258 + if (t[0] == 0x54) return 1; //???
259 + if (t[0] == 0x47) return 1; //Client: file segment request
260 + if (t[0] == 0x46) return 1; //Client: download segment
261 + if (t[0] == 0x4c) return 1; //Client: Hello-Answer
262 + if (t[0] == 0x4f) return 1; //Client: file status request
263 + if (t[0] == 0x59) return 1; //Client: file request answer
264 + if (t[0] == 0x65) return 1; //Client: ???
265 + if (t[0] == 0x66) return 1; //Client: ???
266 + if (t[0] == 0x51) return 1; //Client: ???
267 + if (t[0] == 0x52) return 1; //Client: ???
268 + if (t[0] == 0x4d) return 1; //Client: ???
269 + if (t[0] == 0x5c) return 1; //Client: ???
270 + if (t[0] == 0x38) return 1; //Client: ???
271 + if (t[0] == 0x69) return 1; //Client: ???
272 + if (t[0] == 0x19) return 1; //Client: ???
273 + if (t[0] == 0x42) return 1; //Client: ???
274 + if (t[0] == 0x34) return 1; //Client: ???
275 + if (t[0] == 0x94) return 1; //Client: ???
276 +//Comment the next line to turn OFF debug information
277 +// printk("IPP2P.search_all_edk: size (%i) ok, no match (%x)\n", packet_len, t[0]);
282 + if (cmd > packet_len - head_len - 5)
284 + if ((t[3] == 0x00) && (t[4] == 0x00))
286 + if (t[5] == 0x01) return 1;
287 + if (t[5] == 0x4c) return 1;
292 + if (t[cmd+5] == 0xe3) return 1; //found another edk-command
293 + if (t[cmd+5] == 0xc5) return 1; //found an emule-command
294 +//Comment the next line to turn OFF debug information
295 +// 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],
296 +// 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]);
303 +/*fast check for Direct Connect send command*/
305 +search_dc (unsigned char *haystack, int packet_len, int head_len)
307 + unsigned char *t = haystack;
309 + if (*(haystack+head_len) != 0x24 )
314 + if (memcmp(t, "Send|", 5) == 0)
323 +/*intensive but slower check for all direct connect packets*/
325 +search_all_dc (unsigned char *haystack, int packet_len, int head_len)
327 + unsigned char *t = haystack;
329 + if ((*(haystack + head_len) == 0x24) && (*(haystack + packet_len - 1) == 0x7c))
332 + if (memcmp(t, "Lock ", 5) == 0) return 1; //hub: hello
333 + if (memcmp(t, "Key ", 4) == 0) return 1; //client: hello
334 + if (memcmp(t, "Hello ", 6) == 0) return 1; //hub:connected
335 + if (memcmp(t, "MyNick ", 7) == 0) return 1; //client-client: hello
336 + if (memcmp(t, "Search ", 7) == 0) return 1; //client: search
337 + if (memcmp(t, "Send", 4) == 0) return 1; //client: start download
338 +//Comment the next line to turn OFF debug information
339 +// 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]);
351 +match(const struct sk_buff *skb,
352 + const struct net_device *in,
353 + const struct net_device *out,
354 + const void *matchinfo,
358 + const struct ipt_p2p_info *info = matchinfo;
359 + unsigned char *haystack;
360 + struct iphdr *ip = skb->nh.iph;
361 + int p2p_result = 0;
364 + int hlen = ntohs(ip->tot_len)-(ip->ihl*4); //hlen = packet-data length
365 + haystack=(char *)ip+(ip->ihl*4); //haystack = packet data
368 + if (((*(haystack+13)) & 1) == 1) return 0; //if FIN bit is set bail out
369 + if (((*(haystack+13)) & 2) == 2) return 0; //if SYN bit is set bail out
370 + if (((*(haystack+13)) & 4) == 4) return 0; //if RST bit is set bail out
373 + head_len = (*(haystack+12))/4; //get TCP-Header-Size
376 + if (((info->cmd & 8) == 8) || ((info->cmd & 4) == 4)) //cmd: kazaa-data || ipp2p-data
380 + p2p_result = search_kazaa(haystack, hlen, head_len);
381 + if (p2p_result == 1) return p2p_result;
387 + if (((info->cmd & 2) == 2) || ((info->cmd & 1) == 1)) //cmd: edk || ipp2p
391 + p2p_result = search_all_edk(haystack, hlen, head_len);
392 + if (p2p_result == 1) return p2p_result;
399 + if (((info->cmd & 16) == 16) || ((info->cmd & 4) == 4)) //cmd: edk-data || ipp2p-data
403 + p2p_result = search_edk(haystack, head_len);
404 + if (p2p_result == 1) return p2p_result;
408 + if (((info->cmd & 32) == 32) || ((info->cmd & 4) == 4)) //cmd: dc-data || ipp2p-data
412 + p2p_result = search_dc(haystack, hlen, head_len);
413 + if (p2p_result == 1) return p2p_result;
417 + if (((info->cmd & 64) == 64) || ((info->cmd & 1) == 1)) //cmd: dc || ipp2p
421 + p2p_result = search_all_dc(haystack, hlen, head_len);
422 + if (p2p_result == 1) return p2p_result;
426 + if (((info->cmd & 128) == 128) || ((info->cmd & 4) == 4)) //cmd: gnu-data || ipp2p-data
430 + p2p_result = search_gnu(haystack, hlen, head_len);
431 + if (p2p_result == 1) return p2p_result;
435 + if (((info->cmd & 256) == 256) || ((info->cmd & 1) == 1)) //cmd: gnu || ipp2p
439 + p2p_result = search_all_gnu(haystack, hlen, head_len);
440 + if (p2p_result == 1) return p2p_result;
445 + if (((info->cmd & 1) == 1) || ((info->cmd & 512) == 512)) //cmd: ipp2p || kazaa
449 + p2p_result = search_all_kazaa(haystack, hlen, head_len);
450 + if (p2p_result == 1) return p2p_result;
456 + if ((info->cmd & 1024) == 1024) //cmd: bit
460 + p2p_result = search_bittorrent(haystack, head_len);
461 + if (p2p_result == 1) return p2p_result;
466 + if ((info->cmd & 2048) == 2048) //cmd: apple
470 + p2p_result = search_apple(haystack, hlen, head_len);
471 + if (p2p_result == 1) return p2p_result;
483 +checkentry(const char *tablename,
484 + const struct ipt_ip *ip,
486 + unsigned int matchsize,
487 + unsigned int hook_mask)
489 + /* Must specify -p tcp */
490 + if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
491 + printk("ipp2p: Only works on TCP packets, use -p tcp\n");
502 +static struct ipt_match ipp2p_match
506 + .checkentry = &checkentry,
511 +static int __init init(void)
513 + return ipt_register_match(&ipp2p_match);
516 +static void __exit fini(void)
518 + ipt_unregister_match(&ipp2p_match);
525 diff -uNr linux-2.6.4-rc1/net/ipv4.orig/netfilter/Kconfig linux-2.6.4-rc1/net/ipv4/netfilter/Kconfig
526 --- linux-2.6.4-rc1/net/ipv4.orig/netfilter/Kconfig 2004-03-03 03:58:03.000000000 +0100
527 +++ linux-2.6.4-rc1/net/ipv4/netfilter/Kconfig 2004-03-03 04:06:59.300251456 +0100
530 To compile it as a module, choose M here. If unsure, say N.
532 +config IP_NF_MATCH_IPP2P
533 + tristate "IPP2P match support"
534 + depends on IP_NF_IPTABLES
536 + IPP2P allows you to match certain packets of some popular
537 + peer-to-peer networks. Use it to drop packets or mark them
538 + for further use (with CONNMARK for example).
540 + To compile it as a module, choose M here. If unsure, say N.
542 config IP_NF_MATCH_OWNER
543 tristate "Owner match support"
544 depends on IP_NF_IPTABLES
545 diff -uNr linux-2.6.4-rc1/net/ipv4.orig/netfilter/Makefile linux-2.6.4-rc1/net/ipv4/netfilter/Makefile
546 --- linux-2.6.4-rc1/net/ipv4.orig/netfilter/Makefile 2004-03-03 04:01:17.000000000 +0100
547 +++ linux-2.6.4-rc1/net/ipv4/netfilter/Makefile 2004-03-03 04:08:22.720569640 +0100
549 obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
550 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
551 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
552 +obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
553 obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
555 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o