├── AUTHORS ├── Makefile ├── ipt ├── Makefile └── libxt_ndpi.c ├── src ├── xt_ndpi.h ├── Makefile └── main.c ├── README ├── INSTALL ├── kernel-patch └── hack-conntrack-events.patch └── COPYING /AUTHORS: -------------------------------------------------------------------------------- 1 | G. Elian Gidoni 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | $(MAKE) -C ipt 3 | $(MAKE) -C src 4 | modules_install: 5 | $(MAKE) -C src modules_install 6 | clean: 7 | $(MAKE) -C src clean 8 | $(MAKE) -C ipt clean -------------------------------------------------------------------------------- /ipt/Makefile: -------------------------------------------------------------------------------- 1 | NDPI_PATH2 := ${NDPI_PATH}/src 2 | NDPI_SRC := ndpi_cpy 3 | NDPI_PRO := ${NDPI_SRC}/lib/protocols 4 | 5 | CFLAGS = -fPIC -I${NDPI_SRC}/include -I${NDPI_SRC}/lib -I../src -DOPENDPI_NETFILTER_MODULE -O2 -Wall 6 | 7 | all: 8 | if test -d ${NDPI_SRC}; then \ 9 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 10 | else \ 11 | mkdir ${NDPI_SRC}; \ 12 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 13 | fi 14 | make libxt_ndpi.so 15 | rm -r ${NDPI_SRC} 16 | lib%.so: lib%.o 17 | $(CC) -shared -o $@ $^; 18 | lib%.o: lib%.c 19 | $(CC) ${CFLAGS} -D_INIT=lib$*_init -c -o $@ $<; 20 | clean: 21 | rm -rf libxt_ndpi.so ${NDPI_SRC} 22 | -------------------------------------------------------------------------------- /src/xt_ndpi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * xt_ndpi.h 3 | * Copyright (C) 2010-2012 G. Elian Gidoni 4 | * 2012 Ed Wildgoose 5 | * 6 | * This file is part of nDPI, an open source deep packet inspection 7 | * library based on the PACE technology by ipoque GmbH 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; version 2 of the License. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #ifndef _LINUX_NETFILTER_XT_NDPI_H 24 | #define _LINUX_NETFILTER_XT_NDPI_H 1 25 | 26 | #include 27 | #include "ndpi_main.h" 28 | 29 | struct xt_ndpi_mtinfo { 30 | NDPI_PROTOCOL_BITMASK flags; 31 | }; 32 | 33 | #endif /* _LINUX_NETFILTER_XT_NDPI_H */ 34 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This package is a GPL implementation of an iptables and netfilter module for 2 | nDPI integration into the Linux kernel. 3 | 4 | The prerequisites are: 5 | 6 | - Tested on Debian 6.0 (Kernel 2.6.32-5) 7 | - Following packages to compile kernel-modules: 8 | linux-headers 9 | iptables-dev >= version 1.4.8-3 10 | nDPI source package 11 | 12 | 13 | Compiled kernel features 14 | ------------------------ 15 | 16 | You do not need to do the below steps for Debian 6 17 | 18 | In order to use nDPI as a kernel module notice that: 19 | 20 | - You should ENABLE Netfilter conntrack events (and also enable Advanced 21 | netfilter features to see it). 22 | 23 | In kernel 2.6.34 its defined as: 24 | 25 | Connection tracking events 26 | Symbol: NF_CONNTRACK_EVENTS 27 | Location: 28 | -> Networking support 29 | -> Networking options 30 | -> Network packet filtering framework (Netfilter) 31 | -> Core Netfilter Configuration 32 | -> Netfilter connection tracking support 33 | 34 | - If your kernel version is 2.6.31 or greater, then you should DISABLE 35 | Netfilter conntrack for the Netlink protocol. 36 | 37 | In kernel 2.6.34 its defined as: 38 | 39 | Connection tracking netlink interface 40 | Symbol: NF_CT_NETLINK 41 | Location: 42 | -> Networking support 43 | -> Networking options 44 | -> Network packet filtering framework (Netfilter) 45 | -> Core Netfilter Configuration 46 | -> Netfilter connection tracking support 47 | 48 | 49 | Once you have downloaded/installed each package and checked for the above 50 | kernel features you can read the INSTALL file. 51 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | nDPI module INSTALL 2 | ---------------------- 3 | 4 | The install the modules follow these steps, always from the modules package 5 | root (i.e. where this file is located) 6 | 7 | - To compile the modules first type: 8 | 9 | NDPI_PATH=/home/foo/ndpi-1.3.0 make 10 | 11 | Where, NDPI_PATH is the path to the original nDPI source code package 12 | (note that you have to extract it first). 13 | 14 | - Then, as root, type: 15 | 16 | make modules_install 17 | 18 | That would install the nDPI module for the given Linux kernel. 19 | 20 | - Finally, also as root, you should copy the iptables module into the 21 | corresponding directory. Usually this is "/lib/xtables" or 22 | "/usr/lib/xtables". 23 | 24 | cp ipt/libxt_ndpi.so /lib/xtables 25 | 26 | Now you can read the following section to learn how to use it. 27 | 28 | 29 | Module usage 30 | ------------ 31 | 32 | Once you have installed both modules ("libxt_ndpi.so" and "xt_ndpi.ko") 33 | you should type (as root): 34 | 35 | modprobe xt_ndpi 36 | 37 | If the module has been successfully loaded you shouldn't see any message. 38 | After loading the kernel module you can use iptables to add a rule. To see 39 | available protocols you can match for in every packet, type (as root): 40 | 41 | iptables -m ndpi --help 42 | 43 | Note that the list is long, you best try: "iptables -m ndpi --help | more" 44 | 45 | An example rule would be (as root): 46 | 47 | iptables -A OUTPUT -m ndpi --http -j REJECT 48 | 49 | This wouldn't allow any HTTP traffic that originates from the machine where the 50 | rule was added. 51 | 52 | In case you want to stop using the nDPI kernel module, first remove every 53 | iptables rule for nDPI and then type (as root): 54 | 55 | modprobe -r xt_ndpi 56 | -------------------------------------------------------------------------------- /ipt/libxt_ndpi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libxt_ndpi.c 3 | * Copyright (C) 2010-2012 G. Elian Gidoni 4 | * 2012 Ed Wildgoose 5 | * 6 | * This file is part of nDPI, an open source deep packet inspection 7 | * library based on the PACE technology by ipoque GmbH 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; version 2 of the License. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | #include "xt_ndpi.h" 32 | 33 | static char *prot_long_str[] = { NDPI_PROTOCOL_LONG_STRING }; 34 | static char *prot_short_str[] = { NDPI_PROTOCOL_SHORT_STRING }; 35 | 36 | static void 37 | ndpi_mt4_save(const void *entry, const struct xt_entry_match *match) 38 | { 39 | const struct xt_ndpi_mtinfo *info = (const void *)match->data; 40 | int i; 41 | 42 | for (i = 1; i <= NDPI_LAST_IMPLEMENTED_PROTOCOL; i++){ 43 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags, i) != 0){ 44 | printf("--%s ", prot_short_str[i]); 45 | } 46 | } 47 | } 48 | 49 | 50 | static void 51 | ndpi_mt4_print(const void *entry, const struct xt_entry_match *match, 52 | int numeric) 53 | { 54 | const struct xt_ndpi_mtinfo *info = (const void *)match->data; 55 | int i; 56 | 57 | for (i = 1; i <= NDPI_LAST_IMPLEMENTED_PROTOCOL; i++){ 58 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags, i) != 0){ 59 | printf("protocol %s ", prot_long_str[i]); 60 | } 61 | } 62 | } 63 | 64 | 65 | static int 66 | ndpi_mt4_parse(int c, char **argv, int invert, unsigned int *flags, 67 | const void *entry, struct xt_entry_match **match) 68 | { 69 | struct xt_ndpi_mtinfo *info = (void *)(*match)->data; 70 | int i; 71 | 72 | *flags = 0; 73 | for (i = 1; i <= NDPI_LAST_IMPLEMENTED_PROTOCOL; i++){ 74 | if (c == i){ 75 | NDPI_ADD_PROTOCOL_TO_BITMASK(info->flags, i); 76 | /*printf("Parameter detected as protocol %s.\n", 77 | prot_long_str[i]);*/ 78 | *flags = 1; 79 | return true; 80 | } 81 | } 82 | 83 | return false; 84 | } 85 | 86 | #ifndef xtables_error 87 | #define xtables_error exit_error 88 | #endif 89 | 90 | static void 91 | ndpi_mt_check (unsigned int flags) 92 | { 93 | if (flags == 0){ 94 | xtables_error(PARAMETER_PROBLEM, "xt_ndpi: You need to " 95 | "specify at least one protocol"); 96 | } 97 | } 98 | 99 | 100 | static void 101 | ndpi_mt_help(void) 102 | { 103 | int i; 104 | 105 | printf("ndpi match options:\n"); 106 | for (i = 1; i <= NDPI_LAST_IMPLEMENTED_PROTOCOL; i++){ 107 | printf("--%s Match for %s protocol packets.\n", 108 | prot_short_str[i], prot_long_str[i]); 109 | } 110 | } 111 | 112 | 113 | static void 114 | ndpi_mt_init (struct xt_entry_match *match) 115 | { 116 | struct xt_ndpi_mtinfo *info = (void *)match->data; 117 | /* inet_pton(PF_INET, "192.0.2.137", &info->dst.in); */ 118 | } 119 | 120 | 121 | static struct option ndpi_mt_opts[NDPI_LAST_IMPLEMENTED_PROTOCOL+1]; 122 | 123 | static struct xtables_match 124 | ndpi_mt4_reg = { 125 | .version = XTABLES_VERSION, 126 | .name = "ndpi", 127 | .revision = 0, 128 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 129 | .family = AF_INET, 130 | #else 131 | .family = NFPROTO_IPV4, 132 | #endif 133 | .size = XT_ALIGN(sizeof(struct xt_ndpi_mtinfo)), 134 | .userspacesize = XT_ALIGN(sizeof(struct xt_ndpi_mtinfo)), 135 | .help = ndpi_mt_help, 136 | .init = ndpi_mt_init, 137 | .parse = ndpi_mt4_parse, 138 | .final_check = ndpi_mt_check, 139 | .print = ndpi_mt4_print, 140 | .save = ndpi_mt4_save, 141 | .extra_opts = ndpi_mt_opts, 142 | }; 143 | 144 | void _init(void) 145 | { 146 | int i; 147 | 148 | for (i = 0; i < NDPI_LAST_IMPLEMENTED_PROTOCOL; i++){ 149 | ndpi_mt_opts[i].name = prot_short_str[i+1]; 150 | ndpi_mt_opts[i].has_arg = false; 151 | ndpi_mt_opts[i].val = i+1; 152 | } 153 | ndpi_mt_opts[i].name = NULL; 154 | ndpi_mt_opts[i].flag = NULL; 155 | ndpi_mt_opts[i].has_arg = 0; 156 | ndpi_mt_opts[i].val = 0; 157 | 158 | xtables_register_match(&ndpi_mt4_reg); 159 | } 160 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | NDPI_PATH2 := ${NDPI_PATH}/src 2 | NDPI_SRC := ndpi_cpy 3 | NDPI_PRO := ${NDPI_SRC}/lib/protocols 4 | 5 | ccflags-y += -I${src}/${NDPI_SRC}/include -I${src}/${NDPI_SRC}/lib -DOPENDPI_NETFILTER_MODULE 6 | 7 | #MODULES_DIR := /lib/modules/$(shell uname -r) 8 | #KERNEL_DIR := ${MODULES_DIR}/build 9 | 10 | obj-m := xt_ndpi.o 11 | xt_ndpi-y := main.o ${NDPI_SRC}/lib/ndpi_main.o \ 12 | ${NDPI_PRO}/afp.o \ 13 | ${NDPI_PRO}/aimini.o \ 14 | ${NDPI_PRO}/applejuice.o \ 15 | ${NDPI_PRO}/armagetron.o \ 16 | ${NDPI_PRO}/battlefield.o \ 17 | ${NDPI_PRO}/bgp.o \ 18 | ${NDPI_PRO}/bittorrent.o \ 19 | ${NDPI_PRO}/citrix.o \ 20 | ${NDPI_PRO}/crossfire.o \ 21 | ${NDPI_PRO}/dcerpc.o \ 22 | ${NDPI_PRO}/dhcp.o \ 23 | ${NDPI_PRO}/dhcpv6.o \ 24 | ${NDPI_PRO}/directconnect.o \ 25 | ${NDPI_PRO}/directdownloadlink.o \ 26 | ${NDPI_PRO}/dns.o \ 27 | ${NDPI_PRO}/dofus.o \ 28 | ${NDPI_PRO}/dropbox.o \ 29 | ${NDPI_PRO}/edonkey.o \ 30 | ${NDPI_PRO}/fasttrack.o \ 31 | ${NDPI_PRO}/feidian.o \ 32 | ${NDPI_PRO}/fiesta.o \ 33 | ${NDPI_PRO}/filetopia.o \ 34 | ${NDPI_PRO}/flash.o \ 35 | ${NDPI_PRO}/florensia.o \ 36 | ${NDPI_PRO}/ftp.o \ 37 | ${NDPI_PRO}/gadu_gadu.o \ 38 | ${NDPI_PRO}/gnutella.o \ 39 | ${NDPI_PRO}/guildwars.o \ 40 | ${NDPI_PRO}/halflife2_and_mods.o \ 41 | ${NDPI_PRO}/http.o \ 42 | ${NDPI_PRO}/http_activesync.o \ 43 | ${NDPI_PRO}/i23v5.o \ 44 | ${NDPI_PRO}/iax.o \ 45 | ${NDPI_PRO}/icecast.o \ 46 | ${NDPI_PRO}/imesh.o \ 47 | ${NDPI_PRO}/ipp.o \ 48 | ${NDPI_PRO}/irc.o \ 49 | ${NDPI_PRO}/jabber.o \ 50 | ${NDPI_PRO}/kerberos.o \ 51 | ${NDPI_PRO}/kontiki.o \ 52 | ${NDPI_PRO}/ldap.o \ 53 | ${NDPI_PRO}/mail_imap.o \ 54 | ${NDPI_PRO}/mail_pop.o \ 55 | ${NDPI_PRO}/mail_smtp.o \ 56 | ${NDPI_PRO}/manolito.o \ 57 | ${NDPI_PRO}/maplestory.o \ 58 | ${NDPI_PRO}/mdns.o \ 59 | ${NDPI_PRO}/meebo.o \ 60 | ${NDPI_PRO}/mgcp.o \ 61 | ${NDPI_PRO}/mms.o \ 62 | ${NDPI_PRO}/msn.o \ 63 | ${NDPI_PRO}/mssql.o \ 64 | ${NDPI_PRO}/mysql.o \ 65 | ${NDPI_PRO}/netbios.o \ 66 | ${NDPI_PRO}/netflow.o \ 67 | ${NDPI_PRO}/nfs.o \ 68 | ${NDPI_PRO}/non_tcp_udp.o \ 69 | ${NDPI_PRO}/ntp.o \ 70 | ${NDPI_PRO}/openft.o \ 71 | ${NDPI_PRO}/oscar.o \ 72 | ${NDPI_PRO}/pando.o \ 73 | ${NDPI_PRO}/pcanywhere.o \ 74 | ${NDPI_PRO}/popo.o \ 75 | ${NDPI_PRO}/postgres.o \ 76 | ${NDPI_PRO}/pplive.o \ 77 | ${NDPI_PRO}/ppstream.o \ 78 | ${NDPI_PRO}/pptp.o \ 79 | ${NDPI_PRO}/qq.o \ 80 | ${NDPI_PRO}/quake.o \ 81 | ${NDPI_PRO}/radius.o \ 82 | ${NDPI_PRO}/rdp.o \ 83 | ${NDPI_PRO}/rtp.o \ 84 | ${NDPI_PRO}/rtsp.o \ 85 | ${NDPI_PRO}/secondlife.o \ 86 | ${NDPI_PRO}/sflow.o \ 87 | ${NDPI_PRO}/shoutcast.o \ 88 | ${NDPI_PRO}/sip.o \ 89 | ${NDPI_PRO}/skype.o \ 90 | ${NDPI_PRO}/smb.o \ 91 | ${NDPI_PRO}/snmp.o \ 92 | ${NDPI_PRO}/socrates.o \ 93 | ${NDPI_PRO}/sopcast.o \ 94 | ${NDPI_PRO}/soulseek.o \ 95 | ${NDPI_PRO}/ssdp.o \ 96 | ${NDPI_PRO}/ssh.o \ 97 | ${NDPI_PRO}/ssl.o \ 98 | ${NDPI_PRO}/stealthnet.o \ 99 | ${NDPI_PRO}/steam.o \ 100 | ${NDPI_PRO}/stun.o \ 101 | ${NDPI_PRO}/syslog.o \ 102 | ${NDPI_PRO}/tds.o \ 103 | ${NDPI_PRO}/teamviewer.o \ 104 | ${NDPI_PRO}/telnet.o \ 105 | ${NDPI_PRO}/tftp.o \ 106 | ${NDPI_PRO}/thunder.o \ 107 | ${NDPI_PRO}/tvants.o \ 108 | ${NDPI_PRO}/tvuplayer.o \ 109 | ${NDPI_PRO}/usenet.o \ 110 | ${NDPI_PRO}/veohtv.o \ 111 | ${NDPI_PRO}/vnc.o \ 112 | ${NDPI_PRO}/warcraft3.o \ 113 | ${NDPI_PRO}/winmx.o \ 114 | ${NDPI_PRO}/world_of_kung_fu.o \ 115 | ${NDPI_PRO}/world_of_warcraft.o \ 116 | ${NDPI_PRO}/xbox.o \ 117 | ${NDPI_PRO}/xdmcp.o \ 118 | ${NDPI_PRO}/yahoo.o \ 119 | ${NDPI_PRO}/zattoo.o 120 | 121 | all: 122 | if test -d ${NDPI_SRC}; then \ 123 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 124 | else \ 125 | mkdir ${NDPI_SRC}; \ 126 | cp ${NDPI_PATH2}/* ${NDPI_SRC} -R; \ 127 | fi 128 | make -C ${KERNEL_DIR} M=$$PWD; 129 | rm -r ${NDPI_SRC} 130 | modules: 131 | make -C ${KERNEL_DIR} M=$$PWD $@; 132 | modules_install: 133 | make -C ${KERNEL_DIR} M=$$PWD $@; 134 | depmod -a; 135 | clean: 136 | make -C ${KERNEL_DIR} M=$$PWD $@; 137 | rm -rf modules.order ${NDPI_SRC} 138 | -------------------------------------------------------------------------------- /kernel-patch/hack-conntrack-events.patch: -------------------------------------------------------------------------------- 1 | commit 0bff241af47f293d27b908ab82a4e2ec5d62385f 2 | Author: Ed W 3 | Date: Wed Oct 24 23:11:44 2012 +0100 4 | 5 | incredibly nasty hack for nDPI + conntrack/netlink 6 | 7 | In recent kernels, only one listener can register for 8 | notification of conntrack events. This is done for 9 | performance reasons and no other in kernel module cares. 10 | This incredibly nasty hack allows a second listener to 11 | register for conntrack notifications. 12 | 13 | Use at your peril. No warranty included... 14 | 15 | diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h 16 | index a88fb69..d39af41 100644 17 | --- a/include/net/netfilter/nf_conntrack_ecache.h 18 | +++ b/include/net/netfilter/nf_conntrack_ecache.h 19 | @@ -78,7 +78,8 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) 20 | struct net *net = nf_ct_net(ct); 21 | struct nf_conntrack_ecache *e; 22 | 23 | - if (net->ct.nf_conntrack_event_cb == NULL) 24 | + if ( (net->ct.nf_conntrack_event_cb == NULL) && 25 | + (net->ct.nf_conntrack_event_cb_2 == NULL) ) 26 | return; 27 | 28 | e = nf_ct_ecache_find(ct); 29 | @@ -97,11 +98,14 @@ nf_conntrack_eventmask_report(unsigned int eventmask, 30 | int ret = 0; 31 | struct net *net = nf_ct_net(ct); 32 | struct nf_ct_event_notifier *notify; 33 | + struct nf_ct_event_notifier *notify_2; 34 | struct nf_conntrack_ecache *e; 35 | 36 | rcu_read_lock(); 37 | + /* Incredibly nasty duplication in order to hack second event */ 38 | notify = rcu_dereference(net->ct.nf_conntrack_event_cb); 39 | - if (notify == NULL) 40 | + notify_2 = rcu_dereference(net->ct.nf_conntrack_event_cb_2); 41 | + if ((notify == NULL) && (notify_2 == NULL)) 42 | goto out_unlock; 43 | 44 | e = nf_ct_ecache_find(ct); 45 | @@ -120,7 +124,8 @@ nf_conntrack_eventmask_report(unsigned int eventmask, 46 | if (!((eventmask | missed) & e->ctmask)) 47 | goto out_unlock; 48 | 49 | - ret = notify->fcn(eventmask | missed, &item); 50 | + ret = min( notify ? notify->fcn(eventmask | missed, &item) : 0, 51 | + notify_2 ? notify_2->fcn(eventmask | missed, &item) : 0 ); 52 | if (unlikely(ret < 0 || missed)) { 53 | spin_lock_bh(&ct->lock); 54 | if (ret < 0) { 55 | diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h 56 | index 7a911ec..24a78d3 100644 57 | --- a/include/net/netns/conntrack.h 58 | +++ b/include/net/netns/conntrack.h 59 | @@ -19,6 +19,7 @@ struct netns_ct { 60 | struct hlist_nulls_head dying; 61 | struct ip_conntrack_stat __percpu *stat; 62 | struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb; 63 | + struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb_2; 64 | struct nf_exp_event_notifier __rcu *nf_expect_event_cb; 65 | int sysctl_events; 66 | unsigned int sysctl_events_retry_timeout; 67 | diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c 68 | index 14af632..9535ab7 100644 69 | --- a/net/netfilter/nf_conntrack_ecache.c 70 | +++ b/net/netfilter/nf_conntrack_ecache.c 71 | @@ -33,12 +33,15 @@ void nf_ct_deliver_cached_events(struct nf_conn *ct) 72 | { 73 | struct net *net = nf_ct_net(ct); 74 | unsigned long events; 75 | + /* Incredibly nasty duplication in order to hack second event */ 76 | struct nf_ct_event_notifier *notify; 77 | + struct nf_ct_event_notifier *notify_2; 78 | struct nf_conntrack_ecache *e; 79 | 80 | rcu_read_lock(); 81 | notify = rcu_dereference(net->ct.nf_conntrack_event_cb); 82 | - if (notify == NULL) 83 | + notify_2 = rcu_dereference(net->ct.nf_conntrack_event_cb_2); 84 | + if ( (notify == NULL) && (notify_2 == NULL) ) 85 | goto out_unlock; 86 | 87 | e = nf_ct_ecache_find(ct); 88 | @@ -62,7 +65,8 @@ void nf_ct_deliver_cached_events(struct nf_conn *ct) 89 | if (!((events | missed) & e->ctmask)) 90 | goto out_unlock; 91 | 92 | - ret = notify->fcn(events | missed, &item); 93 | + ret = min( notify ? notify->fcn(events | missed, &item) : 0, 94 | + notify_2 ? notify_2->fcn(events | missed, &item) : 0); 95 | if (unlikely(ret < 0 || missed)) { 96 | spin_lock_bh(&ct->lock); 97 | if (ret < 0) 98 | @@ -83,15 +87,21 @@ int nf_conntrack_register_notifier(struct net *net, 99 | { 100 | int ret = 0; 101 | struct nf_ct_event_notifier *notify; 102 | + struct nf_ct_event_notifier *notify_2; 103 | 104 | mutex_lock(&nf_ct_ecache_mutex); 105 | notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb, 106 | lockdep_is_held(&nf_ct_ecache_mutex)); 107 | - if (notify != NULL) { 108 | + notify_2 = rcu_dereference_protected(net->ct.nf_conntrack_event_cb_2, 109 | + lockdep_is_held(&nf_ct_ecache_mutex)); 110 | + if ( (notify != NULL) && (notify_2 != NULL) ) { 111 | ret = -EBUSY; 112 | goto out_unlock; 113 | } 114 | - rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new); 115 | + if (notify == NULL) 116 | + rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new); 117 | + else 118 | + rcu_assign_pointer(net->ct.nf_conntrack_event_cb_2, new); 119 | mutex_unlock(&nf_ct_ecache_mutex); 120 | return ret; 121 | 122 | @@ -105,12 +115,18 @@ void nf_conntrack_unregister_notifier(struct net *net, 123 | struct nf_ct_event_notifier *new) 124 | { 125 | struct nf_ct_event_notifier *notify; 126 | + struct nf_ct_event_notifier *notify_2; 127 | 128 | mutex_lock(&nf_ct_ecache_mutex); 129 | notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb, 130 | lockdep_is_held(&nf_ct_ecache_mutex)); 131 | - BUG_ON(notify != new); 132 | - RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); 133 | + notify_2 = rcu_dereference_protected(net->ct.nf_conntrack_event_cb_2, 134 | + lockdep_is_held(&nf_ct_ecache_mutex)); 135 | + BUG_ON((notify != new) || (notify_2 != new)); 136 | + if (notify == new) 137 | + RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); 138 | + else 139 | + RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb_2, NULL); 140 | mutex_unlock(&nf_ct_ecache_mutex); 141 | } 142 | EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); 143 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | * Copyright (C) 2010-2012 G. Elian Gidoni 4 | * 2012 Ed Wildgoose 5 | * 6 | * This file is part of nDPI, an open source deep packet inspection 7 | * library based on the PACE technology by ipoque GmbH 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; version 2 of the License. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | #include "ndpi_main.h" 41 | #include "xt_ndpi.h" 42 | 43 | MODULE_LICENSE("GPL"); 44 | MODULE_AUTHOR("G. Elian Gidoni "); 45 | MODULE_DESCRIPTION("nDPI wrapper"); 46 | MODULE_ALIAS("ipt_ndpi"); 47 | 48 | /* flow tracking */ 49 | struct osdpi_flow_node { 50 | struct rb_node node; 51 | struct nf_conn * ct; 52 | /* result only, not used for flow identification */ 53 | u32 detected_protocol; 54 | /* last pointer assigned at run time */ 55 | struct ndpi_flow_struct *ndpi_flow; 56 | }; 57 | 58 | /* id tracking */ 59 | struct osdpi_id_node { 60 | struct rb_node node; 61 | struct kref refcnt; 62 | union nf_inet_addr ip; 63 | /* last pointer assigned at run time */ 64 | struct ndpi_id_struct *ndpi_id; 65 | }; 66 | 67 | static u32 size_id_struct = 0; 68 | static u32 size_flow_struct = 0; 69 | 70 | static struct rb_root osdpi_flow_root = RB_ROOT; 71 | static struct rb_root osdpi_id_root = RB_ROOT; 72 | 73 | static struct kmem_cache *osdpi_flow_cache __read_mostly; 74 | static struct kmem_cache *osdpi_id_cache __read_mostly; 75 | 76 | static NDPI_PROTOCOL_BITMASK protocols_bitmask; 77 | static atomic_t protocols_cnt[NDPI_LAST_IMPLEMENTED_PROTOCOL]; 78 | 79 | DEFINE_SPINLOCK(flow_lock); 80 | DEFINE_SPINLOCK(id_lock); 81 | DEFINE_SPINLOCK(ipq_lock); 82 | 83 | 84 | /* detection */ 85 | static struct ndpi_detection_module_struct *ndpi_struct = NULL; 86 | static u32 detection_tick_resolution = 1000; 87 | 88 | /* debug functions */ 89 | 90 | static void debug_printf(u32 protocol, void *id_struct, 91 | ndpi_log_level_t log_level, const char *format, ...) 92 | { 93 | /* do nothing */ 94 | 95 | va_list args; 96 | va_start(args, format); 97 | switch (log_level) 98 | { 99 | case NDPI_LOG_ERROR: 100 | vprintk(format, args); 101 | break; 102 | case NDPI_LOG_TRACE: 103 | vprintk(format, args); 104 | break; 105 | 106 | case NDPI_LOG_DEBUG: 107 | vprintk(format, args); 108 | break; 109 | } 110 | va_end(args); 111 | } 112 | 113 | 114 | static void *malloc_wrapper(unsigned long size) 115 | { 116 | return kmalloc(size, GFP_KERNEL); 117 | } 118 | 119 | 120 | static void free_wrapper(void *freeable) 121 | { 122 | kfree(freeable); 123 | } 124 | 125 | static struct osdpi_flow_node * 126 | ndpi_flow_search(struct rb_root *root, struct nf_conn *ct) 127 | { 128 | struct osdpi_flow_node *data; 129 | struct rb_node *node = root->rb_node; 130 | 131 | while (node) { 132 | data = rb_entry(node, struct osdpi_flow_node, node); 133 | 134 | if (ct < data->ct) 135 | node = node->rb_left; 136 | else if (ct > data->ct) 137 | node = node->rb_right; 138 | else 139 | return data; 140 | } 141 | 142 | return NULL; 143 | } 144 | 145 | 146 | static int 147 | ndpi_flow_insert(struct rb_root *root, struct osdpi_flow_node *data) 148 | { 149 | struct osdpi_flow_node *this; 150 | struct rb_node **new = &(root->rb_node), *parent = NULL; 151 | 152 | while (*new) { 153 | this = rb_entry(*new, struct osdpi_flow_node, node); 154 | 155 | parent = *new; 156 | if (data->ct < this->ct) 157 | new = &((*new)->rb_left); 158 | else if (data->ct > this->ct) 159 | new = &((*new)->rb_right); 160 | else 161 | return 0; 162 | } 163 | rb_link_node(&data->node, parent, new); 164 | rb_insert_color(&data->node, root); 165 | 166 | return 1; 167 | } 168 | 169 | 170 | static struct osdpi_id_node * 171 | ndpi_id_search(struct rb_root *root, union nf_inet_addr *ip) 172 | { 173 | int res; 174 | struct osdpi_id_node *data; 175 | struct rb_node *node = root->rb_node; 176 | 177 | while (node) { 178 | data = rb_entry(node, struct osdpi_id_node, node); 179 | res = memcmp(ip, &data->ip, sizeof(union nf_inet_addr)); 180 | 181 | if (res < 0) 182 | node = node->rb_left; 183 | else if (res > 0) 184 | node = node->rb_right; 185 | else 186 | return data; 187 | } 188 | 189 | return NULL; 190 | } 191 | 192 | 193 | static int 194 | ndpi_id_insert(struct rb_root *root, struct osdpi_id_node *data) 195 | { 196 | int res; 197 | struct osdpi_id_node *this; 198 | struct rb_node **new = &(root->rb_node), *parent = NULL; 199 | 200 | while (*new) { 201 | this = rb_entry(*new, struct osdpi_id_node, node); 202 | res = memcmp(&data->ip, &this->ip, sizeof(union nf_inet_addr)); 203 | 204 | parent = *new; 205 | if (res < 0) 206 | new = &((*new)->rb_left); 207 | else if (res > 0) 208 | new = &((*new)->rb_right); 209 | else 210 | return 0; 211 | } 212 | rb_link_node(&data->node, parent, new); 213 | rb_insert_color(&data->node, root); 214 | 215 | return 1; 216 | } 217 | 218 | 219 | static void 220 | ndpi_id_release(struct kref *kref) 221 | { 222 | struct osdpi_id_node * id; 223 | 224 | id = container_of (kref, struct osdpi_id_node, refcnt); 225 | rb_erase(&id->node, &osdpi_id_root); 226 | kmem_cache_free (osdpi_id_cache, id); 227 | } 228 | 229 | 230 | static struct osdpi_flow_node * 231 | ndpi_alloc_flow (struct nf_conn * ct) 232 | { 233 | struct osdpi_flow_node *flow; 234 | 235 | spin_lock_bh (&flow_lock); 236 | flow = ndpi_flow_search (&osdpi_flow_root, ct); 237 | if (flow != NULL){ 238 | spin_unlock_bh (&flow_lock); 239 | return flow; 240 | } 241 | flow = kmem_cache_zalloc (osdpi_flow_cache, GFP_ATOMIC); 242 | if (flow == NULL){ 243 | pr_err("xt_ndpi: couldn't allocate new flow.\n"); 244 | spin_unlock_bh (&flow_lock); 245 | return NULL; 246 | } 247 | flow->ct = ct; 248 | flow->ndpi_flow = (struct ndpi_flow_struct *) 249 | ((char*)&flow->ndpi_flow+sizeof(flow->ndpi_flow)); 250 | ndpi_flow_insert (&osdpi_flow_root, flow); 251 | spin_unlock_bh (&flow_lock); 252 | 253 | return flow; 254 | } 255 | 256 | 257 | static void 258 | ndpi_free_flow (struct nf_conn * ct) 259 | { 260 | struct osdpi_flow_node * flow; 261 | 262 | spin_lock_bh (&flow_lock); 263 | flow = ndpi_flow_search (&osdpi_flow_root, ct); 264 | if (flow != NULL){ 265 | rb_erase (&flow->node, &osdpi_flow_root); 266 | kmem_cache_free (osdpi_flow_cache, flow); 267 | } 268 | spin_unlock_bh (&flow_lock); 269 | } 270 | 271 | 272 | static struct osdpi_id_node * 273 | ndpi_alloc_id (union nf_inet_addr * ip) 274 | { 275 | struct osdpi_id_node *id; 276 | 277 | spin_lock_bh (&id_lock); 278 | id = ndpi_id_search (&osdpi_id_root, ip); 279 | if (id != NULL){ 280 | kref_get (&id->refcnt); 281 | }else{ 282 | id = kmem_cache_zalloc (osdpi_id_cache, GFP_ATOMIC); 283 | 284 | if (id == NULL){ 285 | pr_err("xt_ndpi: couldn't allocate new id.\n"); 286 | spin_unlock_bh (&id_lock); 287 | return NULL; 288 | } 289 | memcpy(&id->ip, ip, sizeof(union nf_inet_addr)); 290 | id->ndpi_id = (struct ndpi_id_struct *) 291 | ((char*)&id->ndpi_id+sizeof(id->ndpi_id)); 292 | kref_init (&id->refcnt); 293 | ndpi_id_insert (&osdpi_id_root, id); 294 | } 295 | spin_unlock_bh (&id_lock); 296 | 297 | return id; 298 | } 299 | 300 | 301 | static void 302 | ndpi_free_id (union nf_inet_addr * ip) 303 | { 304 | struct osdpi_id_node *id; 305 | 306 | spin_lock_bh (&id_lock); 307 | id = ndpi_id_search (&osdpi_id_root, ip); 308 | if (id != NULL) 309 | kref_put (&id->refcnt, ndpi_id_release); 310 | spin_unlock_bh (&id_lock); 311 | } 312 | 313 | 314 | static void 315 | ndpi_enable_protocols (const struct xt_ndpi_mtinfo*info) 316 | { 317 | int i; 318 | 319 | for (i = 1; i <= NDPI_LAST_IMPLEMENTED_PROTOCOL; i++){ 320 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags, i) != 0){ 321 | spin_lock_bh (&ipq_lock); 322 | atomic_inc(&protocols_cnt[i-1]); 323 | NDPI_ADD_PROTOCOL_TO_BITMASK(protocols_bitmask, i); 324 | ndpi_set_protocol_detection_bitmask2 325 | (ndpi_struct,&protocols_bitmask); 326 | spin_unlock_bh (&ipq_lock); 327 | } 328 | } 329 | } 330 | 331 | 332 | static void 333 | ndpi_disable_protocols (const struct xt_ndpi_mtinfo*info) 334 | { 335 | int i; 336 | 337 | for (i = 1; i <= NDPI_LAST_IMPLEMENTED_PROTOCOL; i++){ 338 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags, i) != 0){ 339 | spin_lock_bh (&ipq_lock); 340 | if (atomic_dec_and_test(&protocols_cnt[i-1])){ 341 | NDPI_DEL_PROTOCOL_FROM_BITMASK(protocols_bitmask, i); 342 | ndpi_set_protocol_detection_bitmask2 343 | (ndpi_struct, &protocols_bitmask); 344 | } 345 | spin_unlock_bh (&ipq_lock); 346 | } 347 | } 348 | } 349 | 350 | 351 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 352 | static int 353 | ndpi_conntrack_event (struct notifier_block *this, unsigned long ev, 354 | void * data) 355 | { 356 | struct nf_conn * ct = (struct nf_conn *) data; 357 | union nf_inet_addr *src, *dst; 358 | 359 | if (ct == &nf_conntrack_untracked) 360 | return NOTIFY_DONE; 361 | 362 | if (ev & IPCT_DESTROY){ 363 | src = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3; 364 | dst = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3; 365 | 366 | ndpi_free_id (src); 367 | ndpi_free_id (dst); 368 | ndpi_free_flow (ct); 369 | } 370 | 371 | return NOTIFY_DONE; 372 | } 373 | 374 | static struct notifier_block 375 | osdpi_notifier = { 376 | .notifier_call = ndpi_conntrack_event, 377 | }; 378 | 379 | #else 380 | static int 381 | ndpi_conntrack_event(unsigned int events, struct nf_ct_event *item) 382 | { 383 | struct nf_conn * ct = item->ct; 384 | union nf_inet_addr *src, *dst; 385 | 386 | if (ct == &nf_conntrack_untracked) 387 | return 0; 388 | 389 | if (events & (1 << IPCT_DESTROY)){ 390 | src = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3; 391 | dst = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3; 392 | 393 | ndpi_free_id (src); 394 | ndpi_free_id (dst); 395 | ndpi_free_flow (ct); 396 | } 397 | 398 | return 0; 399 | } 400 | 401 | static struct nf_ct_event_notifier 402 | osdpi_notifier = { 403 | .fcn = ndpi_conntrack_event, 404 | }; 405 | 406 | #endif 407 | 408 | 409 | 410 | static u32 411 | ndpi_process_packet(struct nf_conn * ct, const uint64_t time, 412 | const struct iphdr *iph, uint16_t ipsize) 413 | { 414 | u32 proto = NDPI_PROTOCOL_UNKNOWN; 415 | union nf_inet_addr *ipsrc, *ipdst; 416 | struct osdpi_id_node *src, *dst; 417 | struct osdpi_flow_node * flow; 418 | 419 | spin_lock_bh (&flow_lock); 420 | flow = ndpi_flow_search (&osdpi_flow_root, ct); 421 | spin_unlock_bh (&flow_lock); 422 | if (flow == NULL){ 423 | flow = ndpi_alloc_flow(ct); 424 | if (flow == NULL) 425 | return proto; 426 | } 427 | 428 | ipsrc = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3; 429 | 430 | spin_lock_bh (&id_lock); 431 | src = ndpi_id_search (&osdpi_id_root, ipsrc); 432 | spin_unlock_bh (&id_lock); 433 | if (src == NULL) { 434 | src = ndpi_alloc_id(ipsrc); 435 | if (src == NULL) 436 | return proto; 437 | } 438 | 439 | ipdst = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3; 440 | 441 | spin_lock_bh (&id_lock); 442 | dst = ndpi_id_search (&osdpi_id_root, ipdst); 443 | spin_unlock_bh (&id_lock); 444 | if (dst == NULL) { 445 | dst = ndpi_alloc_id(ipdst); 446 | if (dst == NULL) 447 | return proto; 448 | } 449 | 450 | /* here the actual detection is performed */ 451 | spin_lock_bh (&ipq_lock); 452 | proto = ndpi_detection_process_packet(ndpi_struct,flow->ndpi_flow, 453 | (uint8_t *) iph, ipsize, time, 454 | src->ndpi_id, dst->ndpi_id); 455 | flow->detected_protocol = proto; 456 | spin_unlock_bh (&ipq_lock); 457 | 458 | return proto; 459 | } 460 | 461 | 462 | 463 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 464 | static bool 465 | ndpi_mt (const struct sk_buff *skb, 466 | const struct net_device *in, 467 | const struct net_device *out, 468 | const struct xt_match *match, 469 | const void *matchinfo, 470 | int offset, 471 | unsigned int protoff, 472 | bool *hotdrop) 473 | 474 | #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) 475 | static bool 476 | ndpi_mt(const struct sk_buff *skb, const struct xt_match_param *par) 477 | #else 478 | static bool 479 | ndpi_mt(const struct sk_buff *skb, struct xt_action_param *par) 480 | #endif 481 | { 482 | u32 proto; 483 | u64 time; 484 | 485 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 486 | const struct xt_ndpi_mtinfo *info = matchinfo; 487 | #else 488 | const struct xt_ndpi_mtinfo *info = par->matchinfo; 489 | #endif 490 | 491 | enum ip_conntrack_info ctinfo; 492 | struct nf_conn * ct; 493 | struct timeval tv; 494 | struct sk_buff *linearized_skb = NULL; 495 | const struct sk_buff *skb_use = NULL; 496 | 497 | if (skb_is_nonlinear(skb)){ 498 | linearized_skb = skb_copy(skb, GFP_ATOMIC); 499 | if (linearized_skb == NULL) { 500 | pr_info ("xt_ndpi: linearization failed.\n"); 501 | return false; 502 | } 503 | skb_use = linearized_skb; 504 | } else { 505 | skb_use = skb; 506 | } 507 | 508 | ct = nf_ct_get (skb_use, &ctinfo); 509 | if (ct == NULL){ 510 | 511 | if(linearized_skb != NULL){ 512 | kfree_skb(linearized_skb); 513 | } 514 | 515 | return false; 516 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) 517 | } else if (nf_ct_is_untracked(skb)){ 518 | #else 519 | } else if (nf_ct_is_untracked(ct)){ 520 | #endif 521 | pr_info ("xt_ndpi: ignoring untracked sk_buff.\n"); 522 | return false; 523 | } 524 | do_gettimeofday(&tv); 525 | 526 | time = ((uint64_t) tv.tv_sec) * detection_tick_resolution + 527 | tv.tv_usec / (1000000 / detection_tick_resolution); 528 | 529 | /* process the packet */ 530 | proto = ndpi_process_packet(ct, time, ip_hdr(skb_use), skb_use->len); 531 | 532 | if(linearized_skb != NULL){ 533 | kfree_skb(linearized_skb); 534 | } 535 | 536 | 537 | if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(info->flags,proto) != 0) 538 | return true; 539 | 540 | return false; 541 | } 542 | 543 | 544 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 545 | static bool 546 | ndpi_mt_check(const char *tablename, 547 | const void *ip, 548 | const struct xt_match *match, 549 | void *matchinfo, 550 | unsigned int hook_mask) 551 | 552 | { 553 | const struct xt_ndpi_mtinfo *info = matchinfo; 554 | 555 | if (NDPI_BITMASK_IS_ZERO(info->flags)){ 556 | pr_info("None selected protocol.\n"); 557 | return false; 558 | } 559 | 560 | ndpi_enable_protocols (info); 561 | 562 | return nf_ct_l3proto_try_module_get (match->family) == 0; 563 | } 564 | 565 | #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) 566 | static bool 567 | ndpi_mt_check(const struct xt_mtchk_param *par) 568 | { 569 | const struct xt_ndpi_mtinfo *info = par->matchinfo; 570 | 571 | if (NDPI_BITMASK_IS_ZERO(info->flags)){ 572 | pr_info("None selected protocol.\n"); 573 | return false; 574 | } 575 | 576 | ndpi_enable_protocols (info); 577 | 578 | return nf_ct_l3proto_try_module_get (par->family) == 0; 579 | } 580 | #else 581 | static int 582 | ndpi_mt_check(const struct xt_mtchk_param *par) 583 | { 584 | const struct xt_ndpi_mtinfo *info = par->matchinfo; 585 | 586 | if (NDPI_BITMASK_IS_ZERO(info->flags)){ 587 | pr_info("None selected protocol.\n"); 588 | return -EINVAL; 589 | } 590 | 591 | ndpi_enable_protocols (info); 592 | 593 | return nf_ct_l3proto_try_module_get (par->family); 594 | } 595 | #endif 596 | 597 | 598 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 599 | static void 600 | ndpi_mt_destroy (const struct xt_match *match, void *matchinfo) 601 | { 602 | const struct xt_ndpi_mtinfo *info = matchinfo; 603 | 604 | ndpi_disable_protocols (info); 605 | nf_ct_l3proto_module_put (match->family); 606 | } 607 | 608 | #else 609 | static void 610 | ndpi_mt_destroy (const struct xt_mtdtor_param *par) 611 | { 612 | const struct xt_ndpi_mtinfo *info = par->matchinfo; 613 | 614 | ndpi_disable_protocols (info); 615 | nf_ct_l3proto_module_put (par->family); 616 | } 617 | 618 | #endif 619 | 620 | 621 | 622 | static void ndpi_cleanup(void) 623 | { 624 | struct rb_node * next; 625 | struct osdpi_id_node *id; 626 | struct osdpi_flow_node *flow; 627 | 628 | ndpi_exit_detection_module(ndpi_struct, free_wrapper); 629 | 630 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) 631 | nf_conntrack_unregister_notifier (&osdpi_notifier); 632 | #else 633 | nf_conntrack_unregister_notifier (&init_net,&osdpi_notifier); 634 | #endif 635 | 636 | /* free all objects before destroying caches */ 637 | next = rb_first(&osdpi_flow_root); 638 | while (next){ 639 | flow = rb_entry(next, struct osdpi_flow_node, node); 640 | next = rb_next(&flow->node); 641 | rb_erase(&flow->node, &osdpi_flow_root); 642 | kmem_cache_free (osdpi_flow_cache, flow); 643 | } 644 | kmem_cache_destroy (osdpi_flow_cache); 645 | 646 | next = rb_first(&osdpi_id_root); 647 | while (next){ 648 | id = rb_entry(next, struct osdpi_id_node, node); 649 | next = rb_next(&id->node); 650 | rb_erase(&id->node, &osdpi_id_root); 651 | kmem_cache_free (osdpi_id_cache, id); 652 | } 653 | kmem_cache_destroy (osdpi_id_cache); 654 | } 655 | 656 | 657 | static struct xt_match 658 | ndpi_mt_reg __read_mostly = { 659 | .name = "ndpi", 660 | .revision = 0, 661 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) 662 | .family = AF_INET, 663 | #else 664 | .family = NFPROTO_IPV4, 665 | #endif 666 | .match = ndpi_mt, 667 | .checkentry = ndpi_mt_check, 668 | .destroy = ndpi_mt_destroy, 669 | .matchsize = sizeof(struct xt_ndpi_mtinfo), 670 | .me = THIS_MODULE, 671 | }; 672 | 673 | 674 | static int __init ndpi_mt_init(void) 675 | { 676 | int ret, i; 677 | 678 | pr_info("xt_ndpi 0.1 (nDPI wrapper module).\n"); 679 | /* init global detection structure */ 680 | ndpi_struct = ndpi_init_detection_module(detection_tick_resolution, 681 | malloc_wrapper, debug_printf); 682 | if (ndpi_struct == NULL) { 683 | pr_err("xt_ndpi: global structure initialization failed.\n"); 684 | ret = -ENOMEM; 685 | goto err_out; 686 | } 687 | 688 | for (i = 0; i < NDPI_LAST_IMPLEMENTED_PROTOCOL; i++){ 689 | atomic_set (&protocols_cnt[i], 0); 690 | } 691 | 692 | /* disable all protocols */ 693 | NDPI_BITMASK_RESET(protocols_bitmask); 694 | ndpi_set_protocol_detection_bitmask2(ndpi_struct, &protocols_bitmask); 695 | 696 | /* allocate memory for id and flow tracking */ 697 | size_id_struct = ndpi_detection_get_sizeof_ndpi_id_struct(); 698 | size_flow_struct = ndpi_detection_get_sizeof_ndpi_flow_struct(); 699 | 700 | osdpi_flow_cache = kmem_cache_create("xt_ndpi_flows", 701 | sizeof(struct osdpi_flow_node) + 702 | size_flow_struct, 703 | 0, 0, NULL); 704 | if (!osdpi_flow_cache){ 705 | pr_err("xt_ndpi: error creating flow cache.\n"); 706 | ret = -ENOMEM; 707 | goto err_ipq; 708 | } 709 | 710 | osdpi_id_cache = kmem_cache_create("xt_ndpi_ids", 711 | sizeof(struct osdpi_id_node) + 712 | size_id_struct, 713 | 0, 0, NULL); 714 | if (!osdpi_id_cache){ 715 | pr_err("xt_ndpi: error creating ids cache.\n"); 716 | ret = -ENOMEM; 717 | goto err_flow; 718 | } 719 | 720 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) 721 | ret = nf_conntrack_register_notifier(&osdpi_notifier); 722 | #else 723 | ret = nf_conntrack_register_notifier(&init_net,&osdpi_notifier); 724 | #endif 725 | if (ret < 0){ 726 | pr_err("xt_ndpi: error registering notifier.\n"); 727 | goto err_id; 728 | } 729 | 730 | ret = xt_register_match(&ndpi_mt_reg); 731 | if (ret != 0){ 732 | pr_err("xt_ndpi: error registering ndpi match.\n"); 733 | ndpi_cleanup(); 734 | } 735 | 736 | return ret; 737 | 738 | err_id: 739 | kmem_cache_destroy (osdpi_id_cache); 740 | err_flow: 741 | kmem_cache_destroy (osdpi_flow_cache); 742 | err_ipq: 743 | ndpi_exit_detection_module(ndpi_struct, free_wrapper); 744 | err_out: 745 | return ret; 746 | } 747 | 748 | 749 | static void __exit ndpi_mt_exit(void) 750 | { 751 | pr_info("xt_ndpi 1.2 unload.\n"); 752 | 753 | xt_unregister_match(&ndpi_mt_reg); 754 | 755 | ndpi_cleanup(); 756 | } 757 | 758 | 759 | module_init(ndpi_mt_init); 760 | module_exit(ndpi_mt_exit); 761 | --------------------------------------------------------------------------------