abce31dd2d7680ca5142cbaf435cc4ba3f2fa050
[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   else { //Refresh tree link with parent if existing
1411         
1412         struct in_addr zeros;
1413         memset(&zeros,0,sizeof(struct in_addr));
1414          
1415         if (memcmp(&zeros, &myState->ParentId.v4, sizeof(struct in_addr)) != 0) {
1416                 tree_link_req(&myState->ParentId.v4);
1417         }
1418   }
1419
1420   x = NULL;
1421 }
1422
1423
1424
1425
1426 void
1427 mesh_create(void *x)
1428 {
1429 #if !defined(REMOVE_LOG_DEBUG)
1430   struct ipaddr_str buf;
1431 #endif
1432   struct ObampNode *tmp;               //temp pointers used when parsing the list
1433   struct list_head *pos;
1434
1435   struct rt_entry *rt;                 //"rt->rt_best->rtp_metric.cost" is the value you are looking for, a 32 bit
1436
1437   unsigned int mincost = 5;
1438
1439   int meshchanged = 0;
1440
1441   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1442
1443     //Scroll the list
1444     list_for_each(pos, &ListOfObampNodes) {
1445
1446       tmp = list_entry(pos, struct ObampNode, list);
1447
1448       //set every OBAMP node to be NOT neighbor
1449       tmp->wasMesh = tmp->isMesh;
1450
1451       //MeshLock in case mesh link is requested from neighbor
1452       if (tmp->MeshLock == 0 && tmp->outerTreeLink == 0)
1453         tmp->isMesh = 0;
1454
1455       rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
1456
1457       if (rt == NULL) {         //route is not present yet
1458         continue;
1459       }
1460       //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);
1461
1462       if (rt->rt_best->rtp_metric.cost / 65536 > 5) {
1463         continue;               //we not not consider links that are poorer than ETX=5
1464       }
1465       //update min cost
1466       if ((rt->rt_best->rtp_metric.cost / 65536) < mincost)
1467         mincost = (rt->rt_best->rtp_metric.cost / 65536);
1468
1469     }                           //end for each
1470
1471     //now that I know the mincost to the closer OBAMP node I choose my neighbor set
1472     list_for_each(pos, &ListOfObampNodes) {
1473
1474       tmp = list_entry(pos, struct ObampNode, list);
1475       rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
1476
1477       if (rt == NULL) {         //route is not present yet
1478         continue;
1479       }
1480
1481       if (rt->rt_best->rtp_metric.cost / 65536 > 5) {
1482         continue;               //we not not consider links that are poorer than ETX=5
1483       }
1484
1485       if ((rt->rt_best->rtp_metric.cost / 65536) - 1 < mincost) {       //Choose for mesh
1486
1487         tmp->isMesh = 1;
1488         OLSR_DEBUG(LOG_PLUGINS, "Choosed Overlay Neighbor node %s costs %u", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4),
1489                    rt->rt_best->rtp_metric.cost / 65536);
1490
1491         obamp_hello(&tmp->neighbor_ip_addr.v4);
1492
1493
1494       }
1495
1496       if (tmp->outerTreeLink == 1)
1497         obamp_hello(&tmp->neighbor_ip_addr.v4);
1498
1499
1500       if (tmp->isMesh != tmp->wasMesh) {
1501         meshchanged++;
1502         if (tmp->isMesh == 0 && tmp->isTree == 1) {
1503
1504           tmp->isTree = 0;
1505           send_destroy_tree_link(&tmp->neighbor_ip_addr.v4);
1506         
1507         if (memcmp(&tmp->neighbor_ip_addr.v4, &myState->ParentId.v4, sizeof(struct in_addr)) == 0) {
1508                 OLSR_DEBUG(LOG_PLUGINS,"RESET TREE LINKS: I lost tree link with my PARENT");
1509                 reset_tree_links();
1510         }       
1511
1512         }
1513       }
1514
1515     }                           //end for each
1516
1517     if (meshchanged) {
1518       //trigger signalling
1519     }
1520
1521
1522   } else {
1523     OLSR_DEBUG(LOG_PLUGINS, "List empty can't create Overlay Mesh");
1524   }
1525
1526   x = NULL;
1527 }
1528
1529
1530 void
1531 purge_nodes(void *x)
1532 {
1533 #if !defined(REMOVE_LOG_DEBUG)
1534   struct ipaddr_str buf;
1535 #endif
1536   struct ObampNode *tmp;
1537   struct list_head *pos;
1538
1539   int nodesdeleted = 0;
1540
1541   if (myState->TreeHeartBeat > 0)
1542     myState->TreeHeartBeat--;
1543
1544   if (myState->TreeRequestDelay > 0)
1545     myState->TreeRequestDelay--;
1546
1547   if (myState->TreeHeartBeat == 0 && myState->iamcore == 0){ 
1548     OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links"); 
1549     reset_tree_links();
1550     }
1551
1552 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP: Timer Expired Purging Nodes");
1553
1554
1555   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1556
1557     list_for_each(pos, &ListOfObampNodes) {
1558
1559       tmp = list_entry(pos, struct ObampNode, list);
1560       tmp->Texpire--;
1561       if (tmp->MeshLock != 0)
1562         tmp->MeshLock--;
1563
1564       //OLSR_DEBUG(LOG_PLUGINS,"Updating node %s with Texpire %d",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4),tmp->Texpire);
1565       if (tmp->Texpire == 0) {  //purge
1566         OLSR_DEBUG(LOG_PLUGINS, "Purging node %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1567         list_del(pos);
1568         //OLSR_DEBUG(LOG_PLUGINS,"OBAMP CHECK EMPTY %d",list_empty(&ListOfObampNodes));
1569
1570         free(tmp);
1571         nodesdeleted++;
1572       }
1573
1574     }
1575
1576     if (nodesdeleted != 0)
1577       CoreElection();
1578
1579   } else {
1580 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP: List empty");
1581
1582   }
1583
1584   x = NULL;
1585 }
1586
1587
1588 void
1589 obamp_alive_gen(void *x  __attribute__ ((unused)))
1590 {
1591   struct OBAMP_alive myAlive;
1592   OLSR_DEBUG(LOG_PLUGINS, "Calling obamp_alive_gen\n");
1593
1594   memset(&myAlive, 0, sizeof(myAlive));
1595   myAlive.MessageID = OBAMP_ALIVE;
1596   myAlive.status = DoIHaveATreeLink();
1597   olsr_obamp_gen(&myAlive, sizeof(struct OBAMP_alive));
1598 }
1599
1600
1601
1602 /*
1603 When a packet is captured on the sniffing interfaces, it is called EncapFlowInObamp
1604 here we check if the packet is multicast and we forward it to the overlay neighbors if we have a link tree
1605 */
1606
1607 void
1608 EncapFlowInObamp(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
1609 {
1610   unsigned char ipPacket[1500];        //TODO: optimize me
1611
1612 #if !defined(REMOVE_LOG_DEBUG)
1613   struct ipaddr_str buf;
1614 #endif
1615   struct ObampNode *tmp;
1616   struct list_head *pos;
1617
1618   union olsr_ip_addr dst;              /* Destination IP address in captured packet */
1619   struct ip *ipHeader;                 /* The IP header inside the captured IP packet */
1620   struct ip6_hdr *ipHeader6;           /* The IP header inside the captured IP packet */
1621
1622   if (skfd >= 0) {
1623     struct sockaddr_ll pktAddr;
1624     socklen_t addrLen = sizeof(pktAddr);
1625     int nBytes;
1626
1627     nBytes = recvfrom(skfd, ipPacket, 1500,     //TODO: optimize me
1628                       0, (struct sockaddr *)&pktAddr, &addrLen);
1629     if (nBytes < 0) {
1630
1631       return;                   /* for */
1632     }
1633
1634     /* if (nBytes < 0) */
1635     /* Check if the number of received bytes is large enough for an IP
1636      * packet which contains at least a minimum-size IP header.
1637      * Note: There is an apparent bug in the packet socket implementation in
1638      * combination with VLAN interfaces. On a VLAN interface, the value returned
1639      * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
1640      * returned on a non-VLAN interface, for the same ethernet frame. */
1641     if (nBytes < (int)sizeof(struct ip)) {
1642
1643       OLSR_DEBUG(LOG_PLUGINS, "Captured frame too short");
1644       return;                   /* for */
1645     }
1646
1647     if (pktAddr.sll_pkttype == PACKET_OUTGOING || pktAddr.sll_pkttype == PACKET_MULTICAST)      // ||
1648       //pktAddr.sll_pkttype == PACKET_BROADCAST)
1649     {
1650
1651       //do here
1652       if ((ipPacket[0] & 0xf0) == 0x40) {       //IPV4
1653
1654         ipHeader = (struct ip *)ipPacket;
1655
1656         dst.v4 = ipHeader->ip_dst;
1657
1658         /* Only forward multicast packets. If configured, also forward local broadcast packets */
1659         if (IsMulticast(&dst)) {
1660           /* continue */
1661         } else {
1662           return;
1663         }
1664         if (ipHeader->ip_p != SOL_UDP) {
1665           /* Not UDP */
1666           OLSR_DEBUG(LOG_PLUGINS, "NON UDP PACKET\n");
1667           return;               /* for */
1668         } else {
1669           //Forward the packet to tree links
1670           if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1671
1672             list_for_each(pos, &ListOfObampNodes) {
1673
1674               tmp = list_entry(pos, struct ObampNode, list);
1675               if (tmp->isTree == 1) {
1676
1677                 OLSR_DEBUG(LOG_PLUGINS, "Pushing data to Tree link to %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1678                 SendOBAMPData(&tmp->neighbor_ip_addr.v4, ipPacket, nBytes);
1679
1680               }
1681             }
1682           }
1683         }
1684
1685       }                         //END IPV4
1686
1687       else if ((ipPacket[0] & 0xf0) == 0x60) {  //IPv6
1688
1689         ipHeader6 = (struct ip6_hdr *)ipPacket;
1690         if (ipHeader6->ip6_dst.s6_addr[0] == 0xff)      //Multicast
1691         {
1692           //Continua
1693         } else {
1694           return;               //not multicast
1695         }
1696         if (ipHeader6->ip6_nxt != SOL_UDP) {
1697           /* Not UDP */
1698           OLSR_DEBUG(LOG_PLUGINS, "NON UDP PACKET\n");
1699           return;               /* for */
1700         }
1701
1702       }                         //END IPV6
1703       else
1704         return;                 //Is not IP packet
1705
1706       // send the packet to OLSR forward mechanism
1707       // SendOBAMPData(&tmp->neighbor_ip_addr.v6,ipPacket,nBytes);
1708
1709
1710     }                           /* if (pktAddr.sll_pkttype == ...) */
1711   }                             /* if (skfd >= 0 && (FD_ISSET...)) */
1712 }                               /* EncapFlowInObamp */
1713
1714 //This function is called from olsrd_plugin.c and adds to the list the interfaces specified in the configuration file to sniff multicast traffic
1715 int
1716 AddObampSniffingIf(const char *ifName,
1717                    void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
1718 {
1719
1720   struct ObampSniffingIf *ifToAdd;
1721
1722   OLSR_DEBUG(LOG_PLUGINS, "AddObampSniffingIf");
1723
1724
1725   assert(ifName != NULL);
1726
1727   ifToAdd = olsr_malloc(sizeof(struct ObampSniffingIf), "OBAMPSniffingIf");
1728
1729   strncpy(ifToAdd->ifName, ifName, 16); //TODO: 16 fix this
1730   ifToAdd->ifName[15] = '\0';   /* Ensures null termination */
1731
1732   OLSR_DEBUG(LOG_PLUGINS, "Adding interface to list");
1733
1734   list_add(&(ifToAdd->list), &ListOfObampSniffingIf);
1735
1736   OLSR_DEBUG(LOG_PLUGINS, "Adding if %s to list of ObampSniffingIfaces", ifToAdd->ifName);
1737
1738   return 0;
1739 }
1740
1741
1742 int
1743 PreInitOBAMP(void)
1744 {
1745   INIT_LIST_HEAD(&ListOfObampSniffingIf);
1746   return 0;
1747
1748 }
1749
1750 //Start here !!
1751
1752 int
1753 InitOBAMP(void)
1754 {
1755 #if !defined(REMOVE_LOG_DEBUG)
1756   struct ipaddr_str buf;
1757 #endif
1758
1759 //Structs necessary for timers
1760
1761   struct timer_entry *OBAMP_alive_timer;
1762   struct timer_entry *purge_nodes_timer;
1763   struct timer_entry *mesh_create_timer;
1764   struct timer_entry *tree_create_timer;
1765   struct timer_entry *outer_tree_create_timer;
1766
1767
1768
1769   struct olsr_cookie_info *OBAMP_alive_gen_timer_cookie = NULL;
1770   struct olsr_cookie_info *purge_nodes_timer_cookie = NULL;
1771   struct olsr_cookie_info *mesh_create_timer_cookie = NULL;
1772   struct olsr_cookie_info *tree_create_timer_cookie = NULL;
1773   struct olsr_cookie_info *outer_tree_create_timer_cookie = NULL;
1774
1775   if (olsr_cnf->ip_version == AF_INET6) {
1776     OLSR_ERROR(LOG_PLUGINS, "OBAMP does not support IPv6 at the moment.");
1777     return 1;
1778   }
1779
1780 //Setting OBAMP node state
1781   myState = olsr_malloc(sizeof(struct ObampNodeState), "OBAMPNodeState");
1782   myState->iamcore = 1;
1783   myState->TreeHeartBeat = 0;
1784   myState->TreeRequestDelay = 0;
1785   memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
1786   myState->CoreAddress = myState->myipaddr;
1787
1788   myState->DataSequenceNumber = 0;
1789   myState->TreeCreateSequenceNumber = 0;
1790   myState->tree_req_sn = 0;     //TODO: start from random number ?
1791
1792   memset(&myState->ParentId.v4, 0, sizeof(myState->ParentId.v4));
1793   memset(&myState->OldParentId.v4, 1, sizeof(myState->OldParentId.v4));
1794
1795   OLSR_DEBUG(LOG_PLUGINS, "SETUP: my IP - %s", ip4_to_string(&buf, myState->myipaddr.v4));
1796
1797   INIT_LIST_HEAD(&ListOfObampNodes);
1798
1799 //OLSR cookies stuff for timers
1800   OBAMP_alive_gen_timer_cookie = olsr_alloc_cookie("OBAMP Alive Generation", OLSR_COOKIE_TYPE_TIMER);
1801   purge_nodes_timer_cookie = olsr_alloc_cookie("purge nodes Generation", OLSR_COOKIE_TYPE_TIMER);
1802   mesh_create_timer_cookie = olsr_alloc_cookie("mesh create Generation", OLSR_COOKIE_TYPE_TIMER);
1803   tree_create_timer_cookie = olsr_alloc_cookie("tree create Generation", OLSR_COOKIE_TYPE_TIMER);
1804   outer_tree_create_timer_cookie = olsr_alloc_cookie("outer tree create Generation", OLSR_COOKIE_TYPE_TIMER);
1805
1806
1807 //Tells OLSR to launch olsr_parser when the packets for this plugin arrive
1808   olsr_parser_add_function(&olsr_parser, PARSER_TYPE);
1809
1810 // start to send alive messages to appear in other joined lists
1811   OBAMP_alive_timer =
1812     olsr_start_timer(OBAMP_ALIVE_EIVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &obamp_alive_gen, NULL,
1813                      OBAMP_alive_gen_timer_cookie);
1814
1815 // start timer to purge nodes from list in softstate fashion
1816   purge_nodes_timer =
1817     olsr_start_timer(_Texpire_timer_ * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &purge_nodes, NULL,
1818                      purge_nodes_timer_cookie);
1819
1820 //start timer to create mesh
1821   mesh_create_timer =
1822     olsr_start_timer(OBAMP_MESH_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &mesh_create, NULL,
1823                      mesh_create_timer_cookie);
1824
1825 //start timer for tree create procedure
1826   tree_create_timer =
1827     olsr_start_timer(OBAMP_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &tree_create, NULL,
1828                      tree_create_timer_cookie);
1829
1830 //start timer for tree create procedure
1831   outer_tree_create_timer =
1832     olsr_start_timer(OBAMP_OUTER_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &outer_tree_create, NULL,
1833                      tree_create_timer_cookie);
1834
1835
1836 //Create udp server socket for OBAMP signalling and register it to the scheduler
1837   OLSR_DEBUG(LOG_PLUGINS, "Launch Udp Servers");
1838   if (UdpServer() < 0) {
1839     OLSR_DEBUG(LOG_PLUGINS, "Problem in Launch Udp Servers");
1840
1841   };
1842
1843 //Creates a socket for sniffing multicast traffic and registers it to the scheduler
1844   CreateObampSniffingInterfaces();
1845
1846   return 0;
1847 }
1848
1849 /* -------------------------------------------------------------------------
1850  * Function   : CloseOBAMP
1851  * Description: Close the OBAMP plugin and clean up
1852  * Input      : none
1853  * Output     : none
1854  * Return     : none
1855  * Data Used  :
1856  * ------------------------------------------------------------------------- */
1857 void
1858 CloseOBAMP(void)
1859 {
1860 //do something here
1861 }