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