diff mbox

[RFC,2/2] PID-based packet filtering support

Message ID 19b9f7a0f38c1bab367da6f6cf622c8c2b3a4920.1333466900.git.nuno.martins@caixamagica.pt
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Nuno Martins April 4, 2012, 9:16 a.m. UTC
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(-)

Comments

chetan L April 4, 2012, 5:01 p.m. UTC | #1
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
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
chetan L April 4, 2012, 6:57 p.m. UTC | #2
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
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Nuno Martins April 5, 2012, 9:41 a.m. UTC | #3
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
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Nuno Martins April 5, 2012, 10:30 a.m. UTC | #4
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
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
chetan L April 5, 2012, 4:29 p.m. UTC | #5
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
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

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
+ *
+ */