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