1 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ipp2p.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ipp2p.h
2 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ipp2p.h 2003-12-11 00:02:06.929074768 +0100
7 +#define IPP2P_VERSION "0.5a"
13 +#endif //__IPT_IPP2P_H
14 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ipp2p.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_ipp2p.c
15 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
16 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ipp2p.c 2003-12-11 00:02:06.930074616 +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,
360 + const struct ipt_p2p_info *info = matchinfo;
361 + unsigned char *haystack;
362 + struct iphdr *ip = skb->nh.iph;
363 + int p2p_result = 0;
366 + int hlen = ntohs(ip->tot_len)-(ip->ihl*4); //hlen = packet-data length
367 + haystack=(char *)ip+(ip->ihl*4); //haystack = packet data
370 + if (((*(haystack+13)) & 1) == 1) return 0; //if FIN bit is set bail out
371 + if (((*(haystack+13)) & 2) == 2) return 0; //if SYN bit is set bail out
372 + if (((*(haystack+13)) & 4) == 4) return 0; //if RST bit is set bail out
375 + head_len = (*(haystack+12))/4; //get TCP-Header-Size
378 + if (((info->cmd & 8) == 8) || ((info->cmd & 4) == 4)) //cmd: kazaa-data || ipp2p-data
382 + p2p_result = search_kazaa(haystack, hlen, head_len);
383 + if (p2p_result == 1) return p2p_result;
389 + if (((info->cmd & 2) == 2) || ((info->cmd & 1) == 1)) //cmd: edk || ipp2p
393 + p2p_result = search_all_edk(haystack, hlen, head_len);
394 + if (p2p_result == 1) return p2p_result;
401 + if (((info->cmd & 16) == 16) || ((info->cmd & 4) == 4)) //cmd: edk-data || ipp2p-data
405 + p2p_result = search_edk(haystack, head_len);
406 + if (p2p_result == 1) return p2p_result;
410 + if (((info->cmd & 32) == 32) || ((info->cmd & 4) == 4)) //cmd: dc-data || ipp2p-data
414 + p2p_result = search_dc(haystack, hlen, head_len);
415 + if (p2p_result == 1) return p2p_result;
419 + if (((info->cmd & 64) == 64) || ((info->cmd & 1) == 1)) //cmd: dc || ipp2p
423 + p2p_result = search_all_dc(haystack, hlen, head_len);
424 + if (p2p_result == 1) return p2p_result;
428 + if (((info->cmd & 128) == 128) || ((info->cmd & 4) == 4)) //cmd: gnu-data || ipp2p-data
432 + p2p_result = search_gnu(haystack, hlen, head_len);
433 + if (p2p_result == 1) return p2p_result;
437 + if (((info->cmd & 256) == 256) || ((info->cmd & 1) == 1)) //cmd: gnu || ipp2p
441 + p2p_result = search_all_gnu(haystack, hlen, head_len);
442 + if (p2p_result == 1) return p2p_result;
447 + if (((info->cmd & 1) == 1) || ((info->cmd & 512) == 512)) //cmd: ipp2p || kazaa
451 + p2p_result = search_all_kazaa(haystack, hlen, head_len);
452 + if (p2p_result == 1) return p2p_result;
458 + if ((info->cmd & 1024) == 1024) //cmd: bit
462 + p2p_result = search_bittorrent(haystack, head_len);
463 + if (p2p_result == 1) return p2p_result;
468 + if ((info->cmd & 2048) == 2048) //cmd: apple
472 + p2p_result = search_apple(haystack, hlen, head_len);
473 + if (p2p_result == 1) return p2p_result;
485 +checkentry(const char *tablename,
486 + const struct ipt_ip *ip,
488 + unsigned int matchsize,
489 + unsigned int hook_mask)
491 + /* Must specify -p tcp */
492 + if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
493 + printk("ipp2p: Only works on TCP packets, use -p tcp\n");
504 +static struct ipt_match ipp2p_match
514 +static int __init init(void)
516 + return ipt_register_match(&ipp2p_match);
519 +static void __exit fini(void)
521 + ipt_unregister_match(&ipp2p_match);
528 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/Makefile linux-2.6.0-test11/net/ipv4/netfilter/Makefile
529 --- linux-2.6.0-test11.org/net/ipv4/netfilter/Makefile 2003-12-10 23:24:46.000000000 +0100
530 +++ linux-2.6.0-test11/net/ipv4/netfilter/Makefile 2003-12-11 00:02:07.013062000 +0100
532 obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
534 obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
535 +obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
538 obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
539 --- linux-2.6.0-test11.org/net/ipv4/netfilter/Kconfig 2003-12-10 23:13:25.000000000 +0100
540 +++ linux-2.6.0-test11/net/ipv4/netfilter/Kconfig 2003-12-11 00:20:03.590397368 +0100
543 To compile it as a module, choose M here. If unsure, say N.
545 +config IP_NF_MATCH_IPP2P
546 + tristate ' IPP2P match support (EXPERIMENTAL)'
547 + depends on IP_NF_IPTABLES
549 + IPP2P allows you to match certain packets of some popular
550 + peer-to-peer networks. Use it to drop packets or mark them
551 + for further use (with CONNMARK for example).
553 + If you want to compile it as a module, say M here and read
554 + Documentation/modules.txt. If unsure, say `N'.