c6a6461ec33a61e3da1a105e03f1ea2716804ae6
[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(union olsr_ip_addr *originator, const uint8_t *obamp_message, int len)
1105 {
1106   u_int8_t MessageID = obamp_message[0];
1107   const 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 = (const 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(struct olsr_message *msg, const uint8_t *payload, const uint8_t*end, struct interface *in_if
1136             __attribute__ ((unused)), union olsr_ip_addr *ipaddr, enum duplicate_status status __attribute__ ((unused)))
1137 {
1138   //OLSR_DEBUG(LOG_PLUGINS, "OBAMP PLUGIN: Received msg in parser\n");
1139
1140   if (msg->type != MESSAGE_TYPE) {
1141     return;
1142   }
1143
1144   /* Check if message originated from this node.
1145    *         If so - back off */
1146   if (olsr_ipcmp(&msg->originator, &olsr_cnf->router_id) == 0)
1147     return;
1148
1149   /* Check that the neighbor this message was received from is symmetric.
1150    *         If not - back off*/
1151   if (check_neighbor_link(ipaddr) != SYM_LINK) {
1152     //struct ipaddr_str strbuf;
1153     return;
1154   }
1155
1156   PacketReceivedFromOLSR(&msg->originator, payload, end - payload);
1157 }
1158
1159 //Sends a packet in the OLSR network
1160 void
1161 olsr_obamp_gen(unsigned char *packet, int len)
1162 {
1163   /* send buffer: huge */
1164   uint8_t buffer[10240];
1165   struct olsr_message msg;
1166   struct interface *ifn;
1167   uint8_t *curr, *sizeptr;
1168
1169   /* fill message */
1170   msg.type = MESSAGE_TYPE;
1171   msg.vtime = OBAMP_VALID_TIME * MSEC_PER_SEC;
1172   msg.originator = olsr_cnf->router_id;
1173   msg.ttl = MAX_TTL;
1174   msg.hopcnt = 0;
1175   msg.seqno = get_msg_seqno();
1176   msg.size = 0; /* put in later */
1177
1178   curr = buffer;
1179   sizeptr = olsr_put_msg_hdr(&curr, &msg);
1180   memcpy(curr, packet, len);
1181   pkt_put_u16(&sizeptr, curr - buffer + len);
1182
1183   /* looping trough interfaces */
1184   OLSR_FOR_ALL_INTERFACES(ifn) {
1185     if (net_outbuffer_push(ifn, buffer, len) != len) {
1186       /* send data and try again */
1187       net_output(ifn);
1188       if (net_outbuffer_push(ifn, buffer, len) != len) {
1189         OLSR_DEBUG(LOG_PLUGINS, "OBAMP PLUGIN: could not send on interface: %s\n", ifn->int_name);
1190       }
1191     }
1192   }
1193   OLSR_FOR_ALL_INTERFACES_END(ifn);
1194 }
1195
1196 void
1197 outer_tree_create(void *x)
1198 {
1199
1200   struct ObampNode *tmp;               //temp pointers used when parsing the list
1201   struct list_head *pos;
1202
1203
1204   if ((DoIHaveATreeLink() == 0) && (myState->iamcore == 0)) {   //If there are not tree links
1205
1206     if (list_empty(&ListOfObampNodes) == 0) {   //if the list is NOT empty
1207
1208
1209       if (DoIHaveAMeshLink() == 0) {
1210         OLSR_DEBUG(LOG_PLUGINS, "Weird, no mesh links. Maybe other OBAMP nodes are very far (HUGE ETX)");
1211
1212       } else {
1213
1214         //Update my current IP address
1215         memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
1216         //OLSR_DEBUG(LOG_PLUGINS,"SETUP: my IP - %s",ip4_to_string(&buf,myState->myipaddr.v4));
1217         list_for_each(pos, &ListOfObampNodes) {
1218           tmp = list_entry(pos, struct ObampNode, list);
1219           if ((tmp->neighbor_ip_addr.v4.s_addr < myState->myipaddr.v4.s_addr) && (tmp->isMesh == 1)) {
1220             return;             //I have a neighbor that will send a outer tree create for me
1221           }
1222         }
1223         //tree create
1224         OLSR_DEBUG(LOG_PLUGINS, "OUTER TREE CREATE");
1225         tmp = select_tree_anchor();
1226         if (tmp == NULL) {
1227           OLSR_DEBUG(LOG_PLUGINS, "CANT FIND ANCHOR");
1228           return;
1229         }
1230         tmp->isMesh = 1;
1231         tmp->outerTreeLink = 1;
1232         myState->OldParentId.v4 = tmp->neighbor_ip_addr.v4;
1233         myState->ParentId.v4 = tmp->neighbor_ip_addr.v4;
1234         myState->TreeHeartBeat = TREE_HEARTBEAT;
1235         tree_link_req(&tmp->neighbor_ip_addr.v4);
1236
1237       }
1238
1239
1240     } else {
1241       OLSR_DEBUG(LOG_PLUGINS, "List empty can't send OUTER_TREE_CREATE");
1242     }
1243   }
1244   x = NULL;
1245 }
1246
1247
1248 void
1249 tree_create(void *x)
1250 {
1251 #if !defined(REMOVE_LOG_DEBUG)
1252   struct ipaddr_str buf;
1253 #endif
1254   struct ObampNode *tmp;               //temp pointers used when parsing the list
1255   struct list_head *pos;
1256
1257 //Check if I'm core
1258   if (myState->iamcore == 1) {
1259
1260     if (list_empty(&ListOfObampNodes) == 0) {   //if the list is NOT empty
1261
1262       //Scroll the list
1263       list_for_each(pos, &ListOfObampNodes) {
1264
1265         tmp = list_entry(pos, struct ObampNode, list);
1266         if (tmp->isMesh == 1) { //Is neighbor
1267           //send tree create
1268
1269           tree_create_gen(&tmp->neighbor_ip_addr.v4);
1270
1271
1272           OLSR_DEBUG(LOG_PLUGINS, "CORE SENDS TREE CREATE TO node %s ", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1273
1274         }
1275       }
1276     } else {
1277       OLSR_DEBUG(LOG_PLUGINS, "List empty can't send TREE_CREATE");
1278     }
1279
1280   }
1281
1282   x = NULL;
1283 }
1284
1285
1286
1287
1288 void
1289 mesh_create(void *x)
1290 {
1291 #if !defined(REMOVE_LOG_DEBUG)
1292   struct ipaddr_str buf;
1293 #endif
1294   struct ObampNode *tmp;               //temp pointers used when parsing the list
1295   struct list_head *pos;
1296
1297   struct rt_entry *rt;                 //"rt->rt_best->rtp_metric.cost" is the value you are looking for, a 32 bit
1298
1299   unsigned int mincost = 5;
1300
1301   int meshchanged = 0;
1302
1303   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1304
1305     //Scroll the list
1306     list_for_each(pos, &ListOfObampNodes) {
1307
1308       tmp = list_entry(pos, struct ObampNode, list);
1309
1310       //set every OBAMP node to be NOT neighbor
1311       tmp->wasMesh = tmp->isMesh;
1312
1313       //MeshLock in case mesh link is requested from neighbor
1314       if (tmp->MeshLock == 0 && tmp->outerTreeLink == 0)
1315         tmp->isMesh = 0;
1316
1317       rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
1318
1319       if (rt == NULL) {         //route is not present yet
1320         continue;
1321       }
1322       //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);
1323
1324       if (rt->rt_best->rtp_metric.cost / 65536 > 5) {
1325         continue;               //we not not consider links that are poorer than ETX=5
1326       }
1327       //update min cost
1328       if ((rt->rt_best->rtp_metric.cost / 65536) < mincost)
1329         mincost = (rt->rt_best->rtp_metric.cost / 65536);
1330
1331     }                           //end for each
1332
1333     //now that I know the mincost to the closer OBAMP node I choose my neighbor set
1334     list_for_each(pos, &ListOfObampNodes) {
1335
1336       tmp = list_entry(pos, struct ObampNode, list);
1337       rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
1338
1339       if (rt == NULL) {         //route is not present yet
1340         continue;
1341       }
1342
1343       if (rt->rt_best->rtp_metric.cost / 65536 > 5) {
1344         continue;               //we not not consider links that are poorer than ETX=5
1345       }
1346
1347       if ((rt->rt_best->rtp_metric.cost / 65536) - 1 < mincost) {       //Choose for mesh
1348
1349         tmp->isMesh = 1;
1350         OLSR_DEBUG(LOG_PLUGINS, "Choosed Overlay Neighbor node %s costs %u", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4),
1351                    rt->rt_best->rtp_metric.cost / 65536);
1352
1353         obamp_hello(&tmp->neighbor_ip_addr.v4);
1354
1355
1356       }
1357
1358       if (tmp->outerTreeLink == 1)
1359         obamp_hello(&tmp->neighbor_ip_addr.v4);
1360
1361
1362       if (tmp->isMesh != tmp->wasMesh) {
1363         meshchanged++;
1364         if (tmp->isMesh == 0 && tmp->isTree == 1) {
1365
1366           tmp->isTree = 0;
1367
1368         }
1369       }
1370
1371     }                           //end for each
1372
1373     if (meshchanged) {
1374       //trigger signalling
1375     }
1376
1377
1378   } else {
1379     OLSR_DEBUG(LOG_PLUGINS, "List empty can't create Overlay Mesh");
1380   }
1381
1382   x = NULL;
1383 }
1384
1385
1386 void
1387 purge_nodes(void *x)
1388 {
1389 #if !defined(REMOVE_LOG_DEBUG)
1390   struct ipaddr_str buf;
1391 #endif
1392   struct ObampNode *tmp;
1393   struct list_head *pos;
1394
1395   int nodesdeleted = 0;
1396
1397   if (myState->TreeHeartBeat > 0)
1398     myState->TreeHeartBeat--;
1399
1400   if (myState->TreeHeartBeat == 0 && myState->iamcore == 0)
1401     reset_tree_links();
1402
1403
1404
1405 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP: Timer Expired Purging Nodes");
1406
1407
1408   if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1409
1410     list_for_each(pos, &ListOfObampNodes) {
1411
1412       tmp = list_entry(pos, struct ObampNode, list);
1413       tmp->Texpire--;
1414       if (tmp->MeshLock != 0)
1415         tmp->MeshLock--;
1416
1417       //OLSR_DEBUG(LOG_PLUGINS,"Updating node %s with Texpire %d",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4),tmp->Texpire);
1418       if (tmp->Texpire == 0) {  //purge
1419         OLSR_DEBUG(LOG_PLUGINS, "Purging node %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1420         list_del(pos);
1421         //OLSR_DEBUG(LOG_PLUGINS,"OBAMP CHECK EMPTY %d",list_empty(&ListOfObampNodes));
1422
1423         free(tmp);
1424         nodesdeleted++;
1425       }
1426
1427     }
1428
1429     if (nodesdeleted != 0)
1430       CoreElection();
1431
1432   } else {
1433 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP: List empty");
1434
1435   }
1436
1437   x = NULL;
1438 }
1439
1440
1441 void
1442 obamp_alive_gen(void *x)
1443 {
1444   struct OBAMP_alive *myAlive;
1445   OLSR_DEBUG(LOG_PLUGINS, "Calling obamp_alive_gen\n");
1446   myAlive = malloc(sizeof(struct OBAMP_alive));
1447   myAlive->MessageID = OBAMP_ALIVE;
1448   myAlive->status = DoIHaveATreeLink();
1449   olsr_obamp_gen((unsigned char *)myAlive, sizeof(struct OBAMP_alive));
1450   free(myAlive);
1451   x = NULL;
1452
1453 }
1454
1455
1456
1457 /*
1458 When a packet is captured on the sniffing interfaces, it is called EncapFlowInObamp
1459 here we check if the packet is multicast and we forward it to the overlay neighbors if we have a link tree
1460 */
1461
1462 void
1463 EncapFlowInObamp(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
1464 {
1465   unsigned char ipPacket[1500];        //TODO: optimize me
1466
1467 #if !defined(REMOVE_LOG_DEBUG)
1468   struct ipaddr_str buf;
1469 #endif
1470   struct ObampNode *tmp;
1471   struct list_head *pos;
1472
1473   union olsr_ip_addr dst;              /* Destination IP address in captured packet */
1474   struct ip *ipHeader;                 /* The IP header inside the captured IP packet */
1475   struct ip6_hdr *ipHeader6;           /* The IP header inside the captured IP packet */
1476
1477   if (skfd >= 0) {
1478     struct sockaddr_ll pktAddr;
1479     socklen_t addrLen = sizeof(pktAddr);
1480     int nBytes;
1481
1482     nBytes = recvfrom(skfd, ipPacket, 1500,     //TODO: optimize me
1483                       0, (struct sockaddr *)&pktAddr, &addrLen);
1484     if (nBytes < 0) {
1485
1486       return;                   /* for */
1487     }
1488
1489     /* if (nBytes < 0) */
1490     /* Check if the number of received bytes is large enough for an IP
1491      * packet which contains at least a minimum-size IP header.
1492      * Note: There is an apparent bug in the packet socket implementation in
1493      * combination with VLAN interfaces. On a VLAN interface, the value returned
1494      * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
1495      * returned on a non-VLAN interface, for the same ethernet frame. */
1496     if (nBytes < (int)sizeof(struct ip)) {
1497
1498       OLSR_DEBUG(LOG_PLUGINS, "Captured frame too short");
1499       return;                   /* for */
1500     }
1501
1502     if (pktAddr.sll_pkttype == PACKET_OUTGOING || pktAddr.sll_pkttype == PACKET_MULTICAST)      // ||
1503       //pktAddr.sll_pkttype == PACKET_BROADCAST)
1504     {
1505
1506       //do here
1507       if ((ipPacket[0] & 0xf0) == 0x40) {       //IPV4
1508
1509         ipHeader = (struct ip *)ipPacket;
1510
1511         dst.v4 = ipHeader->ip_dst;
1512
1513         /* Only forward multicast packets. If configured, also forward local broadcast packets */
1514         if (IsMulticast(&dst)) {
1515           /* continue */
1516         } else {
1517           return;
1518         }
1519         if (ipHeader->ip_p != SOL_UDP) {
1520           /* Not UDP */
1521           OLSR_DEBUG(LOG_PLUGINS, "NON UDP PACKET\n");
1522           return;               /* for */
1523         } else {
1524           //Forward the packet to tree links
1525           if (list_empty(&ListOfObampNodes) == 0) {     //if the list is NOT empty
1526
1527             list_for_each(pos, &ListOfObampNodes) {
1528
1529               tmp = list_entry(pos, struct ObampNode, list);
1530               if (tmp->isTree == 1) {
1531
1532                 OLSR_DEBUG(LOG_PLUGINS, "Pushing data to Tree link to %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1533                 SendOBAMPData(&tmp->neighbor_ip_addr.v4, ipPacket, nBytes);
1534
1535               }
1536             }
1537           }
1538         }
1539
1540       }                         //END IPV4
1541
1542       else if ((ipPacket[0] & 0xf0) == 0x60) {  //IPv6
1543
1544         ipHeader6 = (struct ip6_hdr *)ipPacket;
1545         if (ipHeader6->ip6_dst.s6_addr[0] == 0xff)      //Multicast
1546         {
1547           //Continua
1548         } else {
1549           return;               //not multicast
1550         }
1551         if (ipHeader6->ip6_nxt != SOL_UDP) {
1552           /* Not UDP */
1553           OLSR_DEBUG(LOG_PLUGINS, "NON UDP PACKET\n");
1554           return;               /* for */
1555         }
1556
1557       }                         //END IPV6
1558       else
1559         return;                 //Is not IP packet
1560
1561       // send the packet to OLSR forward mechanism
1562       // SendOBAMPData(&tmp->neighbor_ip_addr.v6,ipPacket,nBytes);
1563
1564
1565     }                           /* if (pktAddr.sll_pkttype == ...) */
1566   }                             /* if (skfd >= 0 && (FD_ISSET...)) */
1567 }                               /* EncapFlowInObamp */
1568
1569 //This function is called from olsrd_plugin.c and adds to the list the interfaces specified in the configuration file to sniff multicast traffic
1570 int
1571 AddObampSniffingIf(const char *ifName,
1572                    void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
1573 {
1574
1575   struct ObampSniffingIf *ifToAdd;
1576
1577   OLSR_DEBUG(LOG_PLUGINS, "AddObampSniffingIf");
1578
1579
1580   assert(ifName != NULL);
1581
1582   ifToAdd = malloc(sizeof(struct ObampSniffingIf));
1583
1584   strncpy(ifToAdd->ifName, ifName, 16); //TODO: 16 fix this
1585   ifToAdd->ifName[15] = '\0';   /* Ensures null termination */
1586
1587   OLSR_DEBUG(LOG_PLUGINS, "Adding interface to list");
1588
1589   list_add(&(ifToAdd->list), &ListOfObampSniffingIf);
1590
1591   OLSR_DEBUG(LOG_PLUGINS, "Adding if %s to list of ObampSniffingIfaces", ifToAdd->ifName);
1592
1593   return 0;
1594 }
1595
1596
1597 int
1598 PreInitOBAMP(void)
1599 {
1600   INIT_LIST_HEAD(&ListOfObampSniffingIf);
1601   return 0;
1602
1603 }
1604
1605 //Start here !!
1606
1607 int
1608 InitOBAMP(void)
1609 {
1610 #if !defined(REMOVE_LOG_DEBUG)
1611   struct ipaddr_str buf;
1612 #endif
1613
1614 //Structs necessary for timers
1615
1616   struct timer_entry *OBAMP_alive_timer;
1617   struct timer_entry *purge_nodes_timer;
1618   struct timer_entry *mesh_create_timer;
1619   struct timer_entry *tree_create_timer;
1620   struct timer_entry *outer_tree_create_timer;
1621
1622
1623
1624   struct olsr_cookie_info *OBAMP_alive_gen_timer_cookie = NULL;
1625   struct olsr_cookie_info *purge_nodes_timer_cookie = NULL;
1626   struct olsr_cookie_info *mesh_create_timer_cookie = NULL;
1627   struct olsr_cookie_info *tree_create_timer_cookie = NULL;
1628   struct olsr_cookie_info *outer_tree_create_timer_cookie = NULL;
1629
1630   if (olsr_cnf->ip_version == AF_INET6) {
1631     OLSR_ERROR(LOG_PLUGINS, "OBAMP does not support IPv6 at the moment.");
1632     return 1;
1633   }
1634
1635 //Setting OBAMP node state
1636   myState = malloc(sizeof(struct ObampNodeState));
1637   myState->iamcore = 1;
1638   myState->TreeHeartBeat = 0;
1639   memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
1640   myState->CoreAddress = myState->myipaddr;
1641
1642   myState->DataSequenceNumber = 0;
1643   myState->TreeCreateSequenceNumber = 0;
1644   myState->tree_req_sn = 0;     //TODO: start from random number ?
1645
1646   memset(&myState->ParentId.v4, 0, sizeof(myState->ParentId.v4));
1647   memset(&myState->OldParentId.v4, 1, sizeof(myState->OldParentId.v4));
1648
1649   OLSR_DEBUG(LOG_PLUGINS, "SETUP: my IP - %s", ip4_to_string(&buf, myState->myipaddr.v4));
1650
1651   INIT_LIST_HEAD(&ListOfObampNodes);
1652
1653 //OLSR cookies stuff for timers
1654   OBAMP_alive_gen_timer_cookie = olsr_alloc_cookie("OBAMP Alive Generation", OLSR_COOKIE_TYPE_TIMER);
1655   purge_nodes_timer_cookie = olsr_alloc_cookie("purge nodes Generation", OLSR_COOKIE_TYPE_TIMER);
1656   mesh_create_timer_cookie = olsr_alloc_cookie("mesh create Generation", OLSR_COOKIE_TYPE_TIMER);
1657   tree_create_timer_cookie = olsr_alloc_cookie("tree create Generation", OLSR_COOKIE_TYPE_TIMER);
1658   outer_tree_create_timer_cookie = olsr_alloc_cookie("outer tree create Generation", OLSR_COOKIE_TYPE_TIMER);
1659
1660
1661 //Tells OLSR to launch olsr_parser when the packets for this plugin arrive
1662   olsr_parser_add_function(&olsr_parser, PARSER_TYPE);
1663
1664 // start to send alive messages to appear in other joined lists
1665   OBAMP_alive_timer =
1666     olsr_start_timer(OBAMP_ALIVE_EIVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &obamp_alive_gen, NULL,
1667                      OBAMP_alive_gen_timer_cookie);
1668
1669 // start timer to purge nodes from list in softstate fashion
1670   purge_nodes_timer =
1671     olsr_start_timer(_Texpire_timer_ * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &purge_nodes, NULL,
1672                      purge_nodes_timer_cookie);
1673
1674 //start timer to create mesh
1675   mesh_create_timer =
1676     olsr_start_timer(OBAMP_MESH_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &mesh_create, NULL,
1677                      mesh_create_timer_cookie);
1678
1679 //start timer for tree create procedure
1680   tree_create_timer =
1681     olsr_start_timer(OBAMP_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &tree_create, NULL,
1682                      tree_create_timer_cookie);
1683
1684 //start timer for tree create procedure
1685   outer_tree_create_timer =
1686     olsr_start_timer(OBAMP_OUTER_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &outer_tree_create, NULL,
1687                      tree_create_timer_cookie);
1688
1689
1690 //Create udp server socket for OBAMP signalling and register it to the scheduler
1691   OLSR_DEBUG(LOG_PLUGINS, "Launch Udp Servers");
1692   if (UdpServer() < 0) {
1693     OLSR_DEBUG(LOG_PLUGINS, "Problem in Launch Udp Servers");
1694
1695   };
1696
1697 //Creates a socket for sniffing multicast traffic and registers it to the scheduler
1698   CreateObampSniffingInterfaces();
1699
1700   return 0;
1701 }
1702
1703 /* -------------------------------------------------------------------------
1704  * Function   : CloseOBAMP
1705  * Description: Close the OBAMP plugin and clean up
1706  * Input      : none
1707  * Output     : none
1708  * Return     : none
1709  * Data Used  :
1710  * ------------------------------------------------------------------------- */
1711 void
1712 CloseOBAMP(void)
1713 {
1714 //do something here
1715 }