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