2 * OLSR Basic Multicast Forwarding (BMF) plugin.
3 * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
4 * Written by Erik Tromp.
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 Thales, BMF 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 "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
33 /* -------------------------------------------------------------------------
35 * Description: Multicast forwarding functions
36 * Created : 29 Jun 2006
38 * ------------------------------------------------------------------------- */
40 #define _MULTI_THREADED
45 #include <stddef.h> /* NULL */
46 #include <sys/types.h> /* ssize_t */
47 #include <string.h> /* strerror() */
48 #include <stdarg.h> /* va_list, va_start, va_end */
49 #include <errno.h> /* errno */
50 #include <assert.h> /* assert() */
51 #include <linux/if_ether.h> /* ETH_P_IP */
52 #include <linux/if_packet.h> /* struct sockaddr_ll, PACKET_MULTICAST */
53 #include <pthread.h> /* pthread_t, pthread_create() */
54 #include <signal.h> /* sigset_t, sigfillset(), sigdelset(), SIGINT */
55 #include <netinet/ip.h> /* struct ip */
56 #include <netinet/udp.h> /* struct udphdr */
59 #include "defs.h" /* olsr_cnf, OLSR_PRINTF */
61 #include "olsr.h" /* olsr_printf */
62 #include "scheduler.h" /* olsr_register_scheduler_event */
63 #include "mid_set.h" /* mid_lookup_main_addr() */
64 #include "mpr_selector_set.h" /* olsr_lookup_mprs_set() */
65 #include "link_set.h" /* get_best_link_to_neighbor() */
66 #include "net_olsr.h" /* ipequal */
69 #include "NetworkInterfaces.h" /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
70 #include "Address.h" /* IsMulticast() */
71 #include "Packet.h" /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */
72 #include "PacketHistory.h" /* InitPacketHistory() */
74 static pthread_t BmfThread;
75 static int BmfThreadRunning = 0;
77 /* -------------------------------------------------------------------------
78 * Function : BmfPError
79 * Description: Prints an error message at OLSR debug level 1.
80 * First the plug-in name is printed. Then (if format is not NULL
81 * and *format is not empty) the arguments are printed, followed
82 * by a colon and a blank. Then the message and a new-line.
83 * Input : format, arguments
87 * ------------------------------------------------------------------------- */
88 void BmfPError(const char* format, ...)
90 #define MAX_STR_DESC 255
91 char* strErr = strerror(errno);
92 char strDesc[MAX_STR_DESC];
94 /* Rely on short-circuit boolean evaluation */
95 if (format == NULL || *format == '\0')
97 olsr_printf(1, "%s: %s\n", PLUGIN_NAME, strErr);
103 olsr_printf(1, "%s: ", PLUGIN_NAME);
105 va_start(arglist, format);
106 vsnprintf(strDesc, MAX_STR_DESC, format, arglist);
109 strDesc[MAX_STR_DESC - 1] = '\0'; /* Ensures null termination */
111 olsr_printf(1, "%s: %s\n", strDesc, strErr);
115 /* -------------------------------------------------------------------------
116 * Function : MainAddressOf
117 * Description: Lookup the main address of a node
118 * Input : ip - IP address of the node
120 * Return : The main IP address of the node
122 * ------------------------------------------------------------------------- */
123 union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip)
125 union olsr_ip_addr* result;
127 /* TODO: mid_lookup_main_addr() is not thread-safe! */
128 result = mid_lookup_main_addr(ip);
134 } /* MainAddressOf */
136 /* -------------------------------------------------------------------------
137 * Function : EncapsulateAndForwardPacket
138 * Description: Encapsulate a captured raw IP packet and forward it
139 * Input : intf - the network interface on which to forward the packet
140 * encapsulationUdpData - The encapsulation header, followed by
141 * the encapsulated IP packet
145 * ------------------------------------------------------------------------- */
146 static void EncapsulateAndForwardPacket(
147 struct TBmfInterface* intf,
148 unsigned char* encapsulationUdpData)
151 u_int16_t udpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
153 /* The next destination(s) */
154 struct TBestNeighbors bestNeighborLinks;
155 int nPossibleNeighbors;
156 struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
162 /* Retrieve at most two best neigbors to forward the packet to */
163 GetBestTwoNeighbors(&bestNeighborLinks, intf, NULL, NULL, NULL, &nPossibleNeighbors);
165 if (nPossibleNeighbors <= 0)
169 "%s: --> not encap-forwarding on \"%s\": there is no neighbor that needs my retransmission\n",
175 /* Compose destination of encapsulation packet */
177 memset(&forwardTo, 0, sizeof(forwardTo));
178 forwardTo.sin_family = AF_INET;
179 forwardTo.sin_port = htons(BMF_ENCAP_PORT);
181 /* Start by filling in the local broadcast address */
182 forwardTo.sin_addr = intf->broadAddr.v4;
184 /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
185 * packet (to the best neighbor).
186 * - If the BMF mechanism is BM_BROADCAST,
187 * - send one unicast packet if there is one possible neighbor,
188 * - send two unicast packets if there are two possible neighbors, and
189 * - only if there are more than two possible neighbors, then send an
190 * (WLAN-air-expensive, less reliable) broadcast packet. */
191 if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors < 2)
195 else /* BmfMechanism == BM_BROADCAST && nPossibleNeighbors >= 2 */
200 for (i = 0; i < nPacketsToSend; i++)
202 if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors <= 2)
204 forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
207 /* Forward the BMF packet via the encapsulation socket */
208 nBytesWritten = sendto(
209 intf->encapsulatingSkfd,
210 encapsulationUdpData,
213 (struct sockaddr*) &forwardTo,
216 /* Evaluate and display result */
217 if (nBytesWritten != udpDataLen)
219 BmfPError("sendto() error forwarding pkt on \"%s\"", intf->ifName);
223 /* Increase counter */
224 intf->nBmfPacketsTx++;
228 "%s: --> encapsulated and forwarded on \"%s\" to %s\n",
231 inet_ntoa(forwardTo.sin_addr));
232 } /* if (nBytesWritten != udpDataLen) */
234 } /* EncapsulateAndForwardPacket */
236 /* -------------------------------------------------------------------------
237 * Function : BmfPacketCaptured
238 * Description: Handle a captured IP packet
239 * Input : intf - the network interface on which the packet was captured
240 * sllPkttype - the type of packet. Either PACKET_OUTGOING,
241 * PACKET_BROADCAST or PACKET_MULTICAST.
242 * encapsulationUdpData - space for the encapsulation header, followed by
243 * the captured IP packet
246 * Data Used : BmfInterfaces
247 * Notes : The IP packet is assumed to be captured on a socket of family
248 * PF_PACKET and type SOCK_DGRAM (cooked).
249 * ------------------------------------------------------------------------- */
250 static void BmfPacketCaptured(
251 struct TBmfInterface* intf,
252 unsigned char sllPkttype,
253 unsigned char* encapsulationUdpData)
255 union olsr_ip_addr src; /* Source IP address in captured packet */
256 union olsr_ip_addr dst; /* Destination IP address in captured packet */
257 union olsr_ip_addr* origIp; /* Main OLSR address of source of captured packet */
258 struct TBmfInterface* walker;
260 int isFromOlsrNeighbor;
262 unsigned char* ipPacket; /* The captured IP packet... */
263 u_int16_t ipPacketLen; /* ...and its length */
264 struct ip* ipHeader; /* The IP header inside the captured IP packet */
266 struct TEncapHeader* encapHdr;
268 struct ipaddr_str srcBuf, dstBuf;
270 ipHeader = GetIpHeader(encapsulationUdpData);
272 dst.v4 = ipHeader->ip_dst;
274 /* Only forward multicast packets. If configured, also forward local broadcast packets */
275 if (IsMulticast(&dst) ||
276 (EnableLocalBroadcast != 0 && ipequal(&dst, &intf->broadAddr)))
285 ipPacket = GetIpPacket(encapsulationUdpData);
287 /* Don't forward fragments of IP packets. Also, don't forward OLSR packets (UDP
288 * port 698) and BMF encapsulated packets */
289 if (IsIpFragment(ipPacket) || IsOlsrOrBmfPacket(ipPacket))
294 /* Increase counter */
295 intf->nBmfPacketsRx++;
297 /* Check if the frame is captured on an OLSR-enabled interface */
298 isFromOlsrIntf = (intf->olsrIntf != NULL);
300 /* Retrieve the length of the captured packet */
301 ipPacketLen = GetIpTotalLength(ipPacket);
303 src.v4 = ipHeader->ip_src;
307 "%s: %s pkt of %ld bytes captured on %s interface \"%s\": %s->%s\n",
309 sllPkttype == PACKET_OUTGOING ? "outgoing" : "incoming",
311 isFromOlsrIntf ? "OLSR" : "non-OLSR",
313 olsr_ip_to_string(&srcBuf, &src),
314 olsr_ip_to_string(&dstBuf, &dst));
316 /* Lookup main address of source in the MID table of OLSR */
317 origIp = MainAddressOf(&src);
319 /* Calculate packet fingerprint */
320 crc32 = PacketCrc32(ipPacket, ipPacketLen);
322 /* Check if this packet was seen recently */
323 if (CheckAndMarkRecentPacket(crc32))
325 /* Increase counter */
326 intf->nBmfPacketsRxDup++;
330 "%s: --> discarding: packet is duplicate\n",
335 /* Compose encapsulation header */
336 encapHdr = (struct TEncapHeader*) encapsulationUdpData;
337 memset (encapHdr, 0, ENCAP_HDR_LEN);
338 encapHdr->type = BMF_ENCAP_TYPE;
339 encapHdr->len = BMF_ENCAP_LEN;
340 encapHdr->reserved = 0;
341 encapHdr->crc32 = htonl(crc32);
343 /* Check if the frame is captured on an OLSR interface from an OLSR neighbor.
344 * TODO1: get_best_link_to_neighbor() is not thread-safe.
345 * TODO2: get_best_link_to_neighbor() may be very CPU-expensive, a simpler call
346 * would do here (something like 'get_any_link_to_neighbor()'). */
348 (isFromOlsrIntf /* The frame is captured on an OLSR interface... */
349 && get_best_link_to_neighbor(origIp) != NULL); /* ...from an OLSR neighbor */
351 /* Check with OLSR if I am MPR for that neighbor */
352 /* TODO: olsr_lookup_mprs_set() is not thread-safe! */
353 iAmMpr = olsr_lookup_mprs_set(origIp) != NULL;
355 /* Check with each network interface what needs to be done on it */
356 for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
358 /* Is the forwarding interface OLSR-enabled? */
359 int isToOlsrIntf = (walker->olsrIntf != NULL);
361 /* Depending on certain conditions, we decide whether or not to forward
362 * the packet, and if it is forwarded, in which form (encapsulated
363 * or not, TTL decreased or not). These conditions are:
364 * - is the packet is coming in on an OLSR interface or not? (isFromOlsrIntf)
365 * - is the packet going out on an OLSR interface or not? (isToOlsrIntf)
366 * - if the packet if coming in on an OLSR interface:
367 * - is the node that forwarded the packet my OLSR-neighbor? (isFromOlsrNeighbor)
368 * - has the node that forwarded the packet selected me as MPR? (iAmMpr)
370 * Based on these conditions, the following cases can be distinguished:
372 * - Case 1: Packet coming in on an OLSR interface. What to
373 * do with it on an OLSR interface?
375 * - Case 1.1: If the forwarding node is an OLSR neighbor that has *not*
376 * selected me as MPR: don't forward the packet.
377 * - Case 1.2: If the forwarding node is an OLSR neighbor that has selected
378 * me as MPR: encapsulate and forward the packet.
379 * - Case 1.3: If the forwarding node is not an OLSR neighbor: encapsulate
380 * and forward the packet.
381 * NOTE: Case 1.3 is a special case. In the perfect world, we expect to
382 * see only OLSR-neighbors on OLSR-enabled interfaces. Sometimes, however,
383 * ignorant users will connect a host not running OLSR, to a LAN in
384 * which there are hosts running OLSR. Of course these ignorant users,
385 * expecting magic, want to see their multicast packets being forwarded
386 * through the network.
388 * - Case 2: Packet coming in on an OLSR interface. What to do with it on a
389 * non-OLSR interface?
390 * Answer: Forward it.
392 * - Case 3: Packet coming in on a non-OLSR interface. What to
393 * do with it on an OLSR interface?
394 * Answer: Encapsulate and forward it.
396 * - Case 4: Packet coming in on non-OLSR interface. What to do with it on a
397 * non-OLSR interface?
398 * Answer 1: nothing. Multicast routing between non-OLSR interfaces
399 * is to be done by other protocols (e.g. PIM, DVMRP).
400 * Answer 2 (better): Forward it.
403 if (isFromOlsrIntf && isToOlsrIntf)
405 /* Case 1: Forward from an OLSR interface to an OLSR interface */
407 if (isFromOlsrNeighbor && !iAmMpr)
412 struct ipaddr_str buf;
416 "%s: --> not encap-forwarding on \"%s\": I am not selected as MPR by neighbor %s\n",
419 olsr_ip_to_string(&buf, &src));
422 else if (sllPkttype == PACKET_OUTGOING && intf == walker)
426 "%s: --> not encap-forwarding on \"%s\": pkt was captured on that interface\n",
432 /* Case 1.2 and 1.3 */
433 EncapsulateAndForwardPacket(walker, encapsulationUdpData);
435 } /* if (isFromOlsrIntf && isToOlsrIntf) */
437 else if (isFromOlsrIntf && !isToOlsrIntf)
439 /* Case 2: Forward from OLSR interface to non-OLSR interface */
442 struct sockaddr_ll dest;
444 /* If the encapsulated IP packet is a local broadcast packet,
445 * update its destination address to match the subnet of the network
446 * interface on which the packet is being sent. */
447 CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
449 memset(&dest, 0, sizeof(dest));
450 dest.sll_family = AF_PACKET;
451 dest.sll_protocol = htons(ETH_P_IP);
452 dest.sll_ifindex = if_nametoindex(walker->ifName);
453 dest.sll_halen = IFHWADDRLEN;
455 /* Use all-ones as destination MAC address. When the IP destination is
456 * a multicast address, the destination MAC address should normally also
457 * be a multicast address. E.g., when the destination IP is 224.0.0.1,
458 * the destination MAC should be 01:00:5e:00:00:01. However, it does not
459 * seem to matter when the destination MAC address is set to all-ones
461 memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
463 nBytesWritten = sendto(
464 walker->capturingSkfd,
468 (struct sockaddr*) &dest,
470 if (nBytesWritten != ipPacketLen)
472 BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
476 /* Increase counter */
477 walker->nBmfPacketsTx++;
479 OLSR_PRINTF(8, "%s: --> forwarded on \"%s\"\n", PLUGIN_NAME_SHORT, walker->ifName);
481 } /* else if (isFromOlsrIntf && !isToOlsrIntf) */
483 else if (!isFromOlsrIntf && isToOlsrIntf)
485 /* Case 3: Forward from a non-OLSR interface to an OLSR interface.
486 * Encapsulate and forward packet. */
488 EncapsulateAndForwardPacket(walker, encapsulationUdpData);
489 } /* else if (!isFromOlsrIntf && isToOlsrIntf) */
493 /* Case 4: Forward from non-OLSR interface to non-OLSR interface. */
495 /* Don't forward on interface on which packet was received */
500 "%s: --> not forwarding on \"%s\": pkt was captured on that interface\n",
508 struct sockaddr_ll dest;
510 /* If the encapsulated IP packet is a local broadcast packet,
511 * update its destination address to match the subnet of the network
512 * interface on which the packet is being sent. */
513 CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
515 memset(&dest, 0, sizeof(dest));
516 dest.sll_family = AF_PACKET;
517 dest.sll_protocol = htons(ETH_P_IP);
518 dest.sll_ifindex = if_nametoindex(walker->ifName);
519 dest.sll_halen = IFHWADDRLEN;
521 /* Use all-ones as destination MAC address. When the IP destination is
522 * a multicast address, the destination MAC address should normally also
523 * be a multicast address. E.g., when the destination IP is 224.0.0.1,
524 * the destination MAC should be 01:00:5e:00:00:01. However, it does not
525 * seem to matter when the destination MAC address is set to all-ones
527 memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
529 nBytesWritten = sendto(
530 walker->capturingSkfd,
534 (struct sockaddr*) &dest,
536 if (nBytesWritten != ipPacketLen)
538 BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
542 /* Increase counter */
543 walker->nBmfPacketsTx++;
547 "%s: --> forwarded from non-OLSR on non-OLSR \"%s\"\n",
551 } /* if (intf == walker) */
554 } /* BmfPacketCaptured */
556 /* -------------------------------------------------------------------------
557 * Function : BmfEncapsulationPacketReceived
558 * Description: Handle a received BMF-encapsulation packet
559 * Input : intf - the network interface on which the packet was received
560 * forwardedBy - the IP node that forwarded the packet to me
561 * forwardedTo - the destination IP address of the encapsulation
562 * packet, in case the packet was received promiscuously.
563 * Pass NULL if the packet is received normally (unicast or
565 * encapsulationUdpData - the encapsulating IP UDP data, containting
566 * the BMF encapsulation header, followed by the encapsulated
570 * Data Used : BmfInterfaces
571 * ------------------------------------------------------------------------- */
572 static void BmfEncapsulationPacketReceived(
573 struct TBmfInterface* intf,
574 union olsr_ip_addr* forwardedBy,
575 union olsr_ip_addr* forwardedTo,
576 unsigned char* encapsulationUdpData)
578 int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */
579 struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
580 unsigned char* ipPacket; /* The encapsulated IP packet */
581 u_int16_t ipPacketLen; /* Length of the encapsulated IP packet */
582 struct ip* ipHeader; /* IP header inside the encapsulated IP packet */
583 union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */
584 union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */
585 struct TEncapHeader* encapsulationHdr;
586 u_int16_t encapsulationUdpDataLen;
587 struct TBmfInterface* walker;
589 struct ipaddr_str mcSrcBuf, mcDstBuf, forwardedByBuf, forwardedToBuf;
591 /* Are we talking to ourselves? */
592 if (if_ifwithaddr(forwardedBy) != NULL)
597 /* Discard encapsulated packets received on a non-OLSR interface */
598 if (intf->olsrIntf == NULL)
603 /* Retrieve details about the encapsulated IP packet */
604 ipPacket = GetIpPacket(encapsulationUdpData);
605 ipPacketLen = GetIpTotalLength(ipPacket);
606 ipHeader = GetIpHeader(encapsulationUdpData);
608 mcSrc.v4 = ipHeader->ip_src;
609 mcDst.v4 = ipHeader->ip_dst;
611 /* Increase counter */
612 intf->nBmfPacketsRx++;
614 /* Beware: not possible to call olsr_ip_to_string more than 4 times in same printf */
617 "%s: encapsulated pkt of %ld bytes incoming on \"%s\": %s->%s, forwarded by %s to %s\n",
621 olsr_ip_to_string(&mcSrcBuf, &mcSrc),
622 olsr_ip_to_string(&mcDstBuf, &mcDst),
623 olsr_ip_to_string(&forwardedByBuf, forwardedBy),
624 forwardedTo != NULL ? olsr_ip_to_string(&forwardedToBuf, forwardedTo) : "me");
626 /* Get encapsulation header */
627 encapsulationHdr = (struct TEncapHeader*) encapsulationUdpData;
629 /* Verify correct format of BMF encapsulation header */
630 if (encapsulationHdr->type != BMF_ENCAP_TYPE ||
631 encapsulationHdr->len != BMF_ENCAP_LEN ||
632 ntohs(encapsulationHdr->reserved != 0))
636 "%s: --> discarding: format of BMF encapsulation header not recognized\n",
641 /* Check if this packet was seen recently */
642 if (CheckAndMarkRecentPacket(ntohl(encapsulationHdr->crc32)))
644 /* Increase counter */
645 intf->nBmfPacketsRxDup++;
649 "%s: --> discarding: packet is duplicate\n",
654 if (EtherTunTapFd >= 0)
656 /* Unpack the encapsulated IP packet and deliver it locally, by sending
657 * a copy into the local IP stack via the EtherTunTap interface */
659 union olsr_ip_addr broadAddr;
660 int nBytesToWrite, nBytesWritten;
661 unsigned char* bufferToWrite;
663 /* If the encapsulated IP packet is a local broadcast packet,
664 * update its destination address to match the subnet of the EtherTunTap
666 broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
667 CheckAndUpdateLocalBroadcast(ipPacket, &broadAddr);
669 bufferToWrite = ipPacket;
670 nBytesToWrite = ipPacketLen;
672 /* Write the packet into the EtherTunTap interface for local delivery */
673 nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite);
674 if (nBytesWritten != nBytesToWrite)
676 BmfPError("write() error forwarding encapsulated pkt on \"%s\"", EtherTunTapIfName);
682 "%s: --> unpacked and delivered locally on \"%s\"\n",
686 } /* if (EtherTunTapFd >= 0) */
688 /* Check if I am MPR for the forwarder */
689 /* TODO: olsr_lookup_mprs_set() is not thread-safe! */
690 iAmMpr = (olsr_lookup_mprs_set(MainAddressOf(forwardedBy)) != NULL);
692 /* Compose destination address for next hop */
693 memset(&forwardTo, 0, sizeof(forwardTo));
694 forwardTo.sin_family = AF_INET;
695 forwardTo.sin_port = htons(BMF_ENCAP_PORT);
697 /* Retrieve the number of bytes to be forwarded via the encapsulation socket */
698 encapsulationUdpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
700 /* Check with each network interface what needs to be done on it */
701 for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
703 /* What to do with the packet on a non-OLSR interface? Unpack
704 * encapsulated packet, and forward it.
706 * What to do with the packet on an OLSR interface? Forward it only
707 * if the forwarding node has selected us as MPR (iAmMpr).
709 * Note that the packet is always coming in on an OLSR interface, because
710 * it is an encapsulated BMF packet. */
712 /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
713 if (walker->olsrIntf == NULL)
716 struct sockaddr_ll dest;
718 /* If the encapsulated IP packet is a local broadcast packet,
719 * update its destination address to match the subnet of the network
720 * interface on which the packet is being sent. */
721 CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
723 memset(&dest, 0, sizeof(dest));
724 dest.sll_family = AF_PACKET;
725 dest.sll_protocol = htons(ETH_P_IP);
726 dest.sll_ifindex = if_nametoindex(walker->ifName);
727 dest.sll_halen = IFHWADDRLEN;
729 /* Use all-ones as destination MAC address. When the IP destination is
730 * a multicast address, the destination MAC address should normally also
731 * be a multicast address. E.g., when the destination IP is 224.0.0.1,
732 * the destination MAC should be 01:00:5e:00:00:01. However, it does not
733 * seem to matter when the destination MAC address is set to all-ones
735 memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
737 nBytesWritten = sendto(
738 walker->capturingSkfd,
742 (struct sockaddr*) &dest,
744 if (nBytesWritten != ipPacketLen)
746 BmfPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);
750 /* Increase counter */
751 walker->nBmfPacketsTx++;
755 "%s: --> unpacked and forwarded on \"%s\"\n",
759 } /* if (walker->olsrIntf == NULL) */
761 /* To an OLSR interface: forward the packet, but only if this node is
762 * selected as MPR by the forwarding node */
765 struct TBestNeighbors bestNeighborLinks;
766 int nPossibleNeighbors;
771 /* Retrieve at most two best neigbors to forward the packet to */
778 &nPossibleNeighbors);
780 if (nPossibleNeighbors <= 0)
784 "%s: --> not forwarding on \"%s\": there is no neighbor that needs my retransmission\n",
791 /* Compose destination of encapsulation packet.
792 * Start by filling in the local broadcast address. */
793 forwardTo.sin_addr = walker->broadAddr.v4;
795 /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
796 * packet (to the best neighbor). Other neighbors listen promiscuously.
797 * - If the BMF mechanism is BM_BROADCAST,
798 * - send one unicast packet if there is one possible neighbor,
799 * - send two unicast packets if there are two possible neighbors, and
800 * - only if there are more than two possible neighbors, then send an
801 * (WLAN-air-expensive, less reliable) broadcast packet. */
802 if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors < 2)
806 else /* BmfMechanism == BM_BROADCAST && nPossibleNeighbors >= 2 */
811 for (i = 0; i < nPacketsToSend; i++)
813 if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors <= 2)
815 /* For unicast, overwrite the local broadcast address which was filled in
817 forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
820 /* Forward the BMF packet via the encapsulation socket */
821 nBytesWritten = sendto(
822 walker->encapsulatingSkfd,
823 encapsulationUdpData,
824 encapsulationUdpDataLen,
826 (struct sockaddr*) &forwardTo,
829 /* Evaluate and display result */
830 if (nBytesWritten != encapsulationUdpDataLen)
832 BmfPError("sendto() error forwarding encapsulated pkt on \"%s\"", walker->ifName);
836 /* Increase counter */
837 walker->nBmfPacketsTx++;
841 "%s: --> forwarded on \"%s\" to %s\n",
844 inet_ntoa(forwardTo.sin_addr));
847 } /* else if (iAmMpr) */
849 else /* walker->olsrIntf != NULL && !iAmMpr */
852 struct ipaddr_str buf;
854 /* 'walker' is an OLSR interface, but I am not selected as MPR. In that
855 * case, don't forward. */
858 "%s: --> not forwarding on \"%s\": I am not selected as MPR by %s\n",
861 olsr_ip_to_string(&buf, forwardedBy));
864 } /* BmfEncapsulationPacketReceived */
866 /* -------------------------------------------------------------------------
867 * Function : BmfTunPacketCaptured
868 * Description: Handle an IP packet, captured outgoing on the tuntap interface
869 * Input : encapsulationUdpData - space for the encapsulation header, followed by
870 * the captured outgoing IP packet
874 * Notes : The packet is assumed to be captured on a socket of family
875 * PF_PACKET and type SOCK_DGRAM (cooked).
876 * ------------------------------------------------------------------------- */
877 static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
879 union olsr_ip_addr srcIp;
880 union olsr_ip_addr dstIp;
881 union olsr_ip_addr broadAddr;
882 struct TBmfInterface* walker;
883 unsigned char* ipPacket;
884 u_int16_t ipPacketLen;
887 struct TEncapHeader* encapHdr;
889 struct ipaddr_str srcIpBuf, dstIpBuf;
891 ipPacket = GetIpPacket(encapsulationUdpData);
892 ipPacketLen = GetIpTotalLength(ipPacket);
893 ipHeader = GetIpHeader(encapsulationUdpData);
895 /* Only forward multicast packets. If configured, also forward local broadcast packets */
896 dstIp.v4 = ipHeader->ip_dst;
898 broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
899 if (IsMulticast(&dstIp) ||
900 (EnableLocalBroadcast != 0 && ipequal(&dstIp, &broadAddr)))
909 srcIp.v4 = ipHeader->ip_src;
913 "%s: outgoing pkt of %ld bytes captured on tuntap interface \"%s\": %s->%s\n",
917 olsr_ip_to_string(&srcIpBuf, &srcIp),
918 olsr_ip_to_string(&dstIpBuf, &dstIp));
920 /* Calculate packet fingerprint */
921 crc32 = PacketCrc32(ipPacket, ipPacketLen);
923 /* Check if this packet was seen recently */
924 if (CheckAndMarkRecentPacket(crc32))
928 "%s: --> discarding: packet is duplicate\n",
933 /* Compose encapsulation header */
934 encapHdr = (struct TEncapHeader*) encapsulationUdpData;
935 memset (encapHdr, 0, ENCAP_HDR_LEN);
936 encapHdr->type = BMF_ENCAP_TYPE;
937 encapHdr->len = BMF_ENCAP_LEN;
938 encapHdr->reserved = 0;
939 encapHdr->crc32 = htonl(crc32);
941 /* Check with each network interface what needs to be done on it */
942 for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
944 /* Is the forwarding interface OLSR-enabled? */
945 if (walker->olsrIntf != NULL)
947 /* On an OLSR interface: encapsulate and forward packet. */
949 EncapsulateAndForwardPacket(walker, encapsulationUdpData);
953 /* On a non-OLSR interface: what to do?
954 * Answer 1: nothing. Multicast routing between non-OLSR interfaces
955 * is to be done by other protocols (e.g. PIM, DVMRP).
956 * Answer 2 (better): Forward it. */
959 struct sockaddr_ll dest;
961 /* If the encapsulated IP packet is a local broadcast packet,
962 * update its destination address to match the subnet of the network
963 * interface on which the packet is being sent. */
964 CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
966 memset(&dest, 0, sizeof(dest));
967 dest.sll_family = AF_PACKET;
968 dest.sll_protocol = htons(ETH_P_IP);
969 dest.sll_ifindex = if_nametoindex(walker->ifName);
970 dest.sll_halen = IFHWADDRLEN;
972 /* Use all-ones as destination MAC address. When the IP destination is
973 * a multicast address, the destination MAC address should normally also
974 * be a multicast address. E.g., when the destination IP is 224.0.0.1,
975 * the destination MAC should be 01:00:5e:00:00:01. However, it does not
976 * seem to matter when the destination MAC address is set to all-ones
978 memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
980 nBytesWritten = sendto(
981 walker->capturingSkfd,
985 (struct sockaddr*) &dest,
987 if (nBytesWritten != ipPacketLen)
989 BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName);
993 /* Increase counter */
994 walker->nBmfPacketsTx++;
998 "%s: --> forwarded from non-OLSR to non-OLSR \"%s\"\n",
1004 } /* BmfTunPacketCaptured */
1006 /* -------------------------------------------------------------------------
1008 * Description: Wait (blocking) for IP packets, then call the handler for each
1013 * Data Used : BmfInterfaces
1014 * ------------------------------------------------------------------------- */
1015 static void DoBmf(void)
1018 unsigned char rxBuffer[BMF_BUFFER_SIZE];
1021 assert(HighestSkfd >= 0);
1023 /* Make a local copy of the set of file descriptors that select() can
1024 * modify to indicate which descriptors actually changed status */
1027 /* Wait (blocking) for packets received on any of the sockets.
1028 * NOTE: don't use a timeout (last parameter). It causes a high system CPU load! */
1029 nFdBitsSet = select(HighestSkfd + 1, &rxFdSet, NULL, NULL, NULL);
1034 BmfPError("select() error");
1039 while (nFdBitsSet > 0)
1041 struct TBmfInterface* walker;
1043 /* Check if a packet was received on the capturing socket (if any)
1044 * of each network interface */
1045 for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
1047 int skfd = walker->capturingSkfd;
1048 if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
1050 struct sockaddr_ll pktAddr;
1051 socklen_t addrLen = sizeof(pktAddr);
1053 unsigned char* ipPacket;
1055 /* A packet was captured. */
1059 /* Receive the captured Ethernet frame, leaving space for the BMF
1060 * encapsulation header */
1061 ipPacket = GetIpPacket(rxBuffer);
1065 BMF_BUFFER_SIZE - ENCAP_HDR_LEN,
1067 (struct sockaddr*)&pktAddr,
1071 BmfPError("recvfrom() error on \"%s\"", walker->ifName);
1074 } /* if (nBytes < 0) */
1076 /* Check if the number of received bytes is large enough for an IP
1077 * packet which contains at least a minimum-size IP header.
1078 * Note: There is an apparent bug in the packet socket implementation in
1079 * combination with VLAN interfaces. On a VLAN interface, the value returned
1080 * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
1081 * returned on a non-VLAN interface, for the same ethernet frame. */
1082 if (nBytes < (int)sizeof(struct ip))
1086 "%s: captured frame too short (%d bytes) on \"%s\"\n",
1094 if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
1095 pktAddr.sll_pkttype == PACKET_MULTICAST ||
1096 pktAddr.sll_pkttype == PACKET_BROADCAST)
1098 /* A multicast or broadcast packet was captured */
1100 BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer);
1102 } /* if (pktAddr.sll_pkttype == ...) */
1103 } /* if (skfd >= 0 && (FD_ISSET...)) */
1106 /* Check if a BMF encapsulation packet was received on the listening
1107 * socket (if any) of each network interface */
1108 for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
1110 int skfd = walker->listeningSkfd;
1111 if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
1113 struct sockaddr_ll pktAddr;
1114 socklen_t addrLen = sizeof(pktAddr);
1117 struct ip* ipHeader;
1118 struct udphdr* udpHeader;
1120 union olsr_ip_addr forwardedBy;
1121 union olsr_ip_addr forwardedTo;
1123 /* Heard a BMF packet */
1132 (struct sockaddr*)&pktAddr,
1136 BmfPError("recvfrom() error on \"%s\"", walker->ifName);
1139 } /* if (nBytes < 0) */
1141 /* Check if the received packet is actually directed to another
1142 * node on the LAN */
1143 if (pktAddr.sll_pkttype != PACKET_OTHERHOST)
1145 /* No, the packet is directed to this node. In that case it will
1146 * be, or will already have been received, via the encapsulating
1147 * socket. Discard it here. */
1149 } /* if (pktAddr.sll_pkttype ...) */
1151 /* Check if the received packet is UDP - BMF port */
1152 ipHeader = (struct ip*)rxBuffer;
1153 if (ipHeader->ip_p != SOL_UDP)
1159 udpHeader = (struct udphdr*)(rxBuffer + GetIpHeaderLength(rxBuffer));
1160 destPort = ntohs(udpHeader->dest);
1161 if (destPort != BMF_ENCAP_PORT)
1167 /* Check if the number of received bytes is large enough for a minimal BMF
1168 * encapsulation packet, at least:
1169 * - the IP header of the encapsulation IP packet
1170 * - the UDP header of the encapsulation IP packet
1171 * - the encapsulation header
1172 * - a minimum IP header inside the encapsulated packet
1173 * Note: on a VLAN interface, the value returned by 'recvfrom' may (but need
1174 * not) be 4 (bytes) larger than the value returned on a non-VLAN interface, for
1175 * the same ethernet frame. */
1177 GetIpHeaderLength(rxBuffer) +
1178 sizeof(struct udphdr) +
1181 if (nBytes < minimumLength)
1185 "%s: captured a too short encapsulation packet (%d bytes) on \"%s\"\n",
1193 forwardedBy.v4 = ipHeader->ip_src;
1194 forwardedTo.v4 = ipHeader->ip_dst;
1195 BmfEncapsulationPacketReceived(
1199 rxBuffer + GetIpHeaderLength(rxBuffer) + sizeof(struct udphdr));
1201 } /* if (skfd >= 0 && (FD_ISSET...)) */
1204 /* Check if a packet was received on the encapsulating socket (if any)
1205 * of each network interface */
1206 for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
1208 int skfd = walker->encapsulatingSkfd;
1209 if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
1211 struct sockaddr_in from;
1212 socklen_t fromLen = sizeof(from);
1215 union olsr_ip_addr forwardedBy;
1217 /* An encapsulated packet was received */
1226 (struct sockaddr*)&from,
1230 BmfPError("recvfrom() error on \"%s\"", walker->ifName);
1233 } /* if (nBytes < 0) */
1235 forwardedBy.v4 = from.sin_addr;
1237 /* Check if the number of received bytes is large enough for a minimal BMF
1238 * encapsulation packet, at least:
1239 * - the encapsulation header
1240 * - a minimum IP header inside the encapsulated packet */
1244 if (nBytes < minimumLength)
1246 struct ipaddr_str buf;
1249 "%s: received a too short encapsulation packet (%d bytes) from %s on \"%s\"\n",
1252 olsr_ip_to_string(&buf, &forwardedBy),
1258 /* Unfortunately, the recvfrom call does not return the destination
1259 * of the encapsulation packet (the destination may be either the
1260 * my unicast or my local broadcast address). Therefore we fill in 'NULL'
1261 * for the 'forwardedTo' parameter. */
1262 BmfEncapsulationPacketReceived(walker, &forwardedBy, NULL, rxBuffer);
1264 } /* if (skfd >= 0 && (FD_ISSET...)) */
1267 if (nFdBitsSet > 0 && FD_ISSET(EtherTunTapFd, &rxFdSet))
1269 /* Check if an application has sent a packet out via the tuntap
1270 * network interface */
1273 unsigned char* ipPacket;
1274 unsigned char* bufferToRead;
1275 size_t nBytesToRead;
1279 /* Receive the packet, leaving space for the BMF encapsulation header */
1280 ipPacket = GetIpPacket(rxBuffer);
1282 bufferToRead = ipPacket;
1283 nBytesToRead = BMF_BUFFER_SIZE - ENCAP_HDR_LEN;
1285 nBytes = read(EtherTunTapFd, bufferToRead, nBytesToRead);
1289 BmfPError("recvfrom() error on \"%s\"", EtherTunTapIfName);
1293 /* Check if the number of received bytes is large enough for an IP
1294 * packet which contains at least a minimum-size IP header */
1295 if (nBytes < (int)sizeof(struct ip))
1299 "%s: captured packet too short (%d bytes) on \"%s\"\n",
1306 /* An outbound packet was captured */
1308 BmfTunPacketCaptured(rxBuffer);
1310 } /* if (nBytes < ... */
1311 } /* if (nBytes < 0) */
1312 } /* if (nFdBitsSet > 0 && ... */
1313 } /* while (nFdBitsSet > 0) */
1316 /* -------------------------------------------------------------------------
1317 * Function : BmfSignalHandler
1318 * Description: Signal handler function
1319 * Input : signo - signal being handled
1322 * Data Used : BmfThreadRunning
1323 * ------------------------------------------------------------------------- */
1324 static void BmfSignalHandler(int signo __attribute__((unused)))
1326 BmfThreadRunning = 0;
1327 } /* BmfSignalHandler */
1329 /* -------------------------------------------------------------------------
1331 * Description: Receiver thread function
1332 * Input : useless - not used
1335 * Data Used : BmfThreadRunning
1336 * Notes : Another thread can gracefully stop this thread by sending
1338 * ------------------------------------------------------------------------- */
1339 static void* BmfRun(void* useless __attribute__((unused)))
1341 /* Mask all signals except SIGALRM */
1342 sigset_t blockedSigs;
1343 sigfillset(&blockedSigs);
1344 sigdelset(&blockedSigs, SIGALRM);
1345 if (pthread_sigmask(SIG_BLOCK, &blockedSigs, NULL) != 0)
1347 BmfPError("pthread_sigmask() error");
1350 /* Set up the signal handler for the process: use SIGALRM to terminate
1351 * the BMF thread. Only if a signal handler is specified, does a blocking
1352 * system call return with errno set to EINTR; if a signal hander is not
1353 * specified, any system call in which the thread may be waiting will not
1354 * return. Note that the BMF thread is usually blocked in the select()
1355 * function (see DoBmf()). */
1356 if (signal(SIGALRM, BmfSignalHandler) == SIG_ERR)
1358 BmfPError("signal() error");
1361 /* Call the thread function until flagged to exit */
1362 while (BmfThreadRunning != 0)
1370 /* -------------------------------------------------------------------------
1371 * Function : InterfaceChange
1372 * Description: Callback function passed to OLSRD for it to call whenever a
1373 * network interface has been added, removed or updated
1374 * Input : interf - the network interface to deal with
1375 * action - indicates if the specified network interface was
1376 * added, removed or updated.
1380 * ------------------------------------------------------------------------- */
1381 int InterfaceChange(struct interface* interf, int action)
1385 case (IFCHG_IF_ADD):
1386 AddInterface(interf);
1387 olsr_printf(1, "%s: interface %s added\n", PLUGIN_NAME, interf->int_name);
1390 case (IFCHG_IF_REMOVE):
1391 /* We cannot just remove the interface, because the receive-thread is likely
1392 * to be waiting in select(...) for packets coming in via the interface.
1393 * Therefore we first close BMF (CloseBmf()), interrupting and kiling the
1394 * receive-thread so that it is safe to remove this (and all other)
1395 * interfaces. After that, BMF is re-started (InitBmf(interf)). */
1398 olsr_printf(1, "%s: interface %s removed\n", PLUGIN_NAME, interf->int_name);
1401 case (IFCHG_IF_UPDATE):
1402 olsr_printf(1, "%s: interface %s updated\n", PLUGIN_NAME, interf->int_name);
1408 "%s: interface %s: error - unknown action (%d)\n",
1410 interf->int_name, action);
1415 } /* InterfaceChange */
1417 /* -------------------------------------------------------------------------
1418 * Function : InitBmf
1419 * Description: Initialize the BMF plugin
1420 * Input : skipThisIntf - specifies which network interface should not
1421 * be enabled for BMF. Pass NULL if not applicable.
1423 * Return : fail (0) or success (1)
1424 * Data Used : BmfThreadRunning, BmfThread
1425 * ------------------------------------------------------------------------- */
1426 int InitBmf(struct interface* skipThisIntf)
1428 CreateBmfNetworkInterfaces(skipThisIntf);
1430 /* Start running the multicast packet processing thread */
1431 BmfThreadRunning = 1;
1432 if (pthread_create(&BmfThread, NULL, BmfRun, NULL) != 0)
1434 BmfPError("pthread_create() error");
1438 if (EtherTunTapFd >= 0)
1440 /* Deactivate IP spoof filter for EtherTunTap interface */
1441 DeactivateSpoofFilter();
1443 /* If the BMF network interface has a sensible IP address, it is a good idea
1444 * to route all multicast traffic through that interface */
1445 if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
1447 AddMulticastRoute();
1454 /* -------------------------------------------------------------------------
1455 * Function : CloseBmf
1456 * Description: Close the BMF plugin and clean up
1460 * Data Used : BmfThread
1461 * ------------------------------------------------------------------------- */
1464 if (EtherTunTapFd >= 0)
1466 /* If there is a multicast route, try to delete it first */
1467 DeleteMulticastRoute();
1469 /* Restore IP spoof filter for EtherTunTap interface */
1470 RestoreSpoofFilter();
1473 if (BmfThreadRunning)
1475 /* Signal BmfThread to exit */
1476 /* Strangely enough, all running threads receive the SIGALRM signal. But only the
1477 * BMF thread is affected by this signal, having specified a handler for this
1478 * signal in its thread entry function BmfRun(...). */
1479 if (pthread_kill(BmfThread, SIGALRM) != 0)
1481 BmfPError("pthread_kill() error");
1484 /* Wait for BmfThread to acknowledge */
1485 if (pthread_join(BmfThread, NULL) != 0)
1487 BmfPError("pthread_join() error");
1491 /* Clean up after the BmfThread has been killed */
1492 CloseBmfNetworkInterfaces();