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