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