+++ /dev/null
-diff -urN iptables-1.2.11.old/extensions/libipt_ipp2p.c iptables-1.2.11/extensions/libipt_ipp2p.c
---- iptables-1.2.11.old/extensions/libipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
-+++ iptables-1.2.11/extensions/libipt_ipp2p.c 2005-03-12 00:50:27.000000000 +0100
-@@ -0,0 +1,455 @@
-+
-+#include <stdio.h>
-+#include <netdb.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <getopt.h>
-+#include <ctype.h>
-+
-+#include <iptables.h>
-+
-+#include <linux/netfilter_ipv4/ipt_ipp2p.h>
-+
-+
-+
-+
-+static void
-+help(void)
-+{
-+ printf(
-+ "IPP2P v%s options:\n"
-+ " --ipp2p Grab all known p2p packets\n"
-+ " --ipp2p-data Identify all known p2p download commands (obsolete)\n\n"
-+ " --edk [TCP&UDP] All known eDonkey/eMule/Overnet packets\n"
-+ " --dc [TCP] All known Direct Connect packets\n"
-+ " --kazaa [TCP&UDP] All known KaZaA packets\n"
-+ " --gnu [TCP&UDP] All known Gnutella packets\n"
-+ " --bit [TCP&UDP] All known BitTorrent packets\n"
-+ " --apple [TCP] All known AppleJuice packets (beta - just a few tests until now)\n"
-+ " --winmx [TCP] All known WinMX (beta - need feedback)\n"
-+ " --soul [TCP] All known SoulSeek (beta - need feedback!)\n"
-+ " --ares [TCP] All known Ares - use with DROP only (beta - need feedback!)\n\n"
-+ " --edk-data [TCP] eDonkey/eMule/Overnet download commands (obsolete)\n"
-+ " --dc-data [TCP] Direct Connect download command (obsolete)\n"
-+ " --kazaa-data [TCP] KaZaA download command (obsolete)\n"
-+ " --gnu-data [TCP] Gnutella download command (obsolete)\n"
-+ "\nNote that the follwing options will have the same meaning:\n"
-+ " '--ipp2p' is equal to '--edk --dc --kazaa --gnu'\n"
-+ " '--ipp2p-data' is equal to '--edk-data --dc-data --kazaa-data --gnu-data'\n"
-+ "\nIPP2P was intended for TCP only. Due to increasing usage of UDP we needed to change this.\n"
-+ "You can now use -p udp to search UDP packets only or without -p switch to search UDP and TCP packets.\n"
-+ "\nSee README included with this package for more details or visit http://www.ipp2p.org\n"
-+ "\nExamples:\n"
-+ " iptables -A FORWARD -m ipp2p --ipp2p -j MARK --set-mark 0x01\n"
-+ " iptables -A FORWARD -p udp -m ipp2p --kazaa --bit -j DROP\n"
-+ " iptables -A FORWARD -p tcp -m ipp2p --edk --soul -j DROP\n\n"
-+ , IPP2P_VERSION);
-+}
-+
-+
-+
-+static struct option opts[] = {
-+ { "ipp2p", 0, 0, '1' },
-+ { "edk", 0, 0, '2' },
-+ { "ipp2p-data", 0, 0, '3' },
-+ { "kazaa-data", 0, 0, '4' },
-+ { "edk-data", 0, 0, '5' },
-+ { "dc-data", 0, 0, '6' },
-+ { "dc", 0, 0, '7' },
-+ { "gnu-data", 0, 0, '8' },
-+ { "gnu", 0, 0, '9' },
-+ { "kazaa", 0, 0, 'a' },
-+ { "bit", 0, 0, 'b' },
-+ { "apple", 0, 0, 'c' },
-+ { "soul", 0, 0, 'd' },
-+ { "winmx", 0, 0, 'e' },
-+ { "ares", 0, 0, 'f' },
-+ { "debug", 0, 0, 'g' },
-+ {0}
-+};
-+
-+
-+
-+static void
-+init(struct ipt_entry_match *m, unsigned int *nfcache)
-+{
-+ struct ipt_p2p_info *info = (struct ipt_p2p_info *)m->data;
-+
-+ *nfcache |= NFC_UNKNOWN;
-+
-+ /*init the module with default values*/
-+ info->cmd = 0;
-+ info->debug = 0;
-+
-+}
-+
-+
-+static int
-+parse(int c, char **argv, int invert, unsigned int *flags,
-+ const struct ipt_entry *entry,
-+ unsigned int *nfcache,
-+ struct ipt_entry_match **match)
-+{
-+ struct ipt_p2p_info *info = (struct ipt_p2p_info *)(*match)->data;
-+
-+ switch (c) {
-+ case '1': /*cmd: ipp2p*/
-+ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p' may only be "
-+ "specified once!");
-+ if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p-data' may only be "
-+ "specified alone!");
-+ if ((*flags) != 0)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p' may only be "
-+ "specified alone!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += SHORT_HAND_IPP2P;
-+ info->cmd = *flags;
-+ break;
-+
-+ case '2': /*cmd: edk*/
-+ if ((*flags & IPP2P_EDK) == IPP2P_EDK)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--edk' may only be "
-+ "specified once");
-+ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p' may only be "
-+ "specified alone!");
-+ if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p-data' may only be "
-+ "specified alone!");
-+ if ((*flags & IPP2P_DATA_EDK) == IPP2P_DATA_EDK)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: use `--edk' OR `--edk-data' but not both of them!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_EDK;
-+ info->cmd = *flags;
-+ break;
-+
-+ case '3': /*cmd: ipp2p-data*/
-+ if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p-data' may only be "
-+ "specified once!");
-+ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p' may only be "
-+ "specified alone!");
-+ if ((*flags) != 0)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p-data' may only be "
-+ "specified alone!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += SHORT_HAND_DATA;
-+ info->cmd = *flags;
-+ break;
-+
-+ case '4': /*cmd: kazaa-data*/
-+ if ((*flags & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--kazaa-data' may only be "
-+ "specified once!");
-+ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p' may only be "
-+ "specified alone!");
-+ if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p-data' may only be "
-+ "specified alone!");
-+ if ((*flags & IPP2P_KAZAA) == IPP2P_KAZAA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: use `--kazaa' OR `--kazaa-data' but not both of them!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_DATA_KAZAA;
-+ info->cmd = *flags;
-+ break;
-+
-+ case '5': /*cmd: edk-data*/
-+ if ((*flags & IPP2P_DATA_EDK) == IPP2P_DATA_EDK)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--edk-data' may only be "
-+ "specified once!");
-+ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p' may only be "
-+ "specified alone!");
-+ if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p-data' may only be "
-+ "specified alone!");
-+ if ((*flags & IPP2P_EDK) == IPP2P_EDK)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: use `--edk' OR `--edk-data' but not both of them!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_DATA_EDK;
-+ info->cmd = *flags;
-+ break;
-+
-+ case '6': /*cmd: dc-data*/
-+ if ((*flags & IPP2P_DATA_DC) == IPP2P_DATA_DC)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--dc-data' may only be "
-+ "specified once!");
-+ if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p-data' may only be "
-+ "specified alone!");
-+ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p' may only be "
-+ "specified alone!");
-+ if ((*flags & IPP2P_DC) == IPP2P_DC)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: use `--dc' OR `--dc-data' but not both of them!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_DATA_DC;
-+ info->cmd = *flags;
-+ break;
-+
-+ case '7': /*cmd: dc*/
-+ if ((*flags & IPP2P_DC) == IPP2P_DC)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--dc' may only be "
-+ "specified once!");
-+ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p' may only be "
-+ "specified alone!");
-+ if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p-data' may only be "
-+ "specified alone!");
-+ if ((*flags & IPP2P_DATA_DC) == IPP2P_DATA_DC)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: use `--dc' OR `--dc-data' but not both of them!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_DC;
-+ info->cmd = *flags;
-+ break;
-+
-+
-+ case '8': /*cmd: gnu-data*/
-+ if ((*flags & IPP2P_DATA_GNU) == IPP2P_DATA_GNU)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--gnu-data' may only be "
-+ "specified once!");
-+ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p' may only be "
-+ "specified alone!");
-+ if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p-data' may only be "
-+ "specified alone!");
-+ if ((*flags & IPP2P_GNU) == IPP2P_GNU)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: use `--gnu' OR `--gnu-data' but not both of them!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_DATA_GNU;
-+ info->cmd = *flags;
-+ break;
-+
-+ case '9': /*cmd: gnu*/
-+ if ((*flags & IPP2P_GNU) == IPP2P_GNU)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--gnu' may only be "
-+ "specified once!");
-+ if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p-data' may only be "
-+ "specified alone!");
-+ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p' may only be "
-+ "specified alone!");
-+ if ((*flags & IPP2P_DATA_GNU) == IPP2P_DATA_GNU)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: use `--gnu' OR `--gnu-data' but not both of them!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_GNU;
-+ info->cmd = *flags;
-+ break;
-+
-+ case 'a': /*cmd: kazaa*/
-+ if ((*flags & IPP2P_KAZAA) == IPP2P_KAZAA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--kazaa' may only be "
-+ "specified once!");
-+ if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p-data' may only be "
-+ "specified alone!");
-+ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ipp2p' may only be "
-+ "specified alone!");
-+ if ((*flags & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: use `--kazaa' OR `--kazaa-data' but not both of them!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_KAZAA;
-+ info->cmd = *flags;
-+ break;
-+
-+ case 'b': /*cmd: bit*/
-+ if ((*flags & IPP2P_BIT) == IPP2P_BIT)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--bit' may only be "
-+ "specified once!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_BIT;
-+ info->cmd = *flags;
-+ break;
-+
-+ case 'c': /*cmd: apple*/
-+ if ((*flags & IPP2P_APPLE) == IPP2P_APPLE)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--apple' may only be "
-+ "specified once!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_APPLE;
-+ info->cmd = *flags;
-+ break;
-+
-+
-+ case 'd': /*cmd: soul*/
-+ if ((*flags & IPP2P_SOUL) == IPP2P_SOUL)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--soul' may only be "
-+ "specified once!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_SOUL;
-+ info->cmd = *flags;
-+ break;
-+
-+
-+ case 'e': /*cmd: winmx*/
-+ if ((*flags & IPP2P_WINMX) == IPP2P_WINMX)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--winmx' may only be "
-+ "specified once!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_WINMX;
-+ info->cmd = *flags;
-+ break;
-+
-+ case 'f': /*cmd: ares*/
-+ if ((*flags & IPP2P_ARES) == IPP2P_ARES)
-+ exit_error(PARAMETER_PROBLEM,
-+ "ipp2p: `--ares' may only be "
-+ "specified once!");
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ *flags += IPP2P_ARES;
-+ info->cmd = *flags;
-+ break;
-+
-+ case 'g': /*cmd: debug*/
-+ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
-+ info->debug = 1;
-+ break;
-+
-+ default:
-+ exit_error(PARAMETER_PROBLEM,
-+ "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+static void
-+final_check(unsigned int flags)
-+{
-+ if (!flags)
-+ exit_error(PARAMETER_PROBLEM,
-+ "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
-+}
-+
-+
-+
-+static void
-+print(const struct ipt_ip *ip,
-+ const struct ipt_entry_match *match,
-+ int numeric)
-+{
-+ struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
-+
-+ printf("ipp2p v%s", IPP2P_VERSION);
-+ if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf(" --ipp2p");
-+ if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf(" --ipp2p-data");
-+ if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf(" --kazaa");
-+ if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf(" --kazaa-data");
-+ if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf(" --gnu-data");
-+ if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf(" --gnu");
-+ if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf(" --edk");
-+ if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf(" --edk-data");
-+ if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf(" --dc-data");
-+ if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf(" --dc");
-+ if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf(" --bit");
-+ if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf(" --apple");
-+ if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf(" --soul");
-+ if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf(" --winmx");
-+ if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf(" --ares");
-+ if (info->debug != 0) printf(" --debug");
-+ printf(" ");
-+}
-+
-+
-+
-+static void
-+save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-+{
-+ struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
-+
-+ if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf("--ipp2p ");
-+ if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf("--ipp2p-data ");
-+ if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf("--kazaa ");
-+ if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf("--kazaa-data ");
-+ if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf("--gnu-data ");
-+ if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf("--gnu ");
-+ if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf("--edk ");
-+ if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf("--edk-data ");
-+ if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf("--dc-data ");
-+ if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf("--dc ");
-+ if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf("--bit ");
-+ if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf("--apple ");
-+ if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf("--soul ");
-+ if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf("--winmx ");
-+ if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf("--ares ");
-+ if (info->debug != 0) printf("--debug ");
-+}
-+
-+
-+
-+
-+static
-+struct iptables_match ipp2p=
-+{
-+ .next = NULL,
-+ .name = "ipp2p",
-+ .version = IPTABLES_VERSION,
-+ .size = IPT_ALIGN(sizeof(struct ipt_p2p_info)),
-+ .userspacesize = IPT_ALIGN(sizeof(struct ipt_p2p_info)),
-+ .help = &help,
-+ .init = &init,
-+ .parse = &parse,
-+ .final_check = &final_check,
-+ .print = &print,
-+ .save = &save,
-+ .extra_opts = opts
-+};
-+
-+
-+
-+void _init(void)
-+{
-+ register_match(&ipp2p);
-+}
-+
-diff -urN iptables-1.2.11.old/extensions/Makefile iptables-1.2.11/extensions/Makefile
---- iptables-1.2.11.old/extensions/Makefile 2004-06-17 12:22:54.000000000 +0200
-+++ iptables-1.2.11/extensions/Makefile 2005-03-12 00:50:12.000000000 +0100
-@@ -8,6 +8,10 @@
- PF_EXT_SLIB:=ah connlimit connmark conntrack dscp ecn esp helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc sctp standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG
- PF6_EXT_SLIB:=eui64 hl icmpv6 length limit mac mark multiport owner standard tcp udp HL LOG MARK TRACE
-
-+
-+# ipp2p
-+PF_EXT_SLIB += ipp2p
-+
- # Optionals
- PF_EXT_SLIB_OPTS:=$(foreach T,$(wildcard extensions/.*-test),$(shell KERNEL_DIR=$(KERNEL_DIR) $(T)))
- PF6_EXT_SLIB_OPTS:=$(foreach T,$(wildcard extensions/.*-test6),$(shell KERNEL_DIR=$(KERNEL_DIR) $(T)))
-diff -urN iptables-1.2.11.old/include/linux/netfilter_ipv4/ipt_ipp2p.h iptables-1.2.11/include/linux/netfilter_ipv4/ipt_ipp2p.h
---- iptables-1.2.11.old/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
-+++ iptables-1.2.11/include/linux/netfilter_ipv4/ipt_ipp2p.h 2005-03-12 00:50:46.000000000 +0100
-@@ -0,0 +1,29 @@
-+#ifndef __IPT_IPP2P_H
-+#define __IPT_IPP2P_H
-+#define IPP2P_VERSION "0.7.4"
-+
-+struct ipt_p2p_info {
-+ int cmd;
-+ int debug;
-+};
-+
-+#endif //__IPT_IPP2P_H
-+
-+#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
-+#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
-+#define SHORT_HAND_NONE 5 /* no short hand*/
-+
-+#define IPP2P_EDK 2
-+#define IPP2P_DATA_KAZAA 8
-+#define IPP2P_DATA_EDK 16
-+#define IPP2P_DATA_DC 32
-+#define IPP2P_DC 64
-+#define IPP2P_DATA_GNU 128
-+#define IPP2P_GNU 256
-+#define IPP2P_KAZAA 512
-+#define IPP2P_BIT 1024
-+#define IPP2P_APPLE 2048
-+#define IPP2P_SOUL 4096
-+#define IPP2P_WINMX 8192
-+#define IPP2P_ARES 16384
-+
--- /dev/null
+diff -urN iptables.old/extensions/Makefile iptables.dev/extensions/Makefile
+--- iptables.old/extensions/Makefile 2005-07-20 04:22:56.000000000 +0200
++++ iptables.dev/extensions/Makefile 2006-03-23 14:42:28.000000000 +0100
+@@ -8,6 +8,10 @@
+ PF_EXT_SLIB:=ah addrtype comment connlimit connmark conntrack dscp ecn esp hashlimit helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc sctp standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NFQUEUE NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG
+ PF6_EXT_SLIB:=eui64 hl icmpv6 length limit mac mark multiport owner physdev standard tcp udp HL LOG NFQUEUE MARK TRACE
+
++
++# ipp2p
++PF_EXT_SLIB += ipp2p
++
+ # Optionals
+ PF_EXT_SLIB_OPTS:=$(foreach T,$(wildcard extensions/.*-test),$(shell KERNEL_DIR=$(KERNEL_DIR) $(T)))
+ PF6_EXT_SLIB_OPTS:=$(foreach T,$(wildcard extensions/.*-test6),$(shell KERNEL_DIR=$(KERNEL_DIR) $(T)))
+diff -urN iptables.old/extensions/libipt_ipp2p.c iptables.dev/extensions/libipt_ipp2p.c
+--- iptables.old/extensions/libipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/libipt_ipp2p.c 2006-03-23 14:43:26.000000000 +0100
+@@ -0,0 +1,401 @@
++
++#include <stdio.h>
++#include <netdb.h>
++#include <string.h>
++#include <stdlib.h>
++#include <getopt.h>
++#include <ctype.h>
++
++#include <iptables.h>
++
++#include <linux/netfilter_ipv4/ipt_ipp2p.h>
++
++static void
++help(void)
++{
++ printf(
++ "IPP2P v%s options:\n"
++ " --ipp2p Grab all known p2p packets\n"
++ " --edk [TCP&UDP] All known eDonkey/eMule/Overnet packets\n"
++ " --dc [TCP] All known Direct Connect packets\n"
++ " --kazaa [TCP&UDP] All known KaZaA packets\n"
++ " --gnu [TCP&UDP] All known Gnutella packets\n"
++ " --bit [TCP&UDP] All known BitTorrent packets\n"
++ " --apple [TCP] All known AppleJuice packets\n"
++ " --winmx [TCP] All known WinMX\n"
++ " --soul [TCP] All known SoulSeek\n"
++ " --ares [TCP] All known Ares\n\n"
++ " EXPERIMENTAL protocols (please send feedback to: ipp2p@ipp2p.org) :\n"
++ " --mute [TCP] All known Mute packets\n"
++ " --waste [TCP] All known Waste packets\n"
++ " --xdcc [TCP] All known XDCC packets (only xdcc login)\n\n"
++ " DEBUG SUPPPORT, use only if you know why\n"
++ " --debug Generate kernel debug output, THIS WILL SLOW DOWN THE FILTER\n"
++ "\nNote that the follwing options will have the same meaning:\n"
++ " '--ipp2p' is equal to '--edk --dc --kazaa --gnu --bit --apple --winmx --soul --ares'\n"
++ "\nIPP2P was intended for TCP only. Due to increasing usage of UDP we needed to change this.\n"
++ "You can now use -p udp to search UDP packets only or without -p switch to search UDP and TCP packets.\n"
++ "\nSee README included with this package for more details or visit http://www.ipp2p.org\n"
++ "\nExamples:\n"
++ " iptables -A FORWARD -m ipp2p --ipp2p -j MARK --set-mark 0x01\n"
++ " iptables -A FORWARD -p udp -m ipp2p --kazaa --bit -j DROP\n"
++ " iptables -A FORWARD -p tcp -m ipp2p --edk --soul -j DROP\n\n"
++ , IPP2P_VERSION);
++}
++
++static struct option opts[] = {
++ { "ipp2p", 0, 0, '1' },
++ { "edk", 0, 0, '2' },
++ { "dc", 0, 0, '7' },
++ { "gnu", 0, 0, '9' },
++ { "kazaa", 0, 0, 'a' },
++ { "bit", 0, 0, 'b' },
++ { "apple", 0, 0, 'c' },
++ { "soul", 0, 0, 'd' },
++ { "winmx", 0, 0, 'e' },
++ { "ares", 0, 0, 'f' },
++ { "mute", 0, 0, 'g' },
++ { "waste", 0, 0, 'h' },
++ { "xdcc", 0, 0, 'i' },
++ { "debug", 0, 0, 'j' },
++ {0}
++};
++
++
++
++static void
++init(struct ipt_entry_match *m, unsigned int *nfcache)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)m->data;
++
++ *nfcache |= NFC_UNKNOWN;
++
++ /*init the module with default values*/
++ info->cmd = 0;
++ info->debug = 0;
++
++}
++
++
++static int
++parse(int c, char **argv, int invert, unsigned int *flags,
++ const struct ipt_entry *entry,
++ unsigned int *nfcache,
++ struct ipt_entry_match **match)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)(*match)->data;
++
++ switch (c) {
++ case '1': /*cmd: ipp2p*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified once!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags) != 0)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += SHORT_HAND_IPP2P;
++ info->cmd = *flags;
++ break;
++
++ case '2': /*cmd: edk*/
++ if ((*flags & IPP2P_EDK) == IPP2P_EDK)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--edk' may only be "
++ "specified once");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & IPP2P_DATA_EDK) == IPP2P_DATA_EDK)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--edk' OR `--edk-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_EDK;
++ info->cmd = *flags;
++ break;
++
++
++ case '7': /*cmd: dc*/
++ if ((*flags & IPP2P_DC) == IPP2P_DC)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--dc' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & IPP2P_DATA_DC) == IPP2P_DATA_DC)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--dc' OR `--dc-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_DC;
++ info->cmd = *flags;
++ break;
++
++
++ case '9': /*cmd: gnu*/
++ if ((*flags & IPP2P_GNU) == IPP2P_GNU)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--gnu' may only be "
++ "specified once!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if ((*flags & IPP2P_DATA_GNU) == IPP2P_DATA_GNU)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--gnu' OR `--gnu-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_GNU;
++ info->cmd = *flags;
++ break;
++
++ case 'a': /*cmd: kazaa*/
++ if ((*flags & IPP2P_KAZAA) == IPP2P_KAZAA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--kazaa' may only be "
++ "specified once!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if ((*flags & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--kazaa' OR `--kazaa-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_KAZAA;
++ info->cmd = *flags;
++ break;
++
++ case 'b': /*cmd: bit*/
++ if ((*flags & IPP2P_BIT) == IPP2P_BIT)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--bit' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_BIT;
++ info->cmd = *flags;
++ break;
++
++ case 'c': /*cmd: apple*/
++ if ((*flags & IPP2P_APPLE) == IPP2P_APPLE)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--apple' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_APPLE;
++ info->cmd = *flags;
++ break;
++
++
++ case 'd': /*cmd: soul*/
++ if ((*flags & IPP2P_SOUL) == IPP2P_SOUL)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--soul' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_SOUL;
++ info->cmd = *flags;
++ break;
++
++
++ case 'e': /*cmd: winmx*/
++ if ((*flags & IPP2P_WINMX) == IPP2P_WINMX)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--winmx' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_WINMX;
++ info->cmd = *flags;
++ break;
++
++ case 'f': /*cmd: ares*/
++ if ((*flags & IPP2P_ARES) == IPP2P_ARES)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ares' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_ARES;
++ info->cmd = *flags;
++ break;
++
++ case 'g': /*cmd: mute*/
++ if ((*flags & IPP2P_MUTE) == IPP2P_MUTE)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--mute' may only be "
++ "specified once!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_MUTE;
++ info->cmd = *flags;
++ break;
++ case 'h': /*cmd: waste*/
++ if ((*flags & IPP2P_WASTE) == IPP2P_WASTE)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--waste' may only be "
++ "specified once!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_WASTE;
++ info->cmd = *flags;
++ break;
++ case 'i': /*cmd: xdcc*/
++ if ((*flags & IPP2P_XDCC) == IPP2P_XDCC)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ares' may only be "
++ "specified once!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_XDCC;
++ info->cmd = *flags;
++ break;
++
++ case 'j': /*cmd: debug*/
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ info->debug = 1;
++ break;
++
++ default:
++// exit_error(PARAMETER_PROBLEM,
++// "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
++ return 0;
++ }
++ return 1;
++}
++
++
++static void
++final_check(unsigned int flags)
++{
++ if (!flags)
++ exit_error(PARAMETER_PROBLEM,
++ "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
++}
++
++
++
++static void
++print(const struct ipt_ip *ip,
++ const struct ipt_entry_match *match,
++ int numeric)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
++
++ printf("ipp2p v%s", IPP2P_VERSION);
++ if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf(" --ipp2p");
++// if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf(" --ipp2p-data");
++ if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf(" --kazaa");
++// if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf(" --kazaa-data");
++// if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf(" --gnu-data");
++ if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf(" --gnu");
++ if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf(" --edk");
++// if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf(" --edk-data");
++// if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf(" --dc-data");
++ if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf(" --dc");
++ if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf(" --bit");
++ if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf(" --apple");
++ if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf(" --soul");
++ if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf(" --winmx");
++ if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf(" --ares");
++ if ((info->cmd & IPP2P_MUTE) == IPP2P_MUTE) printf(" --mute");
++ if ((info->cmd & IPP2P_WASTE) == IPP2P_WASTE) printf(" --waste");
++ if ((info->cmd & IPP2P_XDCC) == IPP2P_XDCC) printf(" --xdcc");
++ if (info->debug != 0) printf(" --debug");
++ printf(" ");
++}
++
++
++
++static void
++save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
++
++ if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf("--ipp2p ");
++// if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf("--ipp2p-data ");
++ if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf("--kazaa ");
++// if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf("--kazaa-data ");
++// if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf("--gnu-data ");
++ if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf("--gnu ");
++ if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf("--edk ");
++// if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf("--edk-data ");
++// if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf("--dc-data ");
++ if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf("--dc ");
++ if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf("--bit ");
++ if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf("--apple ");
++ if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf("--soul ");
++ if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf("--winmx ");
++ if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf("--ares ");
++ if ((info->cmd & IPP2P_MUTE) == IPP2P_MUTE) printf(" --mute");
++ if ((info->cmd & IPP2P_WASTE) == IPP2P_WASTE) printf(" --waste");
++ if ((info->cmd & IPP2P_XDCC) == IPP2P_XDCC) printf(" --xdcc");
++ if (info->debug != 0) printf("--debug ");
++}
++
++
++
++
++static
++struct iptables_match ipp2p=
++{
++ .next = NULL,
++ .name = "ipp2p",
++ .version = IPTABLES_VERSION,
++ .size = IPT_ALIGN(sizeof(struct ipt_p2p_info)),
++ .userspacesize = IPT_ALIGN(sizeof(struct ipt_p2p_info)),
++ .help = &help,
++ .init = &init,
++ .parse = &parse,
++ .final_check = &final_check,
++ .print = &print,
++ .save = &save,
++ .extra_opts = opts
++};
++
++
++
++void _init(void)
++{
++ register_match(&ipp2p);
++}
++
+diff -urN iptables.old/include/linux/netfilter_ipv4/ipt_ipp2p.h iptables.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h
+--- iptables.old/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h 2006-03-23 14:44:26.000000000 +0100
+@@ -0,0 +1,31 @@
++#ifndef __IPT_IPP2P_H
++#define __IPT_IPP2P_H
++#define IPP2P_VERSION "0.8.1_rc1"
++
++struct ipt_p2p_info {
++ int cmd;
++ int debug;
++};
++
++#endif //__IPT_IPP2P_H
++
++#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
++//#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
++#define SHORT_HAND_NONE 5 /* no short hand*/
++
++#define IPP2P_EDK (1 << 1)
++#define IPP2P_DATA_KAZAA (1 << 2)
++#define IPP2P_DATA_EDK (1 << 3)
++#define IPP2P_DATA_DC (1 << 4)
++#define IPP2P_DC (1 << 5)
++#define IPP2P_DATA_GNU (1 << 6)
++#define IPP2P_GNU (1 << 7)
++#define IPP2P_KAZAA (1 << 8)
++#define IPP2P_BIT (1 << 9)
++#define IPP2P_APPLE (1 << 10)
++#define IPP2P_SOUL (1 << 11)
++#define IPP2P_WINMX (1 << 12)
++#define IPP2P_ARES (1 << 13)
++#define IPP2P_MUTE (1 << 14)
++#define IPP2P_WASTE (1 << 15)
++#define IPP2P_XDCC (1 << 16)
CONFIG_IP_NF_MATCH_LAYER7=m
# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_IPP2P=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_TIME=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_LAYER7=m
# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_IPP2P=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_TIME=m
CONFIG_IP_NF_MATCH_RECENT=m
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.16
-# Tue Mar 21 00:25:31 2006
+# Thu Mar 23 15:31:19 2006
#
CONFIG_MIPS=y
CONFIG_NET_IPIP=m
CONFIG_NET_IPGRE=m
# CONFIG_NET_IPGRE_BROADCAST is not set
+CONFIG_IPSEC_NAT_TRAVERSAL=y
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
-CONFIG_IPSEC_NAT_TRAVERSAL=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
CONFIG_IP_NF_MATCH_LAYER7=m
# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_IPP2P=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_TIME=m
CONFIG_IP_NF_MATCH_RECENT=m
+++ /dev/null
-diff -urN linux-2.4.29.old/include/linux/netfilter_ipv4/ipt_ipp2p.h linux-2.4.29/include/linux/netfilter_ipv4/ipt_ipp2p.h
---- linux-2.4.29.old/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.29/include/linux/netfilter_ipv4/ipt_ipp2p.h 2005-03-12 00:44:17.000000000 +0100
-@@ -0,0 +1,29 @@
-+#ifndef __IPT_IPP2P_H
-+#define __IPT_IPP2P_H
-+#define IPP2P_VERSION "0.7.4"
-+
-+struct ipt_p2p_info {
-+ int cmd;
-+ int debug;
-+};
-+
-+#endif //__IPT_IPP2P_H
-+
-+#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
-+#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
-+#define SHORT_HAND_NONE 5 /* no short hand*/
-+
-+#define IPP2P_EDK 2
-+#define IPP2P_DATA_KAZAA 8
-+#define IPP2P_DATA_EDK 16
-+#define IPP2P_DATA_DC 32
-+#define IPP2P_DC 64
-+#define IPP2P_DATA_GNU 128
-+#define IPP2P_GNU 256
-+#define IPP2P_KAZAA 512
-+#define IPP2P_BIT 1024
-+#define IPP2P_APPLE 2048
-+#define IPP2P_SOUL 4096
-+#define IPP2P_WINMX 8192
-+#define IPP2P_ARES 16384
-+
-diff -urN linux-2.4.29.old/net/ipv4/netfilter/Config.in linux-2.4.29/net/ipv4/netfilter/Config.in
---- linux-2.4.29.old/net/ipv4/netfilter/Config.in 2005-03-12 00:40:38.000000000 +0100
-+++ linux-2.4.29/net/ipv4/netfilter/Config.in 2005-03-12 00:42:57.000000000 +0100
-@@ -26,6 +26,7 @@
- dep_tristate ' TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES
- dep_tristate ' recent match support' CONFIG_IP_NF_MATCH_RECENT $CONFIG_IP_NF_IPTABLES
- dep_tristate ' ECN match support' CONFIG_IP_NF_MATCH_ECN $CONFIG_IP_NF_IPTABLES
-+ dep_tristate ' peer to peer traffic match support' CONFIG_IP_NF_MATCH_IPP2P $CONFIG_IP_NF_IPTABLES
-
- dep_tristate ' DSCP match support' CONFIG_IP_NF_MATCH_DSCP $CONFIG_IP_NF_IPTABLES
-
-diff -urN linux-2.4.29.old/net/ipv4/netfilter/ipt_ipp2p.c linux-2.4.29/net/ipv4/netfilter/ipt_ipp2p.c
---- linux-2.4.29.old/net/ipv4/netfilter/ipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.29/net/ipv4/netfilter/ipt_ipp2p.c 2005-03-12 00:44:02.000000000 +0100
-@@ -0,0 +1,661 @@
-+#if defined(MODVERSIONS)
-+#include <linux/modversions.h>
-+#endif
-+#include <linux/module.h>
-+#include <linux/netfilter_ipv4/ip_tables.h>
-+#include <linux/version.h>
-+#include <linux/netfilter_ipv4/ipt_ipp2p.h>
-+//#include "ipt_ipp2p.h"
-+#include <net/tcp.h>
-+#include <net/udp.h>
-+
-+#define get_u8(X,O) (*(__u8 *)(X + O))
-+#define get_u16(X,O) (*(__u16 *)(X + O))
-+#define get_u32(X,O) (*(__u32 *)(X + O))
-+
-+MODULE_AUTHOR("Eicke Friedrich <ipp2p@ipp2p.org>");
-+MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
-+MODULE_LICENSE("GPL");
-+
-+
-+/*Search for UDP eDonkey/eMule/Kad commands*/
-+int
-+udp_search_edk (unsigned char *haystack, int packet_len)
-+{
-+ unsigned char *t = haystack;
-+ t += 8;
-+
-+ switch (t[0]) {
-+ case 0xe3: { /*edonkey*/
-+ switch (t[1]) {
-+ /* e3 9a + 16Bytes Hash | size == 26 */
-+ case 0x9a: if (packet_len == 26) return ((IPP2P_EDK * 100) + 1);
-+ /* e3 96 xx yy zz kk | size == 14 | server status request */
-+ case 0x96: if (packet_len == 14) return ((IPP2P_EDK * 100) + 2);
-+ /* e3 a2 | size == 10 or 14 <-- recheck*/
-+ }
-+ }
-+
-+ case 0xc5: { /*emule*/
-+ switch (t[1]) {
-+ /* c5 91 xx yy | size == 12 (8+4) | xx != 0x00 -- xx yy queue rating */
-+ case 0x91: if ((packet_len == 12) && (t[2] != 0x00)) return ((IPP2P_EDK * 100) + 3);
-+ /* c5 90 xx .. yy | size == 26 (8+2+16) | xx .. yy == hash -- file ping */
-+ case 0x90: if ((packet_len == 26) && (t[2] != 0x00)) return ((IPP2P_EDK * 100) + 4);
-+ /* c5 92 | size == 10 (8+2) -- file not found */
-+ case 0x92: if (packet_len == 10) return ((IPP2P_EDK * 100) + 5);
-+ /* c5 93 | size == 10 (8+2) -- queue full */
-+ case 0x93: if (packet_len == 10) return ((IPP2P_EDK * 100) + 6);
-+ }
-+ }
-+
-+ case 0xe4: { /*kad*/
-+ switch (t[1]) {
-+ /* e4 50 | size == 12 */
-+ case 0x50: if (packet_len == 12) return ((IPP2P_EDK * 100) + 7);
-+ /* e4 58 | size == 14 */
-+ case 0x58: if ((packet_len == 14) && (t[2] != 0x00)) return ((IPP2P_EDK * 100) + 8);
-+ /* e4 59 | size == 10 */
-+ case 0x59: if (packet_len == 10) return ((IPP2P_EDK * 100) + 9);
-+ /* e4 30 .. | t[18] == 0x01 | size > 26 | --> search */
-+ case 0x30: if ((packet_len > 26) && (t[18] == 0x01)) return ((IPP2P_EDK * 100) + 10);
-+ /* e4 28 .. 00 | t[68] == 0x00 | size > 76 */
-+ case 0x28: if ((packet_len > 76) && (t[68] == 0x00)) return ((IPP2P_EDK * 100) + 11);
-+ /* e4 20 .. | size == 43 */
-+ case 0x20: if ((packet_len == 43) && (t[2] != 0x00) && (t[34] != 0x00)) return ((IPP2P_EDK * 100) + 12);
-+ /* e4 00 .. 00 | size == 35 ? */
-+ case 0x00: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 13);
-+ /* e4 10 .. 00 | size == 35 ? */
-+ case 0x10: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 14);
-+ /* e4 18 .. 00 | size == 35 ? */
-+ case 0x18: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 15);
-+ /* e4 40 .. | t[18] == 0x01 | t[19] == 0x00 | size > 40 */
-+ case 0x40: if ((packet_len > 40) && (t[18] == 0x01) && (t[19] == 0x00)) return ((IPP2P_EDK * 100) + 16);
-+ }
-+ }
-+
-+ default: return 0;
-+ } /* end of switch (t[0]) */
-+}/*udp_search_edk*/
-+
-+
-+/*Search for UDP Gnutella commands*/
-+int
-+udp_search_gnu (unsigned char *haystack, int packet_len)
-+{
-+ unsigned char *t = haystack;
-+ t += 8;
-+
-+ if (memcmp(t, "GND", 3) == 0) return ((IPP2P_GNU * 100) + 1);
-+ if (memcmp(t, "GNUTELLA ", 9) == 0) return ((IPP2P_GNU * 100) + 2);
-+ return 0;
-+}/*udp_search_gnu*/
-+
-+
-+/*Search for UDP KaZaA commands*/
-+int
-+udp_search_kazaa (unsigned char *haystack, int packet_len)
-+{
-+ unsigned char *t = haystack;
-+
-+ if (t[packet_len-1] == 0x00){
-+ t += (packet_len - 6);
-+ if (memcmp(t, "KaZaA", 5) == 0) return (IPP2P_KAZAA * 100);
-+ }
-+ return 0;
-+}/*udp_search_kazaa*/
-+
-+
-+/*Search for UDP BitTorrent commands*/
-+int
-+udp_search_bit (unsigned char *haystack, int packet_len)
-+{
-+ unsigned char *t = haystack;
-+
-+ /* packet_len has to be 24 */
-+ if (packet_len != 24) return 0;
-+
-+ t += 8;
-+
-+ /* ^ 00 00 04 17 27 10 19 80 */
-+ if ((ntohl(get_u32(t, 0)) == 0x00000417) && (ntohl(get_u32(t, 4)) == 0x27101980)) return (IPP2P_BIT * 100);
-+
-+ return 0;
-+}/*udp_search_bit*/
-+
-+
-+
-+/*Search for Ares commands*/
-+int
-+search_ares (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ unsigned char *t = haystack;
-+ t += head_len;
-+
-+ if ((packet_len - head_len) == 6){ /* possible connect command*/
-+ if ((t[0] == 0x03) && (t[1] == 0x00) && (t[2] == 0x5a) && (t[3] == 0x04) && (t[4] == 0x03) && (t[5] == 0x05))
-+ return ((IPP2P_ARES * 100) + 1); /* found connect packet: 03 00 5a 04 03 05 */
-+ }
-+ if ((packet_len - head_len) == 60){ /* possible download command*/
-+ if ((t[59] == 0x0a) && (t[58] == 0x0a)){
-+ if (memcmp(t, "PUSH SHA1:", 10) == 0) /* found download command */
-+ return ((IPP2P_ARES * 100) + 2);
-+ }
-+ }
-+ return 0;
-+} /*search_ares*/
-+
-+
-+/*Search for SoulSeek commands*/
-+int
-+search_soul (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ unsigned char *t = haystack;
-+ t += head_len;
-+
-+ if (get_u16(t, 0) == (packet_len - head_len - 4)){
-+ /* xx xx 00 00 yy zz 00 00 .. | xx = sizeof(payload) - 4 */
-+ if ((get_u16(t,2) == 0x0000) &&(t[4] != 0x00) && (get_u16(t,6) == 0x0000))
-+ return ((IPP2P_SOUL * 100) + 1);
-+ } else {
-+ /* 00 00 00 00 00 00 00 00 + sizeof(payload) == 8*/
-+ if (((packet_len - head_len) == 8) && (get_u32(t, 0) == 0x00000000) && (get_u32(t, 4) == 0x00000000))
-+ return ((IPP2P_SOUL * 100) + 2);
-+ }
-+
-+ /* 01 xx 00 00 00 yy .. zz 00 00 00 .. | xx == sizeof(nick) | yy .. zz == nick */
-+ if ((t[0] == 0x01) && (t[2] == 0x00) && (get_u16(t,3) == 0x0000) && ((packet_len - head_len) > ((get_u8(t,1))+6)) &&
-+ (t[(get_u8(t,1))+4] != 0x00) && (t[(get_u8(t,1))+5] == 0x01) && (t[(get_u8(t,1))+6] == 0x00))
-+ return ((IPP2P_SOUL * 100) + 3);
-+ return 0;
-+}
-+
-+
-+/*Search for WinMX commands*/
-+int
-+search_winmx (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ unsigned char *t = haystack;
-+ int c;
-+ t += head_len;
-+
-+ if (((packet_len - head_len) == 4) && (memcmp(t, "SEND", 4) == 0)) return ((IPP2P_WINMX * 100) + 1);
-+ if (((packet_len - head_len) == 3) && (memcmp(t, "GET", 3) == 0)) return ((IPP2P_WINMX * 100) + 2);
-+ if (packet_len < (head_len + 10)) return 0;
-+
-+ if ((memcmp(t, "SEND", 4) == 0) || (memcmp(t, "GET", 3) == 0)){
-+ c = head_len + 4;
-+ t += 4;
-+ while (c < packet_len - 5) {
-+ if ((t[0] == 0x20) && (t[1] == 0x22)){
-+ c += 2;
-+ t += 2;
-+ while (c < packet_len - 2) {
-+ if ((t[0] == 0x22) && (t[1] == 0x20)) return ((IPP2P_WINMX * 100) + 3);
-+ t++;
-+ c++;
-+ }
-+ }
-+ t++;
-+ c++;
-+ }
-+ }
-+ return 0;
-+} /*search_winmx*/
-+
-+
-+/*Search for appleJuice commands*/
-+int
-+search_apple (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ unsigned char *t = haystack;
-+ t += head_len;
-+
-+ if ((memcmp(t, "ajprot", 6) == 0) && (t[6] == 0x0d) && (t[7] == 0x0a)) return (IPP2P_APPLE * 100);
-+
-+ return 0;
-+}
-+
-+
-+/*Search for BitTorrent commands*/
-+int
-+search_bittorrent (unsigned char *haystack, int packet_len, int head_len)
-+{
-+
-+ unsigned char *t = haystack;
-+ if (*(haystack+head_len) != 0x13) return 0; /*Bail out of first byte != 0x13*/
-+
-+ t += head_len + 1;
-+
-+ if (memcmp(t, "BitTorrent protocol", 19) == 0) return (IPP2P_BIT * 100);
-+ return 0;
-+}
-+
-+
-+
-+/*check for Kazaa get command*/
-+int
-+search_kazaa (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ unsigned char *t = haystack;
-+
-+ if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;
-+
-+ t += head_len;
-+ if (memcmp(t, "GET /.hash=", 11) == 0)
-+ return (IPP2P_DATA_KAZAA * 100);
-+ else
-+ return 0;
-+}
-+
-+
-+/*check for gnutella get command*/
-+int
-+search_gnu (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ unsigned char *t = haystack;
-+
-+ if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;
-+
-+ t += head_len;
-+ if (memcmp(t, "GET /get/", 9) == 0) return ((IPP2P_DATA_GNU * 100) + 1);
-+ if (memcmp(t, "GET /uri-res/", 13) == 0) return ((IPP2P_DATA_GNU * 100) + 2);
-+
-+ return 0;
-+}
-+
-+
-+/*check for gnutella get commands and other typical data*/
-+int
-+search_all_gnu (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ unsigned char *t = haystack;
-+ int c;
-+
-+ if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;
-+
-+ t += head_len;
-+
-+ if (memcmp(t, "GNUTELLA CONNECT/", 17) == 0) return ((IPP2P_GNU * 100) + 1);
-+ if (memcmp(t, "GNUTELLA/", 9) == 0) return ((IPP2P_GNU * 100) + 2);
-+
-+ if ((memcmp(t, "GET /get/", 9) == 0) || (memcmp(t, "GET /uri-res/", 13) == 0))
-+ {
-+ c = head_len + 8;
-+ t += 8;
-+ while (c < packet_len - 22) {
-+ if ((t[0] == 0x0d) && (t[1] == 0x0a)) {
-+ t += 2;
-+ c += 2;
-+ if ((memcmp(t, "X-Gnutella-", 11) == 0) || (memcmp(t, "X-Queue:", 8) == 0)) return ((IPP2P_GNU * 100) + 3);
-+ } else {
-+ t++;
-+ c++;
-+ }
-+ }
-+ }
-+ return 0;
-+}
-+
-+
-+/*check for KaZaA download commands and other typical data*/
-+int
-+search_all_kazaa (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ unsigned char *t = haystack;
-+ int c;
-+
-+ if (!((*(haystack + packet_len - 2) == 0x0d) && (*(haystack + packet_len - 1) == 0x0a))) return 0;
-+
-+ t += head_len;
-+ if (memcmp(t, "GIVE ", 5) == 0) return ((IPP2P_KAZAA * 100) + 1);
-+
-+ if (memcmp(t, "GET /", 5) == 0) {
-+ c = head_len + 8;
-+ t += 8;
-+ while (c < packet_len - 22) {
-+ if ((t[0] == 0x0d) && (t[1] == 0x0a)) {
-+ t += 2;
-+ c += 2;
-+ if ( memcmp(t, "X-Kazaa-Username: ", 18) == 0 ) return ((IPP2P_KAZAA * 100) + 2);
-+ if ( memcmp(t, "User-Agent: PeerEnabler/", 24) == 0 ) return ((IPP2P_KAZAA * 100) + 3);
-+ } else {
-+ t++;
-+ c++;
-+ }
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+/*fast check for edonkey file segment transfer command*/
-+int
-+search_edk (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ if (*(haystack+head_len) != 0xe3)
-+ return 0;
-+ else {
-+ if (*(haystack+head_len+5) == 0x47)
-+ return (IPP2P_DATA_EDK * 100);
-+ else
-+ return 0;
-+ }
-+}
-+
-+
-+
-+/*intensive but slower search for some edonkey packets including size-check*/
-+int
-+search_all_edk (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ unsigned char *t = haystack;
-+ int cmd;
-+
-+ if (*(haystack+head_len) == 0xd4) {
-+ t += head_len;
-+ cmd = get_u16(t, 1);
-+ if (cmd == (packet_len - head_len - 5)) {
-+ switch (t[5]) {
-+ case 0x82: return ((IPP2P_EDK * 100) + 42);
-+ case 0x15: return ((IPP2P_EDK * 100) + 43);
-+ default: return 0;
-+ }
-+ }
-+ return 0;
-+ }
-+
-+
-+ if (*(haystack+head_len) == 0xc5) { /*search for additional eMule packets*/
-+ t += head_len;
-+ cmd = get_u16(t, 1);
-+
-+ if (cmd == (packet_len - head_len - 5)) {
-+ switch (t[5]) {
-+ case 0x01: return ((IPP2P_EDK * 100) + 30);
-+ case 0x02: return ((IPP2P_EDK * 100) + 31);
-+ case 0x60: return ((IPP2P_EDK * 100) + 32);
-+ case 0x81: return ((IPP2P_EDK * 100) + 33);
-+ case 0x82: return ((IPP2P_EDK * 100) + 34);
-+ case 0x85: return ((IPP2P_EDK * 100) + 35);
-+ case 0x86: return ((IPP2P_EDK * 100) + 36);
-+ case 0x87: return ((IPP2P_EDK * 100) + 37);
-+ case 0x40: return ((IPP2P_EDK * 100) + 38);
-+ case 0x92: return ((IPP2P_EDK * 100) + 39);
-+ case 0x93: return ((IPP2P_EDK * 100) + 40);
-+ case 0x12: return ((IPP2P_EDK * 100) + 41);
-+ default: return 0;
-+ }
-+ }
-+
-+ return 0;
-+ }
-+
-+
-+ if (*(haystack+head_len) != 0xe3)
-+ return 0;
-+ else {
-+ t += head_len;
-+ cmd = get_u16(t, 1);
-+ if (cmd == (packet_len - head_len - 5)) {
-+ switch (t[5]) {
-+ case 0x01: return ((IPP2P_EDK * 100) + 1); /*Client: hello or Server:hello*/
-+ case 0x50: return ((IPP2P_EDK * 100) + 2); /*Client: file status*/
-+ case 0x16: return ((IPP2P_EDK * 100) + 3); /*Client: search*/
-+ case 0x58: return ((IPP2P_EDK * 100) + 4); /*Client: file request*/
-+ case 0x48: return ((IPP2P_EDK * 100) + 5); /*???*/
-+ case 0x54: return ((IPP2P_EDK * 100) + 6); /*???*/
-+ case 0x47: return ((IPP2P_EDK * 100) + 7); /*Client: file segment request*/
-+ case 0x46: return ((IPP2P_EDK * 100) + 8); /*Client: download segment*/
-+ case 0x4c: return ((IPP2P_EDK * 100) + 9); /*Client: Hello-Answer*/
-+ case 0x4f: return ((IPP2P_EDK * 100) + 10); /*Client: file status request*/
-+ case 0x59: return ((IPP2P_EDK * 100) + 11); /*Client: file request answer*/
-+ case 0x65: return ((IPP2P_EDK * 100) + 12); /*Client: ???*/
-+ case 0x66: return ((IPP2P_EDK * 100) + 13); /*Client: ???*/
-+ case 0x51: return ((IPP2P_EDK * 100) + 14); /*Client: ???*/
-+ case 0x52: return ((IPP2P_EDK * 100) + 15); /*Client: ???*/
-+ case 0x4d: return ((IPP2P_EDK * 100) + 16); /*Client: ???*/
-+ case 0x5c: return ((IPP2P_EDK * 100) + 17); /*Client: ???*/
-+ case 0x38: return ((IPP2P_EDK * 100) + 18); /*Client: ???*/
-+ case 0x69: return ((IPP2P_EDK * 100) + 19); /*Client: ???*/
-+ case 0x19: return ((IPP2P_EDK * 100) + 20); /*Client: ???*/
-+ case 0x42: return ((IPP2P_EDK * 100) + 21); /*Client: ???*/
-+ case 0x34: return ((IPP2P_EDK * 100) + 22); /*Client: ???*/
-+ case 0x94: return ((IPP2P_EDK * 100) + 23); /*Client: ???*/
-+ case 0x1c: return ((IPP2P_EDK * 100) + 24); /*Client: ???*/
-+ case 0x6a: return ((IPP2P_EDK * 100) + 25); /*Client: ???*/
-+ default: return 0;
-+ }
-+ } else {
-+ if (cmd > packet_len - head_len - 5) {
-+ if ((t[3] == 0x00) && (t[4] == 0x00)) {
-+ if (t[5] == 0x01) return ((IPP2P_EDK * 100) + 26);
-+ if (t[5] == 0x4c) return ((IPP2P_EDK * 100) + 27);
-+ }
-+ return 0;
-+
-+ } /*non edk packet*/
-+ if (t[cmd+5] == 0xe3) return ((IPP2P_EDK * 100) + 28);/*found another edk-command*/
-+ if (t[cmd+5] == 0xc5) return ((IPP2P_EDK * 100) + 29);/*found an emule-command*/
-+ return 0;
-+ }
-+ }
-+}
-+
-+
-+/*fast check for Direct Connect send command*/
-+int
-+search_dc (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ unsigned char *t = haystack;
-+
-+ if (*(haystack+head_len) != 0x24 )
-+ return 0;
-+ else {
-+ t += head_len + 1;
-+ if (memcmp(t, "Send|", 5) == 0)
-+ return (IPP2P_DATA_DC * 100);
-+ else
-+ return 0;
-+ }
-+
-+}
-+
-+
-+/*intensive but slower check for all direct connect packets*/
-+int
-+search_all_dc (unsigned char *haystack, int packet_len, int head_len)
-+{
-+ unsigned char *t = haystack;
-+
-+ if ((*(haystack + head_len) == 0x24) && (*(haystack + packet_len - 1) == 0x7c)) {
-+ t += head_len + 1;
-+ if (memcmp(t, "Lock ", 5) == 0) return ((IPP2P_DC * 100) + 1); /*hub: hello*/
-+ if (memcmp(t, "Key ", 4) == 0) return ((IPP2P_DC * 100) + 2); /*client: hello*/
-+ if (memcmp(t, "Hello ", 6) == 0) return ((IPP2P_DC * 100) + 3); /*hub:connected*/
-+ if (memcmp(t, "MyNick ", 7) == 0) return ((IPP2P_DC * 100) + 4); /*client-client: hello*/
-+ if (memcmp(t, "Search ", 7) == 0) return ((IPP2P_DC * 100) + 5); /*client: search*/
-+ if (memcmp(t, "Send", 4) == 0) return ((IPP2P_DC * 100) + 6); /*client: start download*/
-+ return 0;
-+ } else
-+ return 0;
-+}
-+
-+
-+static struct {
-+ int command;
-+ __u8 short_hand; /*for fucntions included in short hands*/
-+ int packet_len;
-+ int (*function_name) (unsigned char *, int, int);
-+} matchlist[] = {
-+ {IPP2P_EDK,SHORT_HAND_IPP2P,40, &search_all_edk},
-+ {IPP2P_DATA_KAZAA,SHORT_HAND_DATA,200, &search_kazaa},
-+ {IPP2P_DATA_EDK,SHORT_HAND_DATA,60, &search_edk},
-+ {IPP2P_DATA_DC,SHORT_HAND_DATA,26, &search_dc},
-+ {IPP2P_DC,SHORT_HAND_IPP2P,25, search_all_dc},
-+ {IPP2P_DATA_GNU,SHORT_HAND_DATA,40, &search_gnu},
-+ {IPP2P_GNU,SHORT_HAND_IPP2P,35, &search_all_gnu},
-+ {IPP2P_KAZAA,SHORT_HAND_IPP2P,35, &search_all_kazaa},
-+ {IPP2P_BIT,SHORT_HAND_NONE,40, &search_bittorrent},
-+ {IPP2P_APPLE,SHORT_HAND_NONE,20, &search_apple},
-+ {IPP2P_SOUL,SHORT_HAND_NONE,25, &search_soul},
-+ {IPP2P_WINMX,SHORT_HAND_NONE,20, &search_winmx},
-+ {IPP2P_ARES,SHORT_HAND_NONE,25, &search_ares},
-+ {0,0,0,NULL}
-+};
-+
-+
-+static struct {
-+ int command;
-+ __u8 short_hand; /*for fucntions included in short hands*/
-+ int packet_len;
-+ int (*function_name) (unsigned char *, int);
-+} udp_list[] = {
-+ {IPP2P_KAZAA,SHORT_HAND_IPP2P,14, &udp_search_kazaa},
-+ {IPP2P_BIT,SHORT_HAND_NONE,23, &udp_search_bit},
-+ {IPP2P_GNU,SHORT_HAND_IPP2P,11, &udp_search_gnu},
-+ {IPP2P_EDK,SHORT_HAND_IPP2P,9, &udp_search_edk},
-+ {0,0,0,NULL}
-+};
-+
-+
-+static int
-+match(const struct sk_buff *skb,
-+ const struct net_device *in,
-+ const struct net_device *out,
-+ const void *matchinfo,
-+ int offset,
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-+ const void *hdr,
-+ u_int16_t datalen,
-+#endif
-+
-+ int *hotdrop)
-+{
-+ const struct ipt_p2p_info *info = matchinfo;
-+ unsigned char *haystack;
-+ struct iphdr *ip = skb->nh.iph;
-+ int p2p_result = 0, i = 0;
-+ int head_len;
-+ int hlen = ntohs(ip->tot_len)-(ip->ihl*4); /*hlen = packet-data length*/
-+
-+ /*must not be a fragment*/
-+ if (offset) {
-+ if (info->debug) printk("IPP2P.match: offset found %i \n",offset);
-+ return 0;
-+ }
-+
-+ /*make sure that skb is linear*/
-+ if(skb_is_nonlinear(skb)){
-+ if (info->debug) printk("IPP2P.match: nonlinear skb found\n");
-+ return 0;
-+ }
-+
-+
-+ haystack=(char *)ip+(ip->ihl*4); /*haystack = packet data*/
-+
-+ switch (ip->protocol){
-+ case IPPROTO_TCP: /*what to do with a TCP packet*/
-+ {
-+ struct tcphdr *tcph = (void *) ip + ip->ihl * 4;
-+
-+ if (tcph->fin) return 0; /*if FIN bit is set bail out*/
-+ if (tcph->syn) return 0; /*if SYN bit is set bail out*/
-+ if (tcph->rst) return 0; /*if RST bit is set bail out*/
-+ head_len = tcph->doff * 4; /*get TCP-Header-Size*/
-+ while (matchlist[i].command) {
-+ if ((((info->cmd & matchlist[i].command) == matchlist[i].command) ||
-+ ((info->cmd & matchlist[i].short_hand) == matchlist[i].short_hand)) &&
-+ (hlen > matchlist[i].packet_len)) {
-+ p2p_result = matchlist[i].function_name(haystack, hlen, head_len);
-+ if (p2p_result)
-+ {
-+ if (info->debug) printk("IPP2P.debug:TCP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
-+ p2p_result, NIPQUAD(ip->saddr),ntohs(tcph->source), NIPQUAD(ip->daddr),ntohs(tcph->dest),hlen);
-+ return p2p_result;
-+ }
-+ }
-+ i++;
-+ }
-+ return p2p_result;
-+ }
-+
-+ case IPPROTO_UDP: /*what to do with an UDP packet*/
-+ {
-+ struct udphdr *udph = (void *) ip + ip->ihl * 4;
-+
-+ while (udp_list[i].command){
-+ if ((((info->cmd & udp_list[i].command) == udp_list[i].command) ||
-+ ((info->cmd & udp_list[i].short_hand) == udp_list[i].short_hand)) &&
-+ (hlen > udp_list[i].packet_len)) {
-+ p2p_result = udp_list[i].function_name(haystack, hlen);
-+ if (p2p_result){
-+ if (info->debug) printk("IPP2P.debug:UDP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
-+ p2p_result, NIPQUAD(ip->saddr),ntohs(udph->source), NIPQUAD(ip->daddr),ntohs(udph->dest),hlen);
-+ return p2p_result;
-+ }
-+ }
-+ i++;
-+ }
-+ return p2p_result;
-+ }
-+
-+ default: return 0;
-+ }
-+}
-+
-+
-+
-+static int
-+checkentry(const char *tablename,
-+ const struct ipt_ip *ip,
-+ void *matchinfo,
-+ unsigned int matchsize,
-+ unsigned int hook_mask)
-+{
-+ /* Must specify -p tcp */
-+/* if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
-+ * printk("ipp2p: Only works on TCP packets, use -p tcp\n");
-+ * return 0;
-+ * }*/
-+ return 1;
-+}
-+
-+
-+
-+
-+static struct ipt_match ipp2p_match = {
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-+ { NULL, NULL },
-+ "ipp2p",
-+ &match,
-+ &checkentry,
-+ NULL,
-+ THIS_MODULE
-+#endif
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-+ .name = "ipp2p",
-+ .match = &match,
-+ .checkentry = &checkentry,
-+ .me = THIS_MODULE,
-+#endif
-+};
-+
-+
-+static int __init init(void)
-+{
-+ printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION);
-+ return ipt_register_match(&ipp2p_match);
-+}
-+
-+static void __exit fini(void)
-+{
-+ ipt_unregister_match(&ipp2p_match);
-+ printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION);
-+}
-+
-+module_init(init);
-+module_exit(fini);
-+
-+
-diff -urN linux-2.4.29.old/net/ipv4/netfilter/Makefile linux-2.4.29/net/ipv4/netfilter/Makefile
---- linux-2.4.29.old/net/ipv4/netfilter/Makefile 2005-03-12 00:40:38.000000000 +0100
-+++ linux-2.4.29/net/ipv4/netfilter/Makefile 2005-03-12 00:42:57.000000000 +0100
-@@ -67,6 +67,7 @@
- obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
- obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
- obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
-+obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
-
- obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
- obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
--- /dev/null
+diff -urN linux.old/include/linux/netfilter_ipv4/ipt_ipp2p.h linux.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h
+--- linux.old/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h 2006-03-23 14:37:56.000000000 +0100
+@@ -0,0 +1,31 @@
++#ifndef __IPT_IPP2P_H
++#define __IPT_IPP2P_H
++#define IPP2P_VERSION "0.8.1_rc1"
++
++struct ipt_p2p_info {
++ int cmd;
++ int debug;
++};
++
++#endif //__IPT_IPP2P_H
++
++#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
++//#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
++#define SHORT_HAND_NONE 5 /* no short hand*/
++
++#define IPP2P_EDK (1 << 1)
++#define IPP2P_DATA_KAZAA (1 << 2)
++#define IPP2P_DATA_EDK (1 << 3)
++#define IPP2P_DATA_DC (1 << 4)
++#define IPP2P_DC (1 << 5)
++#define IPP2P_DATA_GNU (1 << 6)
++#define IPP2P_GNU (1 << 7)
++#define IPP2P_KAZAA (1 << 8)
++#define IPP2P_BIT (1 << 9)
++#define IPP2P_APPLE (1 << 10)
++#define IPP2P_SOUL (1 << 11)
++#define IPP2P_WINMX (1 << 12)
++#define IPP2P_ARES (1 << 13)
++#define IPP2P_MUTE (1 << 14)
++#define IPP2P_WASTE (1 << 15)
++#define IPP2P_XDCC (1 << 16)
+diff -urN linux.old/net/ipv4/netfilter/Config.in linux.dev/net/ipv4/netfilter/Config.in
+--- linux.old/net/ipv4/netfilter/Config.in 2006-03-23 14:35:20.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/Config.in 2006-03-23 14:35:58.000000000 +0100
+@@ -29,6 +29,7 @@
+ dep_tristate ' TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' recent match support' CONFIG_IP_NF_MATCH_RECENT $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' ECN match support' CONFIG_IP_NF_MATCH_ECN $CONFIG_IP_NF_IPTABLES
++ dep_tristate ' peer to peer traffic match support' CONFIG_IP_NF_MATCH_IPP2P $CONFIG_IP_NF_IPTABLES
+
+ dep_tristate ' DSCP match support' CONFIG_IP_NF_MATCH_DSCP $CONFIG_IP_NF_IPTABLES
+
+diff -urN linux.old/net/ipv4/netfilter/Makefile linux.dev/net/ipv4/netfilter/Makefile
+--- linux.old/net/ipv4/netfilter/Makefile 2006-03-23 14:35:20.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/Makefile 2006-03-23 14:35:58.000000000 +0100
+@@ -76,6 +76,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
+ obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
+ obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
++obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
+
+ obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
+ obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
+diff -urN linux.old/net/ipv4/netfilter/ipt_ipp2p.c linux.dev/net/ipv4/netfilter/ipt_ipp2p.c
+--- linux.old/net/ipv4/netfilter/ipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/ipt_ipp2p.c 2006-03-23 14:37:18.000000000 +0100
+@@ -0,0 +1,868 @@
++#if defined(MODVERSIONS)
++#include <linux/modversions.h>
++#endif
++#include <linux/module.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/version.h>
++#include <linux/netfilter_ipv4/ipt_ipp2p.h>
++#include <net/tcp.h>
++#include <net/udp.h>
++
++#define get_u8(X,O) (*(__u8 *)(X + O))
++#define get_u16(X,O) (*(__u16 *)(X + O))
++#define get_u32(X,O) (*(__u32 *)(X + O))
++
++MODULE_AUTHOR("Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>");
++MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
++MODULE_LICENSE("GPL");
++
++
++/*Search for UDP eDonkey/eMule/Kad commands*/
++int
++udp_search_edk (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ t += 8;
++
++ switch (t[0]) {
++ case 0xe3:
++ { /*edonkey*/
++ switch (t[1])
++ {
++ /* client -> server status request */
++ case 0x96:
++ if (packet_len == 14) return ((IPP2P_EDK * 100) + 50);
++ break;
++ /* server -> client status request */
++ case 0x97: if (packet_len == 42) return ((IPP2P_EDK * 100) + 51);
++ break;
++ /* server description request */
++ /* e3 2a ff f0 .. | size == 6 */
++ case 0xa2: if ( (packet_len == 14) && ( get_u16(t,2) == __constant_htons(0xfff0) ) ) return ((IPP2P_EDK * 100) + 52);
++ break;
++ /* server description response */
++ /* e3 a3 ff f0 .. | size > 40 && size < 200 */
++ //case 0xa3: return ((IPP2P_EDK * 100) + 53);
++ // break;
++ case 0x9a: if (packet_len==26) return ((IPP2P_EDK * 100) + 54);
++ break;
++
++ case 0x92: if (packet_len==18) return ((IPP2P_EDK * 100) + 55);
++ break;
++ }
++ break;
++ }
++ case 0xe4:
++ {
++ switch (t[1])
++ {
++ /* e4 20 .. | size == 43 */
++ case 0x20: if ((packet_len == 43) && (t[2] != 0x00) && (t[34] != 0x00)) return ((IPP2P_EDK * 100) + 60);
++ break;
++ /* e4 00 .. 00 | size == 35 ? */
++ case 0x00: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 61);
++ break;
++ /* e4 10 .. 00 | size == 35 ? */
++ case 0x10: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 62);
++ break;
++ /* e4 18 .. 00 | size == 35 ? */
++ case 0x18: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 63);
++ break;
++ /* e4 52 .. | size = 44 */
++ case 0x52: if (packet_len == 44 ) return ((IPP2P_EDK * 100) + 64);
++ break;
++ /* e4 58 .. | size == 6 */
++ case 0x58: if (packet_len == 14 ) return ((IPP2P_EDK * 100) + 65);
++ break;
++ /* e4 59 .. | size == 2 */
++ case 0x59: if (packet_len == 10 )return ((IPP2P_EDK * 100) + 66);
++ break;
++ /* e4 28 .. | packet_len == 52,77,102,127... */
++ case 0x28: if (((packet_len-52) % 25) == 0) return ((IPP2P_EDK * 100) + 67);
++ break;
++ /* e4 50 xx xx | size == 4 */
++ case 0x50: if (packet_len == 12) return ((IPP2P_EDK * 100) + 68);
++ break;
++ /* e4 40 xx xx | size == 48 */
++ case 0x40: if (packet_len == 56) return ((IPP2P_EDK * 100) + 69);
++ break;
++ }
++ break;
++ }
++ } /* end of switch (t[0]) */
++ return 0;
++}/*udp_search_edk*/
++
++
++/*Search for UDP Gnutella commands*/
++int
++udp_search_gnu (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ t += 8;
++
++ if (memcmp(t, "GND", 3) == 0) return ((IPP2P_GNU * 100) + 51);
++ if (memcmp(t, "GNUTELLA ", 9) == 0) return ((IPP2P_GNU * 100) + 52);
++ return 0;
++}/*udp_search_gnu*/
++
++
++/*Search for UDP KaZaA commands*/
++int
++udp_search_kazaa (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++
++ if (t[packet_len-1] == 0x00){
++ t += (packet_len - 6);
++ if (memcmp(t, "KaZaA", 5) == 0) return (IPP2P_KAZAA * 100 +50);
++ }
++
++ return 0;
++}/*udp_search_kazaa*/
++
++/*Search for UDP DirectConnect commands*/
++int
++udp_search_directconnect (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ if ((*(t + 8) == 0x24) && (*(t + packet_len - 1) == 0x7c)) {
++ t+=8;
++ if (memcmp(t, "SR ", 3) == 0) return ((IPP2P_DC * 100) + 60);
++ if (memcmp(t, "Ping ", 5) == 0) return ((IPP2P_DC * 100) + 61);
++ }
++ return 0;
++}/*udp_search_directconnect*/
++
++
++
++/*Search for UDP BitTorrent commands*/
++int
++udp_search_bit (unsigned char *haystack, int packet_len)
++{
++ switch(packet_len)
++ {
++ case 24:
++ /* ^ 00 00 04 17 27 10 19 80 */
++ if ((ntohl(get_u32(haystack, 8)) == 0x00000417) && (ntohl(get_u32(haystack, 12)) == 0x27101980))
++ return (IPP2P_BIT * 100 + 50);
++ break;
++ case 44:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000400) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 51);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000400))
++ return (IPP2P_BIT * 100 + 61);
++ break;
++ case 65:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000404) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 52);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000404))
++ return (IPP2P_BIT * 100 + 62);
++ break;
++ case 67:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000406) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 53);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000406))
++ return (IPP2P_BIT * 100 + 63);
++ break;
++ case 211:
++ if (get_u32(haystack, 8) == __constant_htonl(0x00000405))
++ return (IPP2P_BIT * 100 + 54);
++ break;
++ case 29:
++ if ((get_u32(haystack, 8) == __constant_htonl(0x00000401)))
++ return (IPP2P_BIT * 100 + 55);
++ break;
++ case 52:
++ if (get_u32(haystack,8) == __constant_htonl(0x00000827) &&
++ get_u32(haystack,12) == __constant_htonl(0x37502950))
++ return (IPP2P_BIT * 100 + 80);
++ break;
++ default:
++ /* this packet does not have a constant size */
++ if (packet_len >= 40 && get_u32(haystack, 16) == __constant_htonl(0x00000402) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 56);
++ break;
++ }
++
++ /* some extra-bitcomet rules:
++ * "d1:" [a|r] "d2:id20:"
++ */
++ if (packet_len > 30 && get_u8(haystack, 8) == 'd' && get_u8(haystack, 9) == '1' && get_u8(haystack, 10) == ':' )
++ {
++ if (get_u8(haystack, 11) == 'a' || get_u8(haystack, 11) == 'r')
++ {
++ if (memcmp(haystack+12,"d2:id20:",8)==0)
++ return (IPP2P_BIT * 100 + 57);
++ }
++ }
++
++#if 0
++ /* bitlord rules */
++ /* packetlen must be bigger than 40 */
++ /* first 4 bytes are zero */
++ if (packet_len > 40 && get_u32(haystack, 8) == 0x00000000)
++ {
++ /* first rule: 00 00 00 00 01 00 00 xx xx xx xx 00 00 00 00*/
++ if (get_u32(haystack, 12) == 0x00000000 &&
++ get_u32(haystack, 16) == 0x00010000 &&
++ get_u32(haystack, 24) == 0x00000000 )
++ return (IPP2P_BIT * 100 + 71);
++
++ /* 00 01 00 00 0d 00 00 xx xx xx xx 00 00 00 00*/
++ if (get_u32(haystack, 12) == 0x00000001 &&
++ get_u32(haystack, 16) == 0x000d0000 &&
++ get_u32(haystack, 24) == 0x00000000 )
++ return (IPP2P_BIT * 100 + 71);
++
++
++ }
++#endif
++
++ return 0;
++}/*udp_search_bit*/
++
++
++
++/*Search for Ares commands*/
++//#define IPP2P_DEBUG_ARES
++int
++search_ares (const unsigned char *payload, const u16 plen)
++//int search_ares (unsigned char *haystack, int packet_len, int head_len)
++{
++// const unsigned char *t = haystack + head_len;
++
++ /* all ares packets start with */
++ if (payload[1] == 0 && (plen - payload[0]) == 3)
++ {
++ switch (payload[2])
++ {
++ case 0x5a:
++ /* ares connect */
++ if ( plen == 6 && payload[5] == 0x05 ) return ((IPP2P_ARES * 100) + 1);
++ break;
++ case 0x09:
++ /* ares search, min 3 chars --> 14 bytes
++ * lets define a search can be up to 30 chars --> max 34 bytes
++ */
++ if ( plen >= 14 && plen <= 34 ) return ((IPP2P_ARES * 100) + 1);
++ break;
++#ifdef IPP2P_DEBUG_ARES
++ default:
++ printk(KERN_DEBUG "Unknown Ares command %x recognized, len: %u \n", (unsigned int) payload[2],plen);
++#endif /* IPP2P_DEBUG_ARES */
++ }
++ }
++
++#if 0
++ /* found connect packet: 03 00 5a 04 03 05 */
++ /* new version ares 1.8: 03 00 5a xx xx 05 */
++ if ((plen) == 6){ /* possible connect command*/
++ if ((payload[0] == 0x03) && (payload[1] == 0x00) && (payload[2] == 0x5a) && (payload[5] == 0x05))
++ return ((IPP2P_ARES * 100) + 1);
++ }
++ if ((plen) == 60){ /* possible download command*/
++ if ((payload[59] == 0x0a) && (payload[58] == 0x0a)){
++ if (memcmp(t, "PUSH SHA1:", 10) == 0) /* found download command */
++ return ((IPP2P_ARES * 100) + 2);
++ }
++ }
++#endif
++
++ return 0;
++} /*search_ares*/
++
++/*Search for SoulSeek commands*/
++int
++search_soul (const unsigned char *payload, const u16 plen)
++{
++//#define IPP2P_DEBUG_SOUL
++ /* match: xx xx xx xx | xx = sizeof(payload) - 4 */
++ if (get_u32(payload, 0) == (plen - 4)){
++ const __u32 m=get_u32(payload, 4);
++ /* match 00 yy yy 00, yy can be everything */
++ if ( get_u8(payload, 4) == 0x00 && get_u8(payload, 7) == 0x00 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "0: Soulseek command 0x%x recognized\n",get_u32(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 1);
++ }
++
++ /* next match: 01 yy 00 00 | yy can be everything */
++ if ( get_u8(payload, 4) == 0x01 && get_u16(payload, 6) == 0x0000 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "1: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 2);
++ }
++
++ /* 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 */
++ /* try to do this in an intelligent way */
++ /* get all small commandos */
++ switch(m)
++ {
++ case 7:
++ case 9:
++ case 22:
++ case 23:
++ case 26:
++ case 28:
++ case 50:
++ case 51:
++ case 60:
++ case 91:
++ case 92:
++ case 1001:
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "2: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 3);
++ }
++
++ if (m > 0 && m < 6 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "3: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 4);
++ }
++ if (m > 12 && m < 19 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "4: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 5);
++ }
++
++ if (m > 34 && m < 38 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "5: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 6);
++ }
++
++ if (m > 39 && m < 47 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "6: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 7);
++ }
++
++ if (m > 61 && m < 70 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "7: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 8);
++ }
++
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "unknown SOULSEEK command: 0x%x, first 16 bit: 0x%x, first 8 bit: 0x%x ,soulseek ???\n",get_u32(payload, 4),get_u16(payload, 4) >> 16,get_u8(payload, 4) >> 24);
++#endif /* IPP2P_DEBUG_SOUL */
++ }
++
++ /* match 14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00 */
++ /* without size at the beginning !!! */
++ if ( get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01 )
++ {
++ __u32 y=get_u32(payload, 5);
++ /* we need 19 chars + string */
++ if ( (y + 19) <= (plen) )
++ {
++ const unsigned char *w=payload+9+y;
++ if (get_u32(w, 0) == 0x01 && ( get_u16(w, 4) == 0x4600 || get_u16(w, 4) == 0x5000) && get_u32(w, 6) == 0x00);
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "Soulssek special client command recognized\n");
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 9);
++ }
++ }
++ return 0;
++}
++
++
++/*Search for WinMX commands*/
++int
++search_winmx (const unsigned char *payload, const u16 plen)
++{
++//#define IPP2P_DEBUG_WINMX
++ if (((plen) == 4) && (memcmp(payload, "SEND", 4) == 0)) return ((IPP2P_WINMX * 100) + 1);
++ if (((plen) == 3) && (memcmp(payload, "GET", 3) == 0)) return ((IPP2P_WINMX * 100) + 2);
++ //if (packet_len < (head_len + 10)) return 0;
++ if (plen < 10) return 0;
++
++ if ((memcmp(payload, "SEND", 4) == 0) || (memcmp(payload, "GET", 3) == 0)){
++ u16 c=4;
++ const u16 end=plen-2;
++ u8 count=0;
++ while (c < end)
++ {
++ if (payload[c]== 0x20 && payload[c+1] == 0x22)
++ {
++ c++;
++ count++;
++ if (count>=2) return ((IPP2P_WINMX * 100) + 3);
++ }
++ c++;
++ }
++ }
++
++ if ( plen == 149 && payload[0] == '8' )
++ {
++#ifdef IPP2P_DEBUG_WINMX
++ printk(KERN_INFO "maybe WinMX\n");
++#endif
++ if (get_u32(payload,17) == 0 && get_u32(payload,21) == 0 && get_u32(payload,25) == 0 &&
++// get_u32(payload,33) == __constant_htonl(0x71182b1a) && get_u32(payload,37) == __constant_htonl(0x05050000) &&
++// get_u32(payload,133) == __constant_htonl(0x31097edf) && get_u32(payload,145) == __constant_htonl(0xdcb8f792))
++ get_u16(payload,39) == 0 && get_u16(payload,135) == __constant_htons(0x7edf) && get_u16(payload,147) == __constant_htons(0xf792))
++
++ {
++#ifdef IPP2P_DEBUG_WINMX
++ printk(KERN_INFO "got WinMX\n");
++#endif
++ return ((IPP2P_WINMX * 100) + 4);
++ }
++ }
++ return 0;
++} /*search_winmx*/
++
++
++/*Search for appleJuice commands*/
++int
++search_apple (const unsigned char *payload, const u16 plen)
++{
++ if ( (plen > 7) && (payload[6] == 0x0d) && (payload[7] == 0x0a) && (memcmp(payload, "ajprot", 6) == 0)) return (IPP2P_APPLE * 100);
++
++ return 0;
++}
++
++
++/*Search for BitTorrent commands*/
++int
++search_bittorrent (const unsigned char *payload, const u16 plen)
++{
++ if (plen > 20)
++ {
++ /* test for match 0x13+"BitTorrent protocol" */
++ if (payload[0] == 0x13)
++ {
++ if (memcmp(payload+1, "BitTorrent protocol", 19) == 0) return (IPP2P_BIT * 100);
++ }
++
++ /* get tracker commandos, all starts with GET /
++ * then it can follow: scrape| announce
++ * and then ?hash_info=
++ */
++ if (memcmp(payload,"GET /",5) == 0)
++ {
++ /* message scrape */
++ if ( memcmp(payload+5,"scrape?info_hash=",17)==0 ) return (IPP2P_BIT * 100 + 1);
++ /* message announce */
++ if ( memcmp(payload+5,"announce?info_hash=",19)==0 ) return (IPP2P_BIT * 100 + 2);
++ }
++ }
++ else
++ {
++ /* bitcomet encryptes the first packet, so we have to detect another
++ * one later in the flow */
++ /* first try failed, too many missdetections */
++ //if ( size == 5 && get_u32(t,0) == __constant_htonl(1) && t[4] < 3) return (IPP2P_BIT * 100 + 3);
++
++ /* second try: block request packets */
++ if ( plen == 17 && get_u32(payload,0) == __constant_htonl(0x0d) && payload[4] == 0x06 && get_u32(payload,13) == __constant_htonl(0x4000) ) return (IPP2P_BIT * 100 + 3);
++ }
++
++ return 0;
++}
++
++
++
++/*check for Kazaa get command*/
++int
++search_kazaa (const unsigned char *payload, const u16 plen)
++
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a) && memcmp(payload, "GET /.hash=", 11) == 0)
++ return (IPP2P_DATA_KAZAA * 100);
++
++ return 0;
++}
++
++
++/*check for gnutella get command*/
++int
++search_gnu (const unsigned char *payload, const u16 plen)
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++ if (memcmp(payload, "GET /get/", 9) == 0) return ((IPP2P_DATA_GNU * 100) + 1);
++ if (memcmp(payload, "GET /uri-res/", 13) == 0) return ((IPP2P_DATA_GNU * 100) + 2);
++ }
++ return 0;
++}
++
++
++/*check for gnutella get commands and other typical data*/
++int
++search_all_gnu (const unsigned char *payload, const u16 plen)
++{
++
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++
++ if (memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) return ((IPP2P_GNU * 100) + 1);
++ if (memcmp(payload, "GNUTELLA/", 9) == 0) return ((IPP2P_GNU * 100) + 2);
++
++
++ if ((memcmp(payload, "GET /get/", 9) == 0) || (memcmp(payload, "GET /uri-res/", 13) == 0))
++ {
++ u16 c=8;
++ const u16 end=plen-22;
++ while (c < end) {
++ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Gnutella-", 11) == 0) || (memcmp(&payload[c+2], "X-Queue:", 8) == 0)))
++ return ((IPP2P_GNU * 100) + 3);
++ c++;
++ }
++ }
++ }
++ return 0;
++}
++
++
++/*check for KaZaA download commands and other typical data*/
++int
++search_all_kazaa (const unsigned char *payload, const u16 plen)
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++
++ if (memcmp(payload, "GIVE ", 5) == 0) return ((IPP2P_KAZAA * 100) + 1);
++
++ if (memcmp(payload, "GET /", 5) == 0) {
++ u16 c = 8;
++ const u16 end=plen-22;
++ while (c < end) {
++ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0) || (memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0)))
++ return ((IPP2P_KAZAA * 100) + 2);
++ c++;
++ }
++ }
++ }
++ return 0;
++}
++
++/*fast check for edonkey file segment transfer command*/
++int
++search_edk (const unsigned char *payload, const u16 plen)
++{
++ if (payload[0] != 0xe3)
++ return 0;
++ else {
++ if (payload[5] == 0x47)
++ return (IPP2P_DATA_EDK * 100);
++ else
++ return 0;
++ }
++}
++
++
++
++/*intensive but slower search for some edonkey packets including size-check*/
++int
++search_all_edk (const unsigned char *payload, const u16 plen)
++{
++ if (payload[0] != 0xe3)
++ return 0;
++ else {
++ //t += head_len;
++ const u16 cmd = get_u16(payload, 1);
++ if (cmd == (plen - 5)) {
++ switch (payload[5]) {
++ case 0x01: return ((IPP2P_EDK * 100) + 1); /*Client: hello or Server:hello*/
++ case 0x4c: return ((IPP2P_EDK * 100) + 9); /*Client: Hello-Answer*/
++ }
++ }
++ return 0;
++ }
++}
++
++
++/*fast check for Direct Connect send command*/
++int
++search_dc (const unsigned char *payload, const u16 plen)
++{
++
++ if (payload[0] != 0x24 )
++ return 0;
++ else {
++ if (memcmp(&payload[1], "Send|", 5) == 0)
++ return (IPP2P_DATA_DC * 100);
++ else
++ return 0;
++ }
++
++}
++
++
++/*intensive but slower check for all direct connect packets*/
++int
++search_all_dc (const unsigned char *payload, const u16 plen)
++{
++// unsigned char *t = haystack;
++
++ if (payload[0] == 0x24 && payload[plen-1] == 0x7c)
++ {
++ const unsigned char *t=&payload[1];
++ /* Client-Hub-Protocol */
++ if (memcmp(t, "Lock ", 5) == 0) return ((IPP2P_DC * 100) + 1);
++ /* Client-Client-Protocol, some are already recognized by client-hub (like lock) */
++ if (memcmp(t, "MyNick ", 7) == 0) return ((IPP2P_DC * 100) + 38);
++ }
++ return 0;
++}
++
++/*check for mute*/
++int
++search_mute (const unsigned char *payload, const u16 plen)
++{
++ if ( plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121 )
++ {
++ //printk(KERN_DEBUG "size hit: %u",size);
++ if (memcmp(payload,"PublicKey: ",11) == 0 )
++ {
++ return ((IPP2P_MUTE * 100) + 0);
++
++/* if (memcmp(t+size-14,"\x0aEndPublicKey\x0a",14) == 0)
++ {
++ printk(KERN_DEBUG "end pubic key hit: %u",size);
++
++ }*/
++ }
++ }
++ return 0;
++}
++
++
++/* check for xdcc */
++int
++search_xdcc (const unsigned char *payload, const u16 plen)
++{
++ /* search in small packets only */
++ if (plen > 20 && plen < 200 && payload[plen-1] == 0x0a && payload[plen-2] == 0x0d && memcmp(payload,"PRIVMSG ",8) == 0)
++ {
++
++ u16 x=10;
++ const u16 end=plen - 13;
++
++ /* is seems to be a irc private massage, chedck for xdcc command */
++ while (x < end)
++ {
++ if (payload[x] == ':')
++ {
++ if ( memcmp(&payload[x+1],"xdcc send #",11) == 0 )
++ return ((IPP2P_XDCC * 100) + 0);
++ }
++ x++;
++ }
++ }
++ return 0;
++}
++
++/* search for waste */
++int search_waste(const unsigned char *payload, const u16 plen)
++{
++ if ( plen >= 8 && memcmp(payload,"GET.sha1:",9) == 0)
++ return ((IPP2P_WASTE * 100) + 0);
++
++ return 0;
++}
++
++
++static struct {
++ int command;
++ __u8 short_hand; /*for fucntions included in short hands*/
++ int packet_len;
++ int (*function_name) (const unsigned char *, const u16);
++} matchlist[] = {
++ {IPP2P_EDK,SHORT_HAND_IPP2P,20, &search_all_edk},
++// {IPP2P_DATA_KAZAA,SHORT_HAND_DATA,200, &search_kazaa},
++// {IPP2P_DATA_EDK,SHORT_HAND_DATA,60, &search_edk},
++// {IPP2P_DATA_DC,SHORT_HAND_DATA,26, &search_dc},
++ {IPP2P_DC,SHORT_HAND_IPP2P,5, search_all_dc},
++// {IPP2P_DATA_GNU,SHORT_HAND_DATA,40, &search_gnu},
++ {IPP2P_GNU,SHORT_HAND_IPP2P,5, &search_all_gnu},
++ {IPP2P_KAZAA,SHORT_HAND_IPP2P,5, &search_all_kazaa},
++ {IPP2P_BIT,SHORT_HAND_IPP2P,20, &search_bittorrent},
++ {IPP2P_APPLE,SHORT_HAND_IPP2P,5, &search_apple},
++ {IPP2P_SOUL,SHORT_HAND_IPP2P,5, &search_soul},
++ {IPP2P_WINMX,SHORT_HAND_IPP2P,2, &search_winmx},
++ {IPP2P_ARES,SHORT_HAND_IPP2P,5, &search_ares},
++ {IPP2P_MUTE,SHORT_HAND_NONE,200, &search_mute},
++ {IPP2P_WASTE,SHORT_HAND_NONE,5, &search_waste},
++ {IPP2P_XDCC,SHORT_HAND_NONE,5, &search_xdcc},
++ {0,0,0,NULL}
++};
++
++
++static struct {
++ int command;
++ __u8 short_hand; /*for fucntions included in short hands*/
++ int packet_len;
++ int (*function_name) (unsigned char *, int);
++} udp_list[] = {
++ {IPP2P_KAZAA,SHORT_HAND_IPP2P,14, &udp_search_kazaa},
++ {IPP2P_BIT,SHORT_HAND_IPP2P,23, &udp_search_bit},
++ {IPP2P_GNU,SHORT_HAND_IPP2P,11, &udp_search_gnu},
++ {IPP2P_EDK,SHORT_HAND_IPP2P,9, &udp_search_edk},
++ {IPP2P_DC,SHORT_HAND_IPP2P,12, &udp_search_directconnect},
++ {0,0,0,NULL}
++};
++
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++ const void *hdr,
++ u_int16_t datalen,
++#endif
++
++ int *hotdrop)
++{
++ const struct ipt_p2p_info *info = matchinfo;
++ unsigned char *haystack;
++ struct iphdr *ip = skb->nh.iph;
++ int p2p_result = 0, i = 0;
++// int head_len;
++ int hlen = ntohs(ip->tot_len)-(ip->ihl*4); /*hlen = packet-data length*/
++
++ /*must not be a fragment*/
++ if (offset) {
++ if (info->debug) printk("IPP2P.match: offset found %i \n",offset);
++ return 0;
++ }
++
++ /*make sure that skb is linear*/
++ if(skb_is_nonlinear(skb)){
++ if (info->debug) printk("IPP2P.match: nonlinear skb found\n");
++ return 0;
++ }
++
++
++ haystack=(char *)ip+(ip->ihl*4); /*haystack = packet data*/
++
++ switch (ip->protocol){
++ case IPPROTO_TCP: /*what to do with a TCP packet*/
++ {
++ struct tcphdr *tcph = (void *) ip + ip->ihl * 4;
++
++ if (tcph->fin) return 0; /*if FIN bit is set bail out*/
++ if (tcph->syn) return 0; /*if SYN bit is set bail out*/
++ if (tcph->rst) return 0; /*if RST bit is set bail out*/
++
++ haystack += tcph->doff * 4; /*get TCP-Header-Size*/
++ hlen -= tcph->doff * 4;
++ while (matchlist[i].command) {
++ if ((((info->cmd & matchlist[i].command) == matchlist[i].command) ||
++ ((info->cmd & matchlist[i].short_hand) == matchlist[i].short_hand)) &&
++ (hlen > matchlist[i].packet_len)) {
++ p2p_result = matchlist[i].function_name(haystack, hlen);
++ if (p2p_result)
++ {
++ if (info->debug) printk("IPP2P.debug:TCP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
++ p2p_result, NIPQUAD(ip->saddr),ntohs(tcph->source), NIPQUAD(ip->daddr),ntohs(tcph->dest),hlen);
++ return p2p_result;
++ }
++ }
++ i++;
++ }
++ return p2p_result;
++ }
++
++ case IPPROTO_UDP: /*what to do with an UDP packet*/
++ {
++ struct udphdr *udph = (void *) ip + ip->ihl * 4;
++
++ while (udp_list[i].command){
++ if ((((info->cmd & udp_list[i].command) == udp_list[i].command) ||
++ ((info->cmd & udp_list[i].short_hand) == udp_list[i].short_hand)) &&
++ (hlen > udp_list[i].packet_len)) {
++ p2p_result = udp_list[i].function_name(haystack, hlen);
++ if (p2p_result){
++ if (info->debug) printk("IPP2P.debug:UDP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
++ p2p_result, NIPQUAD(ip->saddr),ntohs(udph->source), NIPQUAD(ip->daddr),ntohs(udph->dest),hlen);
++ return p2p_result;
++ }
++ }
++ i++;
++ }
++ return p2p_result;
++ }
++
++ default: return 0;
++ }
++}
++
++
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ /* Must specify -p tcp */
++/* if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
++ * printk("ipp2p: Only works on TCP packets, use -p tcp\n");
++ * return 0;
++ * }*/
++ return 1;
++}
++
++
++
++
++static struct ipt_match ipp2p_match = {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++ { NULL, NULL },
++ "ipp2p",
++ &match,
++ &checkentry,
++ NULL,
++ THIS_MODULE
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++ .name = "ipp2p",
++ .match = &match,
++ .checkentry = &checkentry,
++ .me = THIS_MODULE,
++#endif
++};
++
++
++static int __init init(void)
++{
++ printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION);
++ return ipt_register_match(&ipp2p_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&ipp2p_match);
++ printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION);
++}
++
++module_init(init);
++module_exit(fini);
++
++
--- /dev/null
+diff -urN linux.old/include/linux/netfilter_ipv4/ipt_ipp2p.h linux.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h
+--- linux.old/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h 2006-03-23 15:24:47.000000000 +0100
+@@ -0,0 +1,31 @@
++#ifndef __IPT_IPP2P_H
++#define __IPT_IPP2P_H
++#define IPP2P_VERSION "0.8.1_rc1"
++
++struct ipt_p2p_info {
++ int cmd;
++ int debug;
++};
++
++#endif //__IPT_IPP2P_H
++
++#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
++//#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
++#define SHORT_HAND_NONE 5 /* no short hand*/
++
++#define IPP2P_EDK (1 << 1)
++#define IPP2P_DATA_KAZAA (1 << 2)
++#define IPP2P_DATA_EDK (1 << 3)
++#define IPP2P_DATA_DC (1 << 4)
++#define IPP2P_DC (1 << 5)
++#define IPP2P_DATA_GNU (1 << 6)
++#define IPP2P_GNU (1 << 7)
++#define IPP2P_KAZAA (1 << 8)
++#define IPP2P_BIT (1 << 9)
++#define IPP2P_APPLE (1 << 10)
++#define IPP2P_SOUL (1 << 11)
++#define IPP2P_WINMX (1 << 12)
++#define IPP2P_ARES (1 << 13)
++#define IPP2P_MUTE (1 << 14)
++#define IPP2P_WASTE (1 << 15)
++#define IPP2P_XDCC (1 << 16)
+diff -urN linux.old/net/ipv4/netfilter/Kconfig linux.dev/net/ipv4/netfilter/Kconfig
+--- linux.old/net/ipv4/netfilter/Kconfig 2006-03-23 15:21:19.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/Kconfig 2006-03-23 15:26:29.000000000 +0100
+@@ -229,6 +229,12 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP_NF_MATCH_IPP2P
++ tristate "IPP2P"
++ depends on IP_NF_IPTABLES
++ help
++ Module for matching traffic of various Peer-to-Peer applications
++
+ config IP_NF_MATCH_TOS
+ tristate "TOS match support"
+ depends on IP_NF_IPTABLES
+diff -urN linux.old/net/ipv4/netfilter/Makefile linux.dev/net/ipv4/netfilter/Makefile
+--- linux.old/net/ipv4/netfilter/Makefile 2006-03-23 15:21:19.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/Makefile 2006-03-23 15:27:00.000000000 +0100
+@@ -49,6 +49,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
+ obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set.o
+ obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
++obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
+ obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
+ obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
+ obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
+diff -urN linux.old/net/ipv4/netfilter/ipt_ipp2p.c linux.dev/net/ipv4/netfilter/ipt_ipp2p.c
+--- linux.old/net/ipv4/netfilter/ipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/net/ipv4/netfilter/ipt_ipp2p.c 2006-03-23 15:24:47.000000000 +0100
+@@ -0,0 +1,868 @@
++#if defined(MODVERSIONS)
++#include <linux/modversions.h>
++#endif
++#include <linux/module.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/version.h>
++#include <linux/netfilter_ipv4/ipt_ipp2p.h>
++#include <net/tcp.h>
++#include <net/udp.h>
++
++#define get_u8(X,O) (*(__u8 *)(X + O))
++#define get_u16(X,O) (*(__u16 *)(X + O))
++#define get_u32(X,O) (*(__u32 *)(X + O))
++
++MODULE_AUTHOR("Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>");
++MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
++MODULE_LICENSE("GPL");
++
++
++/*Search for UDP eDonkey/eMule/Kad commands*/
++int
++udp_search_edk (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ t += 8;
++
++ switch (t[0]) {
++ case 0xe3:
++ { /*edonkey*/
++ switch (t[1])
++ {
++ /* client -> server status request */
++ case 0x96:
++ if (packet_len == 14) return ((IPP2P_EDK * 100) + 50);
++ break;
++ /* server -> client status request */
++ case 0x97: if (packet_len == 42) return ((IPP2P_EDK * 100) + 51);
++ break;
++ /* server description request */
++ /* e3 2a ff f0 .. | size == 6 */
++ case 0xa2: if ( (packet_len == 14) && ( get_u16(t,2) == __constant_htons(0xfff0) ) ) return ((IPP2P_EDK * 100) + 52);
++ break;
++ /* server description response */
++ /* e3 a3 ff f0 .. | size > 40 && size < 200 */
++ //case 0xa3: return ((IPP2P_EDK * 100) + 53);
++ // break;
++ case 0x9a: if (packet_len==26) return ((IPP2P_EDK * 100) + 54);
++ break;
++
++ case 0x92: if (packet_len==18) return ((IPP2P_EDK * 100) + 55);
++ break;
++ }
++ break;
++ }
++ case 0xe4:
++ {
++ switch (t[1])
++ {
++ /* e4 20 .. | size == 43 */
++ case 0x20: if ((packet_len == 43) && (t[2] != 0x00) && (t[34] != 0x00)) return ((IPP2P_EDK * 100) + 60);
++ break;
++ /* e4 00 .. 00 | size == 35 ? */
++ case 0x00: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 61);
++ break;
++ /* e4 10 .. 00 | size == 35 ? */
++ case 0x10: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 62);
++ break;
++ /* e4 18 .. 00 | size == 35 ? */
++ case 0x18: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 63);
++ break;
++ /* e4 52 .. | size = 44 */
++ case 0x52: if (packet_len == 44 ) return ((IPP2P_EDK * 100) + 64);
++ break;
++ /* e4 58 .. | size == 6 */
++ case 0x58: if (packet_len == 14 ) return ((IPP2P_EDK * 100) + 65);
++ break;
++ /* e4 59 .. | size == 2 */
++ case 0x59: if (packet_len == 10 )return ((IPP2P_EDK * 100) + 66);
++ break;
++ /* e4 28 .. | packet_len == 52,77,102,127... */
++ case 0x28: if (((packet_len-52) % 25) == 0) return ((IPP2P_EDK * 100) + 67);
++ break;
++ /* e4 50 xx xx | size == 4 */
++ case 0x50: if (packet_len == 12) return ((IPP2P_EDK * 100) + 68);
++ break;
++ /* e4 40 xx xx | size == 48 */
++ case 0x40: if (packet_len == 56) return ((IPP2P_EDK * 100) + 69);
++ break;
++ }
++ break;
++ }
++ } /* end of switch (t[0]) */
++ return 0;
++}/*udp_search_edk*/
++
++
++/*Search for UDP Gnutella commands*/
++int
++udp_search_gnu (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ t += 8;
++
++ if (memcmp(t, "GND", 3) == 0) return ((IPP2P_GNU * 100) + 51);
++ if (memcmp(t, "GNUTELLA ", 9) == 0) return ((IPP2P_GNU * 100) + 52);
++ return 0;
++}/*udp_search_gnu*/
++
++
++/*Search for UDP KaZaA commands*/
++int
++udp_search_kazaa (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++
++ if (t[packet_len-1] == 0x00){
++ t += (packet_len - 6);
++ if (memcmp(t, "KaZaA", 5) == 0) return (IPP2P_KAZAA * 100 +50);
++ }
++
++ return 0;
++}/*udp_search_kazaa*/
++
++/*Search for UDP DirectConnect commands*/
++int
++udp_search_directconnect (unsigned char *haystack, int packet_len)
++{
++ unsigned char *t = haystack;
++ if ((*(t + 8) == 0x24) && (*(t + packet_len - 1) == 0x7c)) {
++ t+=8;
++ if (memcmp(t, "SR ", 3) == 0) return ((IPP2P_DC * 100) + 60);
++ if (memcmp(t, "Ping ", 5) == 0) return ((IPP2P_DC * 100) + 61);
++ }
++ return 0;
++}/*udp_search_directconnect*/
++
++
++
++/*Search for UDP BitTorrent commands*/
++int
++udp_search_bit (unsigned char *haystack, int packet_len)
++{
++ switch(packet_len)
++ {
++ case 24:
++ /* ^ 00 00 04 17 27 10 19 80 */
++ if ((ntohl(get_u32(haystack, 8)) == 0x00000417) && (ntohl(get_u32(haystack, 12)) == 0x27101980))
++ return (IPP2P_BIT * 100 + 50);
++ break;
++ case 44:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000400) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 51);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000400))
++ return (IPP2P_BIT * 100 + 61);
++ break;
++ case 65:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000404) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 52);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000404))
++ return (IPP2P_BIT * 100 + 62);
++ break;
++ case 67:
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000406) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 53);
++ if (get_u32(haystack, 16) == __constant_htonl(0x00000406))
++ return (IPP2P_BIT * 100 + 63);
++ break;
++ case 211:
++ if (get_u32(haystack, 8) == __constant_htonl(0x00000405))
++ return (IPP2P_BIT * 100 + 54);
++ break;
++ case 29:
++ if ((get_u32(haystack, 8) == __constant_htonl(0x00000401)))
++ return (IPP2P_BIT * 100 + 55);
++ break;
++ case 52:
++ if (get_u32(haystack,8) == __constant_htonl(0x00000827) &&
++ get_u32(haystack,12) == __constant_htonl(0x37502950))
++ return (IPP2P_BIT * 100 + 80);
++ break;
++ default:
++ /* this packet does not have a constant size */
++ if (packet_len >= 40 && get_u32(haystack, 16) == __constant_htonl(0x00000402) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
++ return (IPP2P_BIT * 100 + 56);
++ break;
++ }
++
++ /* some extra-bitcomet rules:
++ * "d1:" [a|r] "d2:id20:"
++ */
++ if (packet_len > 30 && get_u8(haystack, 8) == 'd' && get_u8(haystack, 9) == '1' && get_u8(haystack, 10) == ':' )
++ {
++ if (get_u8(haystack, 11) == 'a' || get_u8(haystack, 11) == 'r')
++ {
++ if (memcmp(haystack+12,"d2:id20:",8)==0)
++ return (IPP2P_BIT * 100 + 57);
++ }
++ }
++
++#if 0
++ /* bitlord rules */
++ /* packetlen must be bigger than 40 */
++ /* first 4 bytes are zero */
++ if (packet_len > 40 && get_u32(haystack, 8) == 0x00000000)
++ {
++ /* first rule: 00 00 00 00 01 00 00 xx xx xx xx 00 00 00 00*/
++ if (get_u32(haystack, 12) == 0x00000000 &&
++ get_u32(haystack, 16) == 0x00010000 &&
++ get_u32(haystack, 24) == 0x00000000 )
++ return (IPP2P_BIT * 100 + 71);
++
++ /* 00 01 00 00 0d 00 00 xx xx xx xx 00 00 00 00*/
++ if (get_u32(haystack, 12) == 0x00000001 &&
++ get_u32(haystack, 16) == 0x000d0000 &&
++ get_u32(haystack, 24) == 0x00000000 )
++ return (IPP2P_BIT * 100 + 71);
++
++
++ }
++#endif
++
++ return 0;
++}/*udp_search_bit*/
++
++
++
++/*Search for Ares commands*/
++//#define IPP2P_DEBUG_ARES
++int
++search_ares (const unsigned char *payload, const u16 plen)
++//int search_ares (unsigned char *haystack, int packet_len, int head_len)
++{
++// const unsigned char *t = haystack + head_len;
++
++ /* all ares packets start with */
++ if (payload[1] == 0 && (plen - payload[0]) == 3)
++ {
++ switch (payload[2])
++ {
++ case 0x5a:
++ /* ares connect */
++ if ( plen == 6 && payload[5] == 0x05 ) return ((IPP2P_ARES * 100) + 1);
++ break;
++ case 0x09:
++ /* ares search, min 3 chars --> 14 bytes
++ * lets define a search can be up to 30 chars --> max 34 bytes
++ */
++ if ( plen >= 14 && plen <= 34 ) return ((IPP2P_ARES * 100) + 1);
++ break;
++#ifdef IPP2P_DEBUG_ARES
++ default:
++ printk(KERN_DEBUG "Unknown Ares command %x recognized, len: %u \n", (unsigned int) payload[2],plen);
++#endif /* IPP2P_DEBUG_ARES */
++ }
++ }
++
++#if 0
++ /* found connect packet: 03 00 5a 04 03 05 */
++ /* new version ares 1.8: 03 00 5a xx xx 05 */
++ if ((plen) == 6){ /* possible connect command*/
++ if ((payload[0] == 0x03) && (payload[1] == 0x00) && (payload[2] == 0x5a) && (payload[5] == 0x05))
++ return ((IPP2P_ARES * 100) + 1);
++ }
++ if ((plen) == 60){ /* possible download command*/
++ if ((payload[59] == 0x0a) && (payload[58] == 0x0a)){
++ if (memcmp(t, "PUSH SHA1:", 10) == 0) /* found download command */
++ return ((IPP2P_ARES * 100) + 2);
++ }
++ }
++#endif
++
++ return 0;
++} /*search_ares*/
++
++/*Search for SoulSeek commands*/
++int
++search_soul (const unsigned char *payload, const u16 plen)
++{
++//#define IPP2P_DEBUG_SOUL
++ /* match: xx xx xx xx | xx = sizeof(payload) - 4 */
++ if (get_u32(payload, 0) == (plen - 4)){
++ const __u32 m=get_u32(payload, 4);
++ /* match 00 yy yy 00, yy can be everything */
++ if ( get_u8(payload, 4) == 0x00 && get_u8(payload, 7) == 0x00 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "0: Soulseek command 0x%x recognized\n",get_u32(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 1);
++ }
++
++ /* next match: 01 yy 00 00 | yy can be everything */
++ if ( get_u8(payload, 4) == 0x01 && get_u16(payload, 6) == 0x0000 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "1: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 2);
++ }
++
++ /* 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 */
++ /* try to do this in an intelligent way */
++ /* get all small commandos */
++ switch(m)
++ {
++ case 7:
++ case 9:
++ case 22:
++ case 23:
++ case 26:
++ case 28:
++ case 50:
++ case 51:
++ case 60:
++ case 91:
++ case 92:
++ case 1001:
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "2: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 3);
++ }
++
++ if (m > 0 && m < 6 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "3: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 4);
++ }
++ if (m > 12 && m < 19 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "4: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 5);
++ }
++
++ if (m > 34 && m < 38 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "5: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 6);
++ }
++
++ if (m > 39 && m < 47 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "6: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 7);
++ }
++
++ if (m > 61 && m < 70 )
++ {
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "7: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 8);
++ }
++
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "unknown SOULSEEK command: 0x%x, first 16 bit: 0x%x, first 8 bit: 0x%x ,soulseek ???\n",get_u32(payload, 4),get_u16(payload, 4) >> 16,get_u8(payload, 4) >> 24);
++#endif /* IPP2P_DEBUG_SOUL */
++ }
++
++ /* match 14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00 */
++ /* without size at the beginning !!! */
++ if ( get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01 )
++ {
++ __u32 y=get_u32(payload, 5);
++ /* we need 19 chars + string */
++ if ( (y + 19) <= (plen) )
++ {
++ const unsigned char *w=payload+9+y;
++ if (get_u32(w, 0) == 0x01 && ( get_u16(w, 4) == 0x4600 || get_u16(w, 4) == 0x5000) && get_u32(w, 6) == 0x00);
++#ifdef IPP2P_DEBUG_SOUL
++ printk(KERN_DEBUG "Soulssek special client command recognized\n");
++#endif /* IPP2P_DEBUG_SOUL */
++ return ((IPP2P_SOUL * 100) + 9);
++ }
++ }
++ return 0;
++}
++
++
++/*Search for WinMX commands*/
++int
++search_winmx (const unsigned char *payload, const u16 plen)
++{
++//#define IPP2P_DEBUG_WINMX
++ if (((plen) == 4) && (memcmp(payload, "SEND", 4) == 0)) return ((IPP2P_WINMX * 100) + 1);
++ if (((plen) == 3) && (memcmp(payload, "GET", 3) == 0)) return ((IPP2P_WINMX * 100) + 2);
++ //if (packet_len < (head_len + 10)) return 0;
++ if (plen < 10) return 0;
++
++ if ((memcmp(payload, "SEND", 4) == 0) || (memcmp(payload, "GET", 3) == 0)){
++ u16 c=4;
++ const u16 end=plen-2;
++ u8 count=0;
++ while (c < end)
++ {
++ if (payload[c]== 0x20 && payload[c+1] == 0x22)
++ {
++ c++;
++ count++;
++ if (count>=2) return ((IPP2P_WINMX * 100) + 3);
++ }
++ c++;
++ }
++ }
++
++ if ( plen == 149 && payload[0] == '8' )
++ {
++#ifdef IPP2P_DEBUG_WINMX
++ printk(KERN_INFO "maybe WinMX\n");
++#endif
++ if (get_u32(payload,17) == 0 && get_u32(payload,21) == 0 && get_u32(payload,25) == 0 &&
++// get_u32(payload,33) == __constant_htonl(0x71182b1a) && get_u32(payload,37) == __constant_htonl(0x05050000) &&
++// get_u32(payload,133) == __constant_htonl(0x31097edf) && get_u32(payload,145) == __constant_htonl(0xdcb8f792))
++ get_u16(payload,39) == 0 && get_u16(payload,135) == __constant_htons(0x7edf) && get_u16(payload,147) == __constant_htons(0xf792))
++
++ {
++#ifdef IPP2P_DEBUG_WINMX
++ printk(KERN_INFO "got WinMX\n");
++#endif
++ return ((IPP2P_WINMX * 100) + 4);
++ }
++ }
++ return 0;
++} /*search_winmx*/
++
++
++/*Search for appleJuice commands*/
++int
++search_apple (const unsigned char *payload, const u16 plen)
++{
++ if ( (plen > 7) && (payload[6] == 0x0d) && (payload[7] == 0x0a) && (memcmp(payload, "ajprot", 6) == 0)) return (IPP2P_APPLE * 100);
++
++ return 0;
++}
++
++
++/*Search for BitTorrent commands*/
++int
++search_bittorrent (const unsigned char *payload, const u16 plen)
++{
++ if (plen > 20)
++ {
++ /* test for match 0x13+"BitTorrent protocol" */
++ if (payload[0] == 0x13)
++ {
++ if (memcmp(payload+1, "BitTorrent protocol", 19) == 0) return (IPP2P_BIT * 100);
++ }
++
++ /* get tracker commandos, all starts with GET /
++ * then it can follow: scrape| announce
++ * and then ?hash_info=
++ */
++ if (memcmp(payload,"GET /",5) == 0)
++ {
++ /* message scrape */
++ if ( memcmp(payload+5,"scrape?info_hash=",17)==0 ) return (IPP2P_BIT * 100 + 1);
++ /* message announce */
++ if ( memcmp(payload+5,"announce?info_hash=",19)==0 ) return (IPP2P_BIT * 100 + 2);
++ }
++ }
++ else
++ {
++ /* bitcomet encryptes the first packet, so we have to detect another
++ * one later in the flow */
++ /* first try failed, too many missdetections */
++ //if ( size == 5 && get_u32(t,0) == __constant_htonl(1) && t[4] < 3) return (IPP2P_BIT * 100 + 3);
++
++ /* second try: block request packets */
++ if ( plen == 17 && get_u32(payload,0) == __constant_htonl(0x0d) && payload[4] == 0x06 && get_u32(payload,13) == __constant_htonl(0x4000) ) return (IPP2P_BIT * 100 + 3);
++ }
++
++ return 0;
++}
++
++
++
++/*check for Kazaa get command*/
++int
++search_kazaa (const unsigned char *payload, const u16 plen)
++
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a) && memcmp(payload, "GET /.hash=", 11) == 0)
++ return (IPP2P_DATA_KAZAA * 100);
++
++ return 0;
++}
++
++
++/*check for gnutella get command*/
++int
++search_gnu (const unsigned char *payload, const u16 plen)
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++ if (memcmp(payload, "GET /get/", 9) == 0) return ((IPP2P_DATA_GNU * 100) + 1);
++ if (memcmp(payload, "GET /uri-res/", 13) == 0) return ((IPP2P_DATA_GNU * 100) + 2);
++ }
++ return 0;
++}
++
++
++/*check for gnutella get commands and other typical data*/
++int
++search_all_gnu (const unsigned char *payload, const u16 plen)
++{
++
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++
++ if (memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) return ((IPP2P_GNU * 100) + 1);
++ if (memcmp(payload, "GNUTELLA/", 9) == 0) return ((IPP2P_GNU * 100) + 2);
++
++
++ if ((memcmp(payload, "GET /get/", 9) == 0) || (memcmp(payload, "GET /uri-res/", 13) == 0))
++ {
++ u16 c=8;
++ const u16 end=plen-22;
++ while (c < end) {
++ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Gnutella-", 11) == 0) || (memcmp(&payload[c+2], "X-Queue:", 8) == 0)))
++ return ((IPP2P_GNU * 100) + 3);
++ c++;
++ }
++ }
++ }
++ return 0;
++}
++
++
++/*check for KaZaA download commands and other typical data*/
++int
++search_all_kazaa (const unsigned char *payload, const u16 plen)
++{
++ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
++ {
++
++ if (memcmp(payload, "GIVE ", 5) == 0) return ((IPP2P_KAZAA * 100) + 1);
++
++ if (memcmp(payload, "GET /", 5) == 0) {
++ u16 c = 8;
++ const u16 end=plen-22;
++ while (c < end) {
++ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0) || (memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0)))
++ return ((IPP2P_KAZAA * 100) + 2);
++ c++;
++ }
++ }
++ }
++ return 0;
++}
++
++/*fast check for edonkey file segment transfer command*/
++int
++search_edk (const unsigned char *payload, const u16 plen)
++{
++ if (payload[0] != 0xe3)
++ return 0;
++ else {
++ if (payload[5] == 0x47)
++ return (IPP2P_DATA_EDK * 100);
++ else
++ return 0;
++ }
++}
++
++
++
++/*intensive but slower search for some edonkey packets including size-check*/
++int
++search_all_edk (const unsigned char *payload, const u16 plen)
++{
++ if (payload[0] != 0xe3)
++ return 0;
++ else {
++ //t += head_len;
++ const u16 cmd = get_u16(payload, 1);
++ if (cmd == (plen - 5)) {
++ switch (payload[5]) {
++ case 0x01: return ((IPP2P_EDK * 100) + 1); /*Client: hello or Server:hello*/
++ case 0x4c: return ((IPP2P_EDK * 100) + 9); /*Client: Hello-Answer*/
++ }
++ }
++ return 0;
++ }
++}
++
++
++/*fast check for Direct Connect send command*/
++int
++search_dc (const unsigned char *payload, const u16 plen)
++{
++
++ if (payload[0] != 0x24 )
++ return 0;
++ else {
++ if (memcmp(&payload[1], "Send|", 5) == 0)
++ return (IPP2P_DATA_DC * 100);
++ else
++ return 0;
++ }
++
++}
++
++
++/*intensive but slower check for all direct connect packets*/
++int
++search_all_dc (const unsigned char *payload, const u16 plen)
++{
++// unsigned char *t = haystack;
++
++ if (payload[0] == 0x24 && payload[plen-1] == 0x7c)
++ {
++ const unsigned char *t=&payload[1];
++ /* Client-Hub-Protocol */
++ if (memcmp(t, "Lock ", 5) == 0) return ((IPP2P_DC * 100) + 1);
++ /* Client-Client-Protocol, some are already recognized by client-hub (like lock) */
++ if (memcmp(t, "MyNick ", 7) == 0) return ((IPP2P_DC * 100) + 38);
++ }
++ return 0;
++}
++
++/*check for mute*/
++int
++search_mute (const unsigned char *payload, const u16 plen)
++{
++ if ( plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121 )
++ {
++ //printk(KERN_DEBUG "size hit: %u",size);
++ if (memcmp(payload,"PublicKey: ",11) == 0 )
++ {
++ return ((IPP2P_MUTE * 100) + 0);
++
++/* if (memcmp(t+size-14,"\x0aEndPublicKey\x0a",14) == 0)
++ {
++ printk(KERN_DEBUG "end pubic key hit: %u",size);
++
++ }*/
++ }
++ }
++ return 0;
++}
++
++
++/* check for xdcc */
++int
++search_xdcc (const unsigned char *payload, const u16 plen)
++{
++ /* search in small packets only */
++ if (plen > 20 && plen < 200 && payload[plen-1] == 0x0a && payload[plen-2] == 0x0d && memcmp(payload,"PRIVMSG ",8) == 0)
++ {
++
++ u16 x=10;
++ const u16 end=plen - 13;
++
++ /* is seems to be a irc private massage, chedck for xdcc command */
++ while (x < end)
++ {
++ if (payload[x] == ':')
++ {
++ if ( memcmp(&payload[x+1],"xdcc send #",11) == 0 )
++ return ((IPP2P_XDCC * 100) + 0);
++ }
++ x++;
++ }
++ }
++ return 0;
++}
++
++/* search for waste */
++int search_waste(const unsigned char *payload, const u16 plen)
++{
++ if ( plen >= 8 && memcmp(payload,"GET.sha1:",9) == 0)
++ return ((IPP2P_WASTE * 100) + 0);
++
++ return 0;
++}
++
++
++static struct {
++ int command;
++ __u8 short_hand; /*for fucntions included in short hands*/
++ int packet_len;
++ int (*function_name) (const unsigned char *, const u16);
++} matchlist[] = {
++ {IPP2P_EDK,SHORT_HAND_IPP2P,20, &search_all_edk},
++// {IPP2P_DATA_KAZAA,SHORT_HAND_DATA,200, &search_kazaa},
++// {IPP2P_DATA_EDK,SHORT_HAND_DATA,60, &search_edk},
++// {IPP2P_DATA_DC,SHORT_HAND_DATA,26, &search_dc},
++ {IPP2P_DC,SHORT_HAND_IPP2P,5, search_all_dc},
++// {IPP2P_DATA_GNU,SHORT_HAND_DATA,40, &search_gnu},
++ {IPP2P_GNU,SHORT_HAND_IPP2P,5, &search_all_gnu},
++ {IPP2P_KAZAA,SHORT_HAND_IPP2P,5, &search_all_kazaa},
++ {IPP2P_BIT,SHORT_HAND_IPP2P,20, &search_bittorrent},
++ {IPP2P_APPLE,SHORT_HAND_IPP2P,5, &search_apple},
++ {IPP2P_SOUL,SHORT_HAND_IPP2P,5, &search_soul},
++ {IPP2P_WINMX,SHORT_HAND_IPP2P,2, &search_winmx},
++ {IPP2P_ARES,SHORT_HAND_IPP2P,5, &search_ares},
++ {IPP2P_MUTE,SHORT_HAND_NONE,200, &search_mute},
++ {IPP2P_WASTE,SHORT_HAND_NONE,5, &search_waste},
++ {IPP2P_XDCC,SHORT_HAND_NONE,5, &search_xdcc},
++ {0,0,0,NULL}
++};
++
++
++static struct {
++ int command;
++ __u8 short_hand; /*for fucntions included in short hands*/
++ int packet_len;
++ int (*function_name) (unsigned char *, int);
++} udp_list[] = {
++ {IPP2P_KAZAA,SHORT_HAND_IPP2P,14, &udp_search_kazaa},
++ {IPP2P_BIT,SHORT_HAND_IPP2P,23, &udp_search_bit},
++ {IPP2P_GNU,SHORT_HAND_IPP2P,11, &udp_search_gnu},
++ {IPP2P_EDK,SHORT_HAND_IPP2P,9, &udp_search_edk},
++ {IPP2P_DC,SHORT_HAND_IPP2P,12, &udp_search_directconnect},
++ {0,0,0,NULL}
++};
++
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++ const void *hdr,
++ u_int16_t datalen,
++#endif
++
++ int *hotdrop)
++{
++ const struct ipt_p2p_info *info = matchinfo;
++ unsigned char *haystack;
++ struct iphdr *ip = skb->nh.iph;
++ int p2p_result = 0, i = 0;
++// int head_len;
++ int hlen = ntohs(ip->tot_len)-(ip->ihl*4); /*hlen = packet-data length*/
++
++ /*must not be a fragment*/
++ if (offset) {
++ if (info->debug) printk("IPP2P.match: offset found %i \n",offset);
++ return 0;
++ }
++
++ /*make sure that skb is linear*/
++ if(skb_is_nonlinear(skb)){
++ if (info->debug) printk("IPP2P.match: nonlinear skb found\n");
++ return 0;
++ }
++
++
++ haystack=(char *)ip+(ip->ihl*4); /*haystack = packet data*/
++
++ switch (ip->protocol){
++ case IPPROTO_TCP: /*what to do with a TCP packet*/
++ {
++ struct tcphdr *tcph = (void *) ip + ip->ihl * 4;
++
++ if (tcph->fin) return 0; /*if FIN bit is set bail out*/
++ if (tcph->syn) return 0; /*if SYN bit is set bail out*/
++ if (tcph->rst) return 0; /*if RST bit is set bail out*/
++
++ haystack += tcph->doff * 4; /*get TCP-Header-Size*/
++ hlen -= tcph->doff * 4;
++ while (matchlist[i].command) {
++ if ((((info->cmd & matchlist[i].command) == matchlist[i].command) ||
++ ((info->cmd & matchlist[i].short_hand) == matchlist[i].short_hand)) &&
++ (hlen > matchlist[i].packet_len)) {
++ p2p_result = matchlist[i].function_name(haystack, hlen);
++ if (p2p_result)
++ {
++ if (info->debug) printk("IPP2P.debug:TCP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
++ p2p_result, NIPQUAD(ip->saddr),ntohs(tcph->source), NIPQUAD(ip->daddr),ntohs(tcph->dest),hlen);
++ return p2p_result;
++ }
++ }
++ i++;
++ }
++ return p2p_result;
++ }
++
++ case IPPROTO_UDP: /*what to do with an UDP packet*/
++ {
++ struct udphdr *udph = (void *) ip + ip->ihl * 4;
++
++ while (udp_list[i].command){
++ if ((((info->cmd & udp_list[i].command) == udp_list[i].command) ||
++ ((info->cmd & udp_list[i].short_hand) == udp_list[i].short_hand)) &&
++ (hlen > udp_list[i].packet_len)) {
++ p2p_result = udp_list[i].function_name(haystack, hlen);
++ if (p2p_result){
++ if (info->debug) printk("IPP2P.debug:UDP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
++ p2p_result, NIPQUAD(ip->saddr),ntohs(udph->source), NIPQUAD(ip->daddr),ntohs(udph->dest),hlen);
++ return p2p_result;
++ }
++ }
++ i++;
++ }
++ return p2p_result;
++ }
++
++ default: return 0;
++ }
++}
++
++
++
++static int
++checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ /* Must specify -p tcp */
++/* if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
++ * printk("ipp2p: Only works on TCP packets, use -p tcp\n");
++ * return 0;
++ * }*/
++ return 1;
++}
++
++
++
++
++static struct ipt_match ipp2p_match = {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
++ { NULL, NULL },
++ "ipp2p",
++ &match,
++ &checkentry,
++ NULL,
++ THIS_MODULE
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++ .name = "ipp2p",
++ .match = &match,
++ .checkentry = &checkentry,
++ .me = THIS_MODULE,
++#endif
++};
++
++
++static int __init init(void)
++{
++ printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION);
++ return ipt_register_match(&ipp2p_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&ipp2p_match);
++ printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION);
++}
++
++module_init(init);
++module_exit(fini);
++
++
CONFIG_IP_NF_MATCH_LAYER7=m
# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set
CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_IPP2P=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_TIME=m
CONFIG_IP_NF_MATCH_RECENT=m