3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 * Visit http://www.olsr.org for more information.
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.
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() */
57 #include <netinet/in.h>
58 #include <netinet/ip6.h>
60 #include <fcntl.h> /* fcntl() */
63 #include "plugin_util.h" /* set_plugin_int */
64 #include "defs.h" /* olsr_cnf, //OLSR_PRINTF */
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"
77 struct ObampNodeState *myState; //Internal state of the OBAMP node
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
84 struct list_head ListOfObampNodes;
86 //List of Non OLSR Interfaces to capture and send multicast traffic to
87 struct list_head ListOfObampSniffingIf;
89 //udp socket used for OBAMP signalling
93 When Outer Tree Create is triggered, a OBAMP node uses this function to
94 determine the closer OBAMP node that has a TreeLink
96 static struct ObampNode *
97 select_tree_anchor(void)
100 struct ObampNode *tmp; //temp pointers used when parsing the list
101 struct ObampNode *best;
102 struct list_head *pos;
104 struct rt_entry *rt; //"rt->rt_best->rtp_metric.cost" is the value you are looking for, a 32 bit
106 unsigned int mincost = 15;
110 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
113 list_for_each(pos, &ListOfObampNodes) { //loop to update min cost
115 tmp = list_entry(pos, struct ObampNode, list);
116 if (tmp->status == 1) {
117 rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
119 if (rt == NULL) { //route is not present yet
120 OLSR_DEBUG(LOG_PLUGINS, "No route present to this anchor");
123 //update best neighbor
124 if ((rt->rt_best->rtp_metric.cost / 65536) < mincost)
131 OLSR_DEBUG(LOG_PLUGINS, "List empty can't create Overlay Mesh");
137 //Creates a OBAMP_DATA message and sends it to the specified destination
139 SendOBAMPData(struct in_addr *addr, unsigned char *ipPacket, int nBytes)
142 struct sockaddr_in si_other;
143 struct OBAMP_data_message4 data_msg;
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;
150 data_msg.CoreAddress = (u_int32_t) myState->CoreAddress.v4.s_addr;
152 data_msg.SequenceNumber = myState->DataSequenceNumber;
153 myState->DataSequenceNumber++;
155 if (nBytes >= 1471) {
156 OLSR_DEBUG(LOG_PLUGINS, "PACKET DROPPED: %d bytes are too much",nBytes);
160 memcpy(data_msg.data, ipPacket, nBytes);
162 data_msg.datalen = nBytes;
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));
176 CreateCaptureSocket(const char *ifName)
178 int ifIndex = if_nametoindex(ifName);
179 struct packet_mreq mreq;
181 struct sockaddr_ll bindTo;
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));
188 skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
191 OLSR_DEBUG(LOG_PLUGINS, "socket(PF_PACKET) error");
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");
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");
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);
221 bindTo.sll_protocol = htons(ETH_P_IPV6);
223 bindTo.sll_ifindex = ifIndex;
224 memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
225 bindTo.sll_halen = IFHWADDRLEN;
227 if (bind(skfd, (struct sockaddr *)&bindTo, sizeof(bindTo)) < 0) {
228 OLSR_DEBUG(LOG_PLUGINS, "bind() error");
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");
240 add_olsr_socket(skfd, &EncapFlowInObamp, NULL, NULL, SP_PR_READ);
243 } /* CreateCaptureSocket */
247 CreateObampSniffingInterfaces(void)
250 struct ObampSniffingIf *tmp;
251 struct list_head *pos;
253 OLSR_DEBUG(LOG_PLUGINS, "CreateObampSniffingInterfaces");
256 if (list_empty(&ListOfObampSniffingIf) == 0) { //if the list is NOT empty
257 OLSR_DEBUG(LOG_PLUGINS, "adding interfaces");
259 list_for_each(pos, &ListOfObampSniffingIf) {
261 tmp = list_entry(pos, struct ObampSniffingIf, list);
262 tmp->skd = CreateCaptureSocket(tmp->ifName);
265 OLSR_DEBUG(LOG_PLUGINS, "List of sniffin interfaces was empty");
273 IsMulticast(union olsr_ip_addr *ipAddress)
275 assert(ipAddress != NULL);
277 return (ntohl(ipAddress->v4.s_addr) & 0xF0000000) == 0xE0000000;
283 activate_tree_link(struct OBAMP_tree_link_ack *ack)
285 #if !defined(REMOVE_LOG_DEBUG)
286 struct ipaddr_str buf;
288 struct ObampNode *tmp;
289 struct list_head *pos;
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");
296 if (ack->SequenceNumber != myState->tree_req_sn - 1) {
298 OLSR_DEBUG(LOG_PLUGINS, "ACK DISCARDED WRONG SEQ NUMBER");
302 list_for_each(pos, &ListOfObampNodes) {
304 tmp = list_entry(pos, struct ObampNode, list);
305 if (tmp->neighbor_ip_addr.v4.s_addr == ack->router_id.v4.s_addr) {
308 myState->TreeHeartBeat = TREE_HEARTBEAT;
309 OLSR_DEBUG(LOG_PLUGINS, "Tree link to %s activated", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
319 When we select a other OBAMP node as a overlay neighbor, we start to send HELLOs to him
320 to inform we are using the unicast path from us to him as a overlay mesh link
323 obamp_hello(struct in_addr *addr)
326 struct OBAMP_hello hello;
327 struct sockaddr_in si_other;
329 memset(&hello, 0, sizeof(hello));
330 hello.MessageID = OBAMP_HELLO;
331 //TODO: refresh IP address
332 hello.router_id = myState->myipaddr;
333 hello.CoreAddress = myState->CoreAddress;
335 //TODO: implement sequence number
336 //hello->HelloSequenceNumber = myState->something;
337 //myState->something++;
339 memset((char *)&si_other, 0, sizeof(si_other));
340 si_other.sin_family = AF_INET;
341 si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
342 si_other.sin_addr = *addr;
343 sendto(sdudp, &hello, sizeof(struct OBAMP_hello), 0, (struct sockaddr *)&si_other, sizeof(si_other));
346 //Request a Tree Link
348 tree_link_req(struct in_addr *addr)
350 if (myState->TreeRequestDelay == 0) {
351 struct OBAMP_tree_link_req req;
352 struct sockaddr_in si_other;
353 #if !defined(REMOVE_LOG_DEBUG)
354 struct ipaddr_str buf;
358 OLSR_DEBUG(LOG_PLUGINS, "Sending tree request to: %s", ip4_to_string(&buf, *addr));
360 memset(&req, 0, sizeof(req));
361 req.MessageID = OBAMP_TREE_REQ;
362 //TODO: refresh IP address
363 req.router_id = myState->myipaddr;
364 req.CoreAddress = myState->CoreAddress;
366 req.SequenceNumber = myState->tree_req_sn;
367 myState->tree_req_sn++;
369 memset((char *)&si_other, 0, sizeof(si_other));
370 si_other.sin_family = AF_INET;
371 si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
372 si_other.sin_addr = *addr;
373 myState->TreeRequestDelay=5;
374 sendto(sdudp, &req, sizeof(struct OBAMP_tree_link_req), 0, (struct sockaddr *)&si_other, sizeof(si_other));
376 else OLSR_DEBUG(LOG_PLUGINS,"Do not send Tree Link Request because there is another one running");
380 tree_link_ack(struct OBAMP_tree_link_req *req)
383 struct sockaddr_in si_other;
386 struct ObampNode *tmp;
387 struct list_head *pos;
388 #if !defined(REMOVE_LOG_DEBUG)
389 struct ipaddr_str buf;
392 struct OBAMP_tree_link_ack ack;
395 if (memcmp(&myState->CoreAddress.v4, &req->CoreAddress.v4, sizeof(struct in_addr)) != 0) {
396 OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
399 //TODO: other checks ?
402 memset(&ack, 0, sizeof(ack));
403 ack.MessageID = OBAMP_TREE_ACK;
404 //TODO: refresh IP address
405 ack.router_id = myState->myipaddr;
406 ack.CoreAddress = myState->CoreAddress;
408 ack.SequenceNumber = req->SequenceNumber;
410 addr = req->router_id.v4;
412 list_for_each(pos, &ListOfObampNodes) {
414 tmp = list_entry(pos, struct ObampNode, list);
415 if (tmp->neighbor_ip_addr.v4.s_addr == req->router_id.v4.s_addr) {
418 OLSR_DEBUG(LOG_PLUGINS, "Tree link to %s activated", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
423 memset((char *)&si_other, 0, sizeof(si_other));
424 si_other.sin_family = AF_INET;
425 si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
426 si_other.sin_addr = addr;
427 sendto(sdudp, &ack, sizeof(struct OBAMP_tree_link_req), 0, (struct sockaddr *)&si_other, sizeof(si_other));
432 init_overlay_neighbor(struct ObampNode *n)
435 n->Texpire = _Texpire_; //If this value expires the OBAMP node is removed from the list
440 n->outerTreeLink = 0;
441 n->DataSeqNumber = 0;
445 tree_create_forward_to(struct in_addr *addr, struct OBAMP_tree_create *mytc)
448 struct sockaddr_in si_other;
449 struct OBAMP_tree_create temptc;
451 memset(&temptc, 0, sizeof(temptc));
452 memcpy(&temptc, mytc, sizeof(struct OBAMP_tree_create));
455 if (memcmp(&myState->CoreAddress.v4, &temptc.CoreAddress.v4, sizeof(struct in_addr)) != 0) {
456 OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
460 temptc.router_id = myState->myipaddr;
462 memset((char *)&si_other, 0, sizeof(si_other));
463 si_other.sin_family = AF_INET;
464 si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
465 si_other.sin_addr = *addr;
467 sendto(sdudp, &temptc, sizeof(struct OBAMP_tree_create), 0, (struct sockaddr *)&si_other, sizeof(si_other));
471 tree_create_gen(struct in_addr *addr)
473 struct OBAMP_tree_create mytc;
474 struct sockaddr_in si_other;
476 OLSR_DEBUG(LOG_PLUGINS, "Calling tree_create_gen\n");
478 memset(&mytc, 0, sizeof(mytc));
479 mytc.MessageID = OBAMP_TREECREATE;
480 mytc.router_id = myState->myipaddr;
481 mytc.CoreAddress = myState->CoreAddress;
482 myState->TreeCreateSequenceNumber++;
483 mytc.SequenceNumber = myState->TreeCreateSequenceNumber;
485 memset((char *)&si_other, 0, sizeof(si_other));
486 si_other.sin_family = AF_INET;
487 si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
488 si_other.sin_addr = *addr;
489 sendto(sdudp, &mytc, sizeof(struct OBAMP_tree_create), 0, (struct sockaddr *)&si_other, sizeof(si_other));
494 printObampNodesList(void)
498 #if !defined(REMOVE_LOG_DEBUG)
499 struct ipaddr_str buf;
501 struct ObampNode *tmp;
502 struct list_head *pos;
504 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
507 OLSR_DEBUG(LOG_PLUGINS, "--------------------NODE STATUS---------");
508 OLSR_DEBUG(LOG_PLUGINS, "---Current Core: %s", ip4_to_string(&buf, myState->CoreAddress.v4));
509 OLSR_DEBUG(LOG_PLUGINS, "---Current Parent: %s", ip4_to_string(&buf, myState->ParentId.v4));
512 OLSR_DEBUG(LOG_PLUGINS, "Number \t IP \t\t IsMesh \t IsTree \t MeshLock \t outerTreeLink");
514 list_for_each(pos, &ListOfObampNodes) {
516 tmp = list_entry(pos, struct ObampNode, list);
518 OLSR_DEBUG(LOG_PLUGINS, "%d \t\t %s \t %d \t\t %d \t\t %d \t\t %d", i, ip4_to_string(&buf, tmp->neighbor_ip_addr.v4),
519 tmp->isMesh, tmp->isTree, tmp->MeshLock, tmp->outerTreeLink);
523 OLSR_DEBUG(LOG_PLUGINS, "----------------------------------------");
529 DoIHaveATreeLink(void)
532 //struct ipaddr_str buf;
533 struct ObampNode *tmp;
534 struct list_head *pos;
536 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
538 list_for_each(pos, &ListOfObampNodes) {
540 tmp = list_entry(pos, struct ObampNode, list);
541 if (tmp->isTree == 1)
550 DoIHaveAMeshLink(void)
553 //struct ipaddr_str buf;
554 struct ObampNode *tmp;
555 struct list_head *pos;
557 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
559 list_for_each(pos, &ListOfObampNodes) {
561 tmp = list_entry(pos, struct ObampNode, list);
562 if (tmp->isMesh == 1)
571 reset_tree_links(void)
574 //struct ipaddr_str buf;
575 struct ObampNode *tmp;
576 struct list_head *pos;
578 OLSR_DEBUG(LOG_PLUGINS,"Reset Tree Links Now");
579 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
581 list_for_each(pos, &ListOfObampNodes) {
583 tmp = list_entry(pos, struct ObampNode, list);
585 tmp->outerTreeLink = 0;
589 memset(&myState->ParentId.v4, 0, sizeof(myState->ParentId.v4));
590 memset(&myState->OldParentId.v4, 1, sizeof(myState->OldParentId.v4));
591 myState->TreeCreateSequenceNumber=0;
597 //Core Election. The Core is the one with the smallest IP Address
601 #if !defined(REMOVE_LOG_DEBUG)
602 struct ipaddr_str buf;
604 struct ObampNode *tmp;
605 struct list_head *pos;
606 u_int32_t smallestIP = 0xFFFFFFFF;
608 //Update my current IP address
609 memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
611 OLSR_DEBUG(LOG_PLUGINS, "SETUP: my IP - %s", ip4_to_string(&buf, myState->myipaddr.v4));
614 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
616 list_for_each(pos, &ListOfObampNodes) {
618 tmp = list_entry(pos, struct ObampNode, list);
619 if (tmp->neighbor_ip_addr.v4.s_addr < smallestIP) {
621 smallestIP = tmp->neighbor_ip_addr.v4.s_addr;
622 OLSR_DEBUG(LOG_PLUGINS, "CoreElection: current smallest IP is - %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
626 //Check if I'm the core.
628 if (myState->myipaddr.v4.s_addr < smallestIP) { //I'm the core
630 if (myState->myipaddr.v4.s_addr == myState->CoreAddress.v4.s_addr) { //I'm was already the core
632 } else { //I'm becoming core
634 myState->CoreAddress = myState->myipaddr;
635 myState->iamcore = 1;
636 myState->TreeCreateSequenceNumber = 0;
637 OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links");
639 OLSR_DEBUG(LOG_PLUGINS, "I'm the core");
642 if (myState->CoreAddress.v4.s_addr == smallestIP) { //the core did not change
644 } else { //core changed
645 myState->iamcore = 0;
646 myState->CoreAddress.v4.s_addr = smallestIP;
647 OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links");
649 OLSR_DEBUG(LOG_PLUGINS, "CoreElection: current Core is - %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
655 else { //List is empty I'm the core
656 OLSR_DEBUG(LOG_PLUGINS, "CoreElection: I'm alone I'm the core");
657 myState->CoreAddress = myState->myipaddr;
658 myState->iamcore = 1;
659 myState->TreeCreateSequenceNumber = 0;
660 OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links");
669 //Starts a UDP listening port for OBAMP signalling
674 struct sockaddr_in addr;
677 if ((sdudp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
678 OLSR_DEBUG(LOG_PLUGINS, "Socket UDP error");
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 */
687 if (bind(sdudp, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
688 OLSR_DEBUG(LOG_PLUGINS, "Socket UDP BIND error");
692 add_olsr_socket(sdudp, &ObampSignalling, NULL, NULL, SP_PR_READ);
699 decap_data(char *buffer)
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;
708 struct ip6_hdr *ip6Header;
709 struct OBAMP_data_message4 *msg;
711 struct sockaddr_ll dest;
712 msg = (struct OBAMP_data_message4 *)buffer;
714 ipPacket = msg->data;
716 ipHeader = (struct ip *)ipPacket;
717 ip6Header = (struct ip6_hdr *)ipPacket;
720 if (list_empty(&ListOfObampSniffingIf) == 0) { //if the list is NOT empty
721 //OLSR_DEBUG(LOG_PLUGINS,"DECAP DATA");
723 list_for_each(pos, &ListOfObampSniffingIf) {
725 tmp = list_entry(pos, struct ObampSniffingIf, list);
726 //tmp->skd = CreateCaptureSocket(tmp->ifName);
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);
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
740 //TODO: if packet is not IP die here
743 dest.sll_ifindex = if_nametoindex(tmp->ifName);
744 dest.sll_halen = IFHWADDRLEN;
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
752 memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
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);
759 OLSR_DEBUG(LOG_PLUGINS, "OBAMP: --> unpacked and forwarded on \"%s\"\n", tmp->ifName);
769 CheckDupData(char *buffer)
772 struct ObampNode *tmp; //temp pointers used when parsing the list
773 struct list_head *pos;
774 struct OBAMP_data_message4 *data_msg;
776 data_msg = (struct OBAMP_data_message4 *)buffer;
779 //Check duplicate data packet
780 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
783 list_for_each(pos, &ListOfObampNodes) {
784 tmp = list_entry(pos, struct ObampNode, list);
786 if (memcmp(&tmp->neighbor_ip_addr.v4, &data_msg->router_id, sizeof(struct in_addr)) == 0) {
788 OLSR_DEBUG(LOG_PLUGINS, "Processing Data Packet %d - Last seen was %d",data_msg->SequenceNumber, tmp->DataSeqNumber);
790 if (tmp->DataSeqNumber == 0) { //First packet received from this host
791 tmp->DataSeqNumber = data_msg->SequenceNumber;
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
797 tmp->DataSeqNumber = data_msg->SequenceNumber;
801 OLSR_DEBUG(LOG_PLUGINS, "DISCARDING DUP PACKET");
813 forward_obamp_data(char *buffer)
816 #if !defined(REMOVE_LOG_DEBUG)
817 struct ipaddr_str buf;
818 struct ipaddr_str buf2;
820 struct ObampNode *tmp; //temp pointers used when parsing the list
821 struct list_head *pos;
822 struct OBAMP_data_message4 *data_msg;
823 struct sockaddr_in si_other;
824 struct in_addr temporary;
827 data_msg = (struct OBAMP_data_message4 *)buffer;
828 temporary.s_addr = data_msg->last_hop;
829 data_msg->last_hop = myState->myipaddr.v4.s_addr;
831 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
834 list_for_each(pos, &ListOfObampNodes) {
835 tmp = list_entry(pos, struct ObampNode, list);
837 if (tmp->isTree == 1 && memcmp(&tmp->neighbor_ip_addr.v4, &temporary.s_addr, 4) != 0) {
838 OLSR_DEBUG(LOG_PLUGINS, "FORWARDING OBAMP DATA TO node %s because come from %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4), ip4_to_string(&buf2,temporary));
842 memset((char *)&si_other, 0, sizeof(si_other));
843 si_other.sin_family = AF_INET;
844 si_other.sin_port = htons(OBAMP_SIGNALLING_PORT);
845 si_other.sin_addr = tmp->neighbor_ip_addr.v4;
846 //sendto(sdudp, data_msg, sizeof(struct OBAMP_data_message), 0, (struct sockaddr *)&si_other, sizeof(si_other));
847 sendto(sdudp, data_msg, 17+data_msg->datalen, 0, (struct sockaddr *)&si_other, sizeof(si_other));
858 manage_hello(char *packet)
861 struct OBAMP_hello *hello;
863 struct ObampNode *tmp; //temp pointers used when parsing the list
864 struct list_head *pos;
866 hello = (struct OBAMP_hello *)packet;
868 //FIRST OF ALL CHECK CORE
869 if (memcmp(&myState->CoreAddress.v4, &hello->CoreAddress.v4, sizeof(struct in_addr)) != 0) {
870 OLSR_DEBUG(LOG_PLUGINS, "Discarding message with no coherent core address");
874 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
877 list_for_each(pos, &ListOfObampNodes) {
878 tmp = list_entry(pos, struct ObampNode, list);
880 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
883 tmp->MeshLock = _MESH_LOCK_;
888 OLSR_DEBUG(LOG_PLUGINS, "Very strange, list cannot be empty here !");
894 manage_tree_create(char *packet)
897 struct OBAMP_tree_create *msg;
899 #if !defined(REMOVE_LOG_DEBUG)
900 struct ipaddr_str buf;
901 struct ipaddr_str buf2; //buf to print debug infos
904 struct ObampNode *tmp; //temp pointers used when parsing the list
905 struct list_head *pos;
906 OLSR_DEBUG(LOG_PLUGINS,"manage_tree_create");
907 msg = (struct OBAMP_tree_create *)packet;
909 if (msg->MessageID != OBAMP_TREECREATE) {
910 OLSR_DEBUG(LOG_PLUGINS, "BIG PROBLEM, I'M IN THIS FUNCTION BUT MESSAGE IS NOT TREE CREATE");
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");
919 if (myState->iamcore == 1) { //I'm core and receiving tree create over a loop
924 if ( (((msg->SequenceNumber > myState->TreeCreateSequenceNumber) && ((msg->SequenceNumber - myState->TreeCreateSequenceNumber ) <= 127)) || ((myState->TreeCreateSequenceNumber > msg->SequenceNumber) && ((myState->TreeCreateSequenceNumber - msg->SequenceNumber) > 127 )) /*myState->TreeCreateSequenceNumber < msg->SequenceNumber*/) || myState->TreeCreateSequenceNumber == 0 ) { //If tree create is not a duplicate
925 OLSR_DEBUG(LOG_PLUGINS, "myState->TreeCreateSequenceNumber < msg->SequenceNumber --- %d < %d",myState->TreeCreateSequenceNumber,msg->SequenceNumber);
926 myState->TreeCreateSequenceNumber = msg->SequenceNumber;
928 //A bug was fixed here a battlemeshv3
929 //myState->OldParentId.v4 = myState->ParentId.v4;
930 //myState->ParentId.v4 = msg->router_id.v4;
932 //if (memcmp(&myState->OldParentId.v4, &myState->ParentId.v4, sizeof(struct in_addr)) != 0) //If it changed
933 if (memcmp(&msg->router_id.v4, &myState->ParentId.v4, sizeof(struct in_addr)) != 0) //If it changed
935 OLSR_DEBUG(LOG_PLUGINS, "Receiving a tree message from a link that is not parent");
936 if (DoIHaveATreeLink() == 0 ) {
937 OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links");
939 myState->ParentId.v4 = msg->router_id.v4;
940 myState->OldParentId.v4 = myState->ParentId.v4;
941 tree_link_req(&msg->router_id.v4);
944 //I have a tree link already, evaluate new parent ??
948 else { //Receiving a TreeCreate from my parent so I can refresh hearthbeat
949 myState->TreeHeartBeat = TREE_HEARTBEAT;
952 //FORWARD the tree message on the mesh
953 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
956 list_for_each(pos, &ListOfObampNodes) {
957 tmp = list_entry(pos, struct ObampNode, list);
959 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
960 if (DoIHaveATreeLink() == 1 ) { //I forward only if I have a link tree to the core ready
961 tree_create_forward_to(&tmp->neighbor_ip_addr.v4, msg);
962 OLSR_DEBUG(LOG_PLUGINS, "FORWARDING TREE CREATE ORIGINATOR %s TO node %s ", ip4_to_string(&buf2, msg->router_id.v4),
963 ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
969 OLSR_DEBUG(LOG_PLUGINS, "Very strange, list cannot be empty here !");
973 OLSR_DEBUG(LOG_PLUGINS, "myState->TreeCreateSequenceNumber < msg->SequenceNumber --- %d < %d",myState->TreeCreateSequenceNumber,msg->SequenceNumber);
974 OLSR_DEBUG(LOG_PLUGINS, "DISCARDING DUP TREE CREATE");
982 ObampSignalling(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
986 char text_buffer[300];
987 struct sockaddr_in addr;
992 memset(&addr, 0, sizeof(struct sockaddr_in));
997 //OLSR_DEBUG(LOG_PLUGINS,"INCOMING OBAMP SIGNALLING");
999 n = recvfrom(skfd, buffer, 1500, 0, (struct sockaddr *)&addr, &len);
1002 OLSR_DEBUG(LOG_PLUGINS, "recvfrom error");
1005 inet_ntop(AF_INET, &addr.sin_addr, text_buffer, sizeof(text_buffer));
1006 //OLSR_DEBUG(LOG_PLUGINS,"Request from host %s, port %d\n", text_buffer, ntohs(addr->sin_port));
1008 MessageID = buffer[0];
1010 switch (MessageID) {
1013 OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_DATA from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1015 if (CheckDupData(buffer)) {
1016 forward_obamp_data(buffer);
1023 OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_HELLO from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1024 manage_hello(buffer);
1027 case OBAMP_TREECREATE:
1029 OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_TREECREATE from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1030 manage_tree_create(buffer);
1034 case OBAMP_TREE_REQ:
1035 OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_TREE_REQ from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1036 tree_link_ack((struct OBAMP_tree_link_req *)buffer);
1039 case OBAMP_TREE_ACK:
1041 OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_TREE_ACK from host %s, port %d\n", text_buffer, ntohs(addr.sin_port));
1042 activate_tree_link((struct OBAMP_tree_link_ack *)buffer);
1055 adds a IPv4 ObampNode in the list if it is new
1056 If a new node is added CoreElection is called to update the current core
1059 addObampNode4(struct in_addr *ipv4, u_int8_t status)
1061 #if !defined(REMOVE_LOG_DEBUG)
1062 struct ipaddr_str buf;
1064 struct ObampNode *neighbor_to_add;
1065 struct ObampNode *tmp;
1066 struct list_head *pos;
1068 neighbor_to_add = olsr_malloc(sizeof(struct ObampNode), "OBAMPNode");
1070 //OLSR_DEBUG(LOG_PLUGINS,"Adding to list node - %s\n",ip4_to_string(&buf,*ipv4));
1073 if (list_empty(&ListOfObampNodes) != 0) { //Empty list
1074 //OLSR_DEBUG(LOG_PLUGINS,"List is empty %d adding first node\n",list_empty(&ListOfObampNodes));
1076 memcpy(&neighbor_to_add->neighbor_ip_addr.v4, ipv4, sizeof(neighbor_to_add->neighbor_ip_addr.v4));
1077 list_add(&(neighbor_to_add->list), &ListOfObampNodes);
1079 init_overlay_neighbor(neighbor_to_add);
1080 neighbor_to_add->status = status;
1082 OLSR_DEBUG(LOG_PLUGINS, "Added to list node as first node- %s\n", ip4_to_string(&buf, *ipv4));
1086 } else { //Some node already in list
1088 //Scroll the list to check if the element already exists
1089 list_for_each(pos, &ListOfObampNodes) {
1091 tmp = list_entry(pos, struct ObampNode, list);
1092 if (memcmp(&tmp->neighbor_ip_addr.v4, ipv4, sizeof(tmp->neighbor_ip_addr.v4)) == 0) {
1093 //OLSR_DEBUG(LOG_PLUGINS,"Node already present in list %s\n",ip4_to_string(&buf,*ipv4));
1094 tmp->Texpire = _Texpire_; //Refresh Texpire
1095 neighbor_to_add->status = status;
1096 free(neighbor_to_add);
1100 //Add element to list
1101 // neighbor_to_add->Texpire=_Texpire_; //Refresh Texpire
1102 OLSR_DEBUG(LOG_PLUGINS, "Adding to list node (NOT FIRST)- %s\n", ip4_to_string(&buf, *ipv4));
1103 memcpy(&neighbor_to_add->neighbor_ip_addr.v4, ipv4, sizeof(neighbor_to_add->neighbor_ip_addr.v4));
1104 list_add(&(neighbor_to_add->list), &ListOfObampNodes);
1105 init_overlay_neighbor(neighbor_to_add);
1106 neighbor_to_add->status = status;
1110 } //End AddObampNode
1114 /* -------------------------------------------------------------------------
1115 * Function : PacketReceivedFromOLSR
1116 * Description: Handle a received packet from a OLSR message
1117 * Input : Obamp Message
1120 * ------------------------------------------------------------------------- */
1122 PacketReceivedFromOLSR(union olsr_ip_addr *originator, const uint8_t *obamp_message, int len)
1124 u_int8_t MessageID = obamp_message[0];
1125 const struct OBAMP_alive *alive;
1126 #if !defined(REMOVE_LOG_DEBUG)
1127 struct ipaddr_str buf;
1130 struct in_addr *myOriginator = (struct in_addr *)originator;
1132 //TODO: this is useless now
1136 switch (MessageID) {
1139 OLSR_DEBUG(LOG_PLUGINS, "OBAMP Received OBAMP_ALIVE from %s\n", ip4_to_string(&buf, *myOriginator));
1140 alive = (const struct OBAMP_alive *)obamp_message;
1141 addObampNode4(myOriginator, alive->status);
1142 printObampNodesList();
1148 } /* PacketReceivedFromOLSR */
1151 //OLSR parser, received OBAMP messages
1153 olsr_parser(struct olsr_message *msg, struct interface *in_if
1154 __attribute__ ((unused)), union olsr_ip_addr *ipaddr, enum duplicate_status status __attribute__ ((unused)))
1156 //OLSR_DEBUG(LOG_PLUGINS, "OBAMP PLUGIN: Received msg in parser\n");
1158 if (msg->type != MESSAGE_TYPE) {
1162 /* Check if message originated from this node.
1163 * If so - back off */
1164 if (olsr_ipcmp(&msg->originator, &olsr_cnf->router_id) == 0)
1167 /* Check that the neighbor this message was received from is symmetric.
1168 * If not - back off*/
1169 if (check_neighbor_link(ipaddr) != SYM_LINK) {
1170 //struct ipaddr_str strbuf;
1174 PacketReceivedFromOLSR(&msg->originator, msg->payload, msg->end - msg->payload);
1177 //Sends a packet in the OLSR network
1179 olsr_obamp_gen(void *packet, int len)
1181 /* send buffer: huge */
1182 uint8_t buffer[10240];
1183 struct olsr_message msg;
1184 struct interface *ifn;
1185 uint8_t *curr, *sizeptr;
1188 msg.type = MESSAGE_TYPE;
1189 msg.vtime = OBAMP_VALID_TIME * MSEC_PER_SEC;
1190 msg.originator = olsr_cnf->router_id;
1193 msg.seqno = get_msg_seqno();
1194 msg.size = 0; /* put in later */
1197 sizeptr = olsr_put_msg_hdr(&curr, &msg);
1198 memcpy(curr, packet, len);
1200 len = curr - buffer + len;
1201 pkt_put_u16(&sizeptr, len);
1203 /* looping trough interfaces */
1204 OLSR_FOR_ALL_INTERFACES(ifn) {
1205 if (net_outbuffer_push(ifn, buffer, len) != len) {
1206 /* send data and try again */
1208 if (net_outbuffer_push(ifn, buffer, len) != len) {
1209 OLSR_DEBUG(LOG_PLUGINS, "OBAMP PLUGIN: could not send on interface: %s\n", ifn->int_name);
1213 OLSR_FOR_ALL_INTERFACES_END(ifn);
1217 outer_tree_create(void *x)
1220 struct ObampNode *tmp; //temp pointers used when parsing the list
1221 struct list_head *pos;
1224 if ((DoIHaveATreeLink() == 0) && (myState->iamcore == 0)) { //If there are not tree links
1226 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
1229 if (DoIHaveAMeshLink() == 0) {
1230 OLSR_DEBUG(LOG_PLUGINS, "Weird, no mesh links. Maybe other OBAMP nodes are very far (HUGE ETX)");
1234 //Update my current IP address
1235 memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
1236 //OLSR_DEBUG(LOG_PLUGINS,"SETUP: my IP - %s",ip4_to_string(&buf,myState->myipaddr.v4));
1237 list_for_each(pos, &ListOfObampNodes) {
1238 tmp = list_entry(pos, struct ObampNode, list);
1239 if ((tmp->neighbor_ip_addr.v4.s_addr < myState->myipaddr.v4.s_addr) && (tmp->isMesh == 1)) {
1240 return; //I have a neighbor that will send a outer tree create for me
1244 OLSR_DEBUG(LOG_PLUGINS, "OUTER TREE CREATE");
1245 tmp = select_tree_anchor();
1247 OLSR_DEBUG(LOG_PLUGINS, "CANT FIND ANCHOR");
1251 tmp->outerTreeLink = 1;
1252 myState->OldParentId.v4 = tmp->neighbor_ip_addr.v4;
1253 myState->ParentId.v4 = tmp->neighbor_ip_addr.v4;
1254 myState->TreeHeartBeat = TREE_HEARTBEAT;
1255 tree_link_req(&tmp->neighbor_ip_addr.v4);
1261 OLSR_DEBUG(LOG_PLUGINS, "List empty can't send OUTER_TREE_CREATE");
1269 tree_create(void *x)
1271 #if !defined(REMOVE_LOG_DEBUG)
1272 struct ipaddr_str buf;
1274 struct ObampNode *tmp; //temp pointers used when parsing the list
1275 struct list_head *pos;
1278 if (myState->iamcore == 1) {
1280 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
1283 list_for_each(pos, &ListOfObampNodes) {
1285 tmp = list_entry(pos, struct ObampNode, list);
1286 if (tmp->isMesh == 1) { //Is neighbor
1289 tree_create_gen(&tmp->neighbor_ip_addr.v4);
1292 OLSR_DEBUG(LOG_PLUGINS, "CORE SENDS TREE CREATE TO node %s ", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1297 OLSR_DEBUG(LOG_PLUGINS, "List empty can't send TREE_CREATE");
1309 mesh_create(void *x)
1311 #if !defined(REMOVE_LOG_DEBUG)
1312 struct ipaddr_str buf;
1314 struct ObampNode *tmp; //temp pointers used when parsing the list
1315 struct list_head *pos;
1317 struct rt_entry *rt; //"rt->rt_best->rtp_metric.cost" is the value you are looking for, a 32 bit
1319 unsigned int mincost = 5;
1321 int meshchanged = 0;
1323 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
1326 list_for_each(pos, &ListOfObampNodes) {
1328 tmp = list_entry(pos, struct ObampNode, list);
1330 //set every OBAMP node to be NOT neighbor
1331 tmp->wasMesh = tmp->isMesh;
1333 //MeshLock in case mesh link is requested from neighbor
1334 if (tmp->MeshLock == 0 && tmp->outerTreeLink == 0)
1337 rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
1339 if (rt == NULL) { //route is not present yet
1342 //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);
1344 if (rt->rt_best->rtp_metric.cost / 65536 > 5) {
1345 continue; //we not not consider links that are poorer than ETX=5
1348 if ((rt->rt_best->rtp_metric.cost / 65536) < mincost)
1349 mincost = (rt->rt_best->rtp_metric.cost / 65536);
1353 //now that I know the mincost to the closer OBAMP node I choose my neighbor set
1354 list_for_each(pos, &ListOfObampNodes) {
1356 tmp = list_entry(pos, struct ObampNode, list);
1357 rt = olsr_lookup_routing_table(&tmp->neighbor_ip_addr);
1359 if (rt == NULL) { //route is not present yet
1363 if (rt->rt_best->rtp_metric.cost / 65536 > 5) {
1364 continue; //we not not consider links that are poorer than ETX=5
1367 if ((rt->rt_best->rtp_metric.cost / 65536) - 1 < mincost) { //Choose for mesh
1370 OLSR_DEBUG(LOG_PLUGINS, "Choosed Overlay Neighbor node %s costs %u", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4),
1371 rt->rt_best->rtp_metric.cost / 65536);
1373 obamp_hello(&tmp->neighbor_ip_addr.v4);
1378 if (tmp->outerTreeLink == 1)
1379 obamp_hello(&tmp->neighbor_ip_addr.v4);
1382 if (tmp->isMesh != tmp->wasMesh) {
1384 if (tmp->isMesh == 0 && tmp->isTree == 1) {
1394 //trigger signalling
1399 OLSR_DEBUG(LOG_PLUGINS, "List empty can't create Overlay Mesh");
1407 purge_nodes(void *x)
1409 #if !defined(REMOVE_LOG_DEBUG)
1410 struct ipaddr_str buf;
1412 struct ObampNode *tmp;
1413 struct list_head *pos;
1415 int nodesdeleted = 0;
1417 if (myState->TreeHeartBeat > 0)
1418 myState->TreeHeartBeat--;
1420 if (myState->TreeRequestDelay > 0)
1421 myState->TreeRequestDelay--;
1423 if (myState->TreeHeartBeat == 0 && myState->iamcore == 0){
1424 OLSR_DEBUG(LOG_PLUGINS,"Calling Reset Tree Links");
1428 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP: Timer Expired Purging Nodes");
1431 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
1433 list_for_each(pos, &ListOfObampNodes) {
1435 tmp = list_entry(pos, struct ObampNode, list);
1437 if (tmp->MeshLock != 0)
1440 //OLSR_DEBUG(LOG_PLUGINS,"Updating node %s with Texpire %d",ip4_to_string(&buf,tmp->neighbor_ip_addr.v4),tmp->Texpire);
1441 if (tmp->Texpire == 0) { //purge
1442 OLSR_DEBUG(LOG_PLUGINS, "Purging node %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1444 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP CHECK EMPTY %d",list_empty(&ListOfObampNodes));
1452 if (nodesdeleted != 0)
1456 //OLSR_DEBUG(LOG_PLUGINS,"OBAMP: List empty");
1465 obamp_alive_gen(void *x __attribute__ ((unused)))
1467 struct OBAMP_alive myAlive;
1468 OLSR_DEBUG(LOG_PLUGINS, "Calling obamp_alive_gen\n");
1470 memset(&myAlive, 0, sizeof(myAlive));
1471 myAlive.MessageID = OBAMP_ALIVE;
1472 myAlive.status = DoIHaveATreeLink();
1473 olsr_obamp_gen(&myAlive, sizeof(struct OBAMP_alive));
1479 When a packet is captured on the sniffing interfaces, it is called EncapFlowInObamp
1480 here we check if the packet is multicast and we forward it to the overlay neighbors if we have a link tree
1484 EncapFlowInObamp(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
1486 unsigned char ipPacket[1500]; //TODO: optimize me
1488 #if !defined(REMOVE_LOG_DEBUG)
1489 struct ipaddr_str buf;
1491 struct ObampNode *tmp;
1492 struct list_head *pos;
1494 union olsr_ip_addr dst; /* Destination IP address in captured packet */
1495 struct ip *ipHeader; /* The IP header inside the captured IP packet */
1496 struct ip6_hdr *ipHeader6; /* The IP header inside the captured IP packet */
1499 struct sockaddr_ll pktAddr;
1500 socklen_t addrLen = sizeof(pktAddr);
1503 nBytes = recvfrom(skfd, ipPacket, 1500, //TODO: optimize me
1504 0, (struct sockaddr *)&pktAddr, &addrLen);
1510 /* if (nBytes < 0) */
1511 /* Check if the number of received bytes is large enough for an IP
1512 * packet which contains at least a minimum-size IP header.
1513 * Note: There is an apparent bug in the packet socket implementation in
1514 * combination with VLAN interfaces. On a VLAN interface, the value returned
1515 * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
1516 * returned on a non-VLAN interface, for the same ethernet frame. */
1517 if (nBytes < (int)sizeof(struct ip)) {
1519 OLSR_DEBUG(LOG_PLUGINS, "Captured frame too short");
1523 if (pktAddr.sll_pkttype == PACKET_OUTGOING || pktAddr.sll_pkttype == PACKET_MULTICAST) // ||
1524 //pktAddr.sll_pkttype == PACKET_BROADCAST)
1528 if ((ipPacket[0] & 0xf0) == 0x40) { //IPV4
1530 ipHeader = (struct ip *)ipPacket;
1532 dst.v4 = ipHeader->ip_dst;
1534 /* Only forward multicast packets. If configured, also forward local broadcast packets */
1535 if (IsMulticast(&dst)) {
1540 if (ipHeader->ip_p != SOL_UDP) {
1542 OLSR_DEBUG(LOG_PLUGINS, "NON UDP PACKET\n");
1545 //Forward the packet to tree links
1546 if (list_empty(&ListOfObampNodes) == 0) { //if the list is NOT empty
1548 list_for_each(pos, &ListOfObampNodes) {
1550 tmp = list_entry(pos, struct ObampNode, list);
1551 if (tmp->isTree == 1) {
1553 OLSR_DEBUG(LOG_PLUGINS, "Pushing data to Tree link to %s", ip4_to_string(&buf, tmp->neighbor_ip_addr.v4));
1554 SendOBAMPData(&tmp->neighbor_ip_addr.v4, ipPacket, nBytes);
1563 else if ((ipPacket[0] & 0xf0) == 0x60) { //IPv6
1565 ipHeader6 = (struct ip6_hdr *)ipPacket;
1566 if (ipHeader6->ip6_dst.s6_addr[0] == 0xff) //Multicast
1570 return; //not multicast
1572 if (ipHeader6->ip6_nxt != SOL_UDP) {
1574 OLSR_DEBUG(LOG_PLUGINS, "NON UDP PACKET\n");
1580 return; //Is not IP packet
1582 // send the packet to OLSR forward mechanism
1583 // SendOBAMPData(&tmp->neighbor_ip_addr.v6,ipPacket,nBytes);
1586 } /* if (pktAddr.sll_pkttype == ...) */
1587 } /* if (skfd >= 0 && (FD_ISSET...)) */
1588 } /* EncapFlowInObamp */
1590 //This function is called from olsrd_plugin.c and adds to the list the interfaces specified in the configuration file to sniff multicast traffic
1592 AddObampSniffingIf(const char *ifName,
1593 void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
1596 struct ObampSniffingIf *ifToAdd;
1598 OLSR_DEBUG(LOG_PLUGINS, "AddObampSniffingIf");
1601 assert(ifName != NULL);
1603 ifToAdd = olsr_malloc(sizeof(struct ObampSniffingIf), "OBAMPSniffingIf");
1605 strncpy(ifToAdd->ifName, ifName, 16); //TODO: 16 fix this
1606 ifToAdd->ifName[15] = '\0'; /* Ensures null termination */
1608 OLSR_DEBUG(LOG_PLUGINS, "Adding interface to list");
1610 list_add(&(ifToAdd->list), &ListOfObampSniffingIf);
1612 OLSR_DEBUG(LOG_PLUGINS, "Adding if %s to list of ObampSniffingIfaces", ifToAdd->ifName);
1621 INIT_LIST_HEAD(&ListOfObampSniffingIf);
1631 #if !defined(REMOVE_LOG_DEBUG)
1632 struct ipaddr_str buf;
1635 //Structs necessary for timers
1637 struct timer_entry *OBAMP_alive_timer;
1638 struct timer_entry *purge_nodes_timer;
1639 struct timer_entry *mesh_create_timer;
1640 struct timer_entry *tree_create_timer;
1641 struct timer_entry *outer_tree_create_timer;
1645 struct olsr_cookie_info *OBAMP_alive_gen_timer_cookie = NULL;
1646 struct olsr_cookie_info *purge_nodes_timer_cookie = NULL;
1647 struct olsr_cookie_info *mesh_create_timer_cookie = NULL;
1648 struct olsr_cookie_info *tree_create_timer_cookie = NULL;
1649 struct olsr_cookie_info *outer_tree_create_timer_cookie = NULL;
1651 if (olsr_cnf->ip_version == AF_INET6) {
1652 OLSR_ERROR(LOG_PLUGINS, "OBAMP does not support IPv6 at the moment.");
1656 //Setting OBAMP node state
1657 myState = olsr_malloc(sizeof(struct ObampNodeState), "OBAMPNodeState");
1658 myState->iamcore = 1;
1659 myState->TreeHeartBeat = 0;
1660 myState->TreeRequestDelay = 0;
1661 memcpy(&myState->myipaddr.v4, &olsr_cnf->router_id, olsr_cnf->ipsize);
1662 myState->CoreAddress = myState->myipaddr;
1664 myState->DataSequenceNumber = 0;
1665 myState->TreeCreateSequenceNumber = 0;
1666 myState->tree_req_sn = 0; //TODO: start from random number ?
1668 memset(&myState->ParentId.v4, 0, sizeof(myState->ParentId.v4));
1669 memset(&myState->OldParentId.v4, 1, sizeof(myState->OldParentId.v4));
1671 OLSR_DEBUG(LOG_PLUGINS, "SETUP: my IP - %s", ip4_to_string(&buf, myState->myipaddr.v4));
1673 INIT_LIST_HEAD(&ListOfObampNodes);
1675 //OLSR cookies stuff for timers
1676 OBAMP_alive_gen_timer_cookie = olsr_alloc_cookie("OBAMP Alive Generation", OLSR_COOKIE_TYPE_TIMER);
1677 purge_nodes_timer_cookie = olsr_alloc_cookie("purge nodes Generation", OLSR_COOKIE_TYPE_TIMER);
1678 mesh_create_timer_cookie = olsr_alloc_cookie("mesh create Generation", OLSR_COOKIE_TYPE_TIMER);
1679 tree_create_timer_cookie = olsr_alloc_cookie("tree create Generation", OLSR_COOKIE_TYPE_TIMER);
1680 outer_tree_create_timer_cookie = olsr_alloc_cookie("outer tree create Generation", OLSR_COOKIE_TYPE_TIMER);
1683 //Tells OLSR to launch olsr_parser when the packets for this plugin arrive
1684 olsr_parser_add_function(&olsr_parser, PARSER_TYPE);
1686 // start to send alive messages to appear in other joined lists
1688 olsr_start_timer(OBAMP_ALIVE_EIVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &obamp_alive_gen, NULL,
1689 OBAMP_alive_gen_timer_cookie);
1691 // start timer to purge nodes from list in softstate fashion
1693 olsr_start_timer(_Texpire_timer_ * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &purge_nodes, NULL,
1694 purge_nodes_timer_cookie);
1696 //start timer to create mesh
1698 olsr_start_timer(OBAMP_MESH_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &mesh_create, NULL,
1699 mesh_create_timer_cookie);
1701 //start timer for tree create procedure
1703 olsr_start_timer(OBAMP_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &tree_create, NULL,
1704 tree_create_timer_cookie);
1706 //start timer for tree create procedure
1707 outer_tree_create_timer =
1708 olsr_start_timer(OBAMP_OUTER_TREE_CREATE_IVAL * MSEC_PER_SEC, OBAMP_JITTER, OLSR_TIMER_PERIODIC, &outer_tree_create, NULL,
1709 tree_create_timer_cookie);
1712 //Create udp server socket for OBAMP signalling and register it to the scheduler
1713 OLSR_DEBUG(LOG_PLUGINS, "Launch Udp Servers");
1714 if (UdpServer() < 0) {
1715 OLSR_DEBUG(LOG_PLUGINS, "Problem in Launch Udp Servers");
1719 //Creates a socket for sniffing multicast traffic and registers it to the scheduler
1720 CreateObampSniffingInterfaces();
1725 /* -------------------------------------------------------------------------
1726 * Function : CloseOBAMP
1727 * Description: Close the OBAMP plugin and clean up
1732 * ------------------------------------------------------------------------- */