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