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