• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/net/ipv4/netfilter/
1#if defined(MODVERSIONS)
2#include <linux/modversions.h>
3#endif
4#include <linux/module.h>
5#include <linux/version.h>
6#include <linux/netfilter_ipv4/ip_tables.h>
7#include <linux/netfilter_ipv4/ipt_ipp2p.h>
8#include <net/tcp.h>
9#include <net/udp.h>
10
11#define get_u8(X,O)  (*(__u8 *)(X + O))
12#define get_u16(X,O)  (*(__u16 *)(X + O))
13#define get_u32(X,O)  (*(__u32 *)(X + O))
14
15MODULE_AUTHOR("Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>");
16MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
17MODULE_LICENSE("GPL");
18
19/*Search for UDP eDonkey/eMule/Kad commands*/
20int udp_search_edk(unsigned char *haystack, int packet_len)
21{
22	unsigned char *t = haystack;
23	t += 8;
24
25	switch (t[0]) {
26	case 0xe3:
27		{		/*edonkey */
28			switch (t[1]) {
29				/* client -> server status request */
30			case 0x96:
31				if (packet_len == 14)
32					return ((IPP2P_EDK * 100) + 50);
33				break;
34				/* server -> client status request */
35			case 0x97:
36				if (packet_len == 42)
37					return ((IPP2P_EDK * 100) + 51);
38				break;
39				/* server description request */
40				/* e3 2a ff f0 .. | size == 6 */
41			case 0xa2:
42				if ((packet_len == 14) && (get_u16(t, 2) == __constant_htons(0xfff0)))
43					return ((IPP2P_EDK * 100) + 52);
44				break;
45				/* server description response */
46				/* e3 a3 ff f0 ..  | size > 40 && size < 200 */
47				//case 0xa3: return ((IPP2P_EDK * 100) + 53);
48				//      break;
49			case 0x9a:
50				if (packet_len == 26)
51					return ((IPP2P_EDK * 100) + 54);
52				break;
53
54			case 0x92:
55				if (packet_len == 18)
56					return ((IPP2P_EDK * 100) + 55);
57				break;
58			}
59			break;
60		}
61	case 0xe4:
62		{
63			switch (t[1]) {
64				/* e4 20 .. | size == 43 */
65			case 0x20:
66				if ((packet_len == 43) && (t[2] != 0x00) && (t[34] != 0x00))
67					return ((IPP2P_EDK * 100) + 60);
68				break;
69				/* e4 00 .. 00 | size == 35 ? */
70			case 0x00:
71				if ((packet_len == 35) && (t[26] == 0x00))
72					return ((IPP2P_EDK * 100) + 61);
73				break;
74				/* e4 10 .. 00 | size == 35 ? */
75			case 0x10:
76				if ((packet_len == 35) && (t[26] == 0x00))
77					return ((IPP2P_EDK * 100) + 62);
78				break;
79				/* e4 18 .. 00 | size == 35 ? */
80			case 0x18:
81				if ((packet_len == 35) && (t[26] == 0x00))
82					return ((IPP2P_EDK * 100) + 63);
83				break;
84				/* e4 52 .. | size = 44 */
85			case 0x52:
86				if (packet_len == 44)
87					return ((IPP2P_EDK * 100) + 64);
88				break;
89				/* e4 58 .. | size == 6 */
90			case 0x58:
91				if (packet_len == 14)
92					return ((IPP2P_EDK * 100) + 65);
93				break;
94				/* e4 59 .. | size == 2 */
95			case 0x59:
96				if (packet_len == 10)
97					return ((IPP2P_EDK * 100) + 66);
98				break;
99				/* e4 28 .. | packet_len == 52,77,102,127... */
100			case 0x28:
101				if (((packet_len - 52) % 25) == 0)
102					return ((IPP2P_EDK * 100) + 67);
103				break;
104				/* e4 50 xx xx | size == 4 */
105			case 0x50:
106				if (packet_len == 12)
107					return ((IPP2P_EDK * 100) + 68);
108				break;
109				/* e4 40 xx xx | size == 48 */
110			case 0x40:
111				if (packet_len == 56)
112					return ((IPP2P_EDK * 100) + 69);
113				break;
114			}
115			break;
116		}
117	}			/* end of switch (t[0]) */
118	return 0;
119}				/*udp_search_edk */
120
121/*Search for UDP Gnutella commands*/
122int udp_search_gnu(unsigned char *haystack, int packet_len)
123{
124	unsigned char *t = haystack;
125	t += 8;
126
127	if (memcmp(t, "GND", 3) == 0)
128		return ((IPP2P_GNU * 100) + 51);
129	if (memcmp(t, "GNUTELLA ", 9) == 0)
130		return ((IPP2P_GNU * 100) + 52);
131	return 0;
132}				/*udp_search_gnu */
133
134/*Search for UDP KaZaA commands*/
135int udp_search_kazaa(unsigned char *haystack, int packet_len)
136{
137	unsigned char *t = haystack;
138
139	if (t[packet_len - 1] == 0x00) {
140		t += (packet_len - 6);
141		if (memcmp(t, "KaZaA", 5) == 0)
142			return (IPP2P_KAZAA * 100 + 50);
143	}
144
145	return 0;
146}				/*udp_search_kazaa */
147
148/*Search for UDP DirectConnect commands*/
149int udp_search_directconnect(unsigned char *haystack, int packet_len)
150{
151	unsigned char *t = haystack;
152	if ((*(t + 8) == 0x24) && (*(t + packet_len - 1) == 0x7c)) {
153		t += 8;
154		if (memcmp(t, "SR ", 3) == 0)
155			return ((IPP2P_DC * 100) + 60);
156		if (memcmp(t, "Ping ", 5) == 0)
157			return ((IPP2P_DC * 100) + 61);
158	}
159	return 0;
160}				/*udp_search_directconnect */
161
162/*Search for UDP BitTorrent commands*/
163int udp_search_bit(unsigned char *haystack, int packet_len)
164{
165	switch (packet_len) {
166	case 24:
167		/* ^ 00 00 04 17 27 10 19 80 */
168		if ((ntohl(get_u32(haystack, 8)) == 0x00000417) && (ntohl(get_u32(haystack, 12)) == 0x27101980))
169			return (IPP2P_BIT * 100 + 50);
170		break;
171	case 44:
172		if (get_u32(haystack, 16) == __constant_htonl(0x00000400)
173		    && get_u32(haystack, 36) == __constant_htonl(0x00000104))
174			return (IPP2P_BIT * 100 + 51);
175		if (get_u32(haystack, 16) == __constant_htonl(0x00000400))
176			return (IPP2P_BIT * 100 + 61);
177		break;
178	case 65:
179		if (get_u32(haystack, 16) == __constant_htonl(0x00000404)
180		    && get_u32(haystack, 36) == __constant_htonl(0x00000104))
181			return (IPP2P_BIT * 100 + 52);
182		if (get_u32(haystack, 16) == __constant_htonl(0x00000404))
183			return (IPP2P_BIT * 100 + 62);
184		break;
185	case 67:
186		if (get_u32(haystack, 16) == __constant_htonl(0x00000406)
187		    && get_u32(haystack, 36) == __constant_htonl(0x00000104))
188			return (IPP2P_BIT * 100 + 53);
189		if (get_u32(haystack, 16) == __constant_htonl(0x00000406))
190			return (IPP2P_BIT * 100 + 63);
191		break;
192	case 211:
193		if (get_u32(haystack, 8) == __constant_htonl(0x00000405))
194			return (IPP2P_BIT * 100 + 54);
195		break;
196	case 29:
197		if ((get_u32(haystack, 8) == __constant_htonl(0x00000401)))
198			return (IPP2P_BIT * 100 + 55);
199		break;
200	case 52:
201		if (get_u32(haystack, 8) == __constant_htonl(0x00000827) &&
202		    get_u32(haystack, 12) == __constant_htonl(0x37502950))
203			return (IPP2P_BIT * 100 + 80);
204		break;
205	default:
206		/* this packet does not have a constant size */
207		if (packet_len >= 40 && get_u32(haystack, 16) == __constant_htonl(0x00000402)
208		    && get_u32(haystack, 36) == __constant_htonl(0x00000104))
209			return (IPP2P_BIT * 100 + 56);
210		break;
211	}
212
213	/* some extra-bitcomet rules:
214	 * "d1:" [a|r] "d2:id20:"
215	 */
216	if (packet_len > 30 && get_u8(haystack, 8) == 'd' && get_u8(haystack, 9) == '1' && get_u8(haystack, 10) == ':') {
217		if (get_u8(haystack, 11) == 'a' || get_u8(haystack, 11) == 'r') {
218			if (memcmp(haystack + 12, "d2:id20:", 8) == 0)
219				return (IPP2P_BIT * 100 + 57);
220		}
221	}
222
223	return 0;
224}				/*udp_search_bit */
225
226/*Search for Ares commands*/
227//#define IPP2P_DEBUG_ARES
228int search_ares(const unsigned char *payload, const u16 plen)
229//int search_ares (unsigned char *haystack, int packet_len, int head_len)
230{
231//      const unsigned char *t = haystack + head_len;
232
233	/* all ares packets start with  */
234	if (payload[1] == 0 && (plen - payload[0]) == 3) {
235		switch (payload[2]) {
236		case 0x5a:
237			/* ares connect */
238			if (plen == 6 && payload[5] == 0x05)
239				return ((IPP2P_ARES * 100) + 1);
240			break;
241		case 0x09:
242			/* ares search, min 3 chars --> 14 bytes
243			 * lets define a search can be up to 30 chars --> max 34 bytes
244			 */
245			if (plen >= 14 && plen <= 34)
246				return ((IPP2P_ARES * 100) + 1);
247			break;
248#ifdef IPP2P_DEBUG_ARES
249		default:
250			printk(KERN_DEBUG "Unknown Ares command %x recognized, len: %u \n", (unsigned int)payload[2], plen);
251#endif /* IPP2P_DEBUG_ARES */
252		}
253	}
254
255	return 0;
256}				/*search_ares */
257
258/*Search for SoulSeek commands*/
259int search_soul(const unsigned char *payload, const u16 plen)
260{
261//#define IPP2P_DEBUG_SOUL
262	/* match: xx xx xx xx | xx = sizeof(payload) - 4 */
263	if (get_u32(payload, 0) == (plen - 4)) {
264		const __u32 m = get_u32(payload, 4);
265		/* match 00 yy yy 00, yy can be everything */
266		if (get_u8(payload, 4) == 0x00 && get_u8(payload, 7) == 0x00) {
267#ifdef IPP2P_DEBUG_SOUL
268			printk(KERN_DEBUG "0: Soulseek command 0x%x recognized\n", get_u32(payload, 4));
269#endif /* IPP2P_DEBUG_SOUL */
270			return ((IPP2P_SOUL * 100) + 1);
271		}
272
273		/* next match: 01 yy 00 00 | yy can be everything */
274		if (get_u8(payload, 4) == 0x01 && get_u16(payload, 6) == 0x0000) {
275#ifdef IPP2P_DEBUG_SOUL
276			printk(KERN_DEBUG "1: Soulseek command 0x%x recognized\n", get_u16(payload, 4));
277#endif /* IPP2P_DEBUG_SOUL */
278			return ((IPP2P_SOUL * 100) + 2);
279		}
280
281		/* other soulseek commandos are: 1-5,7,9,13-18,22,23,26,28,35-37,40-46,50,51,60,62-69,91,92,1001 */
282		/* try to do this in an intelligent way */
283		/* get all small commandos */
284		switch (m) {
285		case 7:
286		case 9:
287		case 22:
288		case 23:
289		case 26:
290		case 28:
291		case 50:
292		case 51:
293		case 60:
294		case 91:
295		case 92:
296		case 1001:
297#ifdef IPP2P_DEBUG_SOUL
298			printk(KERN_DEBUG "2: Soulseek command 0x%x recognized\n", get_u16(payload, 4));
299#endif /* IPP2P_DEBUG_SOUL */
300			return ((IPP2P_SOUL * 100) + 3);
301		}
302
303		if (m > 0 && m < 6) {
304#ifdef IPP2P_DEBUG_SOUL
305			printk(KERN_DEBUG "3: Soulseek command 0x%x recognized\n", get_u16(payload, 4));
306#endif /* IPP2P_DEBUG_SOUL */
307			return ((IPP2P_SOUL * 100) + 4);
308		}
309		if (m > 12 && m < 19) {
310#ifdef IPP2P_DEBUG_SOUL
311			printk(KERN_DEBUG "4: Soulseek command 0x%x recognized\n", get_u16(payload, 4));
312#endif /* IPP2P_DEBUG_SOUL */
313			return ((IPP2P_SOUL * 100) + 5);
314		}
315
316		if (m > 34 && m < 38) {
317#ifdef IPP2P_DEBUG_SOUL
318			printk(KERN_DEBUG "5: Soulseek command 0x%x recognized\n", get_u16(payload, 4));
319#endif /* IPP2P_DEBUG_SOUL */
320			return ((IPP2P_SOUL * 100) + 6);
321		}
322
323		if (m > 39 && m < 47) {
324#ifdef IPP2P_DEBUG_SOUL
325			printk(KERN_DEBUG "6: Soulseek command 0x%x recognized\n", get_u16(payload, 4));
326#endif /* IPP2P_DEBUG_SOUL */
327			return ((IPP2P_SOUL * 100) + 7);
328		}
329
330		if (m > 61 && m < 70) {
331#ifdef IPP2P_DEBUG_SOUL
332			printk(KERN_DEBUG "7: Soulseek command 0x%x recognized\n", get_u16(payload, 4));
333#endif /* IPP2P_DEBUG_SOUL */
334			return ((IPP2P_SOUL * 100) + 8);
335		}
336#ifdef IPP2P_DEBUG_SOUL
337		printk(KERN_DEBUG "unknown SOULSEEK command: 0x%x, first 16 bit: 0x%x, first 8 bit: 0x%x ,soulseek ???\n",
338		       get_u32(payload, 4), get_u16(payload, 4) >> 16, get_u8(payload, 4) >> 24);
339#endif /* IPP2P_DEBUG_SOUL */
340	}
341
342	/* match 14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00 */
343	/* without size at the beginning !!! */
344	if (get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01) {
345		__u32 y = get_u32(payload, 5);
346		/* we need 19 chars + string */
347		if ((y + 19) <= (plen)) {
348			const unsigned char *w = payload + 9 + y;
349			if (get_u32(w, 0) == 0x01 && (get_u16(w, 4) == 0x4600 || get_u16(w, 4) == 0x5000)
350			    && get_u32(w, 6) == 0x00) ;
351#ifdef IPP2P_DEBUG_SOUL
352			printk(KERN_DEBUG "Soulssek special client command recognized\n");
353#endif /* IPP2P_DEBUG_SOUL */
354			return ((IPP2P_SOUL * 100) + 9);
355		}
356	}
357	return 0;
358}
359
360/*Search for WinMX commands*/
361int search_winmx(const unsigned char *payload, const u16 plen)
362{
363//#define IPP2P_DEBUG_WINMX
364	if (((plen) == 4) && (memcmp(payload, "SEND", 4) == 0))
365		return ((IPP2P_WINMX * 100) + 1);
366	if (((plen) == 3) && (memcmp(payload, "GET", 3) == 0))
367		return ((IPP2P_WINMX * 100) + 2);
368	//if (packet_len < (head_len + 10)) return 0;
369	if (plen < 10)
370		return 0;
371
372	if ((memcmp(payload, "SEND", 4) == 0) || (memcmp(payload, "GET", 3) == 0)) {
373		u16 c = 4;
374		const u16 end = plen - 2;
375		u8 count = 0;
376		while (c < end) {
377			if (payload[c] == 0x20 && payload[c + 1] == 0x22) {
378				c++;
379				count++;
380				if (count >= 2)
381					return ((IPP2P_WINMX * 100) + 3);
382			}
383			c++;
384		}
385	}
386
387	if (plen == 149 && payload[0] == '8') {
388#ifdef IPP2P_DEBUG_WINMX
389		printk(KERN_INFO "maybe WinMX\n");
390#endif
391		if (get_u32(payload, 17) == 0 && get_u32(payload, 21) == 0 && get_u32(payload, 25) == 0 &&
392		    get_u16(payload, 39) == 0 && get_u16(payload, 135) == __constant_htons(0x7edf)
393		    && get_u16(payload, 147) == __constant_htons(0xf792))
394		{
395#ifdef IPP2P_DEBUG_WINMX
396			printk(KERN_INFO "got WinMX\n");
397#endif
398			return ((IPP2P_WINMX * 100) + 4);
399		}
400	}
401	return 0;
402}				/*search_winmx */
403
404/*Search for appleJuice commands*/
405int search_apple(const unsigned char *payload, const u16 plen)
406{
407	if ((plen > 7) && (payload[6] == 0x0d) && (payload[7] == 0x0a) && (memcmp(payload, "ajprot", 6) == 0))
408		return (IPP2P_APPLE * 100);
409
410	return 0;
411}
412
413/*Search for BitTorrent commands*/
414int search_bittorrent(const unsigned char *payload, const u16 plen)
415{
416	if (plen > 20) {
417		/* test for match 0x13+"BitTorrent protocol" */
418		if (payload[0] == 0x13) {
419			if (memcmp(payload + 1, "BitTorrent protocol", 19) == 0)
420				return (IPP2P_BIT * 100);
421		}
422
423		/* get tracker commandos, all starts with GET /
424		 * then it can follow: scrape| announce
425		 * and then ?hash_info=
426		 */
427		if (memcmp(payload, "GET /", 5) == 0) {
428			/* message scrape */
429			if (memcmp(payload + 5, "scrape?info_hash=", 17) == 0)
430				return (IPP2P_BIT * 100 + 1);
431			/* message announce */
432			if (memcmp(payload + 5, "announce?info_hash=", 19) == 0)
433				return (IPP2P_BIT * 100 + 2);
434		}
435	} else {
436		/* bitcomet encryptes the first packet, so we have to detect another
437		 * one later in the flow */
438		/* first try failed, too many missdetections */
439		//if ( size == 5 && get_u32(t,0) == __constant_htonl(1) && t[4] < 3) return (IPP2P_BIT * 100 + 3);
440
441		/* second try: block request packets */
442		if (plen == 17 && get_u32(payload, 0) == __constant_htonl(0x0d) && payload[4] == 0x06
443		    && get_u32(payload, 13) == __constant_htonl(0x4000))
444			return (IPP2P_BIT * 100 + 3);
445	}
446
447	return 0;
448}
449
450/*check for Kazaa get command*/
451int search_kazaa(const unsigned char *payload, const u16 plen)
452{
453	if ((payload[plen - 2] == 0x0d) && (payload[plen - 1] == 0x0a) && memcmp(payload, "GET /.hash=", 11) == 0)
454		return (IPP2P_DATA_KAZAA * 100);
455
456	return 0;
457}
458
459/*check for gnutella get command*/
460int search_gnu(const unsigned char *payload, const u16 plen)
461{
462	if ((payload[plen - 2] == 0x0d) && (payload[plen - 1] == 0x0a)) {
463		if (memcmp(payload, "GET /get/", 9) == 0)
464			return ((IPP2P_DATA_GNU * 100) + 1);
465		if (memcmp(payload, "GET /uri-res/", 13) == 0)
466			return ((IPP2P_DATA_GNU * 100) + 2);
467	}
468	return 0;
469}
470
471/*check for gnutella get commands and other typical data*/
472int search_all_gnu(const unsigned char *payload, const u16 plen)
473{
474
475	if ((payload[plen - 2] == 0x0d) && (payload[plen - 1] == 0x0a)) {
476
477		if (memcmp(payload, "GNUTELLA CONNECT/", 17) == 0)
478			return ((IPP2P_GNU * 100) + 1);
479		if (memcmp(payload, "GNUTELLA/", 9) == 0)
480			return ((IPP2P_GNU * 100) + 2);
481
482		if ((memcmp(payload, "GET /get/", 9) == 0) || (memcmp(payload, "GET /uri-res/", 13) == 0)) {
483			u16 c = 8;
484			const u16 end = plen - 22;
485			while (c < end) {
486				if (payload[c] == 0x0a && payload[c + 1] == 0x0d
487				    && ((memcmp(&payload[c + 2], "X-Gnutella-", 11) == 0)
488					|| (memcmp(&payload[c + 2], "X-Queue:", 8) == 0)))
489					return ((IPP2P_GNU * 100) + 3);
490				c++;
491			}
492		}
493	}
494	return 0;
495}
496
497/*check for KaZaA download commands and other typical data*/
498int search_all_kazaa(const unsigned char *payload, const u16 plen)
499{
500	if ((payload[plen - 2] == 0x0d) && (payload[plen - 1] == 0x0a)) {
501
502		if (memcmp(payload, "GIVE ", 5) == 0)
503			return ((IPP2P_KAZAA * 100) + 1);
504
505		if (memcmp(payload, "GET /", 5) == 0) {
506			u16 c = 8;
507			const u16 end = plen - 22;
508			while (c < end) {
509				if (payload[c] == 0x0a && payload[c + 1] == 0x0d
510				    && ((memcmp(&payload[c + 2], "X-Kazaa-Username: ", 18) == 0)
511					|| (memcmp(&payload[c + 2], "User-Agent: PeerEnabler/", 24) == 0)))
512					return ((IPP2P_KAZAA * 100) + 2);
513				c++;
514			}
515		}
516	}
517	return 0;
518}
519
520/*fast check for edonkey file segment transfer command*/
521int search_edk(const unsigned char *payload, const u16 plen)
522{
523	if (payload[0] != 0xe3)
524		return 0;
525	else {
526		if (payload[5] == 0x47)
527			return (IPP2P_DATA_EDK * 100);
528		else
529			return 0;
530	}
531}
532
533/*intensive but slower search for some edonkey packets including size-check*/
534int search_all_edk(const unsigned char *payload, const u16 plen)
535{
536	if (payload[0] != 0xe3)
537		return 0;
538	else {
539		//t += head_len;
540		const u16 cmd = get_u16(payload, 1);
541		if (cmd == (plen - 5)) {
542			switch (payload[5]) {
543			case 0x01:
544				return ((IPP2P_EDK * 100) + 1);	/*Client: hello or Server:hello */
545			case 0x4c:
546				return ((IPP2P_EDK * 100) + 9);	/*Client: Hello-Answer */
547			}
548		}
549		return 0;
550	}
551}
552
553/*fast check for Direct Connect send command*/
554int search_dc(const unsigned char *payload, const u16 plen)
555{
556
557	if (payload[0] != 0x24)
558		return 0;
559	else {
560		if (memcmp(&payload[1], "Send|", 5) == 0)
561			return (IPP2P_DATA_DC * 100);
562		else
563			return 0;
564	}
565
566}
567
568/*intensive but slower check for all direct connect packets*/
569int search_all_dc(const unsigned char *payload, const u16 plen)
570{
571//    unsigned char *t = haystack;
572
573	if (payload[0] == 0x24 && payload[plen - 1] == 0x7c) {
574		const unsigned char *t = &payload[1];
575		/* Client-Hub-Protocol */
576		if (memcmp(t, "Lock ", 5) == 0)
577			return ((IPP2P_DC * 100) + 1);
578		/* Client-Client-Protocol, some are already recognized by client-hub (like lock) */
579		if (memcmp(t, "MyNick ", 7) == 0)
580			return ((IPP2P_DC * 100) + 38);
581	}
582	return 0;
583}
584
585/*check for mute*/
586int search_mute(const unsigned char *payload, const u16 plen)
587{
588	if (plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121) {
589		//printk(KERN_DEBUG "size hit: %u",size);
590		if (memcmp(payload, "PublicKey: ", 11) == 0) {
591			return ((IPP2P_MUTE * 100) + 0);
592		}
593	}
594	return 0;
595}
596
597/* check for xdcc */
598int search_xdcc(const unsigned char *payload, const u16 plen)
599{
600	/* search in small packets only */
601	if (plen > 20 && plen < 200 && payload[plen - 1] == 0x0a && payload[plen - 2] == 0x0d
602	    && memcmp(payload, "PRIVMSG ", 8) == 0) {
603
604		u16 x = 10;
605		const u16 end = plen - 13;
606
607		/* is seems to be a irc private massage, chedck for xdcc command */
608		while (x < end) {
609			if (payload[x] == ':') {
610				if (memcmp(&payload[x + 1], "xdcc send #", 11) == 0)
611					return ((IPP2P_XDCC * 100) + 0);
612			}
613			x++;
614		}
615	}
616	return 0;
617}
618
619/* search for waste */
620int search_waste(const unsigned char *payload, const u16 plen)
621{
622	if (plen >= 8 && memcmp(payload, "GET.sha1:", 9) == 0)
623		return ((IPP2P_WASTE * 100) + 0);
624
625	return 0;
626}
627
628static struct {
629	int command;
630	__u8 short_hand;	/*for fucntions included in short hands */
631	int packet_len;
632	int (*function_name) (const unsigned char *, const u16);
633} matchlist[] = {
634	{IPP2P_EDK, SHORT_HAND_IPP2P, 20, &search_all_edk},
635//	{IPP2P_DATA_KAZAA,SHORT_HAND_DATA,200, &search_kazaa},
636//	{IPP2P_DATA_EDK,SHORT_HAND_DATA,60, &search_edk},
637//	{IPP2P_DATA_DC,SHORT_HAND_DATA,26, &search_dc},
638	{IPP2P_DC, SHORT_HAND_IPP2P, 5, search_all_dc},
639//	{IPP2P_DATA_GNU,SHORT_HAND_DATA,40, &search_gnu},
640	{IPP2P_GNU, SHORT_HAND_IPP2P, 5, &search_all_gnu},
641	{IPP2P_KAZAA, SHORT_HAND_IPP2P, 5, &search_all_kazaa},
642	{IPP2P_BIT, SHORT_HAND_IPP2P, 20, &search_bittorrent},
643	{IPP2P_APPLE, SHORT_HAND_IPP2P, 5, &search_apple},
644	{IPP2P_SOUL, SHORT_HAND_IPP2P, 5, &search_soul},
645	{IPP2P_WINMX, SHORT_HAND_IPP2P, 2, &search_winmx},
646	{IPP2P_ARES, SHORT_HAND_IPP2P, 5, &search_ares},
647	{IPP2P_MUTE, SHORT_HAND_NONE, 200, &search_mute},
648	{IPP2P_WASTE, SHORT_HAND_NONE, 5, &search_waste},
649	{IPP2P_XDCC, SHORT_HAND_NONE, 5, &search_xdcc},
650	{0, 0, 0, NULL}
651};
652
653static struct {
654	int command;
655	__u8 short_hand;	/*for fucntions included in short hands */
656	int packet_len;
657	int (*function_name) (unsigned char *, int);
658} udp_list[] = {
659	{IPP2P_KAZAA, SHORT_HAND_IPP2P, 14, &udp_search_kazaa},
660	{IPP2P_BIT, SHORT_HAND_IPP2P, 23, &udp_search_bit},
661	{IPP2P_GNU, SHORT_HAND_IPP2P, 11, &udp_search_gnu},
662	{IPP2P_EDK, SHORT_HAND_IPP2P, 9, &udp_search_edk},
663	{IPP2P_DC, SHORT_HAND_IPP2P, 12, &udp_search_directconnect},
664	{0, 0, 0, NULL}
665};
666
667static bool match(const struct sk_buff *skb, struct xt_action_param *par)
668{
669	const struct ipt_p2p_info *info = par->matchinfo;
670	const int offset = par->fragoff;
671	unsigned char *haystack;
672	struct iphdr *ip = ip_hdr(skb);
673	int p2p_result = 0, i = 0;
674	int hlen = ntohs(ip->tot_len) - (ip->ihl * 4);	/*hlen = packet-data length */
675
676	/*must not be a fragment */
677	if (offset) {
678		if (info->debug)
679			printk("IPP2P.match: offset found %i \n", offset);
680		return 0;
681	}
682
683	/*make sure that skb is linear */
684	if (skb_is_nonlinear(skb)) {
685		if (info->debug)
686			printk("IPP2P.match: nonlinear skb found\n");
687		return 0;
688	}
689
690	haystack = (char *)ip + (ip->ihl * 4);	/*haystack = packet data */
691
692	switch (ip->protocol) {
693	case IPPROTO_TCP:	/*what to do with a TCP packet */
694		{
695			struct tcphdr *tcph = (void *)ip + ip->ihl * 4;
696
697			if (tcph->fin)
698				return 0;	/*if FIN bit is set bail out */
699			if (tcph->syn)
700				return 0;	/*if SYN bit is set bail out */
701			if (tcph->rst)
702				return 0;	/*if RST bit is set bail out */
703
704			haystack += tcph->doff * 4;	/*get TCP-Header-Size */
705			hlen -= tcph->doff * 4;
706			while (matchlist[i].command) {
707				if ((((info->cmd & matchlist[i].command) == matchlist[i].command) ||
708				     ((info->cmd & matchlist[i].short_hand) == matchlist[i].short_hand)) &&
709				    (hlen > matchlist[i].packet_len)) {
710					p2p_result = matchlist[i].function_name(haystack, hlen);
711					if (p2p_result) {
712						if (info->debug)
713							printk
714							    ("IPP2P.debug:TCP-match: %i from: %pI4:%i to: %pI4:%i Length: %i\n",
715							     p2p_result, &ip->saddr, ntohs(tcph->source),
716							     &ip->daddr, ntohs(tcph->dest), hlen);
717						return p2p_result;
718					}
719				}
720				i++;
721			}
722			return p2p_result;
723		}
724
725	case IPPROTO_UDP:	/*what to do with an UDP packet */
726		{
727			struct udphdr *udph = (void *)ip + ip->ihl * 4;
728
729			while (udp_list[i].command) {
730				if ((((info->cmd & udp_list[i].command) == udp_list[i].command) ||
731				     ((info->cmd & udp_list[i].short_hand) == udp_list[i].short_hand)) &&
732				    (hlen > udp_list[i].packet_len)) {
733					p2p_result = udp_list[i].function_name(haystack, hlen);
734					if (p2p_result) {
735						if (info->debug)
736							printk
737							    ("IPP2P.debug:UDP-match: %i from: %pI4:%i to: %pI4:%i Length: %i\n",
738							     p2p_result, &ip->saddr, ntohs(udph->source),
739							     &ip->daddr, ntohs(udph->dest), hlen);
740						return p2p_result;
741					}
742				}
743				i++;
744			}
745			return p2p_result;
746		}
747
748	default:
749		return 0;
750	}
751}
752
753static int checkentry(const struct xt_mtchk_param *par)
754{
755	return 0;
756}
757
758static struct xt_match ipp2p_match = {
759	.name = "ipp2p",
760	.family = AF_INET,
761	.match = &match,
762	.matchsize = sizeof(struct ipt_p2p_info),
763	.checkentry = &checkentry,
764	.me = THIS_MODULE,
765};
766
767static int __init init(void)
768{
769	printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION);
770	return xt_register_match(&ipp2p_match);
771}
772
773static void __exit fini(void)
774{
775	xt_unregister_match(&ipp2p_match);
776	printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION);
777}
778
779module_init(init);
780module_exit(fini);
781