286df98c0
[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
580 void
581 unsolicited_tree_destroy(void *x)
582 {
583
584   //struct ipaddr_str buf;
585   struct ObampNode *tmp;
586   struct list_head *pos;
587
588   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
589
590     list_for_each(pos, &ListOfObampNodes) {
591
592       tmp = list_entry(pos, struct ObampNode, list);
593       if (tmp->isTree == 0)
594         send_destroy_tree_link(&tmp->neighbor_ip_addr.v4);
595
596     }
597   }
598   x = NULL;
599 }
600
601 static int
602 DoIHaveAMeshLink(void)
603 {
604
605   //struct ipaddr_str buf;
606   struct ObampNode *tmp;
607   struct list_head *pos;
608
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       if (tmp->isMesh == 1)
615         return 1;
616
617     }
618   }
619   return 0;
620 }
621
622 static void
623 reset_tree_links(void)
624 {
625
626   //struct ipaddr_str buf;
627   struct ObampNode *tmp;
628   struct list_head *pos;
629
630   OLSR_DEBUG(LOG_PLUGINS,"Reset Tree Links Now");
631   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
632
633     list_for_each(pos, &ListOfObampNodes) {
634
635       tmp = list_entry(pos, struct ObampNode, list);
636       tmp->isTree = 0;
637       tmp->outerTreeLink = 0;
638     }
639   }
640
641   memset(&myState->ParentId.v4, 0, sizeof(myState->ParentId.v4));
642   memset(&myState->OldParentId.v4, 1, sizeof(myState->OldParentId.v4));
643   myState->TreeCreateSequenceNumber=0;
644
645
646 };
647
648
649 //I received a request to deactivate a tree link
650 static void
651 deactivate_tree_link(struct OBAMP_tree_destroy *destroy_msg)
652 {
653 #if !defined(REMOVE_LOG_DEBUG)
654   struct ipaddr_str buf;
655 #endif
656   struct ObampNode *tmp;
657   struct list_head *pos;
658
659   if (memcmp(&myState->CoreAddress.v4, &destroy_msg->CoreAddress.v4, sizeof(struct in_addr)) != 0) {
660     OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
661     return;
662   }
663
664     list_for_each(pos, &ListOfObampNodes) {
665
666       tmp = list_entry(pos, struct ObampNode, list);
667       if (tmp->neighbor_ip_addr.v4.s_addr == destroy_msg->router_id.v4.s_addr) {
668
669         tmp->isTree = 0;
670         OLSR_DEBUG(LOG_PLUGINS, "Tree link to %s deactivated", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
671         
672         if (memcmp(&tmp->neighbor_ip_addr.v4, &myState->ParentId.v4, sizeof(struct in_addr)) == 0) {
673                 OLSR_DEBUG(LOG_PLUGINS,"RESET TREE LINKS: I lost tree link with my PARENT");
674                 reset_tree_links();
675         }
676
677         return;
678
679       }
680     }
681
682 }
683
684 //Core Election. The Core is the one with the smallest IP Address
685 static void
686 CoreElection(void)
687 {
688 #if !defined(REMOVE_LOG_DEBUG)
689   struct ipaddr_str buf;
690 #endif
691   struct ObampNode *tmp;
692   struct list_head *pos;
693   u_int32_t smallestIP = 0xFFFFFFFF;
694
695   //Update my current IP address
696   memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
697
698   OLSR_DEBUG(LOG_PLUGINS, "SETUP: my IP - %s", ip4_to_string(&buf, myState->myipaddr.v4));
699
700
701   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
702
703     list_for_each(pos, &ListOfObampNodes) {
704
705       tmp = list_entry(pos, struct ObampNode, list);
706       if (tmp->neighbor_ip_addr.v4.s_addr < smallestIP) {
707
708         smallestIP = tmp->neighbor_ip_addr.v4.s_addr;
709         OLSR_DEBUG(LOG_PLUGINS, "CoreElection: current smallest IP is - %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
710
711       };
712     }
713     //Check if I'm the core.
714
715     if (myState->myipaddr.v4.s_addr < smallestIP) {     //I'm the core
716
717       if (myState->myipaddr.v4.s_addr == myState->CoreAddress.v4.s_addr) {      //I'm was already the core
718         return;
719       } else {                  //I'm becoming core
720
721         myState->CoreAddress = myState->myipaddr;
722         myState->iamcore = 1;
723         myState->TreeCreateSequenceNumber = 0;
724         OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
725         reset_tree_links();
726         OLSR_DEBUG(LOG_PLUGINS, "I'm the core");
727       }
728     } else {
729       if (myState->CoreAddress.v4.s_addr == smallestIP) {       //the core did not change
730         return;
731       } else {                  //core changed
732         myState->iamcore = 0;
733         myState->CoreAddress.v4.s_addr = smallestIP;
734         OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
735         reset_tree_links();
736         OLSR_DEBUG(LOG_PLUGINS, "CoreElection: current Core is - %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
737       }
738     }
739
740   }
741
742   else {                        //List is empty I'm the core
743     OLSR_DEBUG(LOG_PLUGINS, "CoreElection: I'm alone I'm the core");
744     myState->CoreAddress = myState->myipaddr;
745     myState->iamcore = 1;
746     myState->TreeCreateSequenceNumber = 0;
747     OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
748     reset_tree_links();
749
750
751
752   }
753
754 }
755
756 //Starts a UDP listening port for OBAMP signalling
757 static int
758 UdpServer(void)
759 {
760
761   struct sockaddr_in addr;
762
763
764   if ((sdudp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
765     OLSR_DEBUG(LOG_PLUGINS, "Socket UDP error");
766     return -1;
767   }
768
769   memset((void *)&addr, 0, sizeof(addr));       /* clear server address */
770   addr.sin_family = AF_INET;    /* address type is INET */
771   addr.sin_port = htons(OBAMP_SIGNALLING_PORT);
772   addr.sin_addr.s_addr = htonl(INADDR_ANY);     /* connect from anywhere */
773   /* bind socket */
774   if (bind(sdudp, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
775     OLSR_DEBUG(LOG_PLUGINS, "Socket UDP BIND error");
776     return (-1);
777   }
778
779   add_olsr_socket(sdudp, &ObampSignalling, NULL, NULL, SP_PR_READ);
780
781   return 0;
782
783 }
784
785 static void
786 decap_data(char *buffer)
787 {
788
789   //struct ipaddr_str buf; //buf to print debug infos
790   struct ObampSniffingIf *tmp;         //temp pointers used when parsing the list
791   struct list_head *pos;
792   unsigned char *ipPacket;
793   int stripped_len;
794   struct ip *ipHeader;
795   struct ip6_hdr *ip6Header;
796   struct OBAMP_data_message4 *msg;
797   int nBytesWritten;
798   struct sockaddr_ll dest;
799   msg = (struct OBAMP_data_message4 *)buffer;
800
801   ipPacket = msg->data;
802
803   ipHeader = (struct ip *)ipPacket;
804   ip6Header = (struct ip6_hdr *)ipPacket;
805
806
807   if (list_empty(&ListOfObampSniffingIf) == 0) {        //if the list is NOT empty
808 //OLSR_DEBUG(LOG_PLUGINS,"DECAP DATA");
809
810     list_for_each(pos, &ListOfObampSniffingIf) {
811
812       tmp = list_entry(pos, struct ObampSniffingIf, list);
813       //tmp->skd = CreateCaptureSocket(tmp->ifName);
814
815
816
817       memset(&dest, 0, sizeof(dest));
818       dest.sll_family = AF_PACKET;
819       if ((ipPacket[0] & 0xf0) == 0x40) {
820         dest.sll_protocol = htons(ETH_P_IP);
821         stripped_len = ntohs(ipHeader->ip_len);
822       }
823       if ((ipPacket[0] & 0xf0) == 0x60) {
824         dest.sll_protocol = htons(ETH_P_IPV6);
825         stripped_len = 40 + ntohs(ip6Header->ip6_plen); //IPv6 Header size (40) + payload_len
826       }
827       //TODO: if packet is not IP die here
828
829
830       dest.sll_ifindex = if_nametoindex(tmp->ifName);
831       dest.sll_halen = IFHWADDRLEN;
832
833       /* Use all-ones as destination MAC address. When the IP destination is
834        * a multicast address, the destination MAC address should normally also
835        * be a multicast address. E.g., when the destination IP is 224.0.0.1,
836        * the destination MAC should be 01:00:5e:00:00:01. However, it does not
837        * seem to matter when the destination MAC address is set to all-ones
838        * in that case. */
839       memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
840
841       nBytesWritten = sendto(tmp->skd, ipPacket, stripped_len, 0, (struct sockaddr *)&dest, sizeof(dest));
842       if (nBytesWritten != stripped_len) {
843         OLSR_DEBUG(LOG_PLUGINS, "sendto() error forwarding unpacked encapsulated pkt on \"%s\"", tmp->ifName);
844       } else {
845
846         OLSR_DEBUG(LOG_PLUGINS, "OBAMP: --> unpacked and forwarded on \"%s\"\n", tmp->ifName);
847       }
848
849
850     }
851   }
852
853 }
854
855
856
857 static int
858 CheckDataFromTreeLink(char *buffer)
859 {
860
861   struct ObampNode *tmp;               //temp pointers used when parsing the list
862   struct list_head *pos;
863   struct OBAMP_data_message4 *data_msg;
864
865   data_msg = (struct OBAMP_data_message4 *)buffer;
866
867   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
868
869     //Scroll the list
870     list_for_each(pos, &ListOfObampNodes) {
871       tmp = list_entry(pos, struct ObampNode, list);
872       //Scroll the list until we find the entry relative to the last hop of the packet we are processing
873       if (memcmp(&tmp->neighbor_ip_addr.v4, &data_msg->last_hop, sizeof(struct in_addr)) == 0) {
874
875         if (tmp->isTree == 1) {  //OK we receive data from a neighbor that we have a tree link with
876           return 1;
877         }
878
879         else{
880           OLSR_DEBUG(LOG_PLUGINS, "DISCARDING DATA PACKET SENT BY NOT TREE NEIGHBOR");
881           send_destroy_tree_link(&tmp->neighbor_ip_addr.v4);
882           return 0;
883         }
884       }
885     }
886   }
887
888   return 0;
889
890 }
891
892
893 static int
894 CheckDupData(char *buffer)
895 {
896
897   struct ObampNode *tmp;               //temp pointers used when parsing the list
898   struct list_head *pos;
899   struct OBAMP_data_message4 *data_msg;
900
901   data_msg = (struct OBAMP_data_message4 *)buffer;
902
903
904   //Check duplicate data packet
905   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
906
907     //Scroll the list
908     list_for_each(pos, &ListOfObampNodes) {
909       tmp = list_entry(pos, struct ObampNode, list);
910
911       if (memcmp(&tmp->neighbor_ip_addr.v4, &data_msg->router_id, sizeof(struct in_addr)) == 0) {
912
913         OLSR_DEBUG(LOG_PLUGINS, "Processing Data Packet %d - Last seen was %d",data_msg->SequenceNumber, tmp->DataSeqNumber);
914         
915         if (tmp->DataSeqNumber == 0) {  //First packet received from this host
916           tmp->DataSeqNumber = data_msg->SequenceNumber;
917           return 1;
918         }
919
920         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
921         {
922         tmp->DataSeqNumber = data_msg->SequenceNumber;
923         return 1;
924         }
925         else{
926           OLSR_DEBUG(LOG_PLUGINS, "DISCARDING DUP PACKET");
927           return 0;
928         }
929       }
930     }
931   }
932
933   return 1;
934
935 }
936
937 static void
938 forward_obamp_data(char *buffer)
939 {
940
941 #if !defined(REMOVE_LOG_DEBUG)
942   struct ipaddr_str buf;
943   struct ipaddr_str buf2;
944 #endif
945   struct ObampNode *tmp;               //temp pointers used when parsing the list
946   struct list_head *pos;
947   struct OBAMP_data_message4 *data_msg;
948   struct sockaddr_in si_other;
949   struct in_addr temporary;
950
951
952   data_msg = (struct OBAMP_data_message4 *)buffer;
953   temporary.s_addr  = data_msg->last_hop;
954   data_msg->last_hop = myState->myipaddr.v4.s_addr;
955
956   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
957
958     //Scroll the list
959     list_for_each(pos, &ListOfObampNodes) {
960       tmp = list_entry(pos, struct ObampNode, list);
961
962       if (tmp->isTree == 1 && memcmp(&tmp->neighbor_ip_addr.v4, &temporary.s_addr, 4) != 0) {
963         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));
964         //FORWARD DATA
965
966
967         memset((char *)&si_other, 0, sizeof(si_other));
968         si_other.sin_family = AF_INET;
969         si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
970         si_other.sin_addr = tmp->neighbor_ip_addr.v4;
971         //sendto(sdudp, data_msg, sizeof(struct OBAMP_data_message), 0, (struct sockaddr *)&si_other, sizeof(si_other));
972         sendto(sdudp, data_msg, 17+data_msg->datalen, 0, (struct sockaddr *)&si_other, sizeof(si_other));
973
974
975       }
976     }
977   }
978
979 }
980
981
982 static void
983 manage_hello(char *packet)
984 {
985
986   struct OBAMP_hello *hello;
987
988   struct ObampNode *tmp;               //temp pointers used when parsing the list
989   struct list_head *pos;
990
991   hello = (struct OBAMP_hello *)packet;
992
993   //FIRST OF ALL CHECK CORE
994   if (memcmp(&myState->CoreAddress.v4, &hello->CoreAddress.v4, sizeof(struct in_addr)) != 0) {
995     OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
996     return;
997   }
998
999   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1000
1001     //Scroll the list
1002     list_for_each(pos, &ListOfObampNodes) {
1003       tmp = list_entry(pos, struct ObampNode, list);
1004
1005       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
1006
1007         tmp->isMesh = 1;
1008         tmp->MeshLock = _MESH_LOCK_;
1009
1010       }
1011     }
1012   } else {
1013     OLSR_DEBUG(LOG_PLUGINS, "Very strange, list cannot be empty here !");
1014   }
1015
1016 }
1017
1018 static void
1019 manage_tree_create(char *packet)
1020 {
1021
1022   struct OBAMP_tree_create *msg;
1023
1024 #if !defined(REMOVE_LOG_DEBUG)
1025   struct ipaddr_str buf;
1026   struct ipaddr_str buf2;              //buf to print debug infos
1027 #endif
1028
1029   struct ObampNode *tmp;               //temp pointers used when parsing the list
1030   struct list_head *pos;
1031   OLSR_DEBUG(LOG_PLUGINS,"manage_tree_create");
1032   msg = (struct OBAMP_tree_create *)packet;
1033
1034   if (msg->MessageID != OBAMP_TREECREATE) {
1035     OLSR_DEBUG(LOG_PLUGINS, "BIG PROBLEM, I'M IN THIS FUNCTION BUT MESSAGE IS NOT TREE CREATE");
1036   }
1037
1038   else {
1039     //FIRST OF ALL CHECK CORE
1040     if (memcmp(&myState->CoreAddress.v4, &msg->CoreAddress.v4, sizeof(struct in_addr)) != 0) {
1041       OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
1042       return;
1043     }
1044     if (myState->iamcore == 1) {        //I'm core and receiving tree create over a loop
1045       return;
1046     } else {
1047
1048
1049       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
1050         OLSR_DEBUG(LOG_PLUGINS, "myState->TreeCreateSequenceNumber < msg->SequenceNumber --- %d < %d",myState->TreeCreateSequenceNumber,msg->SequenceNumber);
1051         myState->TreeCreateSequenceNumber = msg->SequenceNumber;
1052
1053         //A bug was fixed here a battlemeshv3
1054         //myState->OldParentId.v4 = myState->ParentId.v4;
1055         //myState->ParentId.v4 = msg->router_id.v4;
1056
1057         //if (memcmp(&myState->OldParentId.v4, &myState->ParentId.v4, sizeof(struct in_addr)) != 0)       //If it changed
1058         if (memcmp(&msg->router_id.v4, &myState->ParentId.v4, sizeof(struct in_addr)) != 0)       //If it changed
1059         {
1060           OLSR_DEBUG(LOG_PLUGINS, "Receiving a tree message from a link that is not parent");
1061           if (DoIHaveATreeLink() == 0 ) {
1062           OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
1063           reset_tree_links();
1064           myState->ParentId.v4 = msg->router_id.v4;
1065           myState->OldParentId.v4 = myState->ParentId.v4;
1066           tree_link_req(&msg->router_id.v4);
1067           }
1068           else {
1069           //I have a tree link already, evaluate new parent ??
1070           
1071           }
1072         }
1073         else { //Receiving a TreeCreate from my parent so I can refresh hearthbeat
1074         myState->TreeHeartBeat = TREE_HEARTBEAT;
1075         
1076         //FORWARD the tree message on the mesh
1077         if (list_empty(&ListOfObampNodes) == 0) {       //if the list is NOT empty
1078
1079           //Scroll the list
1080           list_for_each(pos, &ListOfObampNodes) {
1081             tmp = list_entry(pos, struct ObampNode, list);
1082
1083             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
1084                 if (DoIHaveATreeLink() == 1 ) { //I forward only if I have a link tree to the core ready
1085               tree_create_forward_to(&tmp->neighbor_ip_addr.v4, msg);
1086               OLSR_DEBUG(LOG_PLUGINS, "FORWARDING TREE CREATE ORIGINATOR %s TO node %s ", ip4_to_string(&buf2, msg->router_id.v4),
1087                          ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1088                 }
1089
1090             }
1091           }
1092         } else {
1093           OLSR_DEBUG(LOG_PLUGINS, "Very strange, list cannot be empty here !");
1094         }
1095        }
1096       } //END IF TREE CREATE IS NOT A DUPLICATE 
1097       else {
1098         
1099         OLSR_DEBUG(LOG_PLUGINS, "myState->TreeCreateSequenceNumber < msg->SequenceNumber --- %d < %d",myState->TreeCreateSequenceNumber,msg->SequenceNumber);
1100         OLSR_DEBUG(LOG_PLUGINS, "DISCARDING DUP TREE CREATE");
1101       }
1102     }
1103   }
1104
1105 }
1106
1107 void
1108 ObampSignalling(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
1109 {
1110
1111   char buffer[1500];
1112   char text_buffer[300];
1113   struct sockaddr_in addr;
1114   int n = 0;
1115   socklen_t len;
1116   u_int8_t MessageID;
1117
1118   memset(&addr, 0, sizeof(struct sockaddr_in));
1119   len = sizeof(addr);
1120
1121   if (skfd > 0) {
1122
1123     //OLSR_DEBUG(LOG_PLUGINS,"INCOMING OBAMP SIGNALLING");
1124
1125     n = recvfrom(skfd, buffer, 1500, 0, (struct sockaddr *)&addr, &len);
1126
1127     if (n < 0) {
1128       OLSR_DEBUG(LOG_PLUGINS, "recvfrom error");
1129     }
1130
1131     inet_ntop(AF_INET, &addr.sin_addr, text_buffer, sizeof(text_buffer));
1132     //OLSR_DEBUG(LOG_PLUGINS,"Request from host %s, port %d\n", text_buffer, ntohs(addr->sin_port));
1133
1134     MessageID = buffer[0];
1135
1136     switch (MessageID) {
1137
1138     case OBAMP_DATA:
1139       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_DATA from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1140
1141       if (CheckDupData(buffer) && CheckDataFromTreeLink(buffer) ) {
1142         forward_obamp_data(buffer);
1143         decap_data(buffer);
1144       }
1145
1146       break;
1147
1148     case OBAMP_HELLO:
1149       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_HELLO from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1150       manage_hello(buffer);
1151       break;
1152
1153     case OBAMP_TREECREATE:
1154       //do here
1155       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_TREECREATE from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1156       manage_tree_create(buffer);
1157
1158       break;
1159
1160     case OBAMP_TREE_REQ:
1161       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_TREE_REQ from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1162       tree_link_ack((struct OBAMP_tree_link_req *)buffer);
1163       break;
1164
1165     case OBAMP_TREE_ACK:
1166       //do here
1167       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_TREE_ACK from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1168       activate_tree_link((struct OBAMP_tree_link_ack *)buffer);
1169       break;
1170
1171
1172     case OBAMP_TREE_DESTROY:
1173       //do here
1174       OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_TREE_DESTROY from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1175       deactivate_tree_link((struct OBAMP_tree_destroy *)buffer);
1176       break;
1177     }
1178
1179
1180   }                             //if skfd<0
1181
1182 }
1183
1184
1185 /*
1186 adds a IPv4 ObampNode in the list if it is new
1187 If a new node is added CoreElection is called to update the current core
1188 */
1189 int
1190 addObampNode4(struct in_addr *ipv4, u_int8_t status)
1191 {
1192 #if !defined(REMOVE_LOG_DEBUG)
1193   struct ipaddr_str buf;
1194 #endif
1195   struct ObampNode *neighbor_to_add;
1196   struct ObampNode *tmp;
1197   struct list_head *pos;
1198
1199   neighbor_to_add = olsr_malloc(sizeof(struct ObampNode), "OBAMPNode");
1200
1201 //OLSR_DEBUG(LOG_PLUGINS,"Adding to list node - %s\n",ip4_to_string(&buf,*ipv4));
1202
1203
1204   if (list_empty(&ListOfObampNodes) != 0) {     //Empty list
1205 //OLSR_DEBUG(LOG_PLUGINS,"List is empty %d adding first node\n",list_empty(&ListOfObampNodes));
1206
1207     memcpy(&neighbor_to_add->neighbor_ip_addr.v4, ipv4, sizeof(neighbor_to_add->neighbor_ip_addr.v4));
1208     list_add(&(neighbor_to_add->list), &ListOfObampNodes);
1209
1210     init_overlay_neighbor(neighbor_to_add);
1211     neighbor_to_add->status = status;
1212
1213     OLSR_DEBUG(LOG_PLUGINS, "Added to list node as first node- %s\n", ip4_to_string(&buf, *ipv4));
1214
1215     CoreElection();
1216
1217   } else {                      //Some node already in list
1218
1219 //Scroll the list to check if the element already exists
1220     list_for_each(pos, &ListOfObampNodes) {
1221
1222       tmp = list_entry(pos, struct ObampNode, list);
1223       if (memcmp(&tmp->neighbor_ip_addr.v4, ipv4, sizeof(tmp->neighbor_ip_addr.v4)) == 0) {
1224         //OLSR_DEBUG(LOG_PLUGINS,"Node already present in list %s\n",ip4_to_string(&buf,*ipv4));
1225         tmp->Texpire = _Texpire_;       //Refresh Texpire
1226         neighbor_to_add->status = status;
1227         free(neighbor_to_add);
1228         return 1;
1229       }
1230     }
1231 //Add element to list
1232 // neighbor_to_add->Texpire=_Texpire_; //Refresh Texpire
1233     OLSR_DEBUG(LOG_PLUGINS, "Adding to list node (NOT FIRST)- %s\n", ip4_to_string(&buf, *ipv4));
1234     memcpy(&neighbor_to_add->neighbor_ip_addr.v4, ipv4, sizeof(neighbor_to_add->neighbor_ip_addr.v4));
1235     list_add(&(neighbor_to_add->list), &ListOfObampNodes);
1236     init_overlay_neighbor(neighbor_to_add);
1237     neighbor_to_add->status = status;
1238     CoreElection();
1239   }                             //end else
1240   return 0;
1241 }                               //End AddObampNode
1242
1243
1244
1245 /* -------------------------------------------------------------------------
1246  * Function   : PacketReceivedFromOLSR
1247  * Description: Handle a received packet from a OLSR message
1248  * Input      : Obamp Message
1249  * Output     : none
1250  * Return     : none
1251  * ------------------------------------------------------------------------- */
1252 static void
1253 PacketReceivedFromOLSR(union olsr_ip_addr *originator, const uint8_t *obamp_message, int len)
1254 {
1255   u_int8_t MessageID = obamp_message[0];
1256   const struct OBAMP_alive *alive;
1257 #if !defined(REMOVE_LOG_DEBUG)
1258   struct ipaddr_str buf;
1259 #endif
1260
1261   struct in_addr *myOriginator = (struct in_addr *)originator;
1262
1263 //TODO: this is useless now
1264   len = 0;
1265
1266 //See obamp.h
1267   switch (MessageID) {
1268
1269   case OBAMP_ALIVE:
1270     OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_ALIVE from %s\n", ip4_to_string(&buf, *myOriginator));
1271     alive = (const struct OBAMP_alive *)obamp_message;
1272     addObampNode4(myOriginator, alive->status);
1273     printObampNodesList();
1274
1275     break;
1276   }
1277
1278
1279 }                               /* PacketReceivedFromOLSR */
1280
1281
1282 //OLSR parser, received OBAMP messages
1283 void
1284 olsr_parser(struct olsr_message *msg, struct interface *in_if
1285             __attribute__ ((unused)), union olsr_ip_addr *ipaddr, enum duplicate_status status __attribute__ ((unused)))
1286 {
1287   //OLSR_DEBUG(LOG_PLUGINS, "OBAMP PLUGIN: Received msg in parser\n");
1288
1289   if (msg->type != MESSAGE_TYPE) {
1290     return;
1291   }
1292
1293   /* Check if message originated from this node.
1294    *         If so - back off */
1295   if (olsr_ipcmp(&msg->originator, &olsr_cnf->router_id) == 0)
1296     return;
1297
1298   /* Check that the neighbor this message was received from is symmetric.
1299    *         If not - back off*/
1300   if (check_neighbor_link(ipaddr) != SYM_LINK) {
1301     //struct ipaddr_str strbuf;
1302     return;
1303   }
1304
1305   PacketReceivedFromOLSR(&msg->originator, msg->payload, msg->end - msg->payload);
1306 }
1307
1308 //Sends a packet in the OLSR network
1309 void
1310 olsr_obamp_gen(void *packet, int len)
1311 {
1312   /* send buffer: huge */
1313   uint8_t buffer[10240];
1314   struct olsr_message msg;
1315   struct interface *ifn;
1316   uint8_t *curr, *sizeptr;
1317
1318   /* fill message */
1319   msg.type = MESSAGE_TYPE;
1320   msg.vtime = OBAMP_VALID_TIME * MSEC_PER_SEC;
1321   msg.originator = olsr_cnf->router_id;
1322   msg.ttl = MAX_TTL;
1323   msg.hopcnt = 0;
1324   msg.seqno = get_msg_seqno();
1325   msg.size = 0; /* put in later */
1326
1327   curr = buffer;
1328   sizeptr = olsr_put_msg_hdr(&curr, &msg);
1329   memcpy(curr, packet, len);
1330
1331   len = curr - buffer + len;
1332   pkt_put_u16(&sizeptr, len);
1333
1334   /* looping trough interfaces */
1335   OLSR_FOR_ALL_INTERFACES(ifn) {
1336     if (net_outbuffer_push(ifn, buffer, len) != len) {
1337       /* send data and try again */
1338       net_output(ifn);
1339       if (net_outbuffer_push(ifn, buffer, len) != len) {
1340         OLSR_DEBUG(LOG_PLUGINS, "OBAMP PLUGIN: could not send on interface: %s\n", ifn->int_name);
1341       }
1342     }
1343   }
1344   OLSR_FOR_ALL_INTERFACES_END(ifn);
1345 }
1346
1347 void
1348 outer_tree_create(void *x)
1349 {
1350
1351   struct ObampNode *tmp;               //temp pointers used when parsing the list
1352   struct list_head *pos;
1353
1354
1355   if ((DoIHaveATreeLink() == 0) && (myState->iamcore == 0)) {   //If there are not tree links
1356
1357     if (list_empty(&ListOfObampNodes) == 0) {   //if the list is NOT empty
1358
1359
1360       if (DoIHaveAMeshLink() == 0) {
1361         OLSR_DEBUG(LOG_PLUGINS, "Weird, no mesh links. Maybe other OBAMP nodes are very far (HUGE ETX)");
1362
1363       } else {
1364
1365         //Update my current IP address
1366         memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
1367         //OLSR_DEBUG(LOG_PLUGINS,"SETUP: my IP - %s",ip4_to_string(&buf,myState->myipaddr.v4));
1368         list_for_each(pos, &ListOfObampNodes) {
1369           tmp = list_entry(pos, struct ObampNode, list);
1370           if ((tmp->neighbor_ip_addr.v4.s_addr < myState->myipaddr.v4.s_addr) && (tmp->isMesh == 1)) {
1371             return;             //I have a neighbor that will send a outer tree create for me
1372           }
1373         }
1374         //tree create
1375         OLSR_DEBUG(LOG_PLUGINS, "OUTER TREE CREATE");
1376         tmp = select_tree_anchor();
1377         if (tmp == NULL) {
1378           OLSR_DEBUG(LOG_PLUGINS, "CANT FIND ANCHOR");
1379           return;
1380         }
1381         tmp->isMesh = 1;
1382         tmp->outerTreeLink = 1;
1383         myState->OldParentId.v4 = tmp->neighbor_ip_addr.v4;
1384         myState->ParentId.v4 = tmp->neighbor_ip_addr.v4;
1385         myState->TreeHeartBeat = TREE_HEARTBEAT;
1386         tree_link_req(&tmp->neighbor_ip_addr.v4);
1387
1388       }
1389
1390
1391     } else {
1392       OLSR_DEBUG(LOG_PLUGINS, "List empty can't send OUTER_TREE_CREATE");
1393     }
1394   }
1395   x = NULL;
1396 }
1397
1398
1399 void
1400 tree_create(void *x)
1401 {
1402 #if !defined(REMOVE_LOG_DEBUG)
1403   struct ipaddr_str buf;
1404 #endif
1405   struct ObampNode *tmp;               //temp pointers used when parsing the list
1406   struct list_head *pos;
1407
1408 //Check if I'm core
1409   if (myState->iamcore == 1) {
1410
1411     if (list_empty(&ListOfObampNodes) == 0) {   //if the list is NOT empty
1412
1413       //Scroll the list
1414       list_for_each(pos, &ListOfObampNodes) {
1415
1416         tmp = list_entry(pos, struct ObampNode, list);
1417         if (tmp->isMesh == 1) { //Is neighbor
1418           //send tree create
1419
1420           tree_create_gen(&tmp->neighbor_ip_addr.v4);
1421
1422
1423           OLSR_DEBUG(LOG_PLUGINS, "CORE SENDS TREE CREATE TO node %s ", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1424
1425         }
1426       }
1427     } else {
1428       OLSR_DEBUG(LOG_PLUGINS, "List empty can't send TREE_CREATE");
1429     }
1430
1431   }
1432
1433   x = NULL;
1434 }
1435
1436
1437
1438
1439 void
1440 mesh_create(void *x)
1441 {
1442 #if !defined(REMOVE_LOG_DEBUG)
1443   struct ipaddr_str buf;
1444 #endif
1445   struct ObampNode *tmp;               //temp pointers used when parsing the list
1446   struct list_head *pos;
1447
1448   struct rt_entry *rt;                 //"rt->rt_best->rtp_metric.cost" is the value you are looking for, a 32 bit
1449
1450   unsigned int mincost = 5;
1451
1452   int meshchanged = 0;
1453
1454   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1455
1456     //Scroll the list
1457     list_for_each(pos, &ListOfObampNodes) {
1458
1459       tmp = list_entry(pos, struct ObampNode, list);
1460
1461       //set every OBAMP node to be NOT neighbor
1462       tmp->wasMesh = tmp->isMesh;
1463
1464       //MeshLock in case mesh link is requested from neighbor
1465       if (tmp->MeshLock == 0 && tmp->outerTreeLink == 0)
1466         tmp->isMesh = 0;
1467
1468       rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
1469
1470       if (rt == NULL) {         //route is not present yet
1471         continue;
1472       }
1473       //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);
1474
1475       if (rt->rt_best->rtp_metric.cost / 65536 > 5) {
1476         continue;               //we not not consider links that are poorer than ETX=5
1477       }
1478       //update min cost
1479       if ((rt->rt_best->rtp_metric.cost / 65536) < mincost)
1480         mincost = (rt->rt_best->rtp_metric.cost / 65536);
1481
1482     }                           //end for each
1483
1484     //now that I know the mincost to the closer OBAMP node I choose my neighbor set
1485     list_for_each(pos, &ListOfObampNodes) {
1486
1487       tmp = list_entry(pos, struct ObampNode, list);
1488       rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
1489
1490       if (rt == NULL) {         //route is not present yet
1491         continue;
1492       }
1493
1494       if (rt->rt_best->rtp_metric.cost / 65536 > 5) {
1495         continue;               //we not not consider links that are poorer than ETX=5
1496       }
1497
1498       if ((rt->rt_best->rtp_metric.cost / 65536) - 1 < mincost) {       //Choose for mesh
1499
1500         tmp->isMesh = 1;
1501         OLSR_DEBUG(LOG_PLUGINS, "Choosed Overlay Neighbor node %s costs %u", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4),
1502                    rt->rt_best->rtp_metric.cost / 65536);
1503
1504         obamp_hello(&tmp->neighbor_ip_addr.v4);
1505
1506
1507       }
1508
1509       if (tmp->outerTreeLink == 1)
1510         obamp_hello(&tmp->neighbor_ip_addr.v4);
1511
1512
1513       if (tmp->isMesh != tmp->wasMesh) {
1514         meshchanged++;
1515         if (tmp->isMesh == 0 && tmp->isTree == 1) {
1516
1517           tmp->isTree = 0;
1518           send_destroy_tree_link(&tmp->neighbor_ip_addr.v4);
1519         
1520         if (memcmp(&tmp->neighbor_ip_addr.v4, &myState->ParentId.v4, sizeof(struct in_addr)) == 0) {
1521                 OLSR_DEBUG(LOG_PLUGINS,"RESET TREE LINKS: I lost tree link with my PARENT");
1522                 reset_tree_links();
1523         }       
1524
1525         }
1526       }
1527
1528     }                           //end for each
1529
1530     if (meshchanged) {
1531       //trigger signalling
1532     }
1533
1534
1535   } else {
1536     OLSR_DEBUG(LOG_PLUGINS, "List empty can't create Overlay Mesh");
1537   }
1538
1539   x = NULL;
1540 }
1541
1542
1543 void
1544 purge_nodes(void *x)
1545 {
1546 #if !defined(REMOVE_LOG_DEBUG)
1547   struct ipaddr_str buf;
1548 #endif
1549   struct ObampNode *tmp;
1550   struct list_head *pos;
1551
1552   int nodesdeleted = 0;
1553
1554   if (myState->TreeHeartBeat > 0)
1555     myState->TreeHeartBeat--;
1556
1557   if (myState->TreeRequestDelay > 0)
1558     myState->TreeRequestDelay--;
1559
1560   if (myState->TreeHeartBeat == 0 && myState->iamcore == 0){ 
1561     OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
1562     reset_tree_links();
1563     }
1564
1565 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP: Timer Expired Purging Nodes");
1566
1567
1568   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1569
1570     list_for_each(pos, &ListOfObampNodes) {
1571
1572       tmp = list_entry(pos, struct ObampNode, list);
1573       tmp->Texpire--;
1574       if (tmp->MeshLock != 0)
1575         tmp->MeshLock--;
1576
1577       //OLSR_DEBUG(LOG_PLUGINS,"Updating node %s with Texpire %d",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4),tmp->Texpire);
1578       if (tmp->Texpire == 0) {  //purge
1579         OLSR_DEBUG(LOG_PLUGINS, "Purging node %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1580         list_del(pos);
1581         //OLSR_DEBUG(LOG_PLUGINS,"OBAMP CHECK EMPTY %d",list_empty(&ListOfObampNodes));
1582
1583         free(tmp);
1584         nodesdeleted++;
1585       }
1586
1587     }
1588
1589     if (nodesdeleted != 0)
1590       CoreElection();
1591
1592   } else {
1593 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP: List empty");
1594
1595   }
1596
1597   x = NULL;
1598 }
1599
1600
1601 void
1602 obamp_alive_gen(void *x  __attribute__ ((unused)))
1603 {
1604   struct OBAMP_alive myAlive;
1605   OLSR_DEBUG(LOG_PLUGINS, "Calling obamp_alive_gen\n");
1606
1607   memset(&myAlive, 0, sizeof(myAlive));
1608   myAlive.MessageID = OBAMP_ALIVE;
1609   myAlive.status = DoIHaveATreeLink();
1610   olsr_obamp_gen(&myAlive, sizeof(struct OBAMP_alive));
1611 }
1612
1613
1614
1615 /*
1616 When a packet is captured on the sniffing interfaces, it is called EncapFlowInObamp
1617 here we check if the packet is multicast and we forward it to the overlay neighbors if we have a link tree
1618 */
1619
1620 void
1621 EncapFlowInObamp(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
1622 {
1623   unsigned char ipPacket[1500];        //TODO: optimize me
1624
1625 #if !defined(REMOVE_LOG_DEBUG)
1626   struct ipaddr_str buf;
1627 #endif
1628   struct ObampNode *tmp;
1629   struct list_head *pos;
1630
1631   union olsr_ip_addr dst;              /* Destination IP address in captured packet */
1632   struct ip *ipHeader;                 /* The IP header inside the captured IP packet */
1633   struct ip6_hdr *ipHeader6;           /* The IP header inside the captured IP packet */
1634
1635   if (skfd >= 0) {
1636     struct sockaddr_ll pktAddr;
1637     socklen_t addrLen = sizeof(pktAddr);
1638     int nBytes;
1639
1640     nBytes = recvfrom(skfd, ipPacket, 1500,     //TODO: optimize me
1641                       0, (struct sockaddr *)&pktAddr, &addrLen);
1642     if (nBytes < 0) {
1643
1644       return;                   /* for */
1645     }
1646
1647     /* if (nBytes < 0) */
1648     /* Check if the number of received bytes is large enough for an IP
1649      * packet which contains at least a minimum-size IP header.
1650      * Note: There is an apparent bug in the packet socket implementation in
1651      * combination with VLAN interfaces. On a VLAN interface, the value returned
1652      * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
1653      * returned on a non-VLAN interface, for the same ethernet frame. */
1654     if (nBytes < (int)sizeof(struct ip)) {
1655
1656       OLSR_DEBUG(LOG_PLUGINS, "Captured frame too short");
1657       return;                   /* for */
1658     }
1659
1660     if (pktAddr.sll_pkttype == PACKET_OUTGOING || pktAddr.sll_pkttype == PACKET_MULTICAST)      // ||
1661       //pktAddr.sll_pkttype == PACKET_BROADCAST)
1662     {
1663
1664       //do here
1665       if ((ipPacket[0] & 0xf0) == 0x40) {       //IPV4
1666
1667         ipHeader = (struct ip *)ipPacket;
1668
1669         dst.v4 = ipHeader->ip_dst;
1670
1671         /* Only forward multicast packets. If configured, also forward local broadcast packets */
1672         if (IsMulticast(&dst)) {
1673           /* continue */
1674         } else {
1675           return;
1676         }
1677         if (ipHeader->ip_p != SOL_UDP) {
1678           /* Not UDP */
1679           OLSR_DEBUG(LOG_PLUGINS, "NON UDP PACKET\n");
1680           return;               /* for */
1681         } else {
1682           //Forward the packet to tree links
1683           if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1684
1685             list_for_each(pos, &ListOfObampNodes) {
1686
1687               tmp = list_entry(pos, struct ObampNode, list);
1688               if (tmp->isTree == 1) {
1689
1690                 OLSR_DEBUG(LOG_PLUGINS, "Pushing data to Tree link to %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1691                 SendOBAMPData(&tmp->neighbor_ip_addr.v4, ipPacket, nBytes);
1692
1693               }
1694             }
1695           }
1696         }
1697
1698       }                         //END IPV4
1699
1700       else if ((ipPacket[0] & 0xf0) == 0x60) {  //IPv6
1701
1702         ipHeader6 = (struct ip6_hdr *)ipPacket;
1703         if (ipHeader6->ip6_dst.s6_addr[0] == 0xff)      //Multicast
1704         {
1705           //Continua
1706         } else {
1707           return;               //not multicast
1708         }
1709         if (ipHeader6->ip6_nxt != SOL_UDP) {
1710           /* Not UDP */
1711           OLSR_DEBUG(LOG_PLUGINS, "NON UDP PACKET\n");
1712           return;               /* for */
1713         }
1714
1715       }                         //END IPV6
1716       else
1717         return;                 //Is not IP packet
1718
1719       // send the packet to OLSR forward mechanism
1720       // SendOBAMPData(&tmp->neighbor_ip_addr.v6,ipPacket,nBytes);
1721
1722
1723     }                           /* if (pktAddr.sll_pkttype == ...) */
1724   }                             /* if (skfd >= 0 && (FD_ISSET...)) */
1725 }                               /* EncapFlowInObamp */
1726
1727 //This function is called from olsrd_plugin.c and adds to the list the interfaces specified in the configuration file to sniff multicast traffic
1728 int
1729 AddObampSniffingIf(const char *ifName,
1730                    void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
1731 {
1732
1733   struct ObampSniffingIf *ifToAdd;
1734
1735   OLSR_DEBUG(LOG_PLUGINS, "AddObampSniffingIf");
1736
1737
1738   assert(ifName != NULL);
1739
1740   ifToAdd = olsr_malloc(sizeof(struct ObampSniffingIf), "OBAMPSniffingIf");
1741
1742   strncpy(ifToAdd->ifName, ifName, 16); //TODO: 16 fix this
1743   ifToAdd->ifName[15] = '\0';   /* Ensures null termination */
1744
1745   OLSR_DEBUG(LOG_PLUGINS, "Adding interface to list");
1746
1747   list_add(&(ifToAdd->list), &ListOfObampSniffingIf);
1748
1749   OLSR_DEBUG(LOG_PLUGINS, "Adding if %s to list of ObampSniffingIfaces", ifToAdd->ifName);
1750
1751   return 0;
1752 }
1753
1754
1755 int
1756 PreInitOBAMP(void)
1757 {
1758   INIT_LIST_HEAD(&ListOfObampSniffingIf);
1759   return 0;
1760
1761 }
1762
1763 //Start here !!
1764
1765 int
1766 InitOBAMP(void)
1767 {
1768 #if !defined(REMOVE_LOG_DEBUG)
1769   struct ipaddr_str buf;
1770 #endif
1771
1772 //Structs necessary for timers
1773
1774   struct timer_entry *OBAMP_alive_timer;
1775   struct timer_entry *purge_nodes_timer;
1776   struct timer_entry *mesh_create_timer;
1777   struct timer_entry *tree_create_timer;
1778   struct timer_entry *outer_tree_create_timer;
1779   struct timer_entry *unsolicited_tree_destroy_timer;
1780
1781
1782
1783   struct olsr_cookie_info *OBAMP_alive_gen_timer_cookie = NULL;
1784   struct olsr_cookie_info *purge_nodes_timer_cookie = NULL;
1785   struct olsr_cookie_info *mesh_create_timer_cookie = NULL;
1786   struct olsr_cookie_info *tree_create_timer_cookie = NULL;
1787   struct olsr_cookie_info *outer_tree_create_timer_cookie = NULL;
1788   struct olsr_cookie_info *unsolicited_tree_destroy_timer_cookie = NULL;
1789
1790   if (olsr_cnf->ip_version == AF_INET6) {
1791     OLSR_ERROR(LOG_PLUGINS, "OBAMP does not support IPv6 at the moment.");
1792     return 1;
1793   }
1794
1795 //Setting OBAMP node state
1796   myState = olsr_malloc(sizeof(struct ObampNodeState), "OBAMPNodeState");
1797   myState->iamcore = 1;
1798   myState->TreeHeartBeat = 0;
1799   myState->TreeRequestDelay = 0;
1800   memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
1801   myState->CoreAddress = myState->myipaddr;
1802
1803   myState->DataSequenceNumber = 0;
1804   myState->TreeCreateSequenceNumber = 0;
1805   myState->tree_req_sn = 0;     //TODO: start from random number ?
1806
1807   memset(&myState->ParentId.v4, 0, sizeof(myState->ParentId.v4));
1808   memset(&myState->OldParentId.v4, 1, sizeof(myState->OldParentId.v4));
1809
1810   OLSR_DEBUG(LOG_PLUGINS, "SETUP: my IP - %s", ip4_to_string(&buf, myState->myipaddr.v4));
1811
1812   INIT_LIST_HEAD(&ListOfObampNodes);
1813
1814 //OLSR cookies stuff for timers
1815   OBAMP_alive_gen_timer_cookie = olsr_alloc_cookie("OBAMP Alive Generation", OLSR_COOKIE_TYPE_TIMER);
1816   purge_nodes_timer_cookie = olsr_alloc_cookie("purge nodes Generation", OLSR_COOKIE_TYPE_TIMER);
1817   mesh_create_timer_cookie = olsr_alloc_cookie("mesh create Generation", OLSR_COOKIE_TYPE_TIMER);
1818   tree_create_timer_cookie = olsr_alloc_cookie("tree create Generation", OLSR_COOKIE_TYPE_TIMER);
1819   outer_tree_create_timer_cookie = olsr_alloc_cookie("outer tree create Generation", OLSR_COOKIE_TYPE_TIMER);
1820   unsolicited_tree_destroy_timer_cookie = olsr_alloc_cookie("tree destroy Generation", OLSR_COOKIE_TYPE_TIMER);
1821
1822
1823 //Tells OLSR to launch olsr_parser when the packets for this plugin arrive
1824   olsr_parser_add_function(&olsr_parser, PARSER_TYPE);
1825
1826 // start to send alive messages to appear in other joined lists
1827   OBAMP_alive_timer =
1828     olsr_start_timer(OBAMP_ALIVE_EIVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &obamp_alive_gen, NULL,
1829                      OBAMP_alive_gen_timer_cookie);
1830
1831 // start timer to purge nodes from list in softstate fashion
1832   purge_nodes_timer =
1833     olsr_start_timer(_Texpire_timer_ * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &purge_nodes, NULL,
1834                      purge_nodes_timer_cookie);
1835
1836 //start timer to create mesh
1837   mesh_create_timer =
1838     olsr_start_timer(OBAMP_MESH_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &mesh_create, NULL,
1839                      mesh_create_timer_cookie);
1840
1841 //start timer for tree create procedure
1842   tree_create_timer =
1843     olsr_start_timer(OBAMP_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &tree_create, NULL,
1844                      tree_create_timer_cookie);
1845
1846 //start timer for tree create procedure
1847   outer_tree_create_timer =
1848     olsr_start_timer(OBAMP_OUTER_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &outer_tree_create, NULL,
1849                      tree_create_timer_cookie);
1850
1851 //start timer for tree create procedure
1852   unsolicited_tree_destroy_timer =
1853     olsr_start_timer(30 * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &unsolicited_tree_destroy, NULL,
1854                      unsolicited_tree_destroy_timer_cookie);
1855
1856 //Create udp server socket for OBAMP signalling and register it to the scheduler
1857   OLSR_DEBUG(LOG_PLUGINS, "Launch Udp Servers");
1858   if (UdpServer() < 0) {
1859     OLSR_DEBUG(LOG_PLUGINS, "Problem in Launch Udp Servers");
1860
1861   };
1862
1863 //Creates a socket for sniffing multicast traffic and registers it to the scheduler
1864   CreateObampSniffingInterfaces();
1865
1866   return 0;
1867 }
1868
1869 /* -------------------------------------------------------------------------
1870  * Function   : CloseOBAMP
1871  * Description: Close the OBAMP plugin and clean up
1872  * Input      : none
1873  * Output     : none
1874  * Return     : none
1875  * Data Used  :
1876  * ------------------------------------------------------------------------- */
1877 void
1878 CloseOBAMP(void)
1879 {
1880 //do something here
1881 }