OBAMP: reverting error from previous commit
[olsrd.git] / lib / obamp / src / obamp.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42
43 /* System includes */
44 #include <stddef.h>             /* NULL */
45 #include <sys/types.h>          /* ssize_t */
46 #include <string.h>             /* strerror() */
47 #include <stdarg.h>             /* va_list, va_start, va_end */
48 #include <errno.h>              /* errno */
49 #include <assert.h>             /* assert() */
50 #include <linux/if_ether.h>     /* ETH_P_IP */
51 #include <linux/if_packet.h>    /* struct sockaddr_ll, PACKET_MULTICAST */
52 #include <signal.h>             /* sigset_t, sigfillset(), sigdelset(), SIGINT */
53 #include <netinet/ip.h>         /* struct ip */
54 #include <netinet/udp.h>        /* struct udphdr */
55 #include <unistd.h>             /* close() */
56
57 #include <netinet/in.h>
58 #include <netinet/ip6.h>
59
60 #include <fcntl.h>              /* fcntl() */
61
62 /* OLSRD includes */
63 #include "plugin_util.h"        /* set_plugin_int */
64 #include "defs.h"               /* olsr_cnf, //OLSR_PRINTF */
65 #include "ipcalc.h"
66 #include "olsr.h"               /* //OLSR_PRINTF */
67 #include "mid_set.h"            /* mid_lookup_main_addr() */
68 #include "link_set.h"           /* get_best_link_to_neighbor() */
69 #include "net_olsr.h"           /* ipequal */
70 #include "olsr_logging.h"
71
72 /* plugin includes */
73 #include "obamp.h"
74 #include "list.h"
75
76
77 struct ObampNodeState *myState;        //Internal state of the OBAMP node
78
79 /*
80 List of all other OBAMP nodes
81 if there is a mesh link the isMesh flag is set to 1
82 if the link is used in the distribution tree the isTree flag is set to 1
83 */
84 struct list_head ListOfObampNodes;
85
86 //List of Non OLSR Interfaces to capture and send multicast traffic to
87 struct list_head ListOfObampSniffingIf;
88
89 //udp socket used for OBAMP signalling
90 int sdudp = -1;
91
92 /*
93 When Outer Tree Create is triggered, a OBAMP node uses this function to
94 determine the closer OBAMP node that has a TreeLink
95 */
96 static struct ObampNode *
97 select_tree_anchor(void)
98 {
99
100   struct ObampNode *tmp;               //temp pointers used when parsing the list
101   struct ObampNode *best;
102   struct list_head *pos;
103
104   struct rt_entry *rt;                 //"rt->rt_best->rtp_metric.cost" is the value you are looking for, a 32 bit
105
106   unsigned int mincost = 15;
107
108   best = NULL;
109
110   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
111
112     //Scroll the list
113     list_for_each(pos, &ListOfObampNodes) {     //loop to update min cost
114
115       tmp = list_entry(pos, struct ObampNode, list);
116       if (tmp->status == 1) {
117         rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
118
119         if (rt == NULL) {       //route is not present yet
120           OLSR_DEBUG(LOG_PLUGINS, "No route present to this anchor");
121           continue;
122         }
123         //update best neighbor
124         if ((rt->rt_best->rtp_metric.cost / 65536) < mincost)
125           best = tmp;
126       }
127     }
128     return best;
129
130   } else {
131     OLSR_DEBUG(LOG_PLUGINS, "List empty can't create Overlay Mesh");
132   }
133   return NULL;
134
135 }
136
137 //Creates a OBAMP_DATA message and sends it to the specified destination
138 static int
139 SendOBAMPData(struct in_addr *addr, unsigned char *ipPacket, int nBytes)
140 {
141
142   struct sockaddr_in si_other;
143   struct OBAMP_data_message4 data_msg;
144
145   memset(&data_msg, 0, sizeof(data_msg));
146   data_msg.MessageID = OBAMP_DATA;
147   data_msg.router_id = (u_int32_t) myState->myipaddr.v4.s_addr;
148   data_msg.last_hop = (u_int32_t) myState->myipaddr.v4.s_addr;
149
150   data_msg.CoreAddress = (u_int32_t) myState->CoreAddress.v4.s_addr;
151
152   data_msg.SequenceNumber = myState->DataSequenceNumber;
153   myState->DataSequenceNumber++;
154
155   if (nBytes >= 1471) {
156     OLSR_DEBUG(LOG_PLUGINS, "PACKET DROPPED: %d bytes are too much",nBytes);
157     return 1;
158   }
159
160   memcpy(data_msg.data, ipPacket, nBytes);
161
162   data_msg.datalen = nBytes;
163
164   memset((char *)&si_other, 0, sizeof(si_other));
165   si_other.sin_family = AF_INET;
166   si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
167   si_other.sin_addr = *addr;
168   //sendto(sdudp, data_msg, sizeof(struct OBAMP_data_message), 0, (struct sockaddr *)&si_other, sizeof(si_other));
169   //TODO: this 17 magic number is okay only for IPv4, we do not worry about this now
170   sendto(sdudp, &data_msg, 17+data_msg.datalen, 0, (struct sockaddr *)&si_other, sizeof(si_other));
171   return 0;
172
173 }
174
175 static int
176 CreateCaptureSocket(const char *ifName)
177 {
178   int ifIndex = if_nametoindex(ifName);
179   struct packet_mreq mreq;
180   struct ifreq req;
181   struct sockaddr_ll bindTo;
182   int skfd = 0;
183
184   /* Open cooked IP packet socket */
185   if (olsr_cnf->ip_version == AF_INET) {
186     skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
187   } else {
188     skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
189   }
190   if (skfd < 0) {
191     OLSR_DEBUG(LOG_PLUGINS, "socket(PF_PACKET) error");
192     return -1;
193   }
194
195   /* Set interface to promiscuous mode */
196   memset(&mreq, 0, sizeof(struct packet_mreq));
197   mreq.mr_ifindex = ifIndex;
198   mreq.mr_type = PACKET_MR_PROMISC;
199   if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
200     OLSR_DEBUG(LOG_PLUGINS, "setsockopt(PACKET_MR_PROMISC) error");
201     close(skfd);
202     return -1;
203   }
204
205   /* Get hardware (MAC) address */
206   memset(&req, 0, sizeof(struct ifreq));
207   strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
208   req.ifr_name[IFNAMSIZ - 1] = '\0';    /* Ensures null termination */
209   if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0) {
210     OLSR_DEBUG(LOG_PLUGINS, "error retrieving MAC address");
211     close(skfd);
212     return -1;
213   }
214
215   /* Bind the socket to the specified interface */
216   memset(&bindTo, 0, sizeof(bindTo));
217   bindTo.sll_family = AF_PACKET;
218   if (olsr_cnf->ip_version == AF_INET) {
219     bindTo.sll_protocol = htons(ETH_P_IP);
220   } else {
221     bindTo.sll_protocol = htons(ETH_P_IPV6);
222   }
223   bindTo.sll_ifindex = ifIndex;
224   memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
225   bindTo.sll_halen = IFHWADDRLEN;
226
227   if (bind(skfd, (struct sockaddr *)&bindTo, sizeof(bindTo)) < 0) {
228     OLSR_DEBUG(LOG_PLUGINS, "bind() error");
229     close(skfd);
230     return -1;
231   }
232
233   /* Set socket to blocking operation */
234   if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0) {
235     OLSR_DEBUG(LOG_PLUGINS, "fcntl() error");
236     close(skfd);
237     return -1;
238   }
239
240   add_olsr_socket(skfd, &EncapFlowInObamp, NULL, NULL, SP_PR_READ);
241
242   return skfd;
243 }                               /* CreateCaptureSocket */
244
245
246 static int
247 CreateObampSniffingInterfaces(void)
248 {
249
250   struct ObampSniffingIf *tmp;
251   struct list_head *pos;
252
253   OLSR_DEBUG(LOG_PLUGINS, "CreateObampSniffingInterfaces");
254
255
256   if (list_empty(&ListOfObampSniffingIf) == 0) {        //if the list is NOT empty
257     OLSR_DEBUG(LOG_PLUGINS, "adding interfaces");
258
259     list_for_each(pos, &ListOfObampSniffingIf) {
260
261       tmp = list_entry(pos, struct ObampSniffingIf, list);
262       tmp->skd = CreateCaptureSocket(tmp->ifName);
263     }
264   } else
265     OLSR_DEBUG(LOG_PLUGINS, "List of sniffin interfaces was empty");
266
267
268   return 0;
269 }
270
271
272 static int
273 IsMulticast(union olsr_ip_addr *ipAddress)
274 {
275   assert(ipAddress != NULL);
276
277   return (ntohl(ipAddress->v4.s_addr) & 0xF0000000) == 0xE0000000;
278 }
279
280
281
282 static void
283 activate_tree_link(struct OBAMP_tree_link_ack *ack)
284 {
285 #if !defined(REMOVE_LOG_DEBUG)
286   struct ipaddr_str buf;
287 #endif
288   struct ObampNode *tmp;
289   struct list_head *pos;
290
291   if (memcmp(&myState->CoreAddress.v4, &ack->CoreAddress.v4, sizeof(struct in_addr)) != 0) {
292     OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
293     return;
294   }
295
296   if (ack->SequenceNumber != myState->tree_req_sn - 1) {
297
298     OLSR_DEBUG(LOG_PLUGINS, "ACK DISCARDED WRONG SEQ NUMBER");
299     return;
300   } else {
301
302     list_for_each(pos, &ListOfObampNodes) {
303
304       tmp = list_entry(pos, struct ObampNode, list);
305       if (tmp->neighbor_ip_addr.v4.s_addr == ack->router_id.v4.s_addr) {
306
307         tmp->isTree = 1;
308         myState->TreeHeartBeat = TREE_HEARTBEAT;
309         OLSR_DEBUG(LOG_PLUGINS, "Tree link to %s activated", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
310         return;
311
312       }
313     }
314   }
315
316 }
317
318
319
320 /*
321 When we select a other OBAMP node as a overlay neighbor, we start to send HELLOs to him
322 to inform we are using the unicast path from us to him  as a overlay mesh link
323 */
324 static void
325 obamp_hello(struct in_addr *addr)
326 {
327
328   struct OBAMP_hello hello;
329   struct sockaddr_in si_other;
330
331   memset(&hello, 0, sizeof(hello));
332   hello.MessageID = OBAMP_HELLO;
333   //TODO: refresh IP address
334   hello.router_id = myState->myipaddr;
335   hello.CoreAddress = myState->CoreAddress;
336
337   //TODO: implement sequence number
338   //hello->HelloSequenceNumber = myState->something;
339   //myState->something++;
340
341   memset((char *)&si_other, 0, sizeof(si_other));
342   si_other.sin_family = AF_INET;
343   si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
344   si_other.sin_addr = *addr;
345   sendto(sdudp, &hello, sizeof(struct OBAMP_hello), 0, (struct sockaddr *)&si_other, sizeof(si_other));
346 }
347
348
349 //Destroy a Tree Link
350 static void
351 send_destroy_tree_link(struct in_addr *addr)
352 {
353   struct OBAMP_tree_destroy msg;
354   struct sockaddr_in si_other;
355   #if !defined(REMOVE_LOG_DEBUG)
356   struct ipaddr_str buf;
357   #endif
358  
359
360   OLSR_DEBUG(LOG_PLUGINS, "Sending tree destroy to: %s", ip4_to_string(&buf, *addr));
361  
362   memset(&msg, 0, sizeof(msg));
363   msg.MessageID = OBAMP_TREE_DESTROY;
364   //TODO: refresh IP address
365   msg.router_id = myState->myipaddr;
366   msg.CoreAddress = myState->CoreAddress;
367
368   memset((char *)&si_other, 0, sizeof(si_other));
369   si_other.sin_family = AF_INET;
370   si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
371   si_other.sin_addr = *addr;
372   sendto(sdudp, &msg, sizeof(struct OBAMP_tree_destroy), 0, (struct sockaddr *)&si_other, sizeof(si_other));
373 }
374
375
376 //Request a Tree Link
377 static void
378 tree_link_req(struct in_addr *addr)
379 {
380   if (myState->TreeRequestDelay == 0) { 
381   struct OBAMP_tree_link_req req;
382   struct sockaddr_in si_other;
383   #if !defined(REMOVE_LOG_DEBUG)
384   struct ipaddr_str buf;
385   #endif
386  
387
388   OLSR_DEBUG(LOG_PLUGINS, "Sending tree request to: %s", ip4_to_string(&buf, *addr));
389  
390   memset(&req, 0, sizeof(req));
391   req.MessageID = OBAMP_TREE_REQ;
392   //TODO: refresh IP address
393   req.router_id = myState->myipaddr;
394   req.CoreAddress = myState->CoreAddress;
395
396   req.SequenceNumber = myState->tree_req_sn;
397   myState->tree_req_sn++;
398
399   memset((char *)&si_other, 0, sizeof(si_other));
400   si_other.sin_family = AF_INET;
401   si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
402   si_other.sin_addr = *addr;
403   myState->TreeRequestDelay=_TREE_REQUEST_DELAY_;
404   sendto(sdudp, &req, sizeof(struct OBAMP_tree_link_req), 0, (struct sockaddr *)&si_other, sizeof(si_other));
405 }
406 else OLSR_DEBUG(LOG_PLUGINS,"Do not send Tree Link Request because there is another one running");
407 }
408
409 static void
410 tree_link_ack(struct OBAMP_tree_link_req *req)
411 {
412
413   struct sockaddr_in si_other;
414   struct in_addr addr;
415
416   struct ObampNode *tmp;
417   struct list_head *pos;
418 #if !defined(REMOVE_LOG_DEBUG)
419   struct ipaddr_str buf;
420 #endif
421
422   struct OBAMP_tree_link_ack ack;
423
424   //Check Core Address
425   if (memcmp(&myState->CoreAddress.v4, &req->CoreAddress.v4, sizeof(struct in_addr)) != 0) {
426     OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
427     return;
428   }
429   //TODO: other checks ?
430
431
432   memset(&ack, 0, sizeof(ack));
433   ack.MessageID = OBAMP_TREE_ACK;
434   //TODO: refresh IP address
435   ack.router_id = myState->myipaddr;
436   ack.CoreAddress = myState->CoreAddress;
437
438   ack.SequenceNumber = req->SequenceNumber;
439
440   addr = req->router_id.v4;
441
442   list_for_each(pos, &ListOfObampNodes) {
443
444     tmp = list_entry(pos, struct ObampNode, list);
445     if (tmp->neighbor_ip_addr.v4.s_addr == req->router_id.v4.s_addr) {
446
447       tmp->isTree = 1;
448       OLSR_DEBUG(LOG_PLUGINS, "Tree link to %s activated", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
449       break;
450     }
451   }
452
453   memset((char *)&si_other, 0, sizeof(si_other));
454   si_other.sin_family = AF_INET;
455   si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
456   si_other.sin_addr = addr;
457   sendto(sdudp, &ack, sizeof(struct OBAMP_tree_link_req), 0, (struct sockaddr *)&si_other, sizeof(si_other));
458 }
459
460
461 static void
462 init_overlay_neighbor(struct ObampNode *n)
463 {
464
465   n->Texpire = _Texpire_;       //If this value expires the OBAMP node is removed from the list
466   n->isMesh = 0;
467   n->wasMesh = 0;
468   n->MeshLock = 0;
469   n->isTree = 0;
470   n->outerTreeLink = 0;
471   n->DataSeqNumber = 0;
472 }
473
474 static void
475 tree_create_forward_to(struct in_addr *addr, struct OBAMP_tree_create *mytc)
476 {
477
478   struct sockaddr_in si_other;
479   struct OBAMP_tree_create temptc;
480
481   memset(&temptc, 0, sizeof(temptc));
482   memcpy(&temptc, mytc, sizeof(struct OBAMP_tree_create));
483
484   //Check Core Address
485   if (memcmp(&myState->CoreAddress.v4, &temptc.CoreAddress.v4, sizeof(struct in_addr)) != 0) {
486     OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
487     return;
488   }
489   //Update router id
490   temptc.router_id = myState->myipaddr;
491
492   memset((char *)&si_other, 0, sizeof(si_other));
493   si_other.sin_family = AF_INET;
494   si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
495   si_other.sin_addr = *addr;
496
497   sendto(sdudp, &temptc, sizeof(struct OBAMP_tree_create), 0, (struct sockaddr *)&si_other, sizeof(si_other));
498 }
499
500 static void
501 tree_create_gen(struct in_addr *addr)
502 {
503   struct OBAMP_tree_create mytc;
504   struct sockaddr_in si_other;
505
506   OLSR_DEBUG(LOG_PLUGINS, "Calling tree_create_gen\n");
507
508   memset(&mytc, 0, sizeof(mytc));
509   mytc.MessageID = OBAMP_TREECREATE;
510   mytc.router_id = myState->myipaddr;
511   mytc.CoreAddress = myState->CoreAddress;
512   myState->TreeCreateSequenceNumber++;
513   mytc.SequenceNumber = myState->TreeCreateSequenceNumber;
514
515   memset((char *)&si_other, 0, sizeof(si_other));
516   si_other.sin_family = AF_INET;
517   si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
518   si_other.sin_addr = *addr;
519   sendto(sdudp, &mytc, sizeof(struct OBAMP_tree_create), 0, (struct sockaddr *)&si_other, sizeof(si_other));
520 }
521
522
523 static void
524 printObampNodesList(void)
525 {
526
527   int i = 1;
528 #if !defined(REMOVE_LOG_DEBUG)
529   struct ipaddr_str buf;
530 #endif
531   struct ObampNode *tmp;
532   struct list_head *pos;
533
534   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
535
536
537     OLSR_DEBUG(LOG_PLUGINS, "--------------------NODE STATUS---------");
538     OLSR_DEBUG(LOG_PLUGINS, "---Current Core: %s", ip4_to_string(&buf, myState->CoreAddress.v4));
539     OLSR_DEBUG(LOG_PLUGINS, "---Current Parent: %s", ip4_to_string(&buf, myState->ParentId.v4));
540
541
542     OLSR_DEBUG(LOG_PLUGINS, "Number \t IP \t\t IsMesh \t IsTree \t MeshLock \t outerTreeLink");
543
544     list_for_each(pos, &ListOfObampNodes) {
545
546       tmp = list_entry(pos, struct ObampNode, list);
547
548       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),
549                  tmp->isMesh, tmp->isTree, tmp->MeshLock, tmp->outerTreeLink);
550
551       i++;
552     }
553     OLSR_DEBUG(LOG_PLUGINS, "----------------------------------------");
554
555   }
556 }
557
558 static int
559 DoIHaveATreeLink(void)
560 {
561
562   //struct ipaddr_str buf;
563   struct ObampNode *tmp;
564   struct list_head *pos;
565
566   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
567
568     list_for_each(pos, &ListOfObampNodes) {
569
570       tmp = list_entry(pos, struct ObampNode, list);
571       if (tmp->isTree == 1)
572         return 1;
573
574     }
575   }
576   return 0;
577 }
578
579 static int
580 DoIHaveAMeshLink(void)
581 {
582
583   //struct ipaddr_str buf;
584   struct ObampNode *tmp;
585   struct list_head *pos;
586
587   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
588
589     list_for_each(pos, &ListOfObampNodes) {
590
591       tmp = list_entry(pos, struct ObampNode, list);
592       if (tmp->isMesh == 1)
593         return 1;
594
595     }
596   }
597   return 0;
598 }
599
600 static void
601 reset_tree_links(void)
602 {
603
604   //struct ipaddr_str buf;
605   struct ObampNode *tmp;
606   struct list_head *pos;
607
608   OLSR_DEBUG(LOG_PLUGINS,"Reset Tree Links Now");
609   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
610
611     list_for_each(pos, &ListOfObampNodes) {
612
613       tmp = list_entry(pos, struct ObampNode, list);
614       tmp->isTree = 0;
615       tmp->outerTreeLink = 0;
616     }
617   }
618
619   memset(&myState->ParentId.v4, 0, sizeof(myState->ParentId.v4));
620   memset(&myState->OldParentId.v4, 1, sizeof(myState->OldParentId.v4));
621   myState->TreeCreateSequenceNumber=0;
622
623
624 };
625
626
627 //I received a request to deactivate a tree link
628 static void
629 deactivate_tree_link(struct OBAMP_tree_destroy *destroy_msg)
630 {
631 #if !defined(REMOVE_LOG_DEBUG)
632   struct ipaddr_str buf;
633 #endif
634   struct ObampNode *tmp;
635   struct list_head *pos;
636
637   if (memcmp(&myState->CoreAddress.v4, &destroy_msg->CoreAddress.v4, sizeof(struct in_addr)) != 0) {
638     OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
639     return;
640   }
641
642     list_for_each(pos, &ListOfObampNodes) {
643
644       tmp = list_entry(pos, struct ObampNode, list);
645       if (tmp->neighbor_ip_addr.v4.s_addr == destroy_msg->router_id.v4.s_addr) {
646
647         tmp->isTree = 0;
648         OLSR_DEBUG(LOG_PLUGINS, "Tree link to %s deactivated", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
649         
650         if (memcmp(&tmp->neighbor_ip_addr.v4, &myState->ParentId.v4, sizeof(struct in_addr)) == 0) {
651                 OLSR_DEBUG(LOG_PLUGINS,"RESET TREE LINKS: I lost tree link with my PARENT");
652                 reset_tree_links();
653         }
654
655         return;
656
657       }
658     }
659
660 }
661
662 //Core Election. The Core is the one with the smallest IP Address
663 static void
664 CoreElection(void)
665 {
666 #if !defined(REMOVE_LOG_DEBUG)
667   struct ipaddr_str buf;
668 #endif
669   struct ObampNode *tmp;
670   struct list_head *pos;
671   u_int32_t smallestIP = 0xFFFFFFFF;
672
673   //Update my current IP address
674   memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
675
676   OLSR_DEBUG(LOG_PLUGINS, "SETUP: my IP - %s", ip4_to_string(&buf, myState->myipaddr.v4));
677
678
679   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
680
681     list_for_each(pos, &ListOfObampNodes) {
682
683       tmp = list_entry(pos, struct ObampNode, list);
684       if (tmp->neighbor_ip_addr.v4.s_addr < smallestIP) {
685
686         smallestIP = tmp->neighbor_ip_addr.v4.s_addr;
687         OLSR_DEBUG(LOG_PLUGINS, "CoreElection: current smallest IP is - %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
688
689       };
690     }
691     //Check if I'm the core.
692
693     if (myState->myipaddr.v4.s_addr < smallestIP) {     //I'm the core
694
695       if (myState->myipaddr.v4.s_addr == myState->CoreAddress.v4.s_addr) {      //I'm was already the core
696         return;
697       } else {                  //I'm becoming core
698
699         myState->CoreAddress = myState->myipaddr;
700         myState->iamcore = 1;
701         myState->TreeCreateSequenceNumber = 0;
702         OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
703         reset_tree_links();
704         OLSR_DEBUG(LOG_PLUGINS, "I'm the core");
705       }
706     } else {
707       if (myState->CoreAddress.v4.s_addr == smallestIP) {       //the core did not change
708         return;
709       } else {                  //core changed
710         myState->iamcore = 0;
711         myState->CoreAddress.v4.s_addr = smallestIP;
712         OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
713         reset_tree_links();
714         OLSR_DEBUG(LOG_PLUGINS, "CoreElection: current Core is - %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
715       }
716     }
717
718   }
719
720   else {                        //List is empty I'm the core
721     OLSR_DEBUG(LOG_PLUGINS, "CoreElection: I'm alone I'm the core");
722     myState->CoreAddress = myState->myipaddr;
723     myState->iamcore = 1;
724     myState->TreeCreateSequenceNumber = 0;
725     OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
726     reset_tree_links();
727
728
729
730   }
731
732 }
733
734 //Starts a UDP listening port for OBAMP signalling
735 static int
736 UdpServer(void)
737 {
738
739   struct sockaddr_in addr;
740
741
742   if ((sdudp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
743     OLSR_DEBUG(LOG_PLUGINS, "Socket UDP error");
744     return -1;
745   }
746
747   memset((void *)&addr, 0, sizeof(addr));       /* clear server address */
748   addr.sin_family = AF_INET;    /* address type is INET */
749   addr.sin_port = htons(OBAMP_SIGNALLING_PORT);
750   addr.sin_addr.s_addr = htonl(INADDR_ANY);     /* connect from anywhere */
751   /* bind socket */
752   if (bind(sdudp, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
753     OLSR_DEBUG(LOG_PLUGINS, "Socket UDP BIND error");
754     return (-1);
755   }
756
757   add_olsr_socket(sdudp, &ObampSignalling, NULL, NULL, SP_PR_READ);
758
759   return 0;
760
761 }
762
763 static void
764 decap_data(char *buffer)
765 {
766
767   //struct ipaddr_str buf; //buf to print debug infos
768   struct ObampSniffingIf *tmp;         //temp pointers used when parsing the list
769   struct list_head *pos;
770   unsigned char *ipPacket;
771   int stripped_len;
772   struct ip *ipHeader;
773   struct ip6_hdr *ip6Header;
774   struct OBAMP_data_message4 *msg;
775   int nBytesWritten;
776   struct sockaddr_ll dest;
777   msg = (struct OBAMP_data_message4 *)buffer;
778
779   ipPacket = msg->data;
780
781   ipHeader = (struct ip *)ipPacket;
782   ip6Header = (struct ip6_hdr *)ipPacket;
783
784
785   if (list_empty(&ListOfObampSniffingIf) == 0) {        //if the list is NOT empty
786 //OLSR_DEBUG(LOG_PLUGINS,"DECAP DATA");
787
788     list_for_each(pos, &ListOfObampSniffingIf) {
789
790       tmp = list_entry(pos, struct ObampSniffingIf, list);
791       //tmp->skd = CreateCaptureSocket(tmp->ifName);
792
793
794
795       memset(&dest, 0, sizeof(dest));
796       dest.sll_family = AF_PACKET;
797       if ((ipPacket[0] & 0xf0) == 0x40) {
798         dest.sll_protocol = htons(ETH_P_IP);
799         stripped_len = ntohs(ipHeader->ip_len);
800       }
801       if ((ipPacket[0] & 0xf0) == 0x60) {
802         dest.sll_protocol = htons(ETH_P_IPV6);
803         stripped_len = 40 + ntohs(ip6Header->ip6_plen); //IPv6 Header size (40) + payload_len
804       }
805       //TODO: if packet is not IP die here
806
807
808       dest.sll_ifindex = if_nametoindex(tmp->ifName);
809       dest.sll_halen = IFHWADDRLEN;
810
811       /* Use all-ones as destination MAC address. When the IP destination is
812        * a multicast address, the destination MAC address should normally also
813        * be a multicast address. E.g., when the destination IP is 224.0.0.1,
814        * the destination MAC should be 01:00:5e:00:00:01. However, it does not
815        * seem to matter when the destination MAC address is set to all-ones
816        * in that case. */
817       memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
818
819       nBytesWritten = sendto(tmp->skd, ipPacket, stripped_len, 0, (struct sockaddr *)&dest, sizeof(dest));
820       if (nBytesWritten != stripped_len) {
821         OLSR_DEBUG(LOG_PLUGINS, "sendto() error forwarding unpacked encapsulated pkt on \"%s\"", tmp->ifName);
822       } else {
823
824         OLSR_DEBUG(LOG_PLUGINS, "OBAMP: --> unpacked and forwarded on \"%s\"\n", tmp->ifName);
825       }
826
827
828     }
829   }
830
831 }
832
833
834
835 static int
836 CheckDataFromTreeLink(char *buffer)
837 {
838
839   struct ObampNode *tmp;               //temp pointers used when parsing the list
840   struct list_head *pos;
841   struct OBAMP_data_message4 *data_msg;
842
843   data_msg = (struct OBAMP_data_message4 *)buffer;
844
845   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
846
847     //Scroll the list
848     list_for_each(pos, &ListOfObampNodes) {
849       tmp = list_entry(pos, struct ObampNode, list);
850       //Scroll the list until we find the entry relative to the last hop of the packet we are processing
851       if (memcmp(&tmp->neighbor_ip_addr.v4, &data_msg->last_hop, sizeof(struct in_addr)) == 0) {
852
853         if (tmp->isTree == 1) {  //OK we receive data from a neighbor that we have a tree link with
854           return 1;
855         }
856
857         else{
858           OLSR_DEBUG(LOG_PLUGINS, "DISCARDING DATA PACKET SENT BY NOT TREE NEIGHBOR");
859           send_destroy_tree_link(&tmp->neighbor_ip_addr.v4);
860           return 0;
861         }
862       }
863     }
864   }
865
866   return 0;
867
868 }
869
870
871 static int
872 CheckDupData(char *buffer)
873 {
874
875   struct ObampNode *tmp;               //temp pointers used when parsing the list
876   struct list_head *pos;
877   struct OBAMP_data_message4 *data_msg;
878
879   data_msg = (struct OBAMP_data_message4 *)buffer;
880
881
882   //Check duplicate data packet
883   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
884
885     //Scroll the list
886     list_for_each(pos, &ListOfObampNodes) {
887       tmp = list_entry(pos, struct ObampNode, list);
888
889       if (memcmp(&tmp->neighbor_ip_addr.v4, &data_msg->router_id, sizeof(struct in_addr)) == 0) {
890
891         OLSR_DEBUG(LOG_PLUGINS, "Processing Data Packet %d - Last seen was %d",data_msg->SequenceNumber, tmp->DataSeqNumber);
892         
893         if (tmp->DataSeqNumber == 0) {  //First packet received from this host
894           tmp->DataSeqNumber = data_msg->SequenceNumber;
895           return 1;
896         }
897
898         if ( ((data_msg->SequenceNumber > tmp->DataSeqNumber) && ((data_msg->SequenceNumber - tmp->DataSeqNumber ) <= 127)) || ((tmp->DataSeqNumber > data_msg->SequenceNumber) && ((tmp->DataSeqNumber - data_msg->SequenceNumber) > 127 ))) //data_msg->SequenceNumber > tmp->DataSeqNumber
899         {
900         tmp->DataSeqNumber = data_msg->SequenceNumber;
901         return 1;
902         }
903         else{
904           OLSR_DEBUG(LOG_PLUGINS, "DISCARDING DUP PACKET");
905           return 0;
906         }
907       }
908     }
909   }
910
911   return 1;
912
913 }
914
915 static void
916 forward_obamp_data(char *buffer)
917 {
918
919 #if !defined(REMOVE_LOG_DEBUG)
920   struct ipaddr_str buf;
921   struct ipaddr_str buf2;
922 #endif
923   struct ObampNode *tmp;               //temp pointers used when parsing the list
924   struct list_head *pos;
925   struct OBAMP_data_message4 *data_msg;
926   struct sockaddr_in si_other;
927   struct in_addr temporary;
928
929
930   data_msg = (struct OBAMP_data_message4 *)buffer;
931   temporary.s_addr  = data_msg->last_hop;
932   data_msg->last_hop = myState->myipaddr.v4.s_addr;
933
934   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
935
936     //Scroll the list
937     list_for_each(pos, &ListOfObampNodes) {
938       tmp = list_entry(pos, struct ObampNode, list);
939
940       if (tmp->isTree == 1 && memcmp(&tmp->neighbor_ip_addr.v4, &temporary.s_addr, 4) != 0) {
941         OLSR_DEBUG(LOG_PLUGINS, "FORWARDING OBAMP DATA TO node %s because come from %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4), ip4_to_string(&buf2,temporary));
942         //FORWARD DATA
943
944
945         memset((char *)&si_other, 0, sizeof(si_other));
946         si_other.sin_family = AF_INET;
947         si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
948         si_other.sin_addr = tmp->neighbor_ip_addr.v4;
949         //sendto(sdudp, data_msg, sizeof(struct OBAMP_data_message), 0, (struct sockaddr *)&si_other, sizeof(si_other));
950         sendto(sdudp, data_msg, 17+data_msg->datalen, 0, (struct sockaddr *)&si_other, sizeof(si_other));
951
952
953       }
954     }
955   }
956
957 }
958
959
960 static void
961 manage_hello(char *packet)
962 {
963
964   struct OBAMP_hello *hello;
965
966   struct ObampNode *tmp;               //temp pointers used when parsing the list
967   struct list_head *pos;
968
969   hello = (struct OBAMP_hello *)packet;
970
971   //FIRST OF ALL CHECK CORE
972   if (memcmp(&myState->CoreAddress.v4, &hello->CoreAddress.v4, sizeof(struct in_addr)) != 0) {
973     OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
974     return;
975   }
976
977   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
978
979     //Scroll the list
980     list_for_each(pos, &ListOfObampNodes) {
981       tmp = list_entry(pos, struct ObampNode, list);
982
983       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
984
985         tmp->isMesh = 1;
986         tmp->MeshLock = _MESH_LOCK_;
987
988       }
989     }
990   } else {
991     OLSR_DEBUG(LOG_PLUGINS, "Very strange, list cannot be empty here !");
992   }
993
994 }
995
996 static void
997 manage_tree_create(char *packet)
998 {
999
1000   struct OBAMP_tree_create *msg;
1001
1002 #if !defined(REMOVE_LOG_DEBUG)
1003   struct ipaddr_str buf;
1004   struct ipaddr_str buf2;              //buf to print debug infos
1005 #endif
1006
1007   struct ObampNode *tmp;               //temp pointers used when parsing the list
1008   struct list_head *pos;
1009   OLSR_DEBUG(LOG_PLUGINS,"manage_tree_create");
1010   msg = (struct OBAMP_tree_create *)packet;
1011
1012   if (msg->MessageID != OBAMP_TREECREATE) {
1013     OLSR_DEBUG(LOG_PLUGINS, "BIG PROBLEM, I'M IN THIS FUNCTION BUT MESSAGE IS NOT TREE CREATE");
1014   }
1015
1016   else {
1017     //FIRST OF ALL CHECK CORE
1018     if (memcmp(&myState->CoreAddress.v4, &msg->CoreAddress.v4, sizeof(struct in_addr)) != 0) {
1019       OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
1020       return;
1021     }
1022     if (myState->iamcore == 1) {        //I'm core and receiving tree create over a loop
1023       return;
1024     } else {
1025
1026
1027       if ( (((msg->SequenceNumber > myState->TreeCreateSequenceNumber) && ((msg->SequenceNumber - myState->TreeCreateSequenceNumber ) <= 127)) || ((myState->TreeCreateSequenceNumber > msg->SequenceNumber) && ((myState->TreeCreateSequenceNumber - msg->SequenceNumber) > 127 ))    /*myState->TreeCreateSequenceNumber < msg->SequenceNumber*/) || myState->TreeCreateSequenceNumber == 0 ) {    //If tree create is not a duplicate
1028         OLSR_DEBUG(LOG_PLUGINS, "myState->TreeCreateSequenceNumber < msg->SequenceNumber --- %d < %d",myState->TreeCreateSequenceNumber,msg->SequenceNumber);
1029         myState->TreeCreateSequenceNumber = msg->SequenceNumber;
1030
1031         //A bug was fixed here a battlemeshv3
1032         //myState->OldParentId.v4 = myState->ParentId.v4;
1033         //myState->ParentId.v4 = msg->router_id.v4;
1034
1035         //if (memcmp(&myState->OldParentId.v4, &myState->ParentId.v4, sizeof(struct in_addr)) != 0)       //If it changed
1036         if (memcmp(&msg->router_id.v4, &myState->ParentId.v4, sizeof(struct in_addr)) != 0)       //If it changed
1037         {
1038           OLSR_DEBUG(LOG_PLUGINS, "Receiving a tree message from a link that is not parent");
1039           if (DoIHaveATreeLink() == 0 ) {
1040           OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
1041           reset_tree_links();
1042           myState->ParentId.v4 = msg->router_id.v4;
1043           myState->OldParentId.v4 = myState->ParentId.v4;
1044           tree_link_req(&msg->router_id.v4);
1045           }
1046           else {
1047           //I have a tree link already, evaluate new parent ??
1048           
1049           }
1050         }
1051         else { //Receiving a TreeCreate from my parent so I can refresh hearthbeat
1052         myState->TreeHeartBeat = TREE_HEARTBEAT;
1053         
1054         //FORWARD the tree message on the mesh
1055         if (list_empty(&ListOfObampNodes) == 0) {       //if the list is NOT empty
1056
1057           //Scroll the list
1058           list_for_each(pos, &ListOfObampNodes) {
1059             tmp = list_entry(pos, struct ObampNode, list);
1060
1061             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
1062                 if (DoIHaveATreeLink() == 1 ) { //I forward only if I have a link tree to the core ready
1063               tree_create_forward_to(&tmp->neighbor_ip_addr.v4, msg);
1064               OLSR_DEBUG(LOG_PLUGINS, "FORWARDING TREE CREATE ORIGINATOR %s TO node %s ", ip4_to_string(&buf2, msg->router_id.v4),
1065                          ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1066                 }
1067
1068             }
1069           }
1070         } else {
1071           OLSR_DEBUG(LOG_PLUGINS, "Very strange, list cannot be empty here !");
1072         }
1073        }
1074       } //END IF TREE CREATE IS NOT A DUPLICATE 
1075       else {
1076         
1077         OLSR_DEBUG(LOG_PLUGINS, "myState->TreeCreateSequenceNumber < msg->SequenceNumber --- %d < %d",myState->TreeCreateSequenceNumber,msg->SequenceNumber);
1078         OLSR_DEBUG(LOG_PLUGINS, "DISCARDING DUP TREE CREATE");
1079       }
1080     }
1081   }
1082
1083 }
1084
1085 void
1086 ObampSignalling(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
1087 {
1088
1089   char buffer[1500];
1090   char text_buffer[300];
1091   struct sockaddr_in addr;
1092   int n = 0;
1093   socklen_t len;
1094   u_int8_t MessageID;
1095
1096   memset(&addr, 0, sizeof(struct sockaddr_in));
1097   len = sizeof(addr);
1098
1099   if (skfd > 0) {
1100
1101     //OLSR_DEBUG(LOG_PLUGINS,"INCOMING OBAMP SIGNALLING");
1102
1103     n = recvfrom(skfd, buffer, 1500, 0, (struct sockaddr *)&addr, &len);
1104
1105     if (n < 0) {
1106       OLSR_DEBUG(LOG_PLUGINS, "recvfrom error");
1107     }
1108
1109     inet_ntop(AF_INET, &addr.sin_addr, text_buffer, sizeof(text_buffer));
1110     //OLSR_DEBUG(LOG_PLUGINS,"Request from host %s, port %d\n", text_buffer, ntohs(addr->sin_port));
1111
1112     MessageID = buffer[0];
1113
1114     switch (MessageID) {
1115
1116     case OBAMP_DATA:
1117       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_DATA from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1118
1119       if (CheckDupData(buffer) && CheckDataFromTreeLink(buffer) ) {
1120         forward_obamp_data(buffer);
1121         decap_data(buffer);
1122       }
1123
1124       break;
1125
1126     case OBAMP_HELLO:
1127       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_HELLO from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1128       manage_hello(buffer);
1129       break;
1130
1131     case OBAMP_TREECREATE:
1132       //do here
1133       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_TREECREATE from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1134       manage_tree_create(buffer);
1135
1136       break;
1137
1138     case OBAMP_TREE_REQ:
1139       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_TREE_REQ from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1140       tree_link_ack((struct OBAMP_tree_link_req *)buffer);
1141       break;
1142
1143     case OBAMP_TREE_ACK:
1144       //do here
1145       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_TREE_ACK from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1146       activate_tree_link((struct OBAMP_tree_link_ack *)buffer);
1147       break;
1148
1149
1150     case OBAMP_TREE_DESTROY:
1151       //do here
1152       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_TREE_DESTROY from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1153       deactivate_tree_link((struct OBAMP_tree_destroy *)buffer);
1154       break;
1155     }
1156
1157
1158   }                             //if skfd<0
1159
1160 }
1161
1162
1163 /*
1164 adds a IPv4 ObampNode in the list if it is new
1165 If a new node is added CoreElection is called to update the current core
1166 */
1167 int
1168 addObampNode4(struct in_addr *ipv4, u_int8_t status)
1169 {
1170 #if !defined(REMOVE_LOG_DEBUG)
1171   struct ipaddr_str buf;
1172 #endif
1173   struct ObampNode *neighbor_to_add;
1174   struct ObampNode *tmp;
1175   struct list_head *pos;
1176
1177   neighbor_to_add = olsr_malloc(sizeof(struct ObampNode), "OBAMPNode");
1178
1179 //OLSR_DEBUG(LOG_PLUGINS,"Adding to list node - %s\n",ip4_to_string(&buf,*ipv4));
1180
1181
1182   if (list_empty(&ListOfObampNodes) != 0) {     //Empty list
1183 //OLSR_DEBUG(LOG_PLUGINS,"List is empty %d adding first node\n",list_empty(&ListOfObampNodes));
1184
1185     memcpy(&neighbor_to_add->neighbor_ip_addr.v4, ipv4, sizeof(neighbor_to_add->neighbor_ip_addr.v4));
1186     list_add(&(neighbor_to_add->list), &ListOfObampNodes);
1187
1188     init_overlay_neighbor(neighbor_to_add);
1189     neighbor_to_add->status = status;
1190
1191     OLSR_DEBUG(LOG_PLUGINS, "Added to list node as first node- %s\n", ip4_to_string(&buf, *ipv4));
1192
1193     CoreElection();
1194
1195   } else {                      //Some node already in list
1196
1197 //Scroll the list to check if the element already exists
1198     list_for_each(pos, &ListOfObampNodes) {
1199
1200       tmp = list_entry(pos, struct ObampNode, list);
1201       if (memcmp(&tmp->neighbor_ip_addr.v4, ipv4, sizeof(tmp->neighbor_ip_addr.v4)) == 0) {
1202         //OLSR_DEBUG(LOG_PLUGINS,"Node already present in list %s\n",ip4_to_string(&buf,*ipv4));
1203         tmp->Texpire = _Texpire_;       //Refresh Texpire
1204         neighbor_to_add->status = status;
1205         free(neighbor_to_add);
1206         return 1;
1207       }
1208     }
1209 //Add element to list
1210 // neighbor_to_add->Texpire=_Texpire_; //Refresh Texpire
1211     OLSR_DEBUG(LOG_PLUGINS, "Adding to list node (NOT FIRST)- %s\n", ip4_to_string(&buf, *ipv4));
1212     memcpy(&neighbor_to_add->neighbor_ip_addr.v4, ipv4, sizeof(neighbor_to_add->neighbor_ip_addr.v4));
1213     list_add(&(neighbor_to_add->list), &ListOfObampNodes);
1214     init_overlay_neighbor(neighbor_to_add);
1215     neighbor_to_add->status = status;
1216     CoreElection();
1217   }                             //end else
1218   return 0;
1219 }                               //End AddObampNode
1220
1221
1222
1223 /* -------------------------------------------------------------------------
1224  * Function   : PacketReceivedFromOLSR
1225  * Description: Handle a received packet from a OLSR message
1226  * Input      : Obamp Message
1227  * Output     : none
1228  * Return     : none
1229  * ------------------------------------------------------------------------- */
1230 static void
1231 PacketReceivedFromOLSR(union olsr_ip_addr *originator, const uint8_t *obamp_message, int len)
1232 {
1233   u_int8_t MessageID = obamp_message[0];
1234   const struct OBAMP_alive *alive;
1235 #if !defined(REMOVE_LOG_DEBUG)
1236   struct ipaddr_str buf;
1237 #endif
1238
1239   struct in_addr *myOriginator = (struct in_addr *)originator;
1240
1241 //TODO: this is useless now
1242   len = 0;
1243
1244 //See obamp.h
1245   switch (MessageID) {
1246
1247   case OBAMP_ALIVE:
1248     OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_ALIVE from %s\n", ip4_to_string(&buf, *myOriginator));
1249     alive = (const struct OBAMP_alive *)obamp_message;
1250     addObampNode4(myOriginator, alive->status);
1251     printObampNodesList();
1252
1253     break;
1254   }
1255
1256
1257 }                               /* PacketReceivedFromOLSR */
1258
1259
1260 //OLSR parser, received OBAMP messages
1261 void
1262 olsr_parser(struct olsr_message *msg, struct interface *in_if
1263             __attribute__ ((unused)), union olsr_ip_addr *ipaddr, enum duplicate_status status __attribute__ ((unused)))
1264 {
1265   //OLSR_DEBUG(LOG_PLUGINS, "OBAMP PLUGIN: Received msg in parser\n");
1266
1267   if (msg->type != MESSAGE_TYPE) {
1268     return;
1269   }
1270
1271   /* Check if message originated from this node.
1272    *         If so - back off */
1273   if (olsr_ipcmp(&msg->originator, &olsr_cnf->router_id) == 0)
1274     return;
1275
1276   /* Check that the neighbor this message was received from is symmetric.
1277    *         If not - back off*/
1278   if (check_neighbor_link(ipaddr) != SYM_LINK) {
1279     //struct ipaddr_str strbuf;
1280     return;
1281   }
1282
1283   PacketReceivedFromOLSR(&msg->originator, msg->payload, msg->end - msg->payload);
1284 }
1285
1286 //Sends a packet in the OLSR network
1287 void
1288 olsr_obamp_gen(void *packet, int len)
1289 {
1290   /* send buffer: huge */
1291   uint8_t buffer[10240];
1292   struct olsr_message msg;
1293   struct interface *ifn;
1294   uint8_t *curr, *sizeptr;
1295
1296   /* fill message */
1297   msg.type = MESSAGE_TYPE;
1298   msg.vtime = OBAMP_VALID_TIME * MSEC_PER_SEC;
1299   msg.originator = olsr_cnf->router_id;
1300   msg.ttl = MAX_TTL;
1301   msg.hopcnt = 0;
1302   msg.seqno = get_msg_seqno();
1303   msg.size = 0; /* put in later */
1304
1305   curr = buffer;
1306   sizeptr = olsr_put_msg_hdr(&curr, &msg);
1307   memcpy(curr, packet, len);
1308
1309   len = curr - buffer + len;
1310   pkt_put_u16(&sizeptr, len);
1311
1312   /* looping trough interfaces */
1313   OLSR_FOR_ALL_INTERFACES(ifn) {
1314     if (net_outbuffer_push(ifn, buffer, len) != len) {
1315       /* send data and try again */
1316       net_output(ifn);
1317       if (net_outbuffer_push(ifn, buffer, len) != len) {
1318         OLSR_DEBUG(LOG_PLUGINS, "OBAMP PLUGIN: could not send on interface: %s\n", ifn->int_name);
1319       }
1320     }
1321   }
1322   OLSR_FOR_ALL_INTERFACES_END(ifn);
1323 }
1324
1325 void
1326 outer_tree_create(void *x)
1327 {
1328
1329   struct ObampNode *tmp;               //temp pointers used when parsing the list
1330   struct list_head *pos;
1331
1332
1333   if ((DoIHaveATreeLink() == 0) && (myState->iamcore == 0)) {   //If there are not tree links
1334
1335     if (list_empty(&ListOfObampNodes) == 0) {   //if the list is NOT empty
1336
1337
1338       if (DoIHaveAMeshLink() == 0) {
1339         OLSR_DEBUG(LOG_PLUGINS, "Weird, no mesh links. Maybe other OBAMP nodes are very far (HUGE ETX)");
1340
1341       } else {
1342
1343         //Update my current IP address
1344         memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
1345         //OLSR_DEBUG(LOG_PLUGINS,"SETUP: my IP - %s",ip4_to_string(&buf,myState->myipaddr.v4));
1346         list_for_each(pos, &ListOfObampNodes) {
1347           tmp = list_entry(pos, struct ObampNode, list);
1348           if ((tmp->neighbor_ip_addr.v4.s_addr < myState->myipaddr.v4.s_addr) && (tmp->isMesh == 1)) {
1349             return;             //I have a neighbor that will send a outer tree create for me
1350           }
1351         }
1352         //tree create
1353         OLSR_DEBUG(LOG_PLUGINS, "OUTER TREE CREATE");
1354         tmp = select_tree_anchor();
1355         if (tmp == NULL) {
1356           OLSR_DEBUG(LOG_PLUGINS, "CANT FIND ANCHOR");
1357           return;
1358         }
1359         tmp->isMesh = 1;
1360         tmp->outerTreeLink = 1;
1361         myState->OldParentId.v4 = tmp->neighbor_ip_addr.v4;
1362         myState->ParentId.v4 = tmp->neighbor_ip_addr.v4;
1363         myState->TreeHeartBeat = TREE_HEARTBEAT;
1364         tree_link_req(&tmp->neighbor_ip_addr.v4);
1365
1366       }
1367
1368
1369     } else {
1370       OLSR_DEBUG(LOG_PLUGINS, "List empty can't send OUTER_TREE_CREATE");
1371     }
1372   }
1373   x = NULL;
1374 }
1375
1376
1377 void
1378 tree_create(void *x)
1379 {
1380 #if !defined(REMOVE_LOG_DEBUG)
1381   struct ipaddr_str buf;
1382 #endif
1383   struct ObampNode *tmp;               //temp pointers used when parsing the list
1384   struct list_head *pos;
1385
1386 //Check if I'm core
1387   if (myState->iamcore == 1) {
1388
1389     if (list_empty(&ListOfObampNodes) == 0) {   //if the list is NOT empty
1390
1391       //Scroll the list
1392       list_for_each(pos, &ListOfObampNodes) {
1393
1394         tmp = list_entry(pos, struct ObampNode, list);
1395         if (tmp->isMesh == 1) { //Is neighbor
1396           //send tree create
1397
1398           tree_create_gen(&tmp->neighbor_ip_addr.v4);
1399
1400
1401           OLSR_DEBUG(LOG_PLUGINS, "CORE SENDS TREE CREATE TO node %s ", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1402
1403         }
1404       }
1405     } else {
1406       OLSR_DEBUG(LOG_PLUGINS, "List empty can't send TREE_CREATE");
1407     }
1408
1409   }
1410
1411   x = NULL;
1412 }
1413
1414
1415
1416
1417 void
1418 mesh_create(void *x)
1419 {
1420 #if !defined(REMOVE_LOG_DEBUG)
1421   struct ipaddr_str buf;
1422 #endif
1423   struct ObampNode *tmp;               //temp pointers used when parsing the list
1424   struct list_head *pos;
1425
1426   struct rt_entry *rt;                 //"rt->rt_best->rtp_metric.cost" is the value you are looking for, a 32 bit
1427
1428   unsigned int mincost = 5;
1429
1430   int meshchanged = 0;
1431
1432   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1433
1434     //Scroll the list
1435     list_for_each(pos, &ListOfObampNodes) {
1436
1437       tmp = list_entry(pos, struct ObampNode, list);
1438
1439       //set every OBAMP node to be NOT neighbor
1440       tmp->wasMesh = tmp->isMesh;
1441
1442       //MeshLock in case mesh link is requested from neighbor
1443       if (tmp->MeshLock == 0 && tmp->outerTreeLink == 0)
1444         tmp->isMesh = 0;
1445
1446       rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
1447
1448       if (rt == NULL) {         //route is not present yet
1449         continue;
1450       }
1451       //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);
1452
1453       if (rt->rt_best->rtp_metric.cost / 65536 > 5) {
1454         continue;               //we not not consider links that are poorer than ETX=5
1455       }
1456       //update min cost
1457       if ((rt->rt_best->rtp_metric.cost / 65536) < mincost)
1458         mincost = (rt->rt_best->rtp_metric.cost / 65536);
1459
1460     }                           //end for each
1461
1462     //now that I know the mincost to the closer OBAMP node I choose my neighbor set
1463     list_for_each(pos, &ListOfObampNodes) {
1464
1465       tmp = list_entry(pos, struct ObampNode, list);
1466       rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
1467
1468       if (rt == NULL) {         //route is not present yet
1469         continue;
1470       }
1471
1472       if (rt->rt_best->rtp_metric.cost / 65536 > 5) {
1473         continue;               //we not not consider links that are poorer than ETX=5
1474       }
1475
1476       if ((rt->rt_best->rtp_metric.cost / 65536) - 1 < mincost) {       //Choose for mesh
1477
1478         tmp->isMesh = 1;
1479         OLSR_DEBUG(LOG_PLUGINS, "Choosed Overlay Neighbor node %s costs %u", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4),
1480                    rt->rt_best->rtp_metric.cost / 65536);
1481
1482         obamp_hello(&tmp->neighbor_ip_addr.v4);
1483
1484
1485       }
1486
1487       if (tmp->outerTreeLink == 1)
1488         obamp_hello(&tmp->neighbor_ip_addr.v4);
1489
1490
1491       if (tmp->isMesh != tmp->wasMesh) {
1492         meshchanged++;
1493         if (tmp->isMesh == 0 && tmp->isTree == 1) {
1494
1495           tmp->isTree = 0;
1496           send_destroy_tree_link(&tmp->neighbor_ip_addr.v4);
1497         
1498         if (memcmp(&tmp->neighbor_ip_addr.v4, &myState->ParentId.v4, sizeof(struct in_addr)) == 0) {
1499                 OLSR_DEBUG(LOG_PLUGINS,"RESET TREE LINKS: I lost tree link with my PARENT");
1500                 reset_tree_links();
1501         }       
1502
1503         }
1504       }
1505
1506     }                           //end for each
1507
1508     if (meshchanged) {
1509       //trigger signalling
1510     }
1511
1512
1513   } else {
1514     OLSR_DEBUG(LOG_PLUGINS, "List empty can't create Overlay Mesh");
1515   }
1516
1517   x = NULL;
1518 }
1519
1520
1521 void
1522 purge_nodes(void *x)
1523 {
1524 #if !defined(REMOVE_LOG_DEBUG)
1525   struct ipaddr_str buf;
1526 #endif
1527   struct ObampNode *tmp;
1528   struct list_head *pos;
1529
1530   int nodesdeleted = 0;
1531
1532   if (myState->TreeHeartBeat > 0)
1533     myState->TreeHeartBeat--;
1534
1535   if (myState->TreeRequestDelay > 0)
1536     myState->TreeRequestDelay--;
1537
1538   if (myState->TreeHeartBeat == 0 && myState->iamcore == 0){ 
1539     OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
1540     reset_tree_links();
1541     }
1542
1543 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP: Timer Expired Purging Nodes");
1544
1545
1546   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1547
1548     list_for_each(pos, &ListOfObampNodes) {
1549
1550       tmp = list_entry(pos, struct ObampNode, list);
1551       tmp->Texpire--;
1552       if (tmp->MeshLock != 0)
1553         tmp->MeshLock--;
1554
1555       //OLSR_DEBUG(LOG_PLUGINS,"Updating node %s with Texpire %d",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4),tmp->Texpire);
1556       if (tmp->Texpire == 0) {  //purge
1557         OLSR_DEBUG(LOG_PLUGINS, "Purging node %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1558         list_del(pos);
1559         //OLSR_DEBUG(LOG_PLUGINS,"OBAMP CHECK EMPTY %d",list_empty(&ListOfObampNodes));
1560
1561         free(tmp);
1562         nodesdeleted++;
1563       }
1564
1565     }
1566
1567     if (nodesdeleted != 0)
1568       CoreElection();
1569
1570   } else {
1571 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP: List empty");
1572
1573   }
1574
1575   x = NULL;
1576 }
1577
1578
1579 void
1580 obamp_alive_gen(void *x  __attribute__ ((unused)))
1581 {
1582   struct OBAMP_alive myAlive;
1583   OLSR_DEBUG(LOG_PLUGINS, "Calling obamp_alive_gen\n");
1584
1585   memset(&myAlive, 0, sizeof(myAlive));
1586   myAlive.MessageID = OBAMP_ALIVE;
1587   myAlive.status = DoIHaveATreeLink();
1588   olsr_obamp_gen(&myAlive, sizeof(struct OBAMP_alive));
1589 }
1590
1591
1592
1593 /*
1594 When a packet is captured on the sniffing interfaces, it is called EncapFlowInObamp
1595 here we check if the packet is multicast and we forward it to the overlay neighbors if we have a link tree
1596 */
1597
1598 void
1599 EncapFlowInObamp(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
1600 {
1601   unsigned char ipPacket[1500];        //TODO: optimize me
1602
1603 #if !defined(REMOVE_LOG_DEBUG)
1604   struct ipaddr_str buf;
1605 #endif
1606   struct ObampNode *tmp;
1607   struct list_head *pos;
1608
1609   union olsr_ip_addr dst;              /* Destination IP address in captured packet */
1610   struct ip *ipHeader;                 /* The IP header inside the captured IP packet */
1611   struct ip6_hdr *ipHeader6;           /* The IP header inside the captured IP packet */
1612
1613   if (skfd >= 0) {
1614     struct sockaddr_ll pktAddr;
1615     socklen_t addrLen = sizeof(pktAddr);
1616     int nBytes;
1617
1618     nBytes = recvfrom(skfd, ipPacket, 1500,     //TODO: optimize me
1619                       0, (struct sockaddr *)&pktAddr, &addrLen);
1620     if (nBytes < 0) {
1621
1622       return;                   /* for */
1623     }
1624
1625     /* if (nBytes < 0) */
1626     /* Check if the number of received bytes is large enough for an IP
1627      * packet which contains at least a minimum-size IP header.
1628      * Note: There is an apparent bug in the packet socket implementation in
1629      * combination with VLAN interfaces. On a VLAN interface, the value returned
1630      * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
1631      * returned on a non-VLAN interface, for the same ethernet frame. */
1632     if (nBytes < (int)sizeof(struct ip)) {
1633
1634       OLSR_DEBUG(LOG_PLUGINS, "Captured frame too short");
1635       return;                   /* for */
1636     }
1637
1638     if (pktAddr.sll_pkttype == PACKET_OUTGOING || pktAddr.sll_pkttype == PACKET_MULTICAST)      // ||
1639       //pktAddr.sll_pkttype == PACKET_BROADCAST)
1640     {
1641
1642       //do here
1643       if ((ipPacket[0] & 0xf0) == 0x40) {       //IPV4
1644
1645         ipHeader = (struct ip *)ipPacket;
1646
1647         dst.v4 = ipHeader->ip_dst;
1648
1649         /* Only forward multicast packets. If configured, also forward local broadcast packets */
1650         if (IsMulticast(&dst)) {
1651           /* continue */
1652         } else {
1653           return;
1654         }
1655         if (ipHeader->ip_p != SOL_UDP) {
1656           /* Not UDP */
1657           OLSR_DEBUG(LOG_PLUGINS, "NON UDP PACKET\n");
1658           return;               /* for */
1659         } else {
1660           //Forward the packet to tree links
1661           if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1662
1663             list_for_each(pos, &ListOfObampNodes) {
1664
1665               tmp = list_entry(pos, struct ObampNode, list);
1666               if (tmp->isTree == 1) {
1667
1668                 OLSR_DEBUG(LOG_PLUGINS, "Pushing data to Tree link to %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1669                 SendOBAMPData(&tmp->neighbor_ip_addr.v4, ipPacket, nBytes);
1670
1671               }
1672             }
1673           }
1674         }
1675
1676       }                         //END IPV4
1677
1678       else if ((ipPacket[0] & 0xf0) == 0x60) {  //IPv6
1679
1680         ipHeader6 = (struct ip6_hdr *)ipPacket;
1681         if (ipHeader6->ip6_dst.s6_addr[0] == 0xff)      //Multicast
1682         {
1683           //Continua
1684         } else {
1685           return;               //not multicast
1686         }
1687         if (ipHeader6->ip6_nxt != SOL_UDP) {
1688           /* Not UDP */
1689           OLSR_DEBUG(LOG_PLUGINS, "NON UDP PACKET\n");
1690           return;               /* for */
1691         }
1692
1693       }                         //END IPV6
1694       else
1695         return;                 //Is not IP packet
1696
1697       // send the packet to OLSR forward mechanism
1698       // SendOBAMPData(&tmp->neighbor_ip_addr.v6,ipPacket,nBytes);
1699
1700
1701     }                           /* if (pktAddr.sll_pkttype == ...) */
1702   }                             /* if (skfd >= 0 && (FD_ISSET...)) */
1703 }                               /* EncapFlowInObamp */
1704
1705 //This function is called from olsrd_plugin.c and adds to the list the interfaces specified in the configuration file to sniff multicast traffic
1706 int
1707 AddObampSniffingIf(const char *ifName,
1708                    void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
1709 {
1710
1711   struct ObampSniffingIf *ifToAdd;
1712
1713   OLSR_DEBUG(LOG_PLUGINS, "AddObampSniffingIf");
1714
1715
1716   assert(ifName != NULL);
1717
1718   ifToAdd = olsr_malloc(sizeof(struct ObampSniffingIf), "OBAMPSniffingIf");
1719
1720   strncpy(ifToAdd->ifName, ifName, 16); //TODO: 16 fix this
1721   ifToAdd->ifName[15] = '\0';   /* Ensures null termination */
1722
1723   OLSR_DEBUG(LOG_PLUGINS, "Adding interface to list");
1724
1725   list_add(&(ifToAdd->list), &ListOfObampSniffingIf);
1726
1727   OLSR_DEBUG(LOG_PLUGINS, "Adding if %s to list of ObampSniffingIfaces", ifToAdd->ifName);
1728
1729   return 0;
1730 }
1731
1732
1733 int
1734 PreInitOBAMP(void)
1735 {
1736   INIT_LIST_HEAD(&ListOfObampSniffingIf);
1737   return 0;
1738
1739 }
1740
1741 //Start here !!
1742
1743 int
1744 InitOBAMP(void)
1745 {
1746 #if !defined(REMOVE_LOG_DEBUG)
1747   struct ipaddr_str buf;
1748 #endif
1749
1750 //Structs necessary for timers
1751
1752   struct timer_entry *OBAMP_alive_timer;
1753   struct timer_entry *purge_nodes_timer;
1754   struct timer_entry *mesh_create_timer;
1755   struct timer_entry *tree_create_timer;
1756   struct timer_entry *outer_tree_create_timer;
1757
1758
1759
1760   struct olsr_cookie_info *OBAMP_alive_gen_timer_cookie = NULL;
1761   struct olsr_cookie_info *purge_nodes_timer_cookie = NULL;
1762   struct olsr_cookie_info *mesh_create_timer_cookie = NULL;
1763   struct olsr_cookie_info *tree_create_timer_cookie = NULL;
1764   struct olsr_cookie_info *outer_tree_create_timer_cookie = NULL;
1765
1766   if (olsr_cnf->ip_version == AF_INET6) {
1767     OLSR_ERROR(LOG_PLUGINS, "OBAMP does not support IPv6 at the moment.");
1768     return 1;
1769   }
1770
1771 //Setting OBAMP node state
1772   myState = olsr_malloc(sizeof(struct ObampNodeState), "OBAMPNodeState");
1773   myState->iamcore = 1;
1774   myState->TreeHeartBeat = 0;
1775   myState->TreeRequestDelay = 0;
1776   memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
1777   myState->CoreAddress = myState->myipaddr;
1778
1779   myState->DataSequenceNumber = 0;
1780   myState->TreeCreateSequenceNumber = 0;
1781   myState->tree_req_sn = 0;     //TODO: start from random number ?
1782
1783   memset(&myState->ParentId.v4, 0, sizeof(myState->ParentId.v4));
1784   memset(&myState->OldParentId.v4, 1, sizeof(myState->OldParentId.v4));
1785
1786   OLSR_DEBUG(LOG_PLUGINS, "SETUP: my IP - %s", ip4_to_string(&buf, myState->myipaddr.v4));
1787
1788   INIT_LIST_HEAD(&ListOfObampNodes);
1789
1790 //OLSR cookies stuff for timers
1791   OBAMP_alive_gen_timer_cookie = olsr_alloc_cookie("OBAMP Alive Generation", OLSR_COOKIE_TYPE_TIMER);
1792   purge_nodes_timer_cookie = olsr_alloc_cookie("purge nodes Generation", OLSR_COOKIE_TYPE_TIMER);
1793   mesh_create_timer_cookie = olsr_alloc_cookie("mesh create Generation", OLSR_COOKIE_TYPE_TIMER);
1794   tree_create_timer_cookie = olsr_alloc_cookie("tree create Generation", OLSR_COOKIE_TYPE_TIMER);
1795   outer_tree_create_timer_cookie = olsr_alloc_cookie("outer tree create Generation", OLSR_COOKIE_TYPE_TIMER);
1796
1797
1798 //Tells OLSR to launch olsr_parser when the packets for this plugin arrive
1799   olsr_parser_add_function(&olsr_parser, PARSER_TYPE);
1800
1801 // start to send alive messages to appear in other joined lists
1802   OBAMP_alive_timer =
1803     olsr_start_timer(OBAMP_ALIVE_EIVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &obamp_alive_gen, NULL,
1804                      OBAMP_alive_gen_timer_cookie);
1805
1806 // start timer to purge nodes from list in softstate fashion
1807   purge_nodes_timer =
1808     olsr_start_timer(_Texpire_timer_ * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &purge_nodes, NULL,
1809                      purge_nodes_timer_cookie);
1810
1811 //start timer to create mesh
1812   mesh_create_timer =
1813     olsr_start_timer(OBAMP_MESH_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &mesh_create, NULL,
1814                      mesh_create_timer_cookie);
1815
1816 //start timer for tree create procedure
1817   tree_create_timer =
1818     olsr_start_timer(OBAMP_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &tree_create, NULL,
1819                      tree_create_timer_cookie);
1820
1821 //start timer for tree create procedure
1822   outer_tree_create_timer =
1823     olsr_start_timer(OBAMP_OUTER_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &outer_tree_create, NULL,
1824                      tree_create_timer_cookie);
1825
1826
1827 //Create udp server socket for OBAMP signalling and register it to the scheduler
1828   OLSR_DEBUG(LOG_PLUGINS, "Launch Udp Servers");
1829   if (UdpServer() < 0) {
1830     OLSR_DEBUG(LOG_PLUGINS, "Problem in Launch Udp Servers");
1831
1832   };
1833
1834 //Creates a socket for sniffing multicast traffic and registers it to the scheduler
1835   CreateObampSniffingInterfaces();
1836
1837   return 0;
1838 }
1839
1840 /* -------------------------------------------------------------------------
1841  * Function   : CloseOBAMP
1842  * Description: Close the OBAMP plugin and clean up
1843  * Input      : none
1844  * Output     : none
1845  * Return     : none
1846  * Data Used  :
1847  * ------------------------------------------------------------------------- */
1848 void
1849 CloseOBAMP(void)
1850 {
1851 //do something here
1852 }