All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] PID-based network traffic monitoring
@ 2012-04-04  9:16 Nuno Martins
  2012-04-04  9:16 ` [RFC PATCH 1/2] Multiple filter function support for BPF filters Nuno Martins
  2012-04-04  9:16 ` [RFC PATCH 2/2] PID-based packet filtering support Nuno Martins
  0 siblings, 2 replies; 8+ messages in thread
From: Nuno Martins @ 2012-04-04  9:16 UTC (permalink / raw)
  To: netdev, nuno.martins; +Cc: Alfredo Matos, Paulo Trezentos

 In this patchset we introduce the support for pid-based network monitoring, through a new BPF/LSF instruction, supported by KProbes to dynamically detect opening and closing connections.
 With these changes it is possible to pass a PID to tcpdump, and monitor the traffic on the network which belongs to a specific PID. More information can be found at the project page [1].

 * The first patch provides the infrastructure to registering custom BPF filter functions through setsockopt.
 * The second patch introduces a pid monitor that keeps track of the ongoing connections (src addr, dst addr, src port, dst, port and protocol), associated to a PID, passed from userspace as part of a custom BFP filter.

 For testing with tcpdump, a modified pcap library is required. The patch can be found at [2].
 This approach is still in early stages of development and under heavy testing. Any feedback or suggestions are appreciated.

 Thanks,

 Nuno Martins.

 [1] http://projects.caixamagica.pt/projects/pidmonitoring
 [2] http://projects.caixamagica.pt/projects/pidmonitoring/attachment/wiki/WikiStart/libpcap.patch

Nuno Martins (2):
  Multiple filter function support for BPF filters
  PID-based packet filtering support

 include/asm-generic/socket.h      |    4 +
 include/linux/filter.h            |    4 +-
 include/linux/socket.h            |   28 +++
 net/Kconfig                       |   15 ++
 net/Makefile                      |    1 +
 net/core/Makefile                 |    3 +-
 net/core/filter.c                 |    8 +-
 net/core/filter_function.c        |  133 +++++++++++
 net/core/sock.c                   |   23 +-
 net/pidmonitor/Makefile           |    3 +
 net/pidmonitor/db_monitor.c       |  389 ++++++++++++++++++++++++++++++
 net/pidmonitor/db_monitor.h       |   51 ++++
 net/pidmonitor/filter.c           |  476 +++++++++++++++++++++++++++++++++++++
 net/pidmonitor/filter.h           |   31 +++
 net/pidmonitor/pidmonitor.c       |  102 ++++++++
 net/pidmonitor/pidmonitor.h       |   63 +++++
 net/pidmonitor/proc_monitor.c     |  116 +++++++++
 net/pidmonitor/proc_monitor.h     |   23 ++
 net/pidmonitor/syscalls_monitor.c |  423 ++++++++++++++++++++++++++++++++
 net/pidmonitor/syscalls_monitor.h |   31 +++
 net/pidmonitor/task_monitor.c     |   77 ++++++
 net/pidmonitor/task_monitor.h     |   23 ++
 22 files changed, 2023 insertions(+), 4 deletions(-)
 create mode 100644 net/core/filter_function.c
 create mode 100644 net/pidmonitor/Makefile
 create mode 100644 net/pidmonitor/db_monitor.c
 create mode 100644 net/pidmonitor/db_monitor.h
 create mode 100644 net/pidmonitor/filter.c
 create mode 100644 net/pidmonitor/filter.h
 create mode 100644 net/pidmonitor/pidmonitor.c
 create mode 100644 net/pidmonitor/pidmonitor.h
 create mode 100644 net/pidmonitor/proc_monitor.c
 create mode 100644 net/pidmonitor/proc_monitor.h
 create mode 100644 net/pidmonitor/syscalls_monitor.c
 create mode 100644 net/pidmonitor/syscalls_monitor.h
 create mode 100644 net/pidmonitor/task_monitor.c
 create mode 100644 net/pidmonitor/task_monitor.h

-- 
1.7.10.rc3.11.gd8282

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [RFC PATCH 1/2] Multiple filter function support for BPF filters
  2012-04-04  9:16 [RFC PATCH 0/2] PID-based network traffic monitoring Nuno Martins
@ 2012-04-04  9:16 ` Nuno Martins
  2012-04-04  9:16 ` [RFC PATCH 2/2] PID-based packet filtering support Nuno Martins
  1 sibling, 0 replies; 8+ messages in thread
From: Nuno Martins @ 2012-04-04  9:16 UTC (permalink / raw)
  To: netdev, nuno.martins; +Cc: Alfredo Matos, Paulo Trezentos

This patch introduces the possibility of attaching multiple filter functions to a PF socket, useful for custom packet filtering.
It maintains a list of registered functions, received through setsockopt from userspace.
The custom filtering functions are compatible with BPF/LSF filter in order to retain compatibility with sk_run_filter and the pcap library.

This mechanism was developed to support the network monitoring by process id on the kernel (second patch in this series).

Signed-off-by: Nuno Martins <nuno.martins@caixamagica.pt>
---
 include/asm-generic/socket.h |    4 ++
 include/linux/filter.h       |    3 +-
 include/linux/socket.h       |   28 +++++++++
 net/Kconfig                  |    8 +++
 net/core/Makefile            |    3 +-
 net/core/filter.c            |    3 +-
 net/core/filter_function.c   |  138 ++++++++++++++++++++++++++++++++++++++++++
 net/core/sock.c              |   23 ++++++-
 8 files changed, 206 insertions(+), 4 deletions(-)

diff --git a/include/asm-generic/socket.h b/include/asm-generic/socket.h
index b1bea03..89c45a9 100644
--- a/include/asm-generic/socket.h
+++ b/include/asm-generic/socket.h
@@ -72,4 +72,8 @@
 /* Instruct lower device to use last 4-bytes of skb data as FCS */
 #define SO_NOFCS		43
 
+#ifdef CONFIG_FILTER_FUNCTION
+#define SO_ATTACH_FILTER_FUNC	44
+#define SO_DETACH_FILTER_FUNC	45
+#endif
 #endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 8eeb205..8d2d9c2 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -90,6 +90,7 @@ struct sock_fprog {	/* Required for SO_ATTACH_FILTER. */
 #define BPF_MISCOP(code) ((code) & 0xf8)
 #define         BPF_TAX         0x00
 #define         BPF_TXA         0x80
+#define         BPF_PROC        0xf0
 
 #ifndef BPF_MAXINSNS
 #define BPF_MAXINSNS 4096
@@ -168,7 +169,7 @@ static inline void bpf_jit_compile(struct sk_filter *fp)
 static inline void bpf_jit_free(struct sk_filter *fp)
 {
 }
-#define SK_RUN_FILTER(FILTER, SKB) sk_run_filter(SKB, FILTER->insns)
+#define SK_RUN_FILTER(FILTER, SKB) (*FILTER->bpf_func)(SKB, FILTER->insns)
 #endif
 
 enum {
diff --git a/include/linux/socket.h b/include/linux/socket.h
index da2d3e2..12acea5 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -316,6 +316,34 @@ struct ucred {
 /* IPX options */
 #define IPX_TYPE	1
 
+#ifdef CONFIG_FILTER_FUNCTION
+#define FILTER_FUNCTION_NAME_LEN 25
+struct filter_function_struct {
+	char name[FILTER_FUNCTION_NAME_LEN];
+	int pid;
+};
+
+#include <linux/list.h>
+
+struct sk_buff;
+struct sock_filter;
+struct sock;
+struct sk_filter;
+
+struct filter_function {
+	struct list_head list;
+	char name[FILTER_FUNCTION_NAME_LEN];
+	int (*init_func)(struct filter_function_struct *ffs);
+	unsigned int (*func)(const struct sk_buff *skb, const struct sock_filter *filter);
+};
+
+extern int attach_filter_function(struct filter_function_struct *ffs, struct sock *sk);
+extern int detach_filter_function(struct filter_function_struct *ffs, struct sock *sk);
+extern int register_filter_function(struct filter_function *ff);
+extern int unregister_filter_function(struct filter_function *ff);
+extern int detect_filter_function(struct sk_filter *fp);
+#endif
+
 extern void cred_to_ucred(struct pid *pid, const struct cred *cred, struct ucred *ucred);
 
 extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
diff --git a/net/Kconfig b/net/Kconfig
index e07272d..6bbce29 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -260,6 +260,14 @@ config BPF_JIT
 	  packet sniffing (libpcap/tcpdump). Note : Admin should enable
 	  this feature changing /proc/sys/net/core/bpf_jit_enable
 
+config FILTER_FUNCTION
+	bool "enable definition of a sniff function"
+	depends on MODULES
+	default y
+	---help---
+	  Dynamicaly define what sniffer function would be used to filter
+	  packets
+
 menu "Network testing"
 
 config NET_PKTGEN
diff --git a/net/core/Makefile b/net/core/Makefile
index 674641b..c3378c5 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -3,7 +3,8 @@
 #
 
 obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
-	 gen_stats.o gen_estimator.o net_namespace.o secure_seq.o flow_dissector.o
+	 gen_stats.o gen_estimator.o net_namespace.o secure_seq.o flow_dissector.o \
+	 filter_function.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
diff --git a/net/core/filter.c b/net/core/filter.c
index 5dea452..0aa1ac6 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -582,7 +582,8 @@ void sk_filter_release_rcu(struct rcu_head *rcu)
 {
 	struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
 
-	bpf_jit_free(fp);
+	if (detect_filter_function(fp))
+		bpf_jit_free(fp);
 	kfree(fp);
 }
 EXPORT_SYMBOL(sk_filter_release_rcu);
diff --git a/net/core/filter_function.c b/net/core/filter_function.c
new file mode 100644
index 0000000..c9b62e3
--- /dev/null
+++ b/net/core/filter_function.c
@@ -0,0 +1,138 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifdef CONFIG_FILTER_FUNCTION
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/filter.h>
+#include <net/sock.h>
+
+LIST_HEAD(filter_list);
+/*EXPORT_SYMBOL(sniff_list);*/
+
+static DEFINE_MUTEX(filter_list_mutex);
+
+int register_filter_function(struct filter_function *ff)
+{
+	list_add(&(ff->list), &filter_list);
+
+	return 0;
+}
+EXPORT_SYMBOL(register_filter_function);
+
+static struct filter_function *find_filter_function_by_addr(void *addr)
+{
+	struct filter_function *ff;
+
+	if (addr == sk_run_filter)
+		return NULL;
+
+	list_for_each_entry(ff, &filter_list, list) {
+		if (ff->func == addr)
+			return ff;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(find_filter_function_by_addr);
+
+static struct filter_function *find_filter_function_by_name(const char *name)
+{
+	struct filter_function *ff;
+	list_for_each_entry(ff, &filter_list, list) {
+		if (strcmp(ff->name, name) == 0)
+			return ff;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(find_filter_function_by_name);
+
+int unregister_filter_function(struct filter_function *ff)
+{
+	list_del(&(ff->list));
+	return 0;
+}
+EXPORT_SYMBOL(unregister_filter_function);
+
+int attach_filter_function(struct filter_function_struct *ffs, struct sock *sk)
+{
+	struct filter_function *ff = NULL;
+	struct sk_filter *old_fp;
+
+	if (strcmp(ffs->name, "sk_run_filter") == 0) {
+		/*if (init_process_filter_function != NULL)
+			init_process_filter_function(ffs);*/
+	} else
+		ff = find_filter_function_by_name(ffs->name);
+
+	if (ff != NULL) {
+		int ret;
+		if (ff->init_func != NULL)
+			ret = ff->init_func(ffs);
+
+		if (ff->func != NULL) {
+			old_fp = rcu_dereference_protected(sk->sk_filter,
+					sock_owned_by_user(sk));
+			if (detect_filter_function(old_fp)) {
+				bpf_jit_free(old_fp);
+			}
+
+			old_fp->bpf_func = ff->func;
+			rcu_assign_pointer(sk->sk_filter, old_fp);
+		}
+	} else {
+		return -1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(attach_filter_function);
+
+int detach_filter_function(struct filter_function_struct *ffs, struct sock *sk)
+{
+	struct sk_filter *old_fp;
+	struct filter_function *ff;
+
+	old_fp = rcu_dereference_protected(sk->sk_filter,
+			sock_owned_by_user(sk));
+
+	ff = find_filter_function_by_addr(old_fp->bpf_func);
+	if (ff) {
+		return 0;
+	}
+
+	return -1;
+}
+EXPORT_SYMBOL(detach_filter_function);
+
+int detect_filter_function(struct sk_filter *fp)
+{
+	return find_filter_function_by_addr(fp->bpf_func) ? 0 : -1;
+}
+EXPORT_SYMBOL(detect_filter_function);
+#endif
diff --git a/net/core/sock.c b/net/core/sock.c
index 9be6d0d..0583bf6d 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -769,7 +769,28 @@ set_rcvbuf:
 	case SO_DETACH_FILTER:
 		ret = sk_detach_filter(sk);
 		break;
-
+#ifdef CONFIG_FILTER_FUNCTION
+	case SO_ATTACH_FILTER_FUNC:
+		ret = -EINVAL;
+		if (optlen == sizeof(struct filter_function_struct)) {
+			struct filter_function_struct ff;
+			ret = -EFAULT;
+			if (copy_from_user(&ff, optval, sizeof(ff)))
+				break;
+			ret = attach_filter_function(&ff, sk);
+		}
+		break;
+	case SO_DETACH_FILTER_FUNC:
+		ret = -EINVAL;
+		if (optlen == sizeof(struct filter_function_struct)) {
+			struct filter_function_struct ff;
+			ret = -EFAULT;
+			if (copy_from_user(&ff, optval, sizeof(ff)))
+				break;
+			ret = detach_filter_function(&ff, sk);
+		}
+		break;
+#endif
 	case SO_PASSSEC:
 		if (valbool)
 			set_bit(SOCK_PASSSEC, &sock->flags);
-- 
1.7.10.rc3.11.gd8282

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [RFC PATCH 2/2] PID-based packet filtering support
  2012-04-04  9:16 [RFC PATCH 0/2] PID-based network traffic monitoring Nuno Martins
  2012-04-04  9:16 ` [RFC PATCH 1/2] Multiple filter function support for BPF filters Nuno Martins
@ 2012-04-04  9:16 ` Nuno Martins
  2012-04-04 17:01   ` chetan loke
  2012-04-04 18:57   ` chetan loke
  1 sibling, 2 replies; 8+ messages in thread
From: Nuno Martins @ 2012-04-04  9:16 UTC (permalink / raw)
  To: netdev, nuno.martins; +Cc: Alfredo Matos, Paulo Trezentos

This patch introduces the pidmonitor module through three main components:

* a custom BFP filter function that acts on PID information

* dynamic KProbes handlers (kretprobe handlers) that intercept system calls (connect, bind, etc.) to determine the connections established by a specific process (pid).

* a repository (RB Tree) for maintaining the packet information to PID
mapping, to allow runtime use of the BPF filter.

Currently, the PID monitor is only available for TCP and UDP on IPv4. IPv6 support is under development.

Signed-off-by: Nuno Martins <nuno.martins@caixamagica.pt>
---
 include/linux/filter.h            |    1 +
 net/Kconfig                       |    7 +
 net/Makefile                      |    1 +
 net/core/filter.c                 |    5 +
 net/core/filter_function.c        |    9 +-
 net/pidmonitor/Makefile           |    3 +
 net/pidmonitor/db_monitor.c       |  389 ++++++++++++++++++++++++++++++
 net/pidmonitor/db_monitor.h       |   51 ++++
 net/pidmonitor/filter.c           |  476 +++++++++++++++++++++++++++++++++++++
 net/pidmonitor/filter.h           |   31 +++
 net/pidmonitor/pidmonitor.c       |  102 ++++++++
 net/pidmonitor/pidmonitor.h       |   63 +++++
 net/pidmonitor/proc_monitor.c     |  116 +++++++++
 net/pidmonitor/proc_monitor.h     |   23 ++
 net/pidmonitor/syscalls_monitor.c |  423 ++++++++++++++++++++++++++++++++
 net/pidmonitor/syscalls_monitor.h |   31 +++
 net/pidmonitor/task_monitor.c     |   77 ++++++
 net/pidmonitor/task_monitor.h     |   23 ++
 18 files changed, 1824 insertions(+), 7 deletions(-)

diff --git a/include/linux/filter.h b/include/linux/filter.h
index 8d2d9c2..f50dc35 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -204,6 +204,7 @@ enum {
 	BPF_S_LDX_IMM,
 	BPF_S_MISC_TAX,
 	BPF_S_MISC_TXA,
+	BPF_S_MISC_PROC,
 	BPF_S_ALU_DIV_K,
 	BPF_S_LD_MEM,
 	BPF_S_LDX_MEM,
diff --git a/net/Kconfig b/net/Kconfig
index 6bbce29..9c74a0f 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -268,6 +268,13 @@ config FILTER_FUNCTION
 	  Dynamicaly define what sniffer function would be used to filter
 	  packets
 
+config MONITOR_PID
+	tristate "network monitoring by process id"
+	depends on MODULES && KPROBES && FILTER_FUNCTION
+	default m
+	---help---
+	  Monitor network defining a pid to sniff the packets
+
 menu "Network testing"
 
 config NET_PKTGEN
diff --git a/net/Makefile b/net/Makefile
index ad432fa..b5e35ab 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -70,3 +70,4 @@ obj-$(CONFIG_CEPH_LIB)		+= ceph/
 obj-$(CONFIG_BATMAN_ADV)	+= batman-adv/
 obj-$(CONFIG_NFC)		+= nfc/
 obj-$(CONFIG_OPENVSWITCH)	+= openvswitch/
+obj-$(CONFIG_MONITOR_PID)	+= pidmonitor/
diff --git a/net/core/filter.c b/net/core/filter.c
index 0aa1ac6..51b41a0 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -277,6 +277,10 @@ load_b:
 		case BPF_S_MISC_TXA:
 			A = X;
 			continue;
+		case BPF_S_MISC_PROC:
+			if ((fentry+1)->code == BPF_S_JMP_JEQ_K)
+				fentry += 1;
+			continue;
 		case BPF_S_RET_K:
 			return K;
 		case BPF_S_RET_A:
@@ -472,6 +476,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
 		[BPF_LDX|BPF_IMM]        = BPF_S_LDX_IMM,
 		[BPF_MISC|BPF_TAX]       = BPF_S_MISC_TAX,
 		[BPF_MISC|BPF_TXA]       = BPF_S_MISC_TXA,
+		[BPF_MISC|BPF_PROC]	 = BPF_S_MISC_PROC,
 		[BPF_RET|BPF_K]          = BPF_S_RET_K,
 		[BPF_RET|BPF_A]          = BPF_S_RET_A,
 		[BPF_ALU|BPF_DIV|BPF_K]  = BPF_S_ALU_DIV_K,
diff --git a/net/core/filter_function.c b/net/core/filter_function.c
index c9b62e3..ee5f5be 100644
--- a/net/core/filter_function.c
+++ b/net/core/filter_function.c
@@ -32,9 +32,7 @@
 #include <linux/filter.h>
 #include <net/sock.h>
 
-LIST_HEAD(filter_list);
-/*EXPORT_SYMBOL(sniff_list);*/
-
+static LIST_HEAD(filter_list);
 static DEFINE_MUTEX(filter_list_mutex);
 
 int register_filter_function(struct filter_function *ff)
@@ -84,10 +82,7 @@ int attach_filter_function(struct filter_function_struct *ffs, struct sock *sk)
 	struct filter_function *ff = NULL;
 	struct sk_filter *old_fp;
 
-	if (strcmp(ffs->name, "sk_run_filter") == 0) {
-		/*if (init_process_filter_function != NULL)
-			init_process_filter_function(ffs);*/
-	} else
+	if (strcmp(ffs->name, "sk_run_filter") != 0)
 		ff = find_filter_function_by_name(ffs->name);
 
 	if (ff != NULL) {
diff --git a/net/pidmonitor/Makefile b/net/pidmonitor/Makefile
new file mode 100644
index 0000000..3fa01dd
--- /dev/null
+++ b/net/pidmonitor/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_MONITOR_PID) += pidnetmonitor.o
+
+pidnetmonitor-objs := syscalls_monitor.o task_monitor.o filter.o proc_monitor.o db_monitor.o pidmonitor.o
diff --git a/net/pidmonitor/db_monitor.c b/net/pidmonitor/db_monitor.c
new file mode 100644
index 0000000..45dfb6d
--- /dev/null
+++ b/net/pidmonitor/db_monitor.c
@@ -0,0 +1,389 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <linux/types.h>
+
+#include <linux/in.h>
+
+#include "pidmonitor.h"
+#include "db_monitor.h"
+
+static struct rb_root db;
+
+/*
+ * returns NULL if there isn't that port int the tree
+ */
+static int is_equal_packet_info(struct packetInfo *pi,
+		struct portInfo *info)
+{
+
+	struct local_addresses_list *tmp = NULL;
+	struct local_addresses_list *address = NULL;
+	struct list_head *pos = NULL;
+
+	switch (pi->protocol) {
+	case IPPROTO_TCP:
+		if (info->tcp)
+			tmp = info->tcp;
+		break;
+	case IPPROTO_UDP:
+		if (info->udp)
+			tmp = info->udp;
+		break;
+	default:
+		return 0;
+	}
+
+	if (!tmp)
+		return 0;
+
+	list_for_each(pos, &(tmp->list)) {
+		address = list_entry(pos, struct local_addresses_list, list);
+		if (pi->address == address->address && pi->pid == address->pid)
+			return 1;
+	}
+
+	return 0;
+}
+
+static struct portInfo *__monitor_search(struct rb_root *root, struct packetInfo *pi)
+{
+	struct rb_node *node = root->rb_node;
+	struct portInfo *data = NULL;
+
+	while (node) {
+		data = container_of(node, struct portInfo, node);
+
+		if (pi->port < data->port)
+			node = node->rb_left;
+		else
+			if (pi->port > data->port)
+				node = node->rb_right;
+			else
+				if (pi->port == data->port) {
+					if (is_equal_packet_info(pi, data) != 0)
+						return data;
+					else
+						return NULL;
+				} else
+					return NULL;
+	}
+	return NULL;
+}
+
+struct portInfo *monitor_search(struct packetInfo *pi)
+{
+	return __monitor_search(&db, pi);
+}
+
+static int add_address(struct packetInfo *lpi, struct local_addresses_list *tmp,
+		int *list_counter, int pid)
+{
+	struct local_addresses_list *address = NULL;
+	struct list_head *pos = NULL;
+	struct local_addresses_list *node = NULL;
+
+	list_for_each(pos, &(tmp->list)) {
+		address = list_entry(pos, struct local_addresses_list, list);
+		if (lpi->address == address->address) {
+			address->counter++;
+			address->pid = pid;
+			return 1;
+		}
+	}
+
+	node = kmalloc(sizeof(*node), GFP_KERNEL);
+
+	if (!node)
+		return -1;
+
+	node->address = lpi->address;
+	node->counter = 1;
+
+	list_add(&(node->list), &(tmp->list));
+	(*list_counter)++;
+	node->pid = pid;
+
+	return 1;
+}
+
+static int insert_address(struct packetInfo *lpi, struct portInfo *port_info)
+{
+
+	switch (lpi->protocol) {
+	case IPPROTO_TCP:
+		if (!(port_info->tcp)) {
+			port_info->tcp = kmalloc(sizeof(struct local_addresses_list), GFP_KERNEL);
+
+			if (!port_info->tcp)
+				return -1;
+
+			INIT_LIST_HEAD(&((port_info->tcp)->list));
+			port_info->tcp->counter = 0;
+		}
+
+		if (lpi->address == 0) {
+			struct local_addresses_list *address = NULL;
+			struct list_head *pos = NULL;
+
+			list_for_each(pos, &(local_list->list)) {
+				struct packetInfo pi;
+				address = list_entry(pos, struct local_addresses_list, list);
+				pi.address = address->address;
+				add_address(&pi, port_info->tcp, &(port_info->tcp_list_counter), lpi->pid);
+			}
+		} else {
+			add_address(lpi, port_info->tcp, &(port_info->tcp_list_counter),lpi->pid);
+		}
+
+		break;
+	case IPPROTO_UDP:
+		if (!(port_info->udp)) {
+			port_info->udp = kmalloc(sizeof(struct local_addresses_list), GFP_KERNEL);
+			if (!port_info->udp)
+				return -1;
+			INIT_LIST_HEAD(&((port_info->udp)->list));
+			port_info->udp->counter = 0;
+		}
+		if (lpi->address == 0) {
+			struct local_addresses_list *address = NULL;
+			struct list_head *pos = NULL;
+
+			list_for_each(pos, &(local_list->list)) {
+				struct packetInfo pi;
+				address = list_entry(pos, struct local_addresses_list, list);
+				pi.address = address->address;
+				add_address(&pi, port_info->udp, &(port_info->udp_list_counter), lpi->pid);
+			}
+		} else {
+			add_address(lpi, port_info->udp, &(port_info->udp_list_counter), lpi->pid);
+		}
+		break;
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
+static struct portInfo *create_packet_info(struct packetInfo *lpi)
+{
+	struct portInfo *pi = NULL;
+	pi = kmalloc(sizeof(*pi), GFP_KERNEL);
+
+	if (!pi)
+		return NULL;
+
+	pi->port = lpi->port;
+	pi->tcp = NULL;
+	pi->tcp_list_counter = 0;
+	pi->udp = NULL;
+	pi->udp_list_counter = 0;
+
+	insert_address(lpi, pi);
+
+	return pi;
+}
+
+static int __monitor_insert(struct rb_root *root, struct packetInfo *lpi)
+{
+	struct rb_node **new = &(root->rb_node), *parent = NULL;
+	struct portInfo *port = NULL;
+
+	while (*new) {
+		struct portInfo *this = container_of(*new, struct portInfo, node);
+
+		parent = *new;
+		if (lpi->port < this->port) {
+			new = &((*new)->rb_left);
+		} else
+			if (lpi->port > this->port) {
+				new = &((*new)->rb_right);
+			} else {
+				insert_address(lpi, this);
+				return 1;
+			}
+	}
+	port = create_packet_info(lpi);
+	if (!port)
+		return -1;
+
+	rb_link_node(&port->node, parent, new);
+	rb_insert_color(&port->node, root);
+
+	return 1;
+}
+
+int monitor_insert(struct packetInfo *lpi)
+{
+	return __monitor_insert(&db, lpi);
+}
+
+int decrement_address(struct packetInfo *lpi,
+		struct local_addresses_list *protocol, int *list_counter)
+{
+	struct local_addresses_list *address = NULL;
+	struct list_head *pos = NULL, *q = NULL;
+
+	list_for_each_safe(pos, q, &(protocol->list)) {
+		address = list_entry(pos, struct local_addresses_list, list);
+		if (lpi->address == address->address) {
+			(address->counter)--;
+			if (address->counter <= 0) {
+				list_del(pos);
+				kfree(address);
+				(*(list_counter))--;
+			}
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static void remove_address_from_node(struct portInfo *pi, struct packetInfo *lpi)
+{
+
+	switch (lpi->protocol) {
+	case IPPROTO_TCP:
+		if (lpi->address) {
+			decrement_address(lpi, pi->tcp, &(pi->tcp_list_counter));
+		} else {
+			struct local_addresses_list *address = NULL;
+			struct list_head *pos = NULL;
+
+			list_for_each(pos, &(local_list->list)) {
+				struct packetInfo aux;
+				address = list_entry(pos, struct local_addresses_list, list);
+				aux.address = address->address;
+				decrement_address(&aux, pi->tcp, &(pi->tcp_list_counter));
+			}
+		}
+		if (pi->tcp_list_counter == 0) {
+			kfree(pi->tcp);
+			pi->tcp = NULL;
+		}
+		break;
+
+	case IPPROTO_UDP:
+		if (lpi->address) {
+			decrement_address(lpi, pi->udp, &(pi->udp_list_counter));
+		} else {
+			struct local_addresses_list *address = NULL;
+			struct list_head *pos = NULL;
+
+			list_for_each(pos, &(local_list->list)) {
+				struct packetInfo aux;
+				address = list_entry(pos, struct local_addresses_list, list);
+				aux.address = address->address;
+				decrement_address(&aux, pi->udp, &(pi->udp_list_counter));
+			}
+
+		}
+		if (pi->udp_list_counter == 0) {
+			kfree(pi->udp);
+			pi->udp = NULL;
+		}
+		break;
+	default:
+		return;
+	}
+}
+
+static void __monitor_erase(struct rb_root *root, struct packetInfo *pi)
+{
+	struct portInfo *data = __monitor_search(root, pi);
+
+	if (data) {
+		remove_address_from_node(data, pi);
+
+		if ((!data->tcp) && !(data->udp)) {
+			rb_erase(&data->node, root);
+			kfree(data);
+		}
+	}
+}
+
+void monitor_erase(struct packetInfo *pi)
+{
+	__monitor_erase(&db, pi);
+}
+
+static void clear_node_info(struct portInfo *pi)
+{
+	struct local_addresses_list *tmp = NULL;
+	struct list_head *pos = NULL, *q = NULL;
+
+	if (pi->tcp_list_counter > 0 && pi->tcp != NULL) {
+		struct local_addresses_list *aux = pi->tcp;
+		list_for_each_safe(pos, q, &(aux->list)) {
+			tmp = list_entry(pos, struct local_addresses_list, list);
+			list_del(pos);
+			kfree(tmp);
+		}
+		pi->tcp_list_counter = 0;
+		kfree(pi->tcp);
+	}
+
+	if (pi->udp_list_counter > 0 && pi->udp != NULL) {
+		struct local_addresses_list *aux = pi->udp;
+		list_for_each_safe(pos, q, &(aux->list))
+		{
+			tmp = list_entry(pos, struct local_addresses_list, list);
+			list_del(pos);
+			kfree(tmp);
+		}
+		pi->udp_list_counter = 0;
+		kfree(pi->udp);
+	}
+}
+
+void clear_all_info(struct rb_root *root)
+{
+	struct rb_node *node = NULL, *next_node = NULL;
+	struct portInfo *p = NULL;
+
+	node = rb_first(root);
+	while (node) {
+		next_node = rb_next(node);
+		p = rb_entry(node, struct portInfo, node);
+		clear_node_info(p);
+
+		rb_erase(node, root);
+		kfree(p);
+		p = NULL;
+		node = next_node;
+	}
+}
+
+void init_db_monitor(void)
+{
+}
+
+void exit_db_monitor(void)
+{
+	clear_all_info(&db);
+}
diff --git a/net/pidmonitor/db_monitor.h b/net/pidmonitor/db_monitor.h
new file mode 100644
index 0000000..ddc18d7
--- /dev/null
+++ b/net/pidmonitor/db_monitor.h
@@ -0,0 +1,51 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef PORTSDB_H_
+#define PORTSDB_H_
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+
+#include "pidmonitor.h"
+
+struct portInfo {
+	struct rb_node node;
+	u16 port;
+	struct local_addresses_list *udp;
+	struct local_addresses_list *tcp;
+	int tcp_list_counter;
+	int udp_list_counter;
+};
+
+extern struct portInfo *monitor_search(struct packetInfo *pi);
+extern int monitor_insert(struct packetInfo *lpi);
+extern void monitor_erase(struct packetInfo *pi);
+void clear_all_info(struct rb_root *root);
+
+extern void init_db_monitor(void);
+extern void exit_db_monitor(void);
+
+#endif /* PORTSDB_H_ */
diff --git a/net/pidmonitor/filter.c b/net/pidmonitor/filter.c
new file mode 100644
index 0000000..121c36a
--- /dev/null
+++ b/net/pidmonitor/filter.c
@@ -0,0 +1,476 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * Linux Socket Filter - Kernel level socket filtering
+ *
+ * Author:
+ *     Jay Schulist <jschlst@samba.org>
+ *
+ * Based on the design of:
+ *     - The Berkeley Packet Filter
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Andi Kleen - Fix a few bad bugs and races.
+ * Kris Katterjohn - Added many additional checks in sk_chk_filter()
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/fcntl.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/if_packet.h>
+#include <linux/gfp.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/netlink.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <asm/uaccess.h>
+#include <asm/unaligned.h>
+#include <linux/filter.h>
+#include <linux/reciprocal_div.h>
+#include <linux/ratelimit.h>
+
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/socket.h>
+
+#include <linux/skbuff.h>
+#include <linux/filter.h>
+#include <asm/unaligned.h>
+
+#include "pidmonitor.h"
+#include "db_monitor.h"
+
+#define		BPF_PROC	0xf0
+
+/* No hurry in this branch */
+static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size)
+{
+	u8 *ptr = NULL;
+
+	if (k >= SKF_NET_OFF)
+		ptr = skb_network_header(skb) + k - SKF_NET_OFF;
+	else if (k >= SKF_LL_OFF)
+		ptr = skb_mac_header(skb) + k - SKF_LL_OFF;
+
+	if (ptr >= skb->head && ptr + size <= skb_tail_pointer(skb))
+		return ptr;
+	return NULL;
+}
+
+static inline void *load_pointer(const struct sk_buff *skb, int k,
+				 unsigned int size, void *buffer)
+{
+	if (k >= 0)
+		return skb_header_pointer(skb, k, size, buffer);
+	return __load_pointer(skb, k, size);
+}
+
+int dynamic_filter(const struct sk_buff *skb, const int pid);
+
+unsigned int process_packets(const struct sk_buff *skb,
+			   const struct sock_filter *fentry)
+{
+	void *ptr;
+	u32 A = 0;			/* Accumulator */
+	u32 X = 0;			/* Index Register */
+	u32 mem[BPF_MEMWORDS];		/* Scratch Memory Store */
+	u32 tmp;
+	int k;
+	/*
+	 * Process array of filter instructions.
+	 */
+	for (;; fentry++) {
+#if defined(CONFIG_X86_32)
+#define	K (fentry->k)
+#else
+		const u32 K = fentry->k;
+#endif
+
+		switch (fentry->code) {
+		case BPF_S_ALU_ADD_X:
+			A += X;
+			continue;
+		case BPF_S_ALU_ADD_K:
+			A += K;
+			continue;
+		case BPF_S_ALU_SUB_X:
+			A -= X;
+			continue;
+		case BPF_S_ALU_SUB_K:
+			A -= K;
+			continue;
+		case BPF_S_ALU_MUL_X:
+			A *= X;
+			continue;
+		case BPF_S_ALU_MUL_K:
+			A *= K;
+			continue;
+		case BPF_S_ALU_DIV_X:
+			if (X == 0)
+				return 0;
+			A /= X;
+			continue;
+		case BPF_S_ALU_DIV_K:
+			A = reciprocal_divide(A, K);
+			continue;
+		case BPF_S_ALU_AND_X:
+			A &= X;
+			continue;
+		case BPF_S_ALU_AND_K:
+			A &= K;
+			continue;
+		case BPF_S_ALU_OR_X:
+			A |= X;
+			continue;
+		case BPF_S_ALU_OR_K:
+			A |= K;
+			continue;
+		case BPF_S_ALU_LSH_X:
+			A <<= X;
+			continue;
+		case BPF_S_ALU_LSH_K:
+			A <<= K;
+			continue;
+		case BPF_S_ALU_RSH_X:
+			A >>= X;
+			continue;
+		case BPF_S_ALU_RSH_K:
+			A >>= K;
+			continue;
+		case BPF_S_ALU_NEG:
+			A = -A;
+			continue;
+		case BPF_S_JMP_JA:
+			fentry += K;
+			continue;
+		case BPF_S_JMP_JGT_K:
+			fentry += (A > K) ? fentry->jt : fentry->jf;
+			continue;
+		case BPF_S_JMP_JGE_K:
+			fentry += (A >= K) ? fentry->jt : fentry->jf;
+			continue;
+		case BPF_S_JMP_JEQ_K:
+			fentry += (A == K) ? fentry->jt : fentry->jf;
+			continue;
+		case BPF_S_JMP_JSET_K:
+			fentry += (A & K) ? fentry->jt : fentry->jf;
+			continue;
+		case BPF_S_JMP_JGT_X:
+			fentry += (A > X) ? fentry->jt : fentry->jf;
+			continue;
+		case BPF_S_JMP_JGE_X:
+			fentry += (A >= X) ? fentry->jt : fentry->jf;
+			continue;
+		case BPF_S_JMP_JEQ_X:
+			fentry += (A == X) ? fentry->jt : fentry->jf;
+			continue;
+		case BPF_S_JMP_JSET_X:
+			fentry += (A & X) ? fentry->jt : fentry->jf;
+			continue;
+		case BPF_S_LD_W_ABS:
+			k = K;
+load_w:
+			ptr = load_pointer(skb, k, 4, &tmp);
+			if (ptr != NULL) {
+				A = get_unaligned_be32(ptr);
+				continue;
+			}
+			return 0;
+		case BPF_S_LD_H_ABS:
+			k = K;
+load_h:
+			ptr = load_pointer(skb, k, 2, &tmp);
+			if (ptr != NULL) {
+				A = get_unaligned_be16(ptr);
+				continue;
+			}
+			return 0;
+		case BPF_S_LD_B_ABS:
+			k = K;
+load_b:
+			ptr = load_pointer(skb, k, 1, &tmp);
+			if (ptr != NULL) {
+				A = *(u8 *)ptr;
+				continue;
+			}
+			return 0;
+		case BPF_S_LD_W_LEN:
+			A = skb->len;
+			continue;
+		case BPF_S_LDX_W_LEN:
+			X = skb->len;
+			continue;
+		case BPF_S_LD_W_IND:
+			k = X + K;
+			goto load_w;
+		case BPF_S_LD_H_IND:
+			k = X + K;
+			goto load_h;
+		case BPF_S_LD_B_IND:
+			k = X + K;
+			goto load_b;
+		case BPF_S_LDX_B_MSH:
+			ptr = load_pointer(skb, K, 1, &tmp);
+			if (ptr != NULL) {
+				X = (*(u8 *)ptr & 0xf) << 2;
+				continue;
+			}
+			return 0;
+		case BPF_S_LD_IMM:
+			A = K;
+			continue;
+		case BPF_S_LDX_IMM:
+			X = K;
+			continue;
+		case BPF_S_LD_MEM:
+			A = mem[K];
+			continue;
+		case BPF_S_LDX_MEM:
+			X = mem[K];
+			continue;
+		case BPF_S_MISC_TAX:
+			X = A;
+			continue;
+		case BPF_S_MISC_TXA:
+			A = X;
+			continue;
+		case BPF_S_MISC_PROC:
+			A = dynamic_filter(skb, ((fentry+1)->k)) ? ((fentry+1)->k) : 0;
+			continue;
+		case BPF_S_RET_K:
+			return K;
+		case BPF_S_RET_A:
+			return A;
+		case BPF_S_ST:
+			mem[K] = A;
+			continue;
+		case BPF_S_STX:
+			mem[K] = X;
+			continue;
+		case BPF_S_ANC_PROTOCOL:
+			A = ntohs(skb->protocol);
+			continue;
+		case BPF_S_ANC_PKTTYPE:
+			A = skb->pkt_type;
+			continue;
+		case BPF_S_ANC_IFINDEX:
+			if (!skb->dev)
+				return 0;
+			A = skb->dev->ifindex;
+			continue;
+		case BPF_S_ANC_MARK:
+			A = skb->mark;
+			continue;
+		case BPF_S_ANC_QUEUE:
+			A = skb->queue_mapping;
+			continue;
+		case BPF_S_ANC_HATYPE:
+			if (!skb->dev)
+				return 0;
+			A = skb->dev->type;
+			continue;
+		case BPF_S_ANC_RXHASH:
+			A = skb->rxhash;
+			continue;
+		case BPF_S_ANC_CPU:
+			A = raw_smp_processor_id();
+			continue;
+		case BPF_S_ANC_NLATTR: {
+			struct nlattr *nla;
+
+			if (skb_is_nonlinear(skb))
+				return 0;
+			if (A > skb->len - sizeof(struct nlattr))
+				return 0;
+
+			nla = nla_find((struct nlattr *)&skb->data[A],
+				       skb->len - A, X);
+			if (nla)
+				A = (void *)nla - (void *)skb->data;
+			else
+				A = 0;
+			continue;
+		}
+		case BPF_S_ANC_NLATTR_NEST: {
+			struct nlattr *nla;
+
+			if (skb_is_nonlinear(skb))
+				return 0;
+			if (A > skb->len - sizeof(struct nlattr))
+				return 0;
+
+			nla = (struct nlattr *)&skb->data[A];
+			if (nla->nla_len > A - skb->len)
+				return 0;
+
+			nla = nla_find_nested(nla, X);
+			if (nla)
+				A = (void *)nla - (void *)skb->data;
+			else
+				A = 0;
+			continue;
+		}
+		default:
+			WARN_RATELIMIT(1, "Unknown code:%u jt:%u tf:%u k:%u\n",
+				       fentry->code, fentry->jt,
+				       fentry->jf, fentry->k);
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+
+unsigned int process_filter_function(const struct sk_buff *skb,
+		const struct sock_filter *filter, const int pid);
+
+extern int init_process_filter_function_fn(struct filter_function_struct *ffs);
+
+static struct filter_function ff = {
+	.name = "process_packet_filter",
+	.init_func = &init_process_filter_function_fn,
+	.func = &process_packets
+};
+
+/*
+ * @pi must be allocated previously
+ * @skb is the buffer passed to the filter
+ */
+static inline int getPacketInfo(const struct sk_buff *skb,
+	struct packetInfo *src_pi, struct packetInfo *dst_pi)
+{
+	u32 tmp;
+	void *ptr;
+	u32 X;
+
+	ptr = skb_header_pointer(skb, 23, 1, &tmp);
+	if (ptr != NULL) {
+		src_pi->protocol = *(u8 *)ptr;
+		dst_pi->protocol = *(u8 *)ptr;
+	} else
+		goto out;
+
+	ptr = skb_header_pointer(skb, 26, 4, &tmp);
+	if (ptr != NULL)
+		src_pi->address = get_unaligned_be32(ptr);
+	else
+		goto out;
+
+	ptr = skb_header_pointer(skb, 30, 4, &tmp);
+	if (ptr != NULL)
+		dst_pi->address = get_unaligned_be32(ptr);
+	else
+		goto out;
+
+	ptr = skb_header_pointer(skb, 14, 1, &tmp);
+	if (ptr != NULL) {
+		X = (*(u8 *)ptr & 0xf) << 2;
+		X += 14;
+		ptr = skb_header_pointer(skb, X, 2, &tmp);
+		if (ptr != NULL)
+			src_pi->port = get_unaligned_be16(ptr);
+		else
+			goto out;
+
+		X += 2;
+		ptr = skb_header_pointer(skb, X, 2, &tmp);
+		if (ptr != NULL)
+			dst_pi->port = get_unaligned_be16(ptr);
+		else
+			goto out;
+	} else
+		goto out;
+
+	return 0;
+
+out:
+	return -1;
+}
+
+int packet_belongs(struct packetInfo *src_pi, struct packetInfo *dst_pi)
+{
+	if ((src_pi->protocol == IPPROTO_TCP || src_pi->protocol == IPPROTO_UDP)) {
+		if (monitor_search(src_pi)) {
+			return src_pi->pid;
+		}
+
+		if (monitor_search(dst_pi)) {
+			return dst_pi->pid;
+		}
+	}
+
+	return 0;
+}
+
+int dynamic_filter(const struct sk_buff *skb, const int pid)
+{
+	void *ptr;
+	u32 A;
+	u32 tmp;
+	int err = -ENODATA;
+
+	ptr = skb_header_pointer(skb, 12, 2, &tmp);
+	if (ptr != NULL) {
+		A = get_unaligned_be16(ptr);
+		if (A == 0x800) {
+			struct packetInfo dst_pi;
+			struct packetInfo src_pi;
+			dst_pi.pid = pid;
+			src_pi.pid = pid;
+			if (!getPacketInfo(skb, &src_pi, &dst_pi))
+				return packet_belongs(&src_pi, &dst_pi);
+		}
+	}
+	return err;
+}
+
+unsigned int process_filter_function(const struct sk_buff *skb,
+					const struct sock_filter *filter, const int pid)
+{
+	return dynamic_filter(skb, pid);
+}
+
+int init_filter(void)
+{
+	register_filter_function(&ff);
+	return 0;
+}
+void exit_filter(void)
+{
+	unregister_filter_function(&ff);
+}
diff --git a/net/pidmonitor/filter.h b/net/pidmonitor/filter.h
new file mode 100644
index 0000000..9405aea
--- /dev/null
+++ b/net/pidmonitor/filter.h
@@ -0,0 +1,31 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef FILTER_H_
+#define FILTER_H_
+
+extern int init_filter(void);
+extern void exit_filter(void);
+
+#endif /* FILTER_H_ */
diff --git a/net/pidmonitor/pidmonitor.c b/net/pidmonitor/pidmonitor.c
new file mode 100644
index 0000000..6acfcfc
--- /dev/null
+++ b/net/pidmonitor/pidmonitor.c
@@ -0,0 +1,102 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <net/net_namespace.h>
+#include <linux/inetdevice.h>
+
+#include "pidmonitor.h"
+#include "filter.h"
+#include "syscalls_monitor.h"
+#include "db_monitor.h"
+
+struct local_addresses_list *local_list;
+
+struct local_addresses_list *list_all_devices_address(void)
+{
+	struct net_device *dev;
+	struct net *net = &init_net;
+	struct local_addresses_list *list = NULL;
+	struct local_addresses_list *tmp = NULL;
+
+	list = kmalloc(sizeof(*list), GFP_KERNEL);
+	INIT_LIST_HEAD(&(list->list));
+
+	for_each_netdev(net, dev) {
+		if (dev->ip_ptr) {
+			struct in_device *in4 = dev->ip_ptr;
+			struct in_ifaddr *addr;
+			for (addr = in4->ifa_list; addr; addr = addr->ifa_next) {
+				tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
+				tmp->address = ntohl(addr->ifa_address);
+				list_add(&(tmp->list), &(list->list));
+			}
+		}
+	}
+	return list;
+}
+
+int remove_local_addresses_list(struct local_addresses_list *list)
+{
+	struct local_addresses_list *tmp;
+	struct list_head *pos = NULL, *q = NULL;
+
+	list_for_each_safe(pos, q, &(list->list)) {
+		tmp = list_entry(pos, struct local_addresses_list, list);
+		list_del(pos);
+		kfree(tmp);
+	}
+
+	return 0;
+}
+
+static int __init monitor_init(void)
+{
+	init_syscalls_monitor();
+	init_db_monitor();
+	init_filter();
+
+	local_list = list_all_devices_address();
+	return 0;
+}
+
+static void __exit monitor_exit(void)
+{
+	int ret = -1;
+
+	exit_db_monitor();
+	exit_filter();
+	exit_syscalls_monitor();
+
+	ret = remove_local_addresses_list(local_list);
+	if (ret == 0)
+		kfree(local_list);
+}
+
+module_init(monitor_init);
+module_exit(monitor_exit);
+MODULE_LICENSE("GPL");
diff --git a/net/pidmonitor/pidmonitor.h b/net/pidmonitor/pidmonitor.h
new file mode 100644
index 0000000..69d4306
--- /dev/null
+++ b/net/pidmonitor/pidmonitor.h
@@ -0,0 +1,63 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef PCAP_MONITORING_H_
+#define PCAP_MONITORING_H_
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <net/net_namespace.h>
+#include <linux/list.h>
+
+struct packetInfo {
+	u8 protocol;
+	u16 port;
+	u32 address;
+	int pid;
+};
+
+#define NIPQUAD(addr) \
+	((unsigned char *)&addr)[3], \
+	((unsigned char *)&addr)[2], \
+	((unsigned char *)&addr)[1], \
+	((unsigned char *)&addr)[0]
+
+struct local_addresses_list {
+	struct list_head list;
+	u32 address;
+	unsigned int pid;
+	int counter;
+};
+
+extern struct local_addresses_list *local_list;
+extern struct socket *sockfd_lookup(int fd, int *err);
+int get_local_packet_info_from_fd(unsigned int fd, struct packetInfo *ret);
+int get_local_packet_info_from_file(struct file *f, struct packetInfo *ret);
+struct local_addresses_list *list_all_devices_address(void);
+int remove_local_addresses_list(struct local_addresses_list *list);
+extern struct net inet;
+
+int init_process_filter_function_fn(struct filter_function_struct *ffs);
+void init_repo_task(int pidnr);
+
+#endif /* PCAP_MONITORING_H_ */
diff --git a/net/pidmonitor/proc_monitor.c b/net/pidmonitor/proc_monitor.c
new file mode 100644
index 0000000..5b41db3
--- /dev/null
+++ b/net/pidmonitor/proc_monitor.c
@@ -0,0 +1,116 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/stat.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/path.h>
+#include <linux/dcache.h>
+#include <linux/socket.h>
+#include <linux/skbuff.h>
+#include <linux/tcp.h>
+#include <net/inet_sock.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <net/net_namespace.h>
+#include <linux/inetdevice.h>
+
+
+#include "pidmonitor.h"
+
+static void get_inet_sock_param(struct inet_sock *inetsock, struct packetInfo *ret)
+{
+	ret->port = inetsock->inet_num;
+	ret->protocol = ((struct sock *)inetsock)->sk_protocol;
+
+	if (ret->port == ntohs(inetsock->inet_sport)) {
+		if (!inetsock->inet_rcv_saddr)
+			ret->address = inetsock->inet_saddr;
+		else
+			ret->address = inetsock->inet_rcv_saddr;
+
+	} else
+		ret->address = inetsock->inet_daddr;
+
+	ret->address = ntohl(ret->address);
+}
+
+
+int get_local_packet_info_from_fd(unsigned int fd, struct packetInfo *ret)
+{
+	struct file *f = fget(fd);
+
+	if (f != NULL) {
+		fput(f);
+		return get_local_packet_info_from_file(f, ret);
+	}
+	return -3;
+}
+
+int get_local_packet_info_from_file(struct file *f, struct packetInfo *ret)
+{
+	struct socket *socket = NULL;
+	short type;
+	unsigned short family;
+	int err = 0;
+
+	if (f != NULL) {
+		struct dentry *dentry;
+		struct inode *d_inode;
+		dentry = f->f_dentry;
+		if (dentry != NULL) {
+			d_inode = dentry->d_inode;
+			if (S_ISSOCK(d_inode->i_mode)) {
+				socket = f->private_data;
+				if (socket == NULL) {
+					err = -5;
+					goto out;
+				}
+				type = socket->type;
+				if (socket->sk == NULL) {
+					err = -6;
+					goto out;
+				}
+				family = socket->sk->__sk_common.skc_family;
+				if (family != AF_INET) {
+					err = -4;
+					goto out;
+				} else {
+					get_inet_sock_param((struct inet_sock *)(socket->sk), ret);
+					err = 0;
+				}
+			} else {
+				err = -1;
+			}
+		} else {
+			err = -2;
+		}
+	} else {
+		err = -3;
+	}
+out:
+	return err;
+
+}
diff --git a/net/pidmonitor/proc_monitor.h b/net/pidmonitor/proc_monitor.h
new file mode 100644
index 0000000..c9ba064
--- /dev/null
+++ b/net/pidmonitor/proc_monitor.h
@@ -0,0 +1,23 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
diff --git a/net/pidmonitor/syscalls_monitor.c b/net/pidmonitor/syscalls_monitor.c
new file mode 100644
index 0000000..69016d5
--- /dev/null
+++ b/net/pidmonitor/syscalls_monitor.c
@@ -0,0 +1,423 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#include <linux/ptrace.h>
+
+#include <linux/module.h>
+#include <linux/kprobes.h>
+
+#include <net/sock.h>
+#include <linux/string.h>
+#include <net/inet_sock.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/list.h>
+
+#include <linux/pid.h>
+#include <asm-generic/errno.h>
+
+#include "pidmonitor.h"
+#include "db_monitor.h"
+
+u64 pid = -1, ppid = -1, tgid = -1;
+
+void set_process_identifiers(u64 lpid)
+{
+	pid = lpid;
+}
+
+int init_process_filter_function_fn(struct filter_function_struct *ffs)
+{
+	set_process_identifiers(ffs->pid);
+	init_repo_task(ffs->pid);
+	return 0;
+}
+int kprobes_index;
+
+#define TO_MONITOR(t) { \
+	if (pid == t->pid) \
+		goto monitor; \
+	else { \
+		my_data->fd = -1; \
+		return 0; \
+	}\
+} while(0);
+
+#define NR_PROBES 7
+
+struct kretprobe *kretprobes;
+
+struct cell {
+	int fd;
+};
+
+struct closeInfo {
+	int fd;
+	struct packetInfo pi;
+};
+
+struct connect_extern_info {
+	struct packetInfo external;
+	int fd;
+};
+
+static int sendto_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	struct task_struct *task = ri->task;
+
+#ifdef CONFIG_X86_32
+	int fd = regs->ax;
+#else
+	int fd = regs->di;
+#endif
+	struct cell *my_data = (struct cell *)ri->data;
+	TO_MONITOR(task)
+
+monitor :
+	my_data->fd = fd;
+	return 0;
+}
+static int sendto_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+
+	int retval = regs_return_value(regs);
+	struct cell *my_data = (struct cell *)ri->data;
+	struct packetInfo pi;
+	int fd = my_data->fd;
+
+	if (my_data->fd == -1) {
+		return 0;
+	}
+
+
+	if (retval >= 0 || retval == -EAGAIN || retval == -EINPROGRESS || retval == -EALREADY) {
+		pi.pid = ri->task->pid;
+		if (!get_local_packet_info_from_fd(fd, &pi))
+			monitor_insert(&pi);
+	}
+	return 0;
+}
+
+static int recvfrom_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	struct task_struct *task = ri->task;
+	struct cell *my_data = (struct cell *)ri->data;
+#ifdef CONFIG_X86_32
+	int fd = regs->ax;
+#else
+	int fd = regs->di;
+#endif
+	TO_MONITOR(task)
+
+monitor :
+	my_data->fd = fd;
+	return 0;
+}
+static int recvfrom_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	int retval = regs_return_value(regs);
+	struct cell *my_data = (struct cell *)ri->data;
+	struct packetInfo pi;
+	int fd = my_data->fd;
+	int err = 0;
+
+	if (my_data->fd == -1) {
+		return 0;
+	}
+
+	if (retval >= 0 || retval == -EAGAIN || retval == -EINPROGRESS) {
+		pi.pid = ri->task->pid;
+		get_local_packet_info_from_fd(fd, &pi);
+		if (err == 0)
+			monitor_insert(&pi);
+	}
+
+	return 0;
+}
+
+static int accept_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	struct task_struct *task = ri->task;
+	struct cell *my_data = (struct cell *)ri->data;
+
+	TO_MONITOR(task)
+
+monitor :
+	my_data->fd = 0;
+	return 0;
+}
+static int accept_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	int retval = regs_return_value(regs);
+	struct cell *my_data = (struct cell *)ri->data;
+	struct packetInfo pi;
+
+	if (my_data->fd == -1) {
+		return 0;
+	}
+
+	if (retval > 0) {
+		pi.pid = ri->task->pid;
+		if (!get_local_packet_info_from_fd(retval, &pi))
+			monitor_insert(&pi);
+	}
+
+	return 0;
+}
+
+static int close_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	struct task_struct *task = ri->task;
+	struct closeInfo *my_data = (struct closeInfo *)ri->data;
+
+#ifdef CONFIG_X86_32
+	struct file *filp = (struct file *)regs->bx;
+#else
+	struct file *filp = (struct file *)regs->si;
+#endif
+
+	int err = -1;
+	TO_MONITOR(task)
+
+monitor :
+
+	err = get_local_packet_info_from_file(filp, &(my_data->pi));
+	if (err >= 0) {
+		my_data->fd = -2;
+	} else {
+		my_data->fd = -1;
+	}
+
+	return 0;
+}
+
+static int close_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	int retval = regs_return_value(regs);
+	struct closeInfo *cI = (struct closeInfo *)ri->data;
+
+	if (cI->fd == -1) {
+		return 0;
+	}
+	if (retval == 0)
+		monitor_erase(&(cI->pi));
+	return 0;
+}
+
+static int bind_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	struct task_struct *task = ri->task;
+#ifdef CONFIG_X86_32
+	int fd = regs->ax;
+#else
+	int fd = regs->di;
+#endif
+	struct cell *my_data = (struct cell *)ri->data;
+	TO_MONITOR(task)
+
+monitor :
+	my_data->fd = fd;
+	return 0;
+}
+
+static int bind_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	int retval = regs_return_value(regs);
+	struct cell *my_data = (struct cell *)ri->data;
+	struct packetInfo pi;
+	int fd = my_data->fd;
+
+	if (my_data->fd == -1) {
+		return 0;
+	}
+
+	pi.pid = ri->task->pid;
+	if (retval == 0 && !get_local_packet_info_from_fd(fd, &pi))
+		monitor_insert(&pi);
+
+	return 0;
+}
+
+static int connect_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	struct task_struct *task = ri->task;
+	struct connect_extern_info *my_data = (struct connect_extern_info *)ri->data;
+#ifdef CONFIG_X86_32
+	int fd = regs->ax;
+	struct sockaddr_in *in = (struct sockaddr_in *)regs->dx;
+#else
+	int fd = regs->di;
+	struct sockaddr_in *in = (struct sockaddr_in *)regs->si;
+#endif
+	TO_MONITOR(task)
+
+monitor :
+	my_data->fd = fd;
+
+	if (!get_local_packet_info_from_fd(fd, &(my_data->external))){
+		my_data->external.address = ntohl(in->sin_addr.s_addr);
+		my_data->external.port = ntohs(in->sin_port);
+		(my_data->external).pid = task->pid;
+		monitor_insert(&(my_data->external));
+	} else {
+		my_data->fd = -1;
+	}
+
+	return 0;
+}
+
+static int connect_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	int retval = regs_return_value(regs);
+	struct connect_extern_info *my_data = (struct connect_extern_info *)ri->data;
+	int fd = my_data->fd;
+	struct packetInfo pi;
+
+	if (fd == -1) {
+		return 0;
+	}
+
+	if (retval == 0 || retval == -EINPROGRESS || retval == -EALREADY || retval == -EISCONN || retval == -EAGAIN) {
+		monitor_erase(&(my_data->external));
+		pi.pid = ri->task->pid;
+		if (!get_local_packet_info_from_fd(fd, &pi))
+			monitor_insert(&pi);
+	}
+
+	return 0;
+}
+
+static int instantiationKRETProbe(struct kretprobe *kret,
+				const char *function_name,
+				kretprobe_handler_t func_handler,
+				kretprobe_handler_t func_entry_handler,
+				ssize_t data_size)
+{
+	int ret = -1;
+
+	struct kprobe kp = {
+		.symbol_name = function_name,
+	};
+
+	kret->kp = kp;
+	kret->handler = func_handler;
+	kret->entry_handler = func_entry_handler;
+	kret->data_size	= data_size;
+	kret->maxactive = 8;
+
+	ret = register_kretprobe(kret);
+	if (ret < 0) {
+		return -1;
+	}
+
+	return ret;
+}
+
+/*
+ * function called on module init to initialize kretprobes common to tcp and udp
+ */
+
+static int init_kretprobes_syscalls(void)
+{
+	int ret = 0;
+
+	kretprobes = kmalloc(sizeof(*kretprobes)*NR_PROBES, GFP_KERNEL);
+
+	if (!kretprobes) {
+		return -1;
+	}
+
+	ret = instantiationKRETProbe((kretprobes+kprobes_index),
+			"sys_bind", bind_ret_handler, bind_entry_handler,
+			(ssize_t)sizeof(struct cell));
+	kprobes_index += 1;
+	if (ret < 0)
+		return -1;
+
+	ret = instantiationKRETProbe((kretprobes+kprobes_index),
+			"sys_connect", connect_ret_handler,
+			connect_entry_handler,
+			(ssize_t)sizeof(struct connect_extern_info));
+	kprobes_index += 1;
+	if (ret < 0)
+		return -1;
+
+	ret = instantiationKRETProbe((kretprobes+kprobes_index),
+			"sock_close", close_ret_handler, close_entry_handler,
+			(ssize_t)sizeof(struct packetInfo));
+	kprobes_index += 1;
+	if (ret < 0)
+		return -1;
+
+	ret = instantiationKRETProbe((kretprobes+kprobes_index),
+			"sys_accept4", accept_ret_handler, accept_entry_handler,
+			(ssize_t)sizeof(struct cell));
+	kprobes_index += 1;
+		if (ret < 0)
+			return -1;
+
+	ret = instantiationKRETProbe((kretprobes+kprobes_index),
+			"sys_sendto", sendto_ret_handler, sendto_entry_handler,
+			(ssize_t)sizeof(struct cell));
+	kprobes_index += 1;
+	if (ret < 0)
+		return -1;
+
+	ret = instantiationKRETProbe((kretprobes+kprobes_index),
+			"sys_recvfrom", recvfrom_ret_handler,
+			recvfrom_entry_handler, (ssize_t)sizeof(struct cell));
+	kprobes_index += 1;
+	if (ret < 0)
+		return -1;
+
+	return kprobes_index;
+}
+
+static void removeKprobe(int index)
+{
+	if ((kretprobes+index) != NULL) {
+		unregister_kretprobe((kretprobes+index));
+	}
+}
+
+static void destroy_kretprobes_syscalls(void)
+{
+	int i = -1;
+
+	for (i = 0; i < kprobes_index ; i++)
+		removeKprobe(i);
+
+	if (kretprobes)
+		kfree(kretprobes);
+}
+
+int init_syscalls_monitor(void)
+{
+	return init_kretprobes_syscalls();
+}
+
+void exit_syscalls_monitor(void)
+{
+	destroy_kretprobes_syscalls();
+}
diff --git a/net/pidmonitor/syscalls_monitor.h b/net/pidmonitor/syscalls_monitor.h
new file mode 100644
index 0000000..1d1a2f6
--- /dev/null
+++ b/net/pidmonitor/syscalls_monitor.h
@@ -0,0 +1,31 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef SYSCALLS_MONITOR_H_
+#define SYSCALLS_MONITOR_H_
+
+extern int init_syscalls_monitor(void);
+extern void exit_syscalls_monitor(void);
+
+#endif /* SYSCALLS_MONITOR_H_ */
diff --git a/net/pidmonitor/task_monitor.c b/net/pidmonitor/task_monitor.c
new file mode 100644
index 0000000..4b9932c
--- /dev/null
+++ b/net/pidmonitor/task_monitor.c
@@ -0,0 +1,77 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/byteorder/generic.h>
+#include <linux/uaccess.h>
+#include <linux/filter.h>
+#include <linux/fdtable.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+
+#include "pidmonitor.h"
+#include "db_monitor.h"
+
+static void read_from_fdtable(struct task_struct *task)
+{
+	int fd;
+	int max_fds;
+	struct file *file;
+
+	max_fds = task->files->fdt->max_fds;
+	for (fd = 0; fd < max_fds ; fd++) {
+		file = fcheck_files(task->files, fd);
+		if (file) {
+			struct packetInfo p;
+			p.pid = task->pid;
+			if (!get_local_packet_info_from_file(file, &p)) {
+				monitor_insert(&p);
+			}
+		}
+	}
+}
+
+static void init_tree(struct task_struct *task)
+{
+
+	if (task == NULL)
+		return;
+
+	rcu_read_lock();
+	read_from_fdtable(task);
+	rcu_read_unlock();
+}
+
+void init_repo_task(int pidnr)
+{
+	struct task_struct *task = NULL;
+	struct pid *pid = find_get_pid(pidnr);
+	rcu_read_lock();
+	task = pid_task(pid, PIDTYPE_PID);
+	put_pid(pid);
+	rcu_read_unlock();
+	init_tree(task);
+}
diff --git a/net/pidmonitor/task_monitor.h b/net/pidmonitor/task_monitor.h
new file mode 100644
index 0000000..c9ba064
--- /dev/null
+++ b/net/pidmonitor/task_monitor.h
@@ -0,0 +1,23 @@
+/*
+ * Packet Filtering System based on BPF / LSF
+ *
+ * Author: Nuno Martins <nuno.martins@caixamagica.pt>
+ *
+ * (c) Copyright Caixa Magica Software, LDA., 2012
+ * (c) Copyright Universidade Nova de Lisboa, 2010-2011
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
-- 
1.7.10.rc3.11.gd8282

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH 2/2] PID-based packet filtering support
  2012-04-04  9:16 ` [RFC PATCH 2/2] PID-based packet filtering support Nuno Martins
@ 2012-04-04 17:01   ` chetan loke
  2012-04-05  9:41     ` Nuno Martins
  2012-04-04 18:57   ` chetan loke
  1 sibling, 1 reply; 8+ messages in thread
From: chetan loke @ 2012-04-04 17:01 UTC (permalink / raw)
  To: Nuno Martins; +Cc: netdev, Alfredo Matos, Paulo Trezentos

On Wed, Apr 4, 2012 at 5:16 AM, Nuno Martins
<nuno.martins@caixamagica.pt> wrote:

>  net/pidmonitor/Makefile           |    3 +

might make sense to prefix files with 'net' tag. Like: net_pidmonitor,
net_proc_monitor.c etc. Because proc_monitor is too generic.


> +static int is_equal_packet_info(struct packetInfo *pi,

It should be 'packet_info' and not 'packetInfo'. Init-char convention
is not used in linux. same goes for portInfo and other structs(if
any).


> +static int insert_address(struct packetInfo *lpi, struct portInfo *port_info)
> +{
> +
> +       switch (lpi->protocol) {
> +       case IPPROTO_TCP:
> +               if (!(port_info->tcp)) {
> +                       port_info->tcp = kmalloc(sizeof(struct local_addresses_list), GFP_KERNEL);

Do you think it might make sense to pre-alloc a list? or
managing/growing that list would add more pain/code than it's worth?
I'm just thinking in terms of search scalability when memory is
fragmented and we have lots of nodes in the tree.But I'm sure you
must've done some light tests.


> +static struct portInfo *create_packet_info(struct packetInfo *lpi)
> +{
> +       struct portInfo *pi = NULL;
> +       pi = kmalloc(sizeof(*pi), GFP_KERNEL);
> +
> +       if (!pi)
> +               return NULL;
> +
> +       pi->port = lpi->port;
> +       pi->tcp = NULL;
> +       pi->tcp_list_counter = 0;
> +       pi->udp = NULL;
> +       pi->udp_list_counter = 0;
> +
> +       insert_address(lpi, pi);
> +
> +       return pi;
> +}
> +

Just thinking out loud - what if packet_info and pid were introduced
as part of struct sock or something? The no need to kmalloc.
And at the end of the bind/accept/other-calls-you-intercept-via-probes
you can populate the structs. Then the kprobes could go away too. But
I know nothing about BPF so I can't really comment for sure.


Chetan

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH 2/2] PID-based packet filtering support
  2012-04-04  9:16 ` [RFC PATCH 2/2] PID-based packet filtering support Nuno Martins
  2012-04-04 17:01   ` chetan loke
@ 2012-04-04 18:57   ` chetan loke
  2012-04-05 10:30     ` Nuno Martins
  1 sibling, 1 reply; 8+ messages in thread
From: chetan loke @ 2012-04-04 18:57 UTC (permalink / raw)
  To: Nuno Martins; +Cc: netdev, Alfredo Matos, Paulo Trezentos

On Wed, Apr 4, 2012 at 5:16 AM, Nuno Martins
<nuno.martins@caixamagica.pt> wrote:


> +int get_local_packet_info_from_fd(unsigned int fd, struct packetInfo *ret)

rename 'ret' to 'pi' or pkt_info or pick a name (must match the
struct). And not just here but everywhere else.

> +{
> +       struct file *f = fget(fd);
> +
> +       if (f != NULL) {
> +               fput(f);

why not 'fput' after you return from 'get_local_packet_info_from_file' ?

> +               return get_local_packet_info_from_file(f, ret);
> +       }
> +       return -3;
> +}
> +


> +int get_local_packet_info_from_file(struct file *f, struct packetInfo *ret)
> +{
> +       struct socket *socket = NULL;
> +       short type;
> +       unsigned short family;
> +       int err = 0;
> +
> +       if (f != NULL) {

This check is redundant because the
caller(get_local_packet_info_from_fd) checks for NULL.

Move this function before get_local_packet_info_from_fd().

re-arranged code looks like:

int get_local_packet_info_from_file(...) {
....
}

int get_local_packet_info_from_fd(...) {
   ...
   ... get_local_packet_info_from_file(f, ret);
   ....
}


Chetan

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH 2/2] PID-based packet filtering support
  2012-04-04 17:01   ` chetan loke
@ 2012-04-05  9:41     ` Nuno Martins
  2012-04-05 16:29       ` chetan loke
  0 siblings, 1 reply; 8+ messages in thread
From: Nuno Martins @ 2012-04-05  9:41 UTC (permalink / raw)
  To: chetan loke; +Cc: netdev, Alfredo Matos, Paulo Trezentos

On 4 April 2012 18:01, chetan loke <loke.chetan@gmail.com> wrote:
> On Wed, Apr 4, 2012 at 5:16 AM, Nuno Martins
> <nuno.martins@caixamagica.pt> wrote:
>
>>  net/pidmonitor/Makefile           |    3 +
>
> might make sense to prefix files with 'net' tag. Like: net_pidmonitor,
> net_proc_monitor.c etc. Because proc_monitor is too generic.
>

Good point, will refactor it.

>
>> +static int is_equal_packet_info(struct packetInfo *pi,
>
> It should be 'packet_info' and not 'packetInfo'. Init-char convention
> is not used in linux. same goes for portInfo and other structs(if
> any).
>
>

Thanks for spotting that. Will be fixed in our tree.


>> +static int insert_address(struct packetInfo *lpi, struct portInfo *port_info)
>> +{
>> +
>> +       switch (lpi->protocol) {
>> +       case IPPROTO_TCP:
>> +               if (!(port_info->tcp)) {
>> +                       port_info->tcp = kmalloc(sizeof(struct local_addresses_list), GFP_KERNEL);
>
> Do you think it might make sense to pre-alloc a list? or
> managing/growing that list would add more pain/code than it's worth?
> I'm just thinking in terms of search scalability when memory is
> fragmented and we have lots of nodes in the tree.But I'm sure you
> must've done some light tests.
>
>
>> +static struct portInfo *create_packet_info(struct packetInfo *lpi)
>> +{
>> +       struct portInfo *pi = NULL;
>> +       pi = kmalloc(sizeof(*pi), GFP_KERNEL);
>> +
>> +       if (!pi)
>> +               return NULL;
>> +
>> +       pi->port = lpi->port;
>> +       pi->tcp = NULL;
>> +       pi->tcp_list_counter = 0;
>> +       pi->udp = NULL;
>> +       pi->udp_list_counter = 0;
>> +
>> +       insert_address(lpi, pi);
>> +
>> +       return pi;
>> +}
>> +


Our tests with 1024 node tree gives us something like 1.3 us on
average. Your suggestion makes a lot of sense, and we will definitely
look into.
This doesn't seem hard to do as we are considering introducing a pid
based hash table, with a tree in each entry, which can and possibly
should be pre-allocated.


>
> Just thinking out loud - what if packet_info and pid were introduced
> as part of struct sock or something? The no need to kmalloc.
> And at the end of the bind/accept/other-calls-you-intercept-via-probes
> you can populate the structs. Then the kprobes could go away too. But
> I know nothing about BPF so I can't really comment for sure.

That's also a good approach. We will look into it.

>
>
> Chetan

Thank you very much for your feedback

Nuno Martins

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH 2/2] PID-based packet filtering support
  2012-04-04 18:57   ` chetan loke
@ 2012-04-05 10:30     ` Nuno Martins
  0 siblings, 0 replies; 8+ messages in thread
From: Nuno Martins @ 2012-04-05 10:30 UTC (permalink / raw)
  To: chetan loke; +Cc: netdev, Alfredo Matos, Paulo Trezentos

On 4 April 2012 19:57, chetan loke <loke.chetan@gmail.com> wrote:
> On Wed, Apr 4, 2012 at 5:16 AM, Nuno Martins
> <nuno.martins@caixamagica.pt> wrote:
>
>
>> +int get_local_packet_info_from_fd(unsigned int fd, struct packetInfo *ret)
>
> rename 'ret' to 'pi' or pkt_info or pick a name (must match the
> struct). And not just here but everywhere else.
>

Corrected.

>> +{
>> +       struct file *f = fget(fd);
>> +
>> +       if (f != NULL) {
>> +               fput(f);
>
> why not 'fput' after you return from 'get_local_packet_info_from_file' ?
>
>> +               return get_local_packet_info_from_file(f, ret);
>> +       }
>> +       return -3;
>> +}
>> +

Yes, it make more sense to make the fput after I have done with the file.


>
>
>> +int get_local_packet_info_from_file(struct file *f, struct packetInfo *ret)
>> +{
>> +       struct socket *socket = NULL;
>> +       short type;
>> +       unsigned short family;
>> +       int err = 0;
>> +
>> +       if (f != NULL) {
>
> This check is redundant because the
> caller(get_local_packet_info_from_fd) checks for NULL.

It's now corrected, it was there because in another function in
task_monitor in the beginning I was not checking for NULL.
So now the check for NULL in get_local_packet_info_from_file
is redundant, is going to be taken away.

>
> Move this function before get_local_packet_info_from_fd().
>
> re-arranged code looks like:
>
> int get_local_packet_info_from_file(...) {
> ....
> }
>
> int get_local_packet_info_from_fd(...) {
>   ...
>   ... get_local_packet_info_from_file(f, ret);
>   ....
> }
>
>

Re-factored the code to look like that.

Thanks for you feedback, and all will be corrected on the next version and on
the repository.

> Chetan

Nuno Martins

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [RFC PATCH 2/2] PID-based packet filtering support
  2012-04-05  9:41     ` Nuno Martins
@ 2012-04-05 16:29       ` chetan loke
  0 siblings, 0 replies; 8+ messages in thread
From: chetan loke @ 2012-04-05 16:29 UTC (permalink / raw)
  To: Nuno Martins; +Cc: netdev, Alfredo Matos, Paulo Trezentos

On Thu, Apr 5, 2012 at 5:41 AM, Nuno Martins
<nuno.martins@caixamagica.pt> wrote:
> Our tests with 1024 node tree gives us something like 1.3 us on
> average. Your suggestion makes a lot of sense, and we will definitely
> look into.
> This doesn't seem hard to do as we are considering introducing a pid
> based hash table, with a tree in each entry, which can and possibly
> should be pre-allocated.

Also as a defensive mechanism(and if not present already) it may not
be a bad idea to add the following check whenever you are adding or
deleting a node:

if (pidmonitor->curr_num_monitored_pid_nodes >
pidmax_or_whichever_runtime_max_scheduler_uses) {
   WARN_ONCE(....);
    delete_all_nodes_from_the_tree(); // including the current one -
if you were in the middle of a new insert.
    // This way at least your monitoring tool might pick this up and
the user/sysadmin might dig into it.
}

Note: pidmonitor is some global struct and
curr_num_monitored_pid_nodes == number of pids you are currently
monitoring.

By adding this minimal code, if there are any stray nodes in the
tree(over a period of time) because of a bug in the clean up logic
then we might be able to detect it.


> Nuno Martins

Chetan

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-04-05 16:29 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-04  9:16 [RFC PATCH 0/2] PID-based network traffic monitoring Nuno Martins
2012-04-04  9:16 ` [RFC PATCH 1/2] Multiple filter function support for BPF filters Nuno Martins
2012-04-04  9:16 ` [RFC PATCH 2/2] PID-based packet filtering support Nuno Martins
2012-04-04 17:01   ` chetan loke
2012-04-05  9:41     ` Nuno Martins
2012-04-05 16:29       ` chetan loke
2012-04-04 18:57   ` chetan loke
2012-04-05 10:30     ` Nuno Martins

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.