Adding the first implementation of the OBAMP plugin. See README file for documentation.
authorSaverio Proto <zioproto@gmail.com>
Mon, 31 Aug 2009 14:17:05 +0000 (16:17 +0200)
committerSaverio Proto <zioproto@gmail.com>
Mon, 31 Aug 2009 14:17:05 +0000 (16:17 +0200)
lib/obamp/Makefile [new file with mode: 0644]
lib/obamp/README [new file with mode: 0644]
lib/obamp/scenario.jpeg [new file with mode: 0644]
lib/obamp/src/list.h [new file with mode: 0644]
lib/obamp/src/obamp.c [new file with mode: 0644]
lib/obamp/src/obamp.h [new file with mode: 0644]
lib/obamp/src/olsrd_plugin.c [new file with mode: 0644]
lib/obamp/version-script.txt [new file with mode: 0644]

diff --git a/lib/obamp/Makefile b/lib/obamp/Makefile
new file mode 100644 (file)
index 0000000..f1da1ef
--- /dev/null
@@ -0,0 +1,33 @@
+
+OLSRD_PLUGIN = true
+PLUGIN_NAME =  olsrd_obamp
+PLUGIN_VER =   1.0.0
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+#LIBS +=       $(OS_LIB_PTHREAD)
+
+# Must be specified along with -lpthread on linux
+#CPPFLAGS += $(OS_CFLAG_PTHREAD)
+
+ifneq ($(OS),linux)
+
+default_target install clean:
+       @echo "*** OBAMP Plugin only supported on Linux, sorry!"
+
+else
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+               $(CC) $(LDFLAGS) -o $(PLUGIN_FULLNAME) $(OBJS) $(LIBS)
+
+install:       $(PLUGIN_FULLNAME)
+               $(STRIP) $(PLUGIN_FULLNAME)
+               $(INSTALL_LIB)
+
+clean:
+               rm -f $(OBJS) $(SRCS:%.c=%.d) $(PLUGIN_FULLNAME)
+
+endif
diff --git a/lib/obamp/README b/lib/obamp/README
new file mode 100644 (file)
index 0000000..405cf51
--- /dev/null
@@ -0,0 +1,76 @@
+= OLSR OBAMP plugin =
+
+This README file is the main documentation source for the OLSR OBAMP plugin
+
+Last update 31/08/2009
+
+== Description ==
+
+The OBAMP plugin lets multicast traffic be forwarded in a OLSR mesh network.
+
+This version of the OBAMP protocol, implemented as a OLSR plugin, is a simplified one for Wireless Community Networks, where we assume the nodes to be in fixed positions on the roof of the houses. All the protocol features regarding mobility have not been implemented.
+
+OBAMP is an overlay protocol. It first makes a mesh network with overlay links (udp tunnels) between the OBAMP nodes, and then it creates a distribution spanning tree over these mesh links.
+
+To explain how the plugin works consider the scenario in the attached figure scenario.jpeg.
+
+There are 7 routers, where only 5 have the OBAMP plugin working. Router 1 2 and 6 also have an attached HNA network with some hosts.
+
+OBAMP nodes generate OLSR OBAMP_ALIVE messages, these OLSR messages are forwarded in the whole network (also by the nodes that do not understand OBAMP thanks to the OLSR design). Because of the flooding mechanism every OBAMP node has a complete list of all the other OBAMP nodes in the mesh network.
+
+Every OBAMP node listens on the UDP port 6226 for OBAMP signalling.
+
+When a OBAMP nodes starts it has 5 timers to periodically start operations:
+
+OBAMP_alive_timer: every obamp node sends alive messages to advertise its presence to the other obamp nodes in the network. In the alive message every nodes states its IP address, and if it has already a tree link or not (we will see later this information is important for the outer tree create procedure).
+The OBAMP network must have a member called "Core", that starts the TREE_CREATE procedure. The core is the node with the smallest IP address. When the list of known OBAMP nodes changes, the Core Election procedure is eventually called.
+
+mesh_create_timer: every obamp node every OBAMP_MESH_CREATE_IVAL evaluates how far the other obamp nodes are and selects a subset of nodes to keep mesh links with. Note that to reduce signalling and to increase scalability, the overylay mesh links are setup only with a subset of the nearest OBAMP nodes. To select the overlay neighbor the OBAMP nodes first calculates the ETX distance of the nearest OBAMP nodes, and the creates overlay mesh links to every node that are far in the range (minETX,minETX+1)
+
+tree_create_timer: the core of the network every OBAMP_TREE_CREATE_IVAL sends a message called TREE_CREATE on its mesh links. The creation of the spanning tree is very similar to the spanning tree protocol. When a TREE_CREATE message is received a OBAMP node enables a tree link with its parent and forwards the TREE_CREATE on the other mesh links. TREE_CREATE messages are generated only by the core and are numbered, so TREE_CREATE received over loops can be discarded.
+
+outer_tree_create_timer: The mesh_create algorithm may create cluster of OBAMP nodes within the network that are disconnected between each other. This happens if there are groups OBAMP nodes that are far from each other. If this happens only the cluster where the Core is present will receive the TREE_CREATE and will receive traffic from the distribution tree. To overcome this problem if in a cluster there are not TREE_CREATE every OBAMP_TREE_CREATE_IVAL the node with the smallest IP in the cluster will make a long mesh link with the nearest node that has at least a tree link. All the necessary information to perform this procedure is diffused in the OBAMP_ALIVE messages.
+
+purge_nodes_timer: checks expire time of various variables, and deletes nodes or tree links in a soft state fashion
+
+The OBAMP nodes will capture the multicast udp traffic from the non-OLSR interfaces, and will forward this traffic encapsulated in the UDP tunnels of the distribution tree.
+The other OBAMP nodes will forward the traffic in the tree and will decapsulate it on their non-OLSR interfaces.
+To avoid duplicated packets the data is carried into OBAMP_DATA messages, that are identified by a sequence number, and the OBAMP source node where the traffic has been encapsulated.
+
+To better understand the protocol we attached a graphic file. In the figure black links represent real radio links, and red links represent overlay mesh links (udp tunnels). Router 1 2 3 and will create a OBAMP cluster, with two mesh links. Router 6 and 7 will create a mesh link between them. Because the mesh_create algorithm does not create a mesh link between the two clusters, the router 6 (supposing it has the smallest IP address in the mesh) will create an outer tree link with Router 3. In this example topology
+In the references there is a URL to a netkit lab where we implemented this scenario to test this implementation.
+
+
+== Configuration ==
+
+To enable the Plugin use the following syntax
+
+LoadPlugin "olsrd_obamp.so.1.0.0"
+{
+PlParam     "NonOlsrIf"  "eth1"
+}
+
+The only (optional) parameter you have to specify are the interface where you want to capture and decapsulate the multicast traffic. Please note that this version of OBAMP will capture and forward only UDP traffic (no multicast ICMP ping).
+
+=== References ===
+
+Main OBAMP protocol Home Page
+http://netgroup.uniroma2.it/Andrea_Detti/obamp/
+
+Netkit lab to test this implementation in a emulated environment
+https://svn.ninux.org/ninuxdeveloping/browser/obamp-netkitlab
+
+Wiki Ninux
+http://wiki.ninux.org/ObampDocs
+
+OBAMP scientific papers:
+
+http://netgroup.uniroma2.it/Andrea_Detti/obamp/obamp_ext.pdf
+http://www.pomposini.it/remo/docs/1569049233.pdf
+http://www.pomposini.it/remo/docs/1569049233.pdf
+
+
+
+=== Contact ===
+ * Saverio Proto zioproto@gmail.com
+ * Claudio Pisa claudio.pisa@clauz.net
diff --git a/lib/obamp/scenario.jpeg b/lib/obamp/scenario.jpeg
new file mode 100644 (file)
index 0000000..130fb71
Binary files /dev/null and b/lib/obamp/scenario.jpeg differ
diff --git a/lib/obamp/src/list.h b/lib/obamp/src/list.h
new file mode 100644 (file)
index 0000000..56be5b0
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+OLSR OBAMP plugin.
+Written by Saverio Proto <zioproto@gmail.com> and Claudio Pisa <clauz@ninux.org>.
+
+    This file is part of OLSR OBAMP PLUGIN.
+
+    The OLSR OBAMP PLUGIN 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 3 of the License, or
+    (at your option) any later version.
+
+    The OLSR OBAMP PLUGIN 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 the OLSR OBAMP PLUGIN.  If not, see <http://www.gnu.org/licenses/>.
+
+ */
+
+//This stuff was from the Kernel, with minor modifications was added here
+
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+/* 
+ * XXX: Resolve conflict between this file and <sys/queue.h> on BSD systems.
+ */
+#ifdef LIST_HEAD
+#undef LIST_HEAD
+#endif
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+       (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries. 
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       next->prev = new;
+       new->next = next;
+       new->prev = prev;
+       prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+       __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+       __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head *prev, struct list_head *next)
+{
+       next->prev = prev;
+       prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+       __list_del(entry->prev, entry->next);
+       //entry->next = (void *) 0;
+       //entry->prev = (void *) 0;
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+       __list_del(entry->prev, entry->next);
+       INIT_LIST_HEAD(entry); 
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+                                 struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(struct list_head *head)
+{
+       return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+                                struct list_head *head)
+{
+       struct list_head *first = list->next;
+       struct list_head *last = list->prev;
+       struct list_head *at = head->next;
+
+       first->prev = head;
+       head->next = first;
+
+       last->next = at;
+       at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+       if (!list_empty(list))
+               __list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+                                   struct list_head *head)
+{
+       if (!list_empty(list)) {
+               __list_splice(list, head);
+               INIT_LIST_HEAD(list);
+       }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+       ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each       -       iterate over a list
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @head:      the head for your list.
+ */
+#define list_for_each(pos, head) \
+       for (pos = (head)->next; pos != (head); \
+               pos = pos->next)
+/**
+ * list_for_each_prev  -       iterate over a list backwards
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @head:      the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+       for (pos = (head)->prev; pos != (head); \
+               pos = pos->prev)
+               
+/**
+ * list_for_each_safe  -       iterate over a list safe against removal of list entry
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @n:         another &struct list_head to use as temporary storage
+ * @head:      the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+       for (pos = (head)->next, n = pos->next; pos != (head); \
+               pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry -       iterate over list of given type
+ * @pos:       the type * to use as a loop counter.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)                         \
+       for (pos = list_entry((head)->next, typeof(*pos), member);      \
+            &pos->member != (head);                                    \
+            pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos:       the type * to use as a loop counter.
+ * @n:         another type * to use as temporary storage
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member)                 \
+       for (pos = list_entry((head)->next, typeof(*pos), member),      \
+               n = list_entry(pos->member.next, typeof(*pos), member); \
+            &pos->member != (head);                                    \
+            pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_continue -       iterate over list of given type
+ *                      continuing after existing point
+ * @pos:        the type * to use as a loop counter.
+ * @head:       the head for your list.
+ * @member:     the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_continue(pos, head, member)                        \
+       for (pos = list_entry(pos->member.next, typeof(*pos), member);  \
+            &pos->member != (head);                                    \
+            pos = list_entry(pos->member.next, typeof(*pos), member))
+
+#endif
diff --git a/lib/obamp/src/obamp.c b/lib/obamp/src/obamp.c
new file mode 100644 (file)
index 0000000..b4f79b4
--- /dev/null
@@ -0,0 +1,1655 @@
+
+/*
+OLSR OBAMP plugin.
+Written by Saverio Proto <zioproto@gmail.com> and Claudio Pisa <clauz@ninux.org>.
+
+    This file is part of OLSR OBAMP PLUGIN.
+
+    The OLSR OBAMP PLUGIN 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 3 of the License, or
+    (at your option) any later version.
+
+    The OLSR OBAMP PLUGIN 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 OLSR OBAMP PLUGIN.  If not, see <http://www.gnu.org/licenses/>.
+
+
+ */
+
+
+/* System includes */
+#include <stddef.h>             /* NULL */
+#include <sys/types.h>          /* ssize_t */
+#include <string.h>             /* strerror() */
+#include <stdarg.h>             /* va_list, va_start, va_end */
+#include <errno.h>              /* errno */
+#include <assert.h>             /* assert() */
+#include <linux/if_ether.h>     /* ETH_P_IP */
+#include <linux/if_packet.h>    /* struct sockaddr_ll, PACKET_MULTICAST */
+#include <signal.h>             /* sigset_t, sigfillset(), sigdelset(), SIGINT */
+#include <netinet/ip.h>         /* struct ip */
+#include <netinet/udp.h>        /* struct udphdr */
+#include <unistd.h>             /* close() */
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+
+#include <fcntl.h> /* fcntl() */
+
+/* OLSRD includes */
+#include "plugin_util.h"        /* set_plugin_int */
+#include "defs.h"               /* olsr_cnf, //OLSR_PRINTF */
+#include "ipcalc.h"
+#include "olsr.h"               /* //OLSR_PRINTF */
+#include "mid_set.h"            /* mid_lookup_main_addr() */
+#include "link_set.h"           /* get_best_link_to_neighbor() */
+#include "net_olsr.h"           /* ipequal */
+#include "olsr_logging.h"
+
+/* plugin includes */
+#include "obamp.h"
+#include "list.h"
+
+
+struct ObampNodeState* myState; //Internal state of the OBAMP node
+/*
+List of all other OBAMP nodes
+if there is a mesh link the isMesh flag is set to 1
+if the link is used in the distribution tree the isTree flag is set to 1
+*/
+struct list_head ListOfObampNodes;
+
+//List of Non OLSR Interfaces to capture and send multicast traffic to
+struct list_head ListOfObampSniffingIf;
+
+//udp socket used for OBAMP signalling
+int sdudp=-1;
+
+/*
+When Outer Tree Create is triggered, a OBAMP node uses this function to
+determine the closer OBAMP node that has a TreeLink
+*/
+static struct ObampNode * select_tree_anchor(void) {
+
+struct ObampNode *tmp; //temp pointers used when parsing the list
+struct ObampNode *best;
+struct list_head *pos;
+
+struct rt_entry *rt; //"rt->rt_best->rtp_metric.cost" is the value you are looking for, a 32 bit
+
+unsigned int mincost = 15;
+
+best=NULL;
+
+if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+
+       //Scroll the list
+       list_for_each(pos,&ListOfObampNodes) { //loop to update min cost
+
+               tmp = list_entry(pos,struct ObampNode,list);
+                       if (tmp->status==1) { 
+                               rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
+                       
+                               if (rt == NULL) {//route is not present yet
+                                       OLSR_DEBUG(LOG_PLUGINS,"No route present to this anchor");
+                                       continue;
+                               }
+                       
+                               //update best neighbor
+                               if ((rt->rt_best->rtp_metric.cost/65536)<mincost) 
+                               best=tmp;
+                       } 
+       }
+       return best;
+
+}
+else {
+OLSR_DEBUG(LOG_PLUGINS,"List empty can't create Overlay Mesh");
+}
+return NULL;
+
+}
+
+//Creates a OBAMP_DATA message and sends it to the specified destination
+static int SendOBAMPData(struct in_addr *addr,unsigned char *ipPacket, int nBytes) {
+
+       struct sockaddr_in si_other;
+       struct OBAMP_data_message *data_msg;
+       data_msg = malloc(sizeof(struct OBAMP_data_message));
+       
+       data_msg->MessageID=OBAMP_DATA;
+       data_msg->router_id = myState->myipaddr;
+       data_msg->last_hop = myState->myipaddr;
+
+       data_msg->CoreAddress = myState->CoreAddress;
+
+       data_msg->SequenceNumber = myState->DataSequenceNumber;
+       myState->DataSequenceNumber++;
+       
+       memcpy(&data_msg->data,ipPacket, nBytes);
+
+       data_msg->datalen=nBytes;
+
+       memset((char *) &si_other, 0, sizeof(si_other));
+       si_other.sin_family = AF_INET;
+       si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
+       si_other.sin_addr = *addr;
+       sendto(sdudp,data_msg,sizeof(struct OBAMP_data_message),0,(struct sockaddr *)&si_other,sizeof(si_other));
+       free(data_msg);
+       return 0;
+
+}
+
+static int CreateCaptureSocket(const char* ifName)
+{
+  int ifIndex = if_nametoindex(ifName);
+  struct packet_mreq mreq;
+  struct ifreq req;
+  struct sockaddr_ll bindTo;
+  int skfd = 0;
+
+  /* Open cooked IP packet socket */
+  if (olsr_cnf->ip_version == AF_INET){
+  skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
+  }
+  else {
+  skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
+  }
+  if (skfd < 0)
+  {
+    OLSR_DEBUG(LOG_PLUGINS,"socket(PF_PACKET) error");
+    return -1;
+  }
+
+  /* Set interface to promiscuous mode */
+  memset(&mreq, 0, sizeof(struct packet_mreq));
+  mreq.mr_ifindex = ifIndex;
+  mreq.mr_type = PACKET_MR_PROMISC;
+  if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
+  {
+   OLSR_DEBUG(LOG_PLUGINS,"setsockopt(PACKET_MR_PROMISC) error");
+    close(skfd);
+    return -1;
+  }
+
+  /* Get hardware (MAC) address */
+  memset(&req, 0, sizeof(struct ifreq));
+  strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
+  req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
+  if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
+  {
+    OLSR_DEBUG(LOG_PLUGINS,"error retrieving MAC address");
+    close(skfd);
+    return -1;
+  }
+
+  /* Bind the socket to the specified interface */
+  memset(&bindTo, 0, sizeof(bindTo));
+  bindTo.sll_family = AF_PACKET;
+  if (olsr_cnf->ip_version == AF_INET){
+  bindTo.sll_protocol = htons(ETH_P_IP);
+  }
+  else{
+  bindTo.sll_protocol = htons(ETH_P_IPV6);
+  }
+  bindTo.sll_ifindex = ifIndex;
+  memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
+  bindTo.sll_halen = IFHWADDRLEN;
+
+  if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
+  {
+    OLSR_DEBUG(LOG_PLUGINS,"bind() error");
+    close(skfd);
+    return -1;
+  }
+
+  /* Set socket to blocking operation */
+  if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
+  {
+    OLSR_DEBUG(LOG_PLUGINS,"fcntl() error");
+    close(skfd);
+    return -1;
+  }
+
+  add_olsr_socket(skfd,&EncapFlowInObamp,NULL,NULL,SP_PR_READ);
+
+  return skfd;
+} /* CreateCaptureSocket */
+
+
+static int CreateObampSniffingInterfaces(void) {
+
+struct ObampSniffingIf *tmp;
+struct list_head *pos;
+
+OLSR_DEBUG(LOG_PLUGINS,"CreateObampSniffingInterfaces");
+
+
+if (list_empty(&ListOfObampSniffingIf)==0) {//if the list is NOT empty
+OLSR_DEBUG(LOG_PLUGINS,"adding interfaces"); 
+
+       list_for_each(pos,&ListOfObampSniffingIf) {
+               
+               tmp = list_entry(pos,struct ObampSniffingIf,list);
+               tmp->skd = CreateCaptureSocket(tmp->ifName);
+       }
+}
+else OLSR_DEBUG(LOG_PLUGINS,"List of sniffin interfaces was empty");
+
+
+  return 0;
+}
+
+
+static int IsMulticast(union olsr_ip_addr* ipAddress)
+{
+  assert(ipAddress != NULL);
+
+  return (ntohl(ipAddress->v4.s_addr) & 0xF0000000) == 0xE0000000;
+}
+
+
+
+static void activate_tree_link(struct OBAMP_tree_link_ack *ack) {
+
+       struct ipaddr_str buf;
+       struct ObampNode *tmp;
+       struct list_head *pos;
+       
+       if ( memcmp(&myState->CoreAddress.v4,&ack->CoreAddress.v4,sizeof(struct in_addr)) !=0){
+       OLSR_DEBUG(LOG_PLUGINS,"Discarding message with no coherent core address");
+       return;
+       }
+
+       if (ack->SequenceNumber != myState->tree_req_sn-1) {
+       
+       OLSR_DEBUG(LOG_PLUGINS,"ACK DISCARDED WRONG SEQ NUMBER");
+       return;
+       }
+       else {
+
+               list_for_each(pos,&ListOfObampNodes) {
+               
+               tmp = list_entry(pos,struct ObampNode,list);
+               if (tmp->neighbor_ip_addr.v4.s_addr == ack->router_id.v4.s_addr){
+                                       
+                       tmp->isTree=1;
+                       OLSR_DEBUG(LOG_PLUGINS,"Tree link to %s activated",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4));
+                       return;
+                                       
+               }
+               }
+       }
+
+}
+
+/*
+When we select a other OBAMP node as a overlay neighbor, we start to send HELLOs to him
+to inform we are using the unicast path from us to him  as a overlay mesh link
+*/
+static void obamp_hello(struct in_addr *addr) {
+
+struct OBAMP_hello *hello;
+       struct sockaddr_in si_other;
+       
+       hello = malloc(sizeof(struct OBAMP_hello));
+       
+       hello->MessageID=OBAMP_HELLO;
+       //TODO: refresh IP address
+       hello->router_id = myState->myipaddr;
+       hello->CoreAddress = myState->CoreAddress;
+
+       //TODO: implement sequence number
+       //hello->HelloSequenceNumber = myState->something;
+       //myState->something++; 
+
+       memset((char *) &si_other, 0, sizeof(si_other));
+       si_other.sin_family = AF_INET;
+       si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
+       si_other.sin_addr = *addr;
+       sendto(sdudp,hello,sizeof(struct OBAMP_hello),0,(struct sockaddr *)&si_other,sizeof(si_other));
+       
+       free(hello);
+}
+
+//Request a Tree Link
+static void tree_link_req(struct in_addr *addr) {
+       
+       struct OBAMP_tree_link_req *req;
+       struct sockaddr_in si_other;
+       
+       req = malloc(sizeof(struct OBAMP_tree_link_req));
+       
+       req->MessageID=OBAMP_TREE_REQ;
+       //TODO: refresh IP address
+       req->router_id = myState->myipaddr;
+       req->CoreAddress = myState->CoreAddress;
+
+       req->SequenceNumber = myState->tree_req_sn;
+       myState->tree_req_sn++; 
+
+       memset((char *) &si_other, 0, sizeof(si_other));
+       si_other.sin_family = AF_INET;
+       si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
+       si_other.sin_addr = *addr;
+       sendto(sdudp,req,sizeof(struct OBAMP_tree_link_req),0,(struct sockaddr *)&si_other,sizeof(si_other));
+       
+       free(req);
+}
+
+static void tree_link_ack(struct OBAMP_tree_link_req *req) {
+
+       struct sockaddr_in si_other;
+       struct in_addr addr;
+
+       struct ObampNode *tmp;
+       struct list_head *pos;
+       struct ipaddr_str buf;
+
+       struct OBAMP_tree_link_ack *ack;
+       
+       //Check Core Address
+       if ( memcmp(&myState->CoreAddress.v4,&req->CoreAddress.v4,sizeof(struct in_addr)) !=0){
+       OLSR_DEBUG(LOG_PLUGINS,"Discarding message with no coherent core address");
+       return;
+       }
+       //TODO: other checks ?
+
+
+       ack = malloc(sizeof(struct OBAMP_tree_link_ack));
+       ack->MessageID=OBAMP_TREE_ACK;
+       //TODO: refresh IP address
+       ack->router_id = myState->myipaddr;
+       ack->CoreAddress = myState->CoreAddress;
+
+       ack->SequenceNumber = req->SequenceNumber;
+
+       addr = req->router_id.v4;
+
+       list_for_each(pos,&ListOfObampNodes) {
+               
+               tmp = list_entry(pos,struct ObampNode,list);
+               if (tmp->neighbor_ip_addr.v4.s_addr == req->router_id.v4.s_addr){
+                                       
+                       tmp->isTree=1;
+                       OLSR_DEBUG(LOG_PLUGINS,"Tree link to %s activated",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4));
+                       break;          
+               }
+       }
+
+       memset((char *) &si_other, 0, sizeof(si_other));
+       si_other.sin_family = AF_INET;
+       si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
+       si_other.sin_addr = addr;
+       sendto(sdudp,ack,sizeof(struct OBAMP_tree_link_req),0,(struct sockaddr *)&si_other,sizeof(si_other));
+
+       free(ack);
+
+}
+
+
+static void init_overlay_neighbor(struct ObampNode *n) {
+
+       n->Texpire=_Texpire_;   //If this value expires the OBAMP node is removed from the list
+       n->isMesh=0;            
+       n->wasMesh=0;
+       n->MeshLock=0;
+       n->isTree=0;
+       n->outerTreeLink=0;
+       n->DataSeqNumber=0;
+}
+
+static void tree_create_forward_to(struct in_addr *addr, struct OBAMP_tree_create* mytc) {
+
+       struct sockaddr_in si_other;
+       struct OBAMP_tree_create *temptc;
+       
+       temptc=malloc(sizeof(struct OBAMP_tree_create));
+       memcpy(temptc,mytc,sizeof(struct OBAMP_tree_create));
+       
+       //Check Core Address
+       if ( memcmp(&myState->CoreAddress.v4,&temptc->CoreAddress.v4,sizeof(struct in_addr)) !=0){
+       OLSR_DEBUG(LOG_PLUGINS,"Discarding message with no coherent core address");
+       return;
+       }
+               
+       //Update router id
+       temptc->router_id = myState->myipaddr;
+
+       memset((char *) &si_other, 0, sizeof(si_other));
+       si_other.sin_family = AF_INET;
+       si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
+       si_other.sin_addr = *addr;
+       
+       sendto(sdudp,temptc,sizeof(struct OBAMP_tree_create),0,(struct sockaddr *)&si_other,sizeof(si_other));
+       free(temptc);
+
+}
+
+static void tree_create_gen(struct in_addr *addr)
+{
+       struct OBAMP_tree_create* mytc;
+       struct sockaddr_in si_other;
+       
+       OLSR_DEBUG(LOG_PLUGINS,"Calling tree_create_gen\n");
+       
+       mytc = malloc(sizeof(struct OBAMP_tree_create));
+       
+       mytc->MessageID = OBAMP_TREECREATE;
+       mytc->router_id = myState->myipaddr;
+       mytc->CoreAddress = myState->CoreAddress;
+       myState->TreeCreateSequenceNumber++;
+       mytc->SequenceNumber = myState->TreeCreateSequenceNumber;
+       
+       memset((char *) &si_other, 0, sizeof(si_other));
+       si_other.sin_family = AF_INET;
+       si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
+       si_other.sin_addr = *addr;
+       sendto(sdudp,mytc,sizeof(struct OBAMP_tree_create),0,(struct sockaddr *)&si_other,sizeof(si_other));
+
+       free(mytc);
+}
+
+
+static void printObampNodesList(void){
+
+       int i=1;
+       struct ipaddr_str buf;
+       struct ObampNode *tmp;
+       struct list_head *pos;
+       
+       if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+       
+
+               OLSR_DEBUG(LOG_PLUGINS,"--------------------NODE STATUS---------");
+               OLSR_DEBUG(LOG_PLUGINS,"---Current Core: %s",ip4_to_string(&buf,myState->CoreAddress.v4));
+               OLSR_DEBUG(LOG_PLUGINS,"---Current Parent: %s",ip4_to_string(&buf,myState->ParentId.v4));
+
+
+               OLSR_DEBUG(LOG_PLUGINS,"Number \t IP \t\t IsMesh \t IsTree \t MeshLock \t outerTreeLink");
+
+               list_for_each(pos,&ListOfObampNodes) {
+       
+                       tmp = list_entry(pos,struct ObampNode,list);
+
+                       OLSR_DEBUG(LOG_PLUGINS,"%d \t\t %s \t %d \t\t %d \t\t %d \t\t %d",i,ip4_to_string(&buf,tmp->neighbor_ip_addr.v4),tmp->isMesh,tmp->isTree,tmp->MeshLock,tmp->outerTreeLink);
+
+                       i++;
+               }
+               OLSR_DEBUG(LOG_PLUGINS,"----------------------------------------");
+
+       }
+}
+
+static int DoIHaveATreeLink(void){
+
+       //struct ipaddr_str buf;
+       struct ObampNode *tmp;
+       struct list_head *pos;
+       
+       if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+       
+               list_for_each(pos,&ListOfObampNodes) {
+       
+               tmp = list_entry(pos,struct ObampNode,list);
+               if (tmp->isTree == 1) return 1; 
+               
+               }
+       }
+       return 0;
+}
+
+static int DoIHaveAMeshLink(void){
+
+       //struct ipaddr_str buf;
+       struct ObampNode *tmp;
+       struct list_head *pos;
+       
+       if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+       
+               list_for_each(pos,&ListOfObampNodes) {
+       
+               tmp = list_entry(pos,struct ObampNode,list);
+               if (tmp->isMesh == 1) return 1; 
+               
+               }
+       }
+       return 0;
+}
+
+static void reset_tree_links(void){
+
+       //struct ipaddr_str buf;
+       struct ObampNode *tmp;
+       struct list_head *pos;
+
+               if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+       
+                       list_for_each(pos,&ListOfObampNodes) {
+       
+                               tmp = list_entry(pos,struct ObampNode,list);
+                               tmp->isTree=0;
+                               tmp->outerTreeLink=0;
+                       }
+               }
+
+       memset(&myState->ParentId.v4,0,sizeof(myState->ParentId.v4));
+       memset(&myState->OldParentId.v4,1,sizeof(myState->OldParentId.v4));
+
+};
+
+
+//Core Election. The Core is the one with the smallest IP Address
+static void CoreElection(void) {
+
+       struct ipaddr_str buf;
+       struct ObampNode *tmp;
+       struct list_head *pos;
+       u_int32_t smallestIP = 0xFFFFFFFF;
+       
+       //Update my current IP address
+       memcpy(&myState->myipaddr.v4,&olsr_cnf->router_id, olsr_cnf->ipsize);
+       
+       OLSR_DEBUG(LOG_PLUGINS,"SETUP: my IP - %s",ip4_to_string(&buf,myState->myipaddr.v4));
+       
+       
+               if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+       
+                       list_for_each(pos,&ListOfObampNodes) {
+       
+                               tmp = list_entry(pos,struct ObampNode,list);
+                               if (tmp->neighbor_ip_addr.v4.s_addr < smallestIP) {
+                               
+                                       smallestIP = tmp->neighbor_ip_addr.v4.s_addr;
+                                       OLSR_DEBUG(LOG_PLUGINS,"CoreElection: current smallest IP is - %s",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4));
+                               
+                               };
+                       }
+                       //Check if I'm the core.
+       
+                       if (myState->myipaddr.v4.s_addr < smallestIP ) { //I'm the core
+                               
+                               if (myState->myipaddr.v4.s_addr == myState->CoreAddress.v4.s_addr) {//I'm was already the core
+                               return;
+                               }
+                               else { //I'm becoming core 
+                               
+                               myState->CoreAddress = myState->myipaddr;
+                               myState->iamcore = 1;
+                               myState->TreeCreateSequenceNumber = 0;
+                               reset_tree_links();
+                               OLSR_DEBUG(LOG_PLUGINS,"I'm the core");
+                               }
+                       }
+                       else    {
+                               if (myState->CoreAddress.v4.s_addr == smallestIP) { //the core did not change
+                               return;
+                               }
+                               else {//core changed
+                               myState->iamcore = 0;
+                               myState->CoreAddress.v4.s_addr = smallestIP;
+                               reset_tree_links();
+                               OLSR_DEBUG(LOG_PLUGINS,"CoreElection: current Core is - %s",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4));
+                               }
+                       }
+       
+               }
+               
+               else { //List is empty I'm the core
+               OLSR_DEBUG(LOG_PLUGINS,"CoreElection: I'm alone I'm the core");
+               myState->CoreAddress = myState->myipaddr;
+               myState->iamcore = 1;
+               myState->TreeCreateSequenceNumber = 0;
+               reset_tree_links();
+
+       
+       
+               }
+
+}
+
+//Starts a UDP listening port for OBAMP signalling
+static int UdpServer(void) {
+
+       struct sockaddr_in addr; 
+       
+       
+       if ((sdudp=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
+       OLSR_DEBUG(LOG_PLUGINS,"Socket UDP error");
+       return -1;
+       }
+       
+       memset((void *)&addr, 0, sizeof(addr));     /* clear server address */ 
+       addr.sin_family = AF_INET;                  /* address type is INET */ 
+       addr.sin_port = htons(OBAMP_SIGNALLING_PORT);
+       addr.sin_addr.s_addr = htonl(INADDR_ANY);   /* connect from anywhere */ 
+       /* bind socket */ 
+       if (bind(sdudp, (struct sockaddr *)&addr, sizeof(addr)) < 0) 
+       { 
+       OLSR_DEBUG(LOG_PLUGINS,"Socket UDP BIND error");
+       return(-1);      
+       } 
+       
+       add_olsr_socket(sdudp, &ObampSignalling, NULL, NULL, SP_PR_READ);
+       
+       return 0;
+
+}
+
+static void decap_data(char *buffer) {
+
+       //struct ipaddr_str buf; //buf to print debug infos
+       struct ObampSniffingIf *tmp; //temp pointers used when parsing the list
+       struct list_head *pos;
+       unsigned char *ipPacket;
+       int stripped_len;
+       struct ip *ipHeader;
+       struct ip6_hdr* ip6Header;
+       struct OBAMP_data_message *msg;
+       int nBytesWritten;
+       struct sockaddr_ll dest;
+       msg = (struct OBAMP_data_message*) buffer;
+
+       ipPacket=msg->data; 
+
+       ipHeader = (struct ip *)ipPacket;
+       ip6Header = (struct ip6_hdr *)ipPacket;
+
+
+if (list_empty(&ListOfObampSniffingIf)==0) {//if the list is NOT empty
+//OLSR_DEBUG(LOG_PLUGINS,"DECAP DATA"); 
+
+       list_for_each(pos,&ListOfObampSniffingIf) {
+               
+               tmp = list_entry(pos,struct ObampSniffingIf,list);
+               //tmp->skd = CreateCaptureSocket(tmp->ifName);
+
+
+
+               memset(&dest, 0, sizeof(dest));
+               dest.sll_family = AF_PACKET;
+               if ((ipPacket[0] & 0xf0) == 0x40) {
+               dest.sll_protocol = htons(ETH_P_IP);
+               stripped_len = ntohs(ipHeader->ip_len);
+               }
+               if ((ipPacket[0] & 0xf0) == 0x60) {
+               dest.sll_protocol = htons(ETH_P_IPV6);
+               stripped_len = 40 + ntohs(ip6Header->ip6_plen); //IPv6 Header size (40) + payload_len 
+               }
+               //TODO: if packet is not IP die here
+      
+
+               dest.sll_ifindex = if_nametoindex(tmp->ifName);
+               dest.sll_halen = IFHWADDRLEN;
+
+      /* Use all-ones as destination MAC address. When the IP destination is
+       * a multicast address, the destination MAC address should normally also
+       * be a multicast address. E.g., when the destination IP is 224.0.0.1,
+       * the destination MAC should be 01:00:5e:00:00:01. However, it does not
+       * seem to matter when the destination MAC address is set to all-ones
+       * in that case. */
+      memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
+
+      nBytesWritten = sendto(tmp->skd, ipPacket, stripped_len, 0, (struct sockaddr *)&dest, sizeof(dest));
+      if (nBytesWritten != stripped_len) {
+        OLSR_DEBUG(LOG_PLUGINS,"sendto() error forwarding unpacked encapsulated pkt on \"%s\"", tmp->ifName);
+      } else {
+
+        OLSR_DEBUG(LOG_PLUGINS,"OBAMP: --> unpacked and forwarded on \"%s\"\n",tmp->ifName);
+      }
+
+
+       }
+}
+
+}
+
+static int CheckDupData(char *buffer) {
+
+       struct ObampNode *tmp; //temp pointers used when parsing the list
+       struct list_head *pos;
+       struct OBAMP_data_message *data_msg;
+
+       data_msg = (struct OBAMP_data_message*) buffer;
+
+
+       //Check duplicate data packet
+       if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+                       
+               //Scroll the list
+               list_for_each(pos,&ListOfObampNodes) {
+                       tmp = list_entry(pos,struct ObampNode,list);
+                                       
+                       if (memcmp(&tmp->neighbor_ip_addr.v4,&data_msg->router_id.v4,sizeof(struct in_addr)) ==0) {
+                                               
+                               
+                               if (tmp->DataSeqNumber == 0) { //First packet received from this host
+                                               tmp->DataSeqNumber = data_msg->SequenceNumber;
+                                               return 1;
+                                       }
+                               if (data_msg->SequenceNumber < tmp->DataSeqNumber) {
+                               
+                               OLSR_DEBUG(LOG_PLUGINS,"DISCARDING DUP PACKET");
+                               return 0;
+                               }       
+                       } 
+               }
+       }
+
+return 1;
+
+}
+
+static void forward_obamp_data(char *buffer) {
+
+       struct ipaddr_str buf; //buf to print debug infos
+       struct ObampNode *tmp; //temp pointers used when parsing the list
+       struct list_head *pos;
+       struct OBAMP_data_message *data_msg;
+
+       struct sockaddr_in si_other;
+
+       
+       data_msg = (struct OBAMP_data_message*) buffer;
+
+       if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+                       
+               //Scroll the list
+               list_for_each(pos,&ListOfObampNodes) {
+                       tmp = list_entry(pos,struct ObampNode,list);
+                                       
+                               if (tmp->isTree==1 && memcmp(&tmp->neighbor_ip_addr.v4,&data_msg->last_hop.v4,sizeof(struct in_addr)) !=0
+                                               ) {
+                                               
+                                               //FORWARD DATA
+                                               data_msg->last_hop = myState->myipaddr;
+
+                                               
+                                               memset((char *) &si_other, 0, sizeof(si_other));
+                                               si_other.sin_family = AF_INET;
+                                               si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
+                                               si_other.sin_addr = tmp->neighbor_ip_addr.v4;
+                                               sendto(sdudp,data_msg,sizeof(struct OBAMP_data_message),0,(struct sockaddr *)&si_other,sizeof(si_other));
+                                               
+                                               OLSR_DEBUG(LOG_PLUGINS,"FORWARDING OBAMP DATA TO node %s ",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4));
+                               
+                                               } 
+               }
+       }
+
+}
+
+
+static void manage_hello (char *packet) {
+
+struct OBAMP_hello* hello;
+
+struct ObampNode *tmp; //temp pointers used when parsing the list
+struct list_head *pos;
+
+hello = (struct OBAMP_hello*) packet;
+
+       //FIRST OF ALL CHECK CORE
+       if ( memcmp(&myState->CoreAddress.v4,&hello->CoreAddress.v4,sizeof(struct in_addr)) !=0){
+               OLSR_DEBUG(LOG_PLUGINS,"Discarding message with no coherent core address");
+               return;
+       }
+
+       if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+                       
+               //Scroll the list
+               list_for_each(pos,&ListOfObampNodes) {
+               tmp = list_entry(pos,struct ObampNode,list);
+                                       
+                                               if (memcmp(&tmp->neighbor_ip_addr.v4,&hello->router_id.v4,sizeof(struct in_addr)) ==0
+                                               ) {//I search in the list the neighbor I received the hello from
+                                       
+                                               tmp->isMesh=1;
+                                               tmp->MeshLock=_MESH_LOCK_;
+                               
+                                               } 
+                                       }
+                               }
+                               else {
+                                       OLSR_DEBUG(LOG_PLUGINS,"Very strange, list cannot be empty here !");
+                               }
+
+}
+
+static void manage_tree_create(char *packet) {
+
+
+       struct OBAMP_tree_create* msg;
+       
+       struct ipaddr_str buf; //buf to print debug infos
+       struct ipaddr_str buf2; //buf to print debug infos
+
+       struct ObampNode *tmp; //temp pointers used when parsing the list
+       struct list_head *pos;
+               
+       msg = (struct OBAMP_tree_create*) packet;
+       
+       if (msg->MessageID != OBAMP_TREECREATE) {
+               OLSR_DEBUG(LOG_PLUGINS,"BIG PROBLEM, I'M IN THIS FUNCTION BUT MESSAGE IS NOT TREE CREATE");
+       }
+       
+       else {
+               //FIRST OF ALL CHECK CORE
+               if ( memcmp(&myState->CoreAddress.v4,&msg->CoreAddress.v4,sizeof(struct in_addr)) !=0){
+               OLSR_DEBUG(LOG_PLUGINS,"Discarding message with no coherent core address");
+               return;
+               }
+               if (myState->iamcore == 1) { //I'm core and receiving tree create over a loop
+               return;
+               }
+               else {  
+                       if (myState->TreeCreateSequenceNumber < msg->SequenceNumber ) { //If tree create is not a duplicate
+                               myState->TreeCreateSequenceNumber = msg->SequenceNumber;
+                               myState->TreeHeartBeat = TREE_HEARTBEAT;
+
+                               
+                               myState->OldParentId.v4 = myState->ParentId.v4;
+                               myState->ParentId.v4 = msg->router_id.v4;
+                               
+                               if (memcmp(&myState->OldParentId.v4,&myState->ParentId.v4,sizeof(struct in_addr)) !=0) //If it changed
+                               {
+                               OLSR_DEBUG(LOG_PLUGINS,"Parent changed requesting tree link");
+                               reset_tree_links();
+                               myState->ParentId.v4 = msg->router_id.v4;
+                               myState->OldParentId.v4 = myState->ParentId.v4;
+                               tree_link_req(&msg->router_id.v4);
+                               }
+                               if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+                       
+                                       //Scroll the list
+                                       list_for_each(pos,&ListOfObampNodes) {
+                                       tmp = list_entry(pos,struct ObampNode,list);
+                                       
+                                               if (tmp->isMesh==1 && memcmp(&tmp->neighbor_ip_addr.v4,&msg->router_id.v4,sizeof(struct in_addr)) !=0
+                                               ) {//Is neighbor and not the originator of this tree create
+                                               tree_create_forward_to(&tmp->neighbor_ip_addr.v4,msg);  
+                                               OLSR_DEBUG(LOG_PLUGINS,"FORWARDING TREE CREATE ORIGINATOR %s TO node %s ",ip4_to_string(&buf2,msg->router_id.v4),ip4_to_string(&buf,tmp->neighbor_ip_addr.v4));
+                               
+                                               } 
+                                       }
+                               }
+                               else {
+                                       OLSR_DEBUG(LOG_PLUGINS,"Very strange, list cannot be empty here !");
+                               }
+                       }
+                       else {
+                       OLSR_DEBUG(LOG_PLUGINS,"DISCARDING DUP TREE CREATE");
+                       }
+               }
+       }
+
+}
+
+void
+ObampSignalling(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
+{
+
+char buffer[1500];
+char text_buffer[300];
+struct sockaddr_in *addr; 
+int n=0;
+socklen_t len;
+u_int8_t MessageID;
+
+addr = malloc(sizeof(struct sockaddr_in));
+memset((void *)addr,0,sizeof(struct sockaddr_in));
+len = sizeof(struct sockaddr_in);
+
+if (skfd>0) {
+
+       //OLSR_DEBUG(LOG_PLUGINS,"INCOMING OBAMP SIGNALLING");
+
+       n = recvfrom(skfd, buffer, 1500, 0, (struct sockaddr *)addr, &len);
+       
+       if (n<0){
+               OLSR_DEBUG(LOG_PLUGINS,"recvfrom error");
+               }
+       
+       inet_ntop(AF_INET, &addr->sin_addr, text_buffer, sizeof(text_buffer));
+       //OLSR_DEBUG(LOG_PLUGINS,"Request from host %s, port %d\n", text_buffer, ntohs(addr->sin_port)); 
+       
+       MessageID=buffer[0];
+       
+       switch (MessageID) {
+       
+       case OBAMP_DATA:
+       OLSR_DEBUG(LOG_PLUGINS,"OBAMP Received OBAMP_DATA from host %s, port %d\n", text_buffer, ntohs(addr->sin_port));
+
+       if (CheckDupData(buffer)) {
+       forward_obamp_data(buffer);
+       decap_data(buffer);
+       }
+
+       break;
+       
+       case OBAMP_HELLO:
+       OLSR_DEBUG(LOG_PLUGINS,"OBAMP Received OBAMP_HELLO from host %s, port %d\n", text_buffer, ntohs(addr->sin_port));
+       manage_hello(buffer);
+       break;
+       
+       case OBAMP_TREECREATE:
+       //do here
+       OLSR_DEBUG(LOG_PLUGINS,"OBAMP Received OBAMP_TREECREATE from host %s, port %d\n", text_buffer, ntohs(addr->sin_port));
+       manage_tree_create(buffer);
+       
+       break;
+       
+       case OBAMP_TREE_REQ:
+       OLSR_DEBUG(LOG_PLUGINS,"OBAMP Received OBAMP_TREE_REQ from host %s, port %d\n", text_buffer, ntohs(addr->sin_port));
+       tree_link_ack((struct OBAMP_tree_link_req *)buffer);
+       break;
+       
+       case OBAMP_TREE_ACK:
+       //do here
+       OLSR_DEBUG(LOG_PLUGINS,"OBAMP Received OBAMP_TREE_ACK from host %s, port %d\n", text_buffer, ntohs(addr->sin_port));
+       activate_tree_link((struct OBAMP_tree_link_ack *)buffer);
+       break;
+       
+       
+       }
+
+
+} //if skfd<0
+
+}
+
+
+/*
+adds a IPv4 ObampNode in the list if it is new
+If a new node is added CoreElection is called to update the current core
+*/
+int addObampNode4(struct in_addr * ipv4, u_int8_t status){
+
+struct ipaddr_str buf; //Printf stuff
+struct ObampNode *neighbor_to_add;
+struct ObampNode *tmp;
+struct list_head *pos;
+
+neighbor_to_add = malloc(sizeof(struct ObampNode));
+
+//OLSR_DEBUG(LOG_PLUGINS,"Adding to list node - %s\n",ip4_to_string(&buf,*ipv4));
+
+
+if (list_empty(&ListOfObampNodes)!=0) { //Empty list
+//OLSR_DEBUG(LOG_PLUGINS,"List is empty %d adding first node\n",list_empty(&ListOfObampNodes));
+
+memcpy(&neighbor_to_add->neighbor_ip_addr.v4,ipv4,sizeof(neighbor_to_add->neighbor_ip_addr.v4));
+list_add(&(neighbor_to_add->list),&ListOfObampNodes);
+
+init_overlay_neighbor(neighbor_to_add);
+neighbor_to_add->status=status;
+
+OLSR_DEBUG(LOG_PLUGINS,"Added to list node as first node- %s\n",ip4_to_string(&buf,*ipv4));
+
+CoreElection();
+
+} 
+else 
+{ //Some node already in list
+
+//Scroll the list to check if the element already exists
+list_for_each(pos,&ListOfObampNodes) {
+
+         tmp = list_entry(pos,struct ObampNode,list);
+        if (memcmp(&tmp->neighbor_ip_addr.v4,ipv4,sizeof(tmp->neighbor_ip_addr.v4)) == 0)
+               {
+               //OLSR_DEBUG(LOG_PLUGINS,"Node already present in list %s\n",ip4_to_string(&buf,*ipv4));
+               tmp->Texpire=_Texpire_; //Refresh Texpire
+               neighbor_to_add->status=status;
+               free(neighbor_to_add);
+               return 1;
+               }
+}
+//Add element to list
+// neighbor_to_add->Texpire=_Texpire_; //Refresh Texpire
+OLSR_DEBUG(LOG_PLUGINS,"Adding to list node (NOT FIRST)- %s\n",ip4_to_string(&buf,*ipv4));
+memcpy(&neighbor_to_add->neighbor_ip_addr.v4,ipv4,sizeof(neighbor_to_add->neighbor_ip_addr.v4));
+list_add(&(neighbor_to_add->list),&ListOfObampNodes);
+init_overlay_neighbor(neighbor_to_add);
+neighbor_to_add->status=status;
+CoreElection();
+} //end else
+return 0;
+} //End AddObampNode
+
+
+
+/* -------------------------------------------------------------------------
+ * Function   : PacketReceivedFromOLSR
+ * Description: Handle a received packet from a OLSR message
+ * Input      : Obamp Message
+ * Output     : none
+ * Return     : none
+ * ------------------------------------------------------------------------- */
+static void
+PacketReceivedFromOLSR(void * originator, unsigned char *obamp_message,int len)
+{
+u_int8_t MessageID = obamp_message[0];
+struct OBAMP_alive *alive;
+struct ipaddr_str buf;
+
+struct in_addr * myOriginator= (struct in_addr *)originator;
+
+//TODO: this is useless now
+len=0;
+
+//See obamp.h
+switch (MessageID) {
+
+case OBAMP_ALIVE:
+OLSR_DEBUG(LOG_PLUGINS,"OBAMP Received OBAMP_ALIVE from %s\n",ip4_to_string(&buf,*myOriginator));
+alive = (struct OBAMP_alive *) obamp_message;
+addObampNode4(myOriginator,alive->status);
+printObampNodesList();
+
+break;
+}
+
+
+} /* PacketReceivedFromOLSR */
+
+
+//OLSR parser, received OBAMP messages
+void
+olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr, enum duplicate_status status __attribute__ ((unused)))
+{
+  union olsr_ip_addr originator;
+  int size;
+  uint32_t vtime;
+  //OLSR_DEBUG(LOG_PLUGINS, "OBAMP PLUGIN: Received msg in parser\n");
+
+  /* Fetch the originator of the messsage */
+  if (olsr_cnf->ip_version == AF_INET) {
+    memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize);
+    vtime = me_to_reltime(m->v4.olsr_vtime);
+    size = ntohs(m->v4.olsr_msgsize);
+  } else {
+    memcpy(&originator, &m->v6.originator, olsr_cnf->ipsize);
+    vtime = me_to_reltime(m->v6.olsr_vtime);
+    size = ntohs(m->v6.olsr_msgsize);
+  }
+
+  /* Check if message originated from this node.
+   *         If so - back off */
+  if (olsr_ipcmp(&originator, &olsr_cnf->router_id) == 0)
+    return;
+
+  /* Check that the neighbor this message was received from is symmetric.
+   *         If not - back off*/
+  if (check_neighbor_link(ipaddr) != SYM_LINK) {
+    //struct ipaddr_str strbuf;
+    return;
+  }
+
+  if (olsr_cnf->ip_version == AF_INET) {
+
+    //IPv4 Case, process your OBAMP packet here:
+    PacketReceivedFromOLSR(&m->v4.originator,(unsigned char *)&m->v4.message, size - 12);
+  } else {
+    //IPv6 Case, process your OBAMP packet here:
+    PacketReceivedFromOLSR(&m->v6.originator,(unsigned char *)&m->v6.message, size - 12 - 96);
+  }
+
+}
+
+//Sends a packet in the OLSR network
+void
+olsr_obamp_gen(unsigned char *packet, int len)
+{
+  /* send buffer: huge */
+  char buffer[10240];
+  union olsr_message *message = (union olsr_message *)buffer;
+  struct interface *ifn;
+
+  /* fill message */
+  if (olsr_cnf->ip_version == AF_INET) {
+    /* IPv4 */
+    message->v4.olsr_msgtype = MESSAGE_TYPE;
+    message->v4.olsr_vtime = reltime_to_me(OBAMP_VALID_TIME * MSEC_PER_SEC);
+    memcpy(&message->v4.originator, &olsr_cnf->router_id, olsr_cnf->ipsize);
+    message->v4.ttl = MAX_TTL;
+    message->v4.hopcnt = 0;
+    message->v4.seqno = htons(get_msg_seqno());
+
+    message->v4.olsr_msgsize = htons(len + 12);
+
+    memcpy(&message->v4.message, packet, len);
+    len = len + 12;
+  } else {
+    /* IPv6 */
+    message->v6.olsr_msgtype = MESSAGE_TYPE;
+    message->v6.olsr_vtime = reltime_to_me(OBAMP_VALID_TIME * MSEC_PER_SEC);
+    memcpy(&message->v6.originator, &olsr_cnf->router_id, olsr_cnf->ipsize);
+    message->v6.ttl = MAX_TTL;
+    message->v6.hopcnt = 0;
+    message->v6.seqno = htons(get_msg_seqno());
+
+    message->v6.olsr_msgsize = htons(len + 12 + 96);
+    memcpy(&message->v6.message, packet, len);
+    len = len + 12 + 96;
+  }
+
+  /* looping trough interfaces */
+  OLSR_FOR_ALL_INTERFACES(ifn) {
+    if (net_outbuffer_push(ifn, message, len) != len) {
+      /* send data and try again */
+      net_output(ifn);
+      if (net_outbuffer_push(ifn, message, len) != len) {
+        OLSR_DEBUG(LOG_PLUGINS, "OBAMP PLUGIN: could not send on interface: %s\n", ifn->int_name);
+      }
+    }
+  }
+  OLSR_FOR_ALL_INTERFACES_END(ifn);
+}
+
+void outer_tree_create(void *x) {
+
+struct ObampNode *tmp; //temp pointers used when parsing the list
+struct list_head *pos;
+
+
+if ( (DoIHaveATreeLink()==0) && (myState->iamcore==0) ) { //If there are not tree links
+
+       if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+       
+       
+                       if (DoIHaveAMeshLink()==0) {
+                               OLSR_DEBUG(LOG_PLUGINS,"Weird, no mesh links. Maybe other OBAMP nodes are very far (HUGE ETX)");
+       
+                       }
+                       else {
+               
+                       //Update my current IP address
+                       memcpy(&myState->myipaddr.v4,&olsr_cnf->router_id, olsr_cnf->ipsize);
+                       //OLSR_DEBUG(LOG_PLUGINS,"SETUP: my IP - %s",ip4_to_string(&buf,myState->myipaddr.v4));
+                       list_for_each(pos,&ListOfObampNodes) {
+                                       tmp = list_entry(pos,struct ObampNode,list);
+                                       if ( (tmp->neighbor_ip_addr.v4.s_addr < myState->myipaddr.v4.s_addr ) && (tmp->isMesh == 1)) {
+                                       return; //I have a neighbor that will send a outer tree create for me
+                                       }
+                               }
+                       //tree create
+                       OLSR_DEBUG(LOG_PLUGINS,"OUTER TREE CREATE");
+                       tmp=select_tree_anchor();
+                       if (tmp==NULL) {
+                               OLSR_DEBUG(LOG_PLUGINS,"CANT FIND ANCHOR");
+                               return;
+                       }
+                       tmp->isMesh=1;
+                       tmp->outerTreeLink=1;
+                       myState->OldParentId.v4 = tmp->neighbor_ip_addr.v4;
+                       myState->ParentId.v4 = tmp->neighbor_ip_addr.v4;
+                       myState->TreeHeartBeat = TREE_HEARTBEAT;
+                       tree_link_req(&tmp->neighbor_ip_addr.v4);
+                       
+                       }
+       
+       
+       }
+       else {
+               OLSR_DEBUG(LOG_PLUGINS,"List empty can't send OUTER_TREE_CREATE");
+       }
+}
+x=NULL;
+}
+
+
+void tree_create(void *x) {
+
+struct ipaddr_str buf; //buf to print debug infos
+struct ObampNode *tmp; //temp pointers used when parsing the list
+struct list_head *pos;
+
+//Check if I'm core
+if (myState->iamcore==1) {
+
+       if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+       
+               //Scroll the list
+               list_for_each(pos,&ListOfObampNodes) {
+       
+               tmp = list_entry(pos,struct ObampNode,list);
+                       if (    tmp->isMesh==1 ) {//Is neighbor 
+                       //send tree create
+                       
+                       tree_create_gen(&tmp->neighbor_ip_addr.v4);
+                       
+                       
+                       OLSR_DEBUG(LOG_PLUGINS,"CORE SENDS TREE CREATE TO node %s ",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4));
+               
+                       } 
+               }
+       }
+       else {
+                       OLSR_DEBUG(LOG_PLUGINS,"List empty can't send TREE_CREATE");
+       }
+
+}
+
+x=NULL;
+}
+
+
+
+
+void mesh_create(void *x) {
+
+struct ipaddr_str buf; //buf to print debug infos
+struct ObampNode *tmp; //temp pointers used when parsing the list
+struct list_head *pos;
+
+struct rt_entry *rt; //"rt->rt_best->rtp_metric.cost" is the value you are looking for, a 32 bit
+
+unsigned int mincost = 5;
+
+int meshchanged=0;
+
+if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+
+       //Scroll the list
+       list_for_each(pos,&ListOfObampNodes) {
+
+         tmp = list_entry(pos,struct ObampNode,list);
+
+       //set every OBAMP node to be NOT neighbor 
+       tmp->wasMesh=tmp->isMesh;
+
+       //MeshLock in case mesh link is requested from neighbor
+       if(tmp->MeshLock == 0 && tmp->outerTreeLink == 0) tmp->isMesh=0;
+
+        rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
+       
+       if (rt == NULL) {//route is not present yet
+       continue;
+       }
+       
+        //OLSR_DEBUG(LOG_PLUGINS,"ROUTING TO node %s costs %u",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4),rt->rt_best->rtp_metric.cost/65536);
+
+       if ( rt->rt_best->rtp_metric.cost/65536 > 5 ) {
+               continue; //we not not consider links that are poorer than ETX=5
+       }
+
+       //update min cost 
+       if ((rt->rt_best->rtp_metric.cost/65536)<mincost) mincost=(rt->rt_best->rtp_metric.cost/65536);
+       
+        } //end for each
+       
+       //now that I know the mincost to the closer OBAMP node I choose my neighbor set
+       list_for_each(pos,&ListOfObampNodes) {
+
+         tmp = list_entry(pos,struct ObampNode,list);
+        rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
+       
+        if (rt == NULL) {//route is not present yet
+               continue;
+        }
+
+        if ( rt->rt_best->rtp_metric.cost/65536 > 5 ) {
+               continue; //we not not consider links that are poorer than ETX=5
+        }
+        
+        if ((rt->rt_best->rtp_metric.cost/65536)-1 < mincost) { //Choose for mesh
+               
+               tmp->isMesh=1;
+               OLSR_DEBUG(LOG_PLUGINS,"Choosed Overlay Neighbor node %s costs %u",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4),rt->rt_best->rtp_metric.cost/65536);
+
+               obamp_hello(&tmp->neighbor_ip_addr.v4);
+
+
+               }
+
+       if (tmp->outerTreeLink == 1) obamp_hello(&tmp->neighbor_ip_addr.v4);
+
+       
+       if (tmp->isMesh!=tmp->wasMesh) {
+               meshchanged++;
+               if ( tmp->isMesh == 0 && tmp->isTree == 1) {
+               
+                       tmp->isTree=0;          
+
+               }
+       }
+       
+       } //end for each
+       
+       if (meshchanged) {
+       //trigger signalling
+       }
+       
+
+}
+else {
+OLSR_DEBUG(LOG_PLUGINS,"List empty can't create Overlay Mesh");
+}
+
+x=NULL;
+}
+
+
+void purge_nodes(void* x) {
+
+struct ipaddr_str buf;
+struct ObampNode *tmp;
+struct list_head *pos;
+
+int nodesdeleted =0;
+
+if (myState->TreeHeartBeat > 0) myState->TreeHeartBeat--;
+
+if (myState->TreeHeartBeat == 0 && myState->iamcore == 0) reset_tree_links();
+
+
+
+//OLSR_DEBUG(LOG_PLUGINS,"OBAMP: Timer Expired Purging Nodes");
+
+
+if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+
+list_for_each(pos,&ListOfObampNodes) {
+
+         tmp = list_entry(pos,struct ObampNode,list);
+        tmp->Texpire--;
+        if (tmp->MeshLock !=0) tmp->MeshLock--;
+
+        //OLSR_DEBUG(LOG_PLUGINS,"Updating node %s with Texpire %d",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4),tmp->Texpire);
+        if (tmp->Texpire == 0) {//purge
+        OLSR_DEBUG(LOG_PLUGINS,"Purging node %s",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4));
+        list_del(pos);
+        //OLSR_DEBUG(LOG_PLUGINS,"OBAMP CHECK EMPTY %d",list_empty(&ListOfObampNodes));
+
+         free(tmp);
+        nodesdeleted++;
+        }
+         
+}
+
+if (nodesdeleted !=0) CoreElection();
+
+}
+else {
+//OLSR_DEBUG(LOG_PLUGINS,"OBAMP: List empty");
+
+}
+
+x=NULL;
+}
+
+
+void obamp_alive_gen(void* x) {
+struct OBAMP_alive* myAlive;
+OLSR_DEBUG(LOG_PLUGINS,"Calling obamp_alive_gen\n");
+myAlive = malloc(sizeof(struct OBAMP_alive));
+myAlive->MessageID = OBAMP_ALIVE;
+myAlive->status = DoIHaveATreeLink();
+olsr_obamp_gen((unsigned char*)myAlive, sizeof(struct OBAMP_alive));
+free(myAlive);
+x=NULL;
+
+}
+
+
+
+/*
+When a packet is captured on the sniffing interfaces, it is called EncapFlowInObamp
+here we check if the packet is multicast and we forward it to the overlay neighbors if we have a link tree
+*/
+
+void EncapFlowInObamp(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
+
+{
+  unsigned char ipPacket[1500]; //TODO: optimize me
+
+  struct ipaddr_str buf;
+  struct ObampNode *tmp;
+  struct list_head *pos;
+
+  union olsr_ip_addr dst; /* Destination IP address in captured packet */
+  struct ip* ipHeader; /* The IP header inside the captured IP packet */
+  struct ip6_hdr* ipHeader6; /* The IP header inside the captured IP packet */
+
+      if (skfd >= 0)
+      {
+        struct sockaddr_ll pktAddr;
+        socklen_t addrLen = sizeof(pktAddr);
+        int nBytes;
+
+       nBytes = recvfrom(
+                       skfd,
+                       ipPacket,
+                       1500, //TODO: optimize me
+                       0,
+                       (struct sockaddr*)&pktAddr,
+                       &addrLen);
+       if (nBytes < 0)
+       {
+
+               return; /* for */
+       } /* if (nBytes < 0) */
+
+       /* Check if the number of received bytes is large enough for an IP
+        * packet which contains at least a minimum-size IP header.
+        * Note: There is an apparent bug in the packet socket implementation in
+        * combination with VLAN interfaces. On a VLAN interface, the value returned
+        * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
+        * returned on a non-VLAN interface, for the same ethernet frame. */
+       if (nBytes < (int)sizeof(struct ip))
+       {
+
+               OLSR_DEBUG(LOG_PLUGINS,"Captured frame too short");
+               return; /* for */
+       }
+
+       if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
+                       pktAddr.sll_pkttype == PACKET_MULTICAST) // ||
+                       //pktAddr.sll_pkttype == PACKET_BROADCAST)
+       {
+               
+               //do here
+       if ((ipPacket[0] & 0xf0) == 0x40) { //IPV4
+
+            ipHeader = (struct ip*) ipPacket;
+
+            dst.v4 = ipHeader->ip_dst;
+
+            /* Only forward multicast packets. If configured, also forward local broadcast packets */
+            if (IsMulticast(&dst))
+            {
+              /* continue */
+            }
+            else
+            {
+              return;
+            }
+            if (ipHeader->ip_p != SOL_UDP)
+            {
+              /* Not UDP */
+              OLSR_DEBUG(LOG_PLUGINS,"NON UDP PACKET\n");
+              return; /* for */
+            }
+           else {
+               //Forward the packet to tree links
+               if (list_empty(&ListOfObampNodes)==0) { //if the list is NOT empty
+
+                       list_for_each(pos,&ListOfObampNodes) {
+               
+                       tmp = list_entry(pos,struct ObampNode,list);
+                       if (tmp->isTree==1){
+                                       
+                               OLSR_DEBUG(LOG_PLUGINS,"Pushing data to Tree link to %s",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4));
+                               SendOBAMPData(&tmp->neighbor_ip_addr.v4,ipPacket,nBytes);
+               
+                       }
+                       }
+               }
+           }
+            
+  }//END IPV4
+
+  else if ((ipPacket[0] & 0xf0) == 0x60) { //IPv6
+  
+            ipHeader6 = (struct ip6_hdr*) ipPacket;
+            if (ipHeader6->ip6_dst.s6_addr[0] == 0xff) //Multicast
+            {
+              //Continua
+            }
+            else
+            {
+            return; //not multicast
+            }
+            if (ipHeader6->ip6_nxt != SOL_UDP)
+            {
+              /* Not UDP */
+              OLSR_DEBUG(LOG_PLUGINS,"NON UDP PACKET\n");
+              return; /* for */
+            }
+            
+  } //END IPV6
+  else return; //Is not IP packet
+
+  // send the packet to OLSR forward mechanism
+  // SendOBAMPData(&tmp->neighbor_ip_addr.v6,ipPacket,nBytes);
+
+
+       } /* if (pktAddr.sll_pkttype == ...) */
+      } /* if (skfd >= 0 && (FD_ISSET...)) */
+} /* EncapFlowInObamp */
+
+//This function is called from olsrd_plugin.c and adds to the list the interfaces specified in the configuration file to sniff multicast traffic
+int AddObampSniffingIf(
+  const char* ifName,
+  void* data __attribute__((unused)),
+  set_plugin_parameter_addon addon __attribute__((unused)))
+{
+
+struct ObampSniffingIf *ifToAdd; 
+
+ OLSR_DEBUG(LOG_PLUGINS,"AddObampSniffingIf");
+
+
+assert(ifName != NULL);
+
+ifToAdd = malloc(sizeof(struct ObampSniffingIf));
+
+  strncpy(ifToAdd->ifName, ifName, 16); //TODO: 16 fix this
+  ifToAdd->ifName[15] = '\0'; /* Ensures null termination */
+
+ OLSR_DEBUG(LOG_PLUGINS,"Adding interface to list");
+
+  list_add(&(ifToAdd->list),&ListOfObampSniffingIf);
+
+  OLSR_DEBUG(LOG_PLUGINS,"Adding if %s to list of ObampSniffingIfaces",ifToAdd->ifName);
+
+  return 0;
+}
+
+
+int PreInitOBAMP(void) {
+ INIT_LIST_HEAD(&ListOfObampSniffingIf);
+return 0;
+
+}
+
+//Start here !!
+
+int InitOBAMP(void)
+{
+struct ipaddr_str buf; //Buffer to print debug to screen
+
+//Structs necessary for timers
+
+struct timer_entry* OBAMP_alive_timer;
+struct timer_entry* purge_nodes_timer;
+struct timer_entry* mesh_create_timer;
+struct timer_entry* tree_create_timer;
+struct timer_entry* outer_tree_create_timer;
+
+
+
+struct olsr_cookie_info *OBAMP_alive_gen_timer_cookie = NULL;
+struct olsr_cookie_info *purge_nodes_timer_cookie = NULL;
+struct olsr_cookie_info *mesh_create_timer_cookie = NULL;
+struct olsr_cookie_info *tree_create_timer_cookie = NULL;
+struct olsr_cookie_info *outer_tree_create_timer_cookie = NULL;
+
+
+//Setting OBAMP node state
+myState = malloc(sizeof(struct ObampNodeState));
+myState->iamcore = 1;
+myState->TreeHeartBeat=0;
+memcpy(&myState->myipaddr.v4,&olsr_cnf->router_id, olsr_cnf->ipsize);
+myState->CoreAddress = myState->myipaddr;
+
+myState->DataSequenceNumber=0;
+myState->TreeCreateSequenceNumber = 0;
+myState->tree_req_sn=0; //TODO: start from random number ?
+
+       memset(&myState->ParentId.v4,0,sizeof(myState->ParentId.v4));
+       memset(&myState->OldParentId.v4,1,sizeof(myState->OldParentId.v4));
+
+OLSR_DEBUG(LOG_PLUGINS,"SETUP: my IP - %s",ip4_to_string(&buf,myState->myipaddr.v4));
+
+INIT_LIST_HEAD(&ListOfObampNodes);
+
+//OLSR cookies stuff for timers
+OBAMP_alive_gen_timer_cookie = olsr_alloc_cookie("OBAMP Alive Generation", OLSR_COOKIE_TYPE_TIMER);
+purge_nodes_timer_cookie = olsr_alloc_cookie("purge nodes Generation", OLSR_COOKIE_TYPE_TIMER);
+mesh_create_timer_cookie = olsr_alloc_cookie("mesh create Generation", OLSR_COOKIE_TYPE_TIMER);
+tree_create_timer_cookie = olsr_alloc_cookie("tree create Generation", OLSR_COOKIE_TYPE_TIMER);
+outer_tree_create_timer_cookie = olsr_alloc_cookie("outer tree create Generation", OLSR_COOKIE_TYPE_TIMER);
+
+
+//Tells OLSR to launch olsr_parser when the packets for this plugin arrive
+olsr_parser_add_function(&olsr_parser, PARSER_TYPE);
+
+// start to send alive messages to appear in other joined lists
+OBAMP_alive_timer = olsr_start_timer(OBAMP_ALIVE_EIVAL * MSEC_PER_SEC,OBAMP_JITTER, OLSR_TIMER_PERIODIC, &obamp_alive_gen, NULL, OBAMP_alive_gen_timer_cookie);
+
+// start timer to purge nodes from list in softstate fashion
+purge_nodes_timer = olsr_start_timer(_Texpire_timer_ * MSEC_PER_SEC,OBAMP_JITTER, OLSR_TIMER_PERIODIC, &purge_nodes, NULL, purge_nodes_timer_cookie);
+
+//start timer to create mesh
+mesh_create_timer = olsr_start_timer(OBAMP_MESH_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC,&mesh_create,NULL,mesh_create_timer_cookie);
+
+//start timer for tree create procedure
+tree_create_timer = olsr_start_timer(OBAMP_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC,&tree_create,NULL,tree_create_timer_cookie);
+
+//start timer for tree create procedure
+outer_tree_create_timer = olsr_start_timer(OBAMP_OUTER_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC,&outer_tree_create,NULL,tree_create_timer_cookie);
+
+
+//Create udp server socket for OBAMP signalling and register it to the scheduler
+OLSR_DEBUG(LOG_PLUGINS,"Launch Udp Servers");
+if ( UdpServer() < 0) {
+OLSR_DEBUG(LOG_PLUGINS,"Problem in Launch Udp Servers");
+
+};
+
+//Creates a socket for sniffing multicast traffic and registers it to the scheduler
+CreateObampSniffingInterfaces();
+
+return 0;
+}         
+
+/* -------------------------------------------------------------------------
+ * Function   : CloseOBAMP
+ * Description: Close the OBAMP plugin and clean up
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  :
+ * ------------------------------------------------------------------------- */
+void
+CloseOBAMP(void)
+{
+//do something here
+}
diff --git a/lib/obamp/src/obamp.h b/lib/obamp/src/obamp.h
new file mode 100644 (file)
index 0000000..171b6ae
--- /dev/null
@@ -0,0 +1,223 @@
+
+/*
+OLSR OBAMP plugin.
+Written by Saverio Proto <zioproto@gmail.com> and Claudio Pisa <clauz@ninux.org>.
+
+    This file is part of OLSR OBAMP PLUGIN.
+
+    The OLSR OBAMP PLUGIN 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 3 of the License, or
+    (at your option) any later version.
+
+    The OLSR OBAMP PLUGIN 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 the OLSR OBAMP PLUGIN.  If not, see <http://www.gnu.org/licenses/>.
+
+ */
+
+
+#ifndef _OBAMP_OBAMP_H
+#define _OBAMP_OBAMP_H
+
+#include "list.h"
+
+#include "plugin.h"             /* union set_plugin_parameter_addon */
+
+#include "parser.h"
+
+#define MESSAGE_TYPE           133                     //TODO: check if this number is ok
+#define PARSER_TYPE            MESSAGE_TYPE
+#define EMISSION_INTERVAL       10                     /* seconds */
+#define EMISSION_JITTER         25                     /* percent */
+#define OBAMP_VALID_TIME       1800                    /* seconds */
+
+/* OBAMP plugin data */
+#define PLUGIN_NAME            "OLSRD OBAMP plugin"
+#define PLUGIN_NAME_SHORT      "OLSRD OBAMP"
+#define PLUGIN_VERSION                 "1.0.0 (" __DATE__ " " __TIME__ ")"
+#define PLUGIN_COPYRIGHT       "  (C) Ninux.org"
+#define PLUGIN_AUTHOR          "  Saverio Proto (zioproto@gmail.com)"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION "\n" PLUGIN_COPYRIGHT "\n" PLUGIN_AUTHOR
+#define PLUGIN_INTERFACE_VERSION 5
+
+#define PLUGIN_DESCR           "OBAMP"
+
+#define OBAMP_JITTER           25                      /* percent */
+#define OBAMP_ALIVE_EIVAL      5
+#define OBAMP_MESH_CREATE_IVAL 5                       //Seconds
+#define OBAMP_TREE_CREATE_IVAL 10                      //seconds
+#define TREE_HEARTBEAT         25                      //seconds
+#define OBAMP_OUTER_TREE_CREATE_IVAL    30             //seconds
+#define _MESH_LOCK_            10                      //seconds
+
+#define _Texpire_              15                       //time in seconds before expire a neighbor
+#define _Texpire_timer_                1                       //time in seconds to parse the list decrement and purge
+
+
+/*OBAMP Protocol MESSAGE IDs */
+
+#define OBAMP_DATA             0
+#define OBAMP_HELLO            1 
+#define OBAMP_TREECREATE       2 
+#define OBAMP_ALIVE            3
+#define OBAMP_TREE_REQ                 4
+#define OBAMP_TREE_ACK                 5
+
+#define OBAMP_SIGNALLING_PORT  6226
+
+
+
+extern struct ObampNodeState* myState; //Internal state of the running OBAMP node
+
+/* Forward declaration of OLSR interface type */
+struct interface;
+
+union olsr_ip_addr *MainAddressOf(union olsr_ip_addr *ip);
+
+void ObampSignalling(int sd, void *x, unsigned int y);
+
+//Gets packets from sniffing interfaces, checks if are multicast, and pushes them to OBAMP tree links
+void EncapFlowInObamp(int sd, void * x, unsigned int y);
+
+//Used to add Sniffing Interfaces read from config file to the list
+int AddObampSniffingIf(const char *ifName, void *data, set_plugin_parameter_addon addon);
+
+
+int InitOBAMP(void);
+int PreInitOBAMP(void);
+void CloseOBAMP(void);
+
+void olsr_obamp_gen(unsigned char *packet, int len);
+
+void obamp_hello_gen(void *para);
+void obamp_alive_gen(void *para);
+void purge_nodes(void *para);
+void mesh_create(void *para);
+void tree_create(void *para);
+void outer_tree_create(void *para);
+
+int addObampNode4(struct in_addr * ipv4, u_int8_t status);
+
+
+/* Parser function to register with the scheduler */
+void olsr_parser(union olsr_message *, struct interface *, union olsr_ip_addr *, enum duplicate_status);
+
+//Struct to describe the other OBAMP nodes in the mesh network
+struct ObampNode {
+
+       union olsr_ip_addr neighbor_ip_addr; //IP address
+
+       int isMesh; //The consider the path from us to this OBAMP node as an overlay mesh link
+       int wasMesh;
+       int outerTreeLink; //I'm using this OBAMP node as an anchor
+       int isTree;//it identifies if it is a link of tree
+       int MeshLock; //Is mesh because requested from neighbor with hello messages
+
+       u_int8_t status; //indicates if this OBAMP node has at least a tree link
+       
+       int Texpire;// TTL to softstate expire
+
+       u_int8_t DataSeqNumber;
+
+       struct list_head list;
+};
+
+//Interfaces of the router not talking OLSR, where we capture the multicast traffic
+struct ObampSniffingIf {
+
+int skd;               //Socket descriptor
+char ifName[16];       //Interface name
+struct list_head list;
+
+};
+
+
+//Internal State of the OBAMP NoDE
+struct ObampNodeState {
+    
+    union olsr_ip_addr myipaddr; //IP ADDRESS
+    union olsr_ip_addr CoreAddress; //CORE IP ADDRESS
+
+    int iamcore; //Indicates if I'm the core
+    
+    u_int8_t TreeCreateSequenceNumber;
+    u_int8_t tree_req_sn;
+    u_int8_t DataSequenceNumber;
+
+    union olsr_ip_addr ParentId;       //Tree link towards the core
+    union olsr_ip_addr OldParentId;
+
+    /*
+       TTL to check if I'm receiving tree_create messages from core
+       if this expires there is a problem with the spanning tree
+
+       */
+    int TreeHeartBeat; 
+};
+
+// OBAMP message types
+
+
+struct OBAMP_data_message {
+
+u_int8_t MessageID;
+union olsr_ip_addr router_id;
+union olsr_ip_addr last_hop;
+u_int8_t SequenceNumber;
+union olsr_ip_addr CoreAddress;
+u_int8_t datalen;
+unsigned char data[1280]; //TODO:fix me
+
+};
+
+struct OBAMP_tree_create {
+
+u_int8_t MessageID;
+union olsr_ip_addr router_id;
+u_int8_t SequenceNumber;
+union olsr_ip_addr CoreAddress;
+
+};
+
+struct OBAMP_tree_link_req {
+
+u_int8_t MessageID;
+union olsr_ip_addr router_id;
+u_int8_t SequenceNumber;
+union olsr_ip_addr CoreAddress;
+};
+
+struct OBAMP_tree_link_ack {
+
+u_int8_t MessageID;
+union olsr_ip_addr router_id;
+u_int8_t SequenceNumber;
+union olsr_ip_addr CoreAddress;
+};
+
+
+struct OBAMP_hello {
+
+u_int8_t MessageID;
+union olsr_ip_addr router_id;
+u_int8_t HelloSequenceNumber;
+union olsr_ip_addr CoreAddress;
+
+};
+
+struct OBAMP_alive {
+
+u_int8_t MessageID;
+u_int8_t status;
+u_int32_t CoreAddress;
+//REMEMBER:Pad to 4 bytes this is a OLSR message
+
+};
+
+#endif /* _OBAMP_OBAMP_H */
+
diff --git a/lib/obamp/src/olsrd_plugin.c b/lib/obamp/src/olsrd_plugin.c
new file mode 100644 (file)
index 0000000..7cf4ea5
--- /dev/null
@@ -0,0 +1,203 @@
+
+/*
+OLSR OBAMP plugin.
+Written by Saverio Proto <zioproto@gmail.com> and Claudio Pisa <clauz@ninux.org>.
+
+    This file is part of OLSR OBAMP PLUGIN.
+
+    The OLSR OBAMP PLUGIN 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 3 of the License, or
+    (at your option) any later version.
+
+    The OLSR OBAMP PLUGIN 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 the OLSR OBAMP PLUGIN.  If not, see <http://www.gnu.org/licenses/>.
+
+
+ */
+
+
+
+/* System includes */
+#include <assert.h>             /* assert() */
+#include <stddef.h>             /* NULL */
+
+/* OLSRD includes */
+#include "plugin.h"
+#include "plugin_loader.h"
+#include "plugin_util.h"
+#include "defs.h"               /* uint8_t, olsr_cnf */
+#include "scheduler.h"          /* olsr_start_timer() */
+#include "olsr_cfg.h"           /* olsr_cnf() */
+#include "olsr_cookie.h"        /* olsr_alloc_cookie() */
+
+/* OBAMP includes */
+#include "obamp.h"               
+#include "list.h"
+
+static void __attribute__ ((constructor)) my_init(void);
+static void __attribute__ ((destructor)) my_fini(void);
+
+static bool obamp_pre_init(void);
+static bool obamp_post_init(void);
+static bool obamp_pre_cleanup(void);
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+
+  { .name = "NonOlsrIf", .set_plugin_parameter = &AddObampSniffingIf, .data = NULL },
+
+};
+
+
+//DEFINE_PLUGIN6(PLUGIN_DESCR, PLUGIN_AUTHOR, obamp_pre_init, olsrd_plugin_init, obamp_pre_cleanup, NULL, true, plugin_parameters)
+
+DEFINE_PLUGIN6(PLUGIN_DESCR, PLUGIN_AUTHOR, obamp_pre_init, obamp_post_init, obamp_pre_cleanup, NULL, true, plugin_parameters)
+
+/**
+ * Constructor of plugin, called before parameters are initialized
+ */
+static bool
+obamp_pre_init(void)
+{
+PreInitOBAMP();
+
+  //return 0;
+  return false;
+}
+
+static bool
+obamp_post_init(void)
+{
+olsrd_plugin_init();
+
+  //return 0;
+  return false;
+}
+
+
+
+/**
+ * Destructor of plugin
+ */
+static bool
+obamp_pre_cleanup(void)
+{
+  //return 0;
+  return false;
+}
+
+
+void olsr_plugin_exit(void);
+
+/* -------------------------------------------------------------------------
+ * Function   : olsrd_plugin_interface_version
+ * Description: Plugin interface version
+ * Input      : none
+ * Output     : none
+ * Return     : OBAMP plugin interface version number
+ * Data Used  : none
+ * Notes      : Called by main OLSRD (olsr_load_dl) to check plugin interface
+ *              version
+ * ------------------------------------------------------------------------- */
+int
+olsrd_plugin_interface_version(void)
+{
+  return PLUGIN_INTERFACE_VERSION;
+
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : olsrd_plugin_init
+ * Description: Plugin initialisation
+ * Input      : none
+ * Output     : none
+ * Return     : fail (0) or success (1)
+ * Data Used  : olsr_cnf
+ * Notes      : Called by main OLSRD (init_olsr_plugin) to initialize plugin
+ * ------------------------------------------------------------------------- */
+int
+olsrd_plugin_init(void)
+{
+  return InitOBAMP();
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : olsr_plugin_exit
+ * Description: Plugin cleanup
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * Notes      : Called by my_fini() at unload of shared object
+ * ------------------------------------------------------------------------- */
+void
+olsr_plugin_exit(void)
+{
+  CloseOBAMP();
+}
+
+
+
+/* -------------------------------------------------------------------------
+ * Function   : olsrd_get_plugin_parameters
+ * Description: Return the parameter table and its size
+ * Input      : none
+ * Output     : params - the parameter table
+ *              size - its size in no. of entries
+ * Return     : none
+ * Data Used  : plugin_parameters
+ * Notes      : Called by main OLSR (init_olsr_plugin) for all plugins
+ * ------------------------------------------------------------------------- */
+void
+olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+  *params = plugin_parameters;
+  *size = ARRAYSIZE(plugin_parameters);
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : my_init
+ * Description: Plugin constructor
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * Notes      : Called at load of shared object
+ * ------------------------------------------------------------------------- */
+static void
+my_init(void)
+{
+  /* Print plugin info to stdout */
+  printf("%s\n", MOD_DESC);
+
+  return;
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : my_fini
+ * Description: Plugin destructor
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * Notes      : Called at unload of shared object
+ * ------------------------------------------------------------------------- */
+static void
+my_fini(void)
+{
+  olsr_plugin_exit();
+}
+
+
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/lib/obamp/version-script.txt b/lib/obamp/version-script.txt
new file mode 100644 (file)
index 0000000..a145659
--- /dev/null
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};