1#include <stdio.h>
2#include <netdb.h>
3#include <string.h>
4#include <stdlib.h>
5#include <getopt.h>
6#include <ctype.h>
7
8#include <iptables.h>
9
10#include <linux/netfilter_ipv4/ipt_ipp2p.h>
11
12#ifndef XTABLES_VERSION
13#define XTABLES_VERSION IPTABLES_VERSION
14#endif
15
16#ifdef IPT_LIB_DIR
17#define xtables_match iptables_match
18#define xtables_register_match register_match
19#endif
20
21static void
22help(void)
23{
24    printf(
25    "IPP2P v%s options:\n"
26    " --ipp2p	Grab all known p2p packets\n"
27    " --edk		[TCP&UDP]	All known eDonkey/eMule/Overnet packets\n"
28    " --dc		[TCP] 		All known Direct Connect packets\n"
29    " --kazaa	[TCP&UDP] 	All known KaZaA packets\n"
30    " --gnu		[TCP&UDP]	All known Gnutella packets\n"
31    " --bit		[TCP&UDP]	All known BitTorrent packets\n"
32    " --apple	[TCP] 		All known AppleJuice packets\n"
33    " --winmx	[TCP] 		All known WinMX\n"
34    " --soul		[TCP] 		All known SoulSeek\n"
35    " --ares		[TCP] 		All known Ares\n\n"
36    " EXPERIMENTAL protocols (please send feedback to: ipp2p@ipp2p.org) :\n"
37    " --mute		[TCP]		All known Mute packets\n"
38    " --waste	[TCP]		All known Waste packets\n"
39    " --xdcc		[TCP]		All known XDCC packets (only xdcc login)\n\n"
40    " DEBUG SUPPPORT, use only if you know why\n"
41    " --debug		Generate kernel debug output, THIS WILL SLOW DOWN THE FILTER\n"
42    "\nNote that the follwing options will have the same meaning:\n"
43    " '--ipp2p' is equal to '--edk --dc --kazaa --gnu --bit --apple --winmx --soul --ares'\n"
44    "\nIPP2P was intended for TCP only. Due to increasing usage of UDP we needed to change this.\n"
45    "You can now use -p udp to search UDP packets only or without -p switch to search UDP and TCP packets.\n"
46    "\nSee README included with this package for more details or visit http://www.ipp2p.org\n"
47    "\nExamples:\n"
48    " iptables -A FORWARD -m ipp2p --ipp2p -j MARK --set-mark 0x01\n"
49    " iptables -A FORWARD -p udp -m ipp2p --kazaa --bit -j DROP\n"
50    " iptables -A FORWARD -p tcp -m ipp2p --edk --soul -j DROP\n\n"
51    , IPP2P_VERSION);
52}
53
54static struct option opts[] = {
55        { "ipp2p", 0, 0, '1' },
56        { "edk", 0, 0, '2' },
57	{ "dc", 0, 0, '7' },
58	{ "gnu", 0, 0, '9' },
59	{ "kazaa", 0, 0, 'a' },
60	{ "bit", 0, 0, 'b' },
61	{ "apple", 0, 0, 'c' },
62	{ "soul", 0, 0, 'd' },
63	{ "winmx", 0, 0, 'e' },
64	{ "ares", 0, 0, 'f' },
65	{ "mute", 0, 0, 'g' },
66	{ "waste", 0, 0, 'h' },
67	{ "xdcc", 0, 0, 'i' },
68	{ "debug", 0, 0, 'j' },
69        {0}
70};
71
72
73static void
74#ifdef _XTABLES_H
75init(struct xt_entry_match *m)
76#else
77init(struct ipt_entry_match *m, unsigned int *nfcache)
78#endif
79{
80    struct ipt_p2p_info *info = (struct ipt_p2p_info *)m->data;
81
82#ifndef _XTABLES_H
83    *nfcache |= NFC_UNKNOWN;
84#endif
85
86    /*init the module with default values*/
87    info->cmd = 0;
88    info->debug = 0;
89
90}
91
92
93static int
94parse(int c, char **argv, int invert, unsigned int *flags,
95#ifdef _XTABLES_H
96      const void *entry, struct xt_entry_match **match)
97#else
98      const struct ipt_entry *entry, unsigned int *nfcache, struct ipt_entry_match **match)
99#endif
100{
101    struct ipt_p2p_info *info = (struct ipt_p2p_info *)(*match)->data;
102
103    switch (c) {
104	case '1':		/*cmd: ipp2p*/
105	    if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
106		    exit_error(PARAMETER_PROBLEM,
107				"ipp2p: `--ipp2p' may only be "
108				"specified once!");
109
110/*	    if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
111		    exit_error(PARAMETER_PROBLEM,
112				"ipp2p: `--ipp2p-data' may only be "
113				"specified alone!");
114*/
115
116	    if ((*flags) != 0)
117		    exit_error(PARAMETER_PROBLEM,
118				"ipp2p: `--ipp2p' may only be "
119				"specified alone!");
120	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
121	    *flags += SHORT_HAND_IPP2P;
122	    info->cmd = *flags;
123	    break;
124
125	case '2':		/*cmd: edk*/
126	    if ((*flags & IPP2P_EDK) == IPP2P_EDK)
127		    exit_error(PARAMETER_PROBLEM,
128				"ipp2p: `--edk' may only be "
129				"specified once");
130	    if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
131		    exit_error(PARAMETER_PROBLEM,
132				"ipp2p: `--ipp2p' may only be "
133				"specified alone!");
134/*	    if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
135		    exit_error(PARAMETER_PROBLEM,
136				"ipp2p: `--ipp2p-data' may only be "
137				"specified alone!");*/
138            if ((*flags & IPP2P_DATA_EDK) == IPP2P_DATA_EDK)
139            exit_error(PARAMETER_PROBLEM,
140                                "ipp2p: use `--edk' OR `--edk-data' but not both of them!");
141	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
142	    *flags += IPP2P_EDK;
143	    info->cmd = *flags;
144	    break;
145
146
147	case '7':		/*cmd: dc*/
148            if ((*flags & IPP2P_DC) == IPP2P_DC)
149            exit_error(PARAMETER_PROBLEM,
150                                "ipp2p: `--dc' may only be "
151                                "specified once!");
152	    if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
153		    exit_error(PARAMETER_PROBLEM,
154				"ipp2p: `--ipp2p' may only be "
155				"specified alone!");
156/*	    if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
157		    exit_error(PARAMETER_PROBLEM,
158				"ipp2p: `--ipp2p-data' may only be "
159				"specified alone!");*/
160            if ((*flags & IPP2P_DATA_DC) == IPP2P_DATA_DC)
161            exit_error(PARAMETER_PROBLEM,
162                                "ipp2p: use `--dc' OR `--dc-data' but not both of them!");
163	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
164            *flags += IPP2P_DC;
165	    info->cmd = *flags;
166	    break;
167
168
169	case '9':		/*cmd: gnu*/
170            if ((*flags & IPP2P_GNU) == IPP2P_GNU)
171            exit_error(PARAMETER_PROBLEM,
172                                "ipp2p: `--gnu' may only be "
173                                "specified once!");
174/*	    if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
175		    exit_error(PARAMETER_PROBLEM,
176				"ipp2p: `--ipp2p-data' may only be "
177				"specified alone!");*/
178	    if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
179		    exit_error(PARAMETER_PROBLEM,
180				"ipp2p: `--ipp2p' may only be "
181				"specified alone!");
182            if ((*flags & IPP2P_DATA_GNU) == IPP2P_DATA_GNU)
183            exit_error(PARAMETER_PROBLEM,
184                                "ipp2p: use `--gnu' OR `--gnu-data' but not both of them!");
185	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
186            *flags += IPP2P_GNU;
187	    info->cmd = *flags;
188	    break;
189
190	case 'a':		/*cmd: kazaa*/
191            if ((*flags & IPP2P_KAZAA) == IPP2P_KAZAA)
192            exit_error(PARAMETER_PROBLEM,
193                                "ipp2p: `--kazaa' may only be "
194                                "specified once!");
195/*	    if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
196		    exit_error(PARAMETER_PROBLEM,
197				"ipp2p: `--ipp2p-data' may only be "
198				"specified alone!");*/
199	    if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
200		    exit_error(PARAMETER_PROBLEM,
201				"ipp2p: `--ipp2p' may only be "
202				"specified alone!");
203            if ((*flags & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA)
204            exit_error(PARAMETER_PROBLEM,
205                                "ipp2p: use `--kazaa' OR `--kazaa-data' but not both of them!");
206	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
207            *flags += IPP2P_KAZAA;
208	    info->cmd = *flags;
209	    break;
210
211	case 'b':		/*cmd: bit*/
212            if ((*flags & IPP2P_BIT) == IPP2P_BIT)
213            exit_error(PARAMETER_PROBLEM,
214                                "ipp2p: `--bit' may only be "
215                                "specified once!");
216	    if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
217		    exit_error(PARAMETER_PROBLEM,
218				"ipp2p: `--ipp2p' may only be "
219				"specified alone!");
220	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
221            *flags += IPP2P_BIT;
222	    info->cmd = *flags;
223	    break;
224
225	case 'c':		/*cmd: apple*/
226            if ((*flags & IPP2P_APPLE) == IPP2P_APPLE)
227            exit_error(PARAMETER_PROBLEM,
228                                "ipp2p: `--apple' may only be "
229                                "specified once!");
230	    if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
231		    exit_error(PARAMETER_PROBLEM,
232				"ipp2p: `--ipp2p' may only be "
233				"specified alone!");
234	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
235            *flags += IPP2P_APPLE;
236	    info->cmd = *flags;
237	    break;
238
239
240	case 'd':		/*cmd: soul*/
241            if ((*flags & IPP2P_SOUL) == IPP2P_SOUL)
242            exit_error(PARAMETER_PROBLEM,
243                                "ipp2p: `--soul' may only be "
244                                "specified once!");
245	    if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
246		    exit_error(PARAMETER_PROBLEM,
247				"ipp2p: `--ipp2p' may only be "
248				"specified alone!");
249	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
250            *flags += IPP2P_SOUL;
251	    info->cmd = *flags;
252	    break;
253
254
255	case 'e':		/*cmd: winmx*/
256            if ((*flags & IPP2P_WINMX) == IPP2P_WINMX)
257            exit_error(PARAMETER_PROBLEM,
258                                "ipp2p: `--winmx' may only be "
259                                "specified once!");
260	    if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
261		    exit_error(PARAMETER_PROBLEM,
262				"ipp2p: `--ipp2p' may only be "
263				"specified alone!");
264	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
265            *flags += IPP2P_WINMX;
266	    info->cmd = *flags;
267	    break;
268
269	case 'f':		/*cmd: ares*/
270            if ((*flags & IPP2P_ARES) == IPP2P_ARES)
271            exit_error(PARAMETER_PROBLEM,
272                                "ipp2p: `--ares' may only be "
273                                "specified once!");
274	    if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
275		    exit_error(PARAMETER_PROBLEM,
276				"ipp2p: `--ipp2p' may only be "
277				"specified alone!");
278	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
279            *flags += IPP2P_ARES;
280	    info->cmd = *flags;
281	    break;
282
283	case 'g':		/*cmd: mute*/
284            if ((*flags & IPP2P_MUTE) == IPP2P_MUTE)
285            exit_error(PARAMETER_PROBLEM,
286                                "ipp2p: `--mute' may only be "
287                                "specified once!");
288	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
289            *flags += IPP2P_MUTE;
290	    info->cmd = *flags;
291	    break;
292	case 'h':		/*cmd: waste*/
293            if ((*flags & IPP2P_WASTE) == IPP2P_WASTE)
294            exit_error(PARAMETER_PROBLEM,
295                                "ipp2p: `--waste' may only be "
296                                "specified once!");
297	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
298            *flags += IPP2P_WASTE;
299	    info->cmd = *flags;
300	    break;
301	case 'i':		/*cmd: xdcc*/
302            if ((*flags & IPP2P_XDCC) == IPP2P_XDCC)
303            exit_error(PARAMETER_PROBLEM,
304                                "ipp2p: `--ares' may only be "
305                                "specified once!");
306	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
307            *flags += IPP2P_XDCC;
308	    info->cmd = *flags;
309	    break;
310
311	case 'j':		/*cmd: debug*/
312	    if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
313	    info->debug = 1;
314	    break;
315
316	default:
317//            exit_error(PARAMETER_PROBLEM,
318//	    "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
319	    return 0;
320    }
321    return 1;
322}
323
324
325static void
326final_check(unsigned int flags)
327{
328    if (!flags)
329            exit_error(PARAMETER_PROBLEM,
330	    "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
331}
332
333static void
334#ifdef _XTABLES_H
335print(const void *ip,
336      const struct xt_entry_match *match,
337#else
338print(const struct ipt_ip *ip,
339      const struct ipt_entry_match *match,
340#endif
341	int numeric)
342{
343    struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
344
345    printf("ipp2p v%s", IPP2P_VERSION);
346    if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf(" --ipp2p");
347//    if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf(" --ipp2p-data");
348    if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf(" --kazaa");
349//    if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf(" --kazaa-data");
350//    if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf(" --gnu-data");
351    if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf(" --gnu");
352    if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf(" --edk");
353//    if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf(" --edk-data");
354//    if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf(" --dc-data");
355    if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf(" --dc");
356    if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf(" --bit");
357    if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf(" --apple");
358    if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf(" --soul");
359    if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf(" --winmx");
360    if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf(" --ares");
361    if ((info->cmd & IPP2P_MUTE) == IPP2P_MUTE) printf(" --mute");
362    if ((info->cmd & IPP2P_WASTE) == IPP2P_WASTE) printf(" --waste");
363    if ((info->cmd & IPP2P_XDCC) == IPP2P_XDCC) printf(" --xdcc");
364    if (info->debug != 0) printf(" --debug");
365    printf(" ");
366}
367
368static void
369#ifdef _XTABLES_H
370save(const void *ip,
371     const struct xt_entry_match *match)
372#else
373save(const struct ipt_ip *ip,
374     const struct ipt_entry_match *match)
375#endif
376{
377    struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
378
379    if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf("--ipp2p ");
380//    if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf("--ipp2p-data ");
381    if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf("--kazaa ");
382//    if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf("--kazaa-data ");
383//    if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf("--gnu-data ");
384    if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf("--gnu ");
385    if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf("--edk ");
386//    if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf("--edk-data ");
387//    if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf("--dc-data ");
388    if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf("--dc ");
389    if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf("--bit ");
390    if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf("--apple ");
391    if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf("--soul ");
392    if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf("--winmx ");
393    if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf("--ares ");
394    if ((info->cmd & IPP2P_MUTE) == IPP2P_MUTE) printf(" --mute");
395    if ((info->cmd & IPP2P_WASTE) == IPP2P_WASTE) printf(" --waste");
396    if ((info->cmd & IPP2P_XDCC) == IPP2P_XDCC) printf(" --xdcc");
397    if (info->debug != 0) printf("--debug ");
398}
399
400
401static
402struct xtables_match ipp2p=
403{
404    .next           = NULL,
405    .name           = "ipp2p",
406    .version        = XTABLES_VERSION,
407    .size           = IPT_ALIGN(sizeof(struct ipt_p2p_info)),
408    .userspacesize  = IPT_ALIGN(sizeof(struct ipt_p2p_info)),
409    .help           = &help,
410    .init           = &init,
411    .parse          = &parse,
412    .final_check    = &final_check,
413    .print          = &print,
414    .save           = &save,
415    .extra_opts     = opts
416};
417
418
419
420void _init(void)
421{
422    xtables_register_match(&ipp2p);
423}
424
425