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