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 <signal.h> /* sigset_t, sigfillset(), sigdelset(), SIGINT */
54 #include <netinet/ip.h> /* struct ip */
55 #include <netinet/udp.h> /* struct udphdr */
56 #include <unistd.h> /* read(), write() */
57 #include <sys/poll.h> /* Daniele Lacamera: Added guard poll for sendto(), needs poll.h */
60 #include "plugin_util.h" /* set_plugin_int */
61 #include "defs.h" /* olsr_cnf, OLSR_PRINTF */
63 #include "olsr.h" /* olsr_printf */
64 #include "mid_set.h" /* mid_lookup_main_addr() */
65 #include "mpr_selector_set.h" /* olsr_lookup_mprs_set() */
66 #include "link_set.h" /* get_best_link_to_neighbor() */
67 #include "net_olsr.h" /* ipequal */
70 #include "NetworkInterfaces.h" /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
71 #include "Address.h" /* IsMulticast() */
72 #include "Packet.h" /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */
73 #include "PacketHistory.h" /* InitPacketHistory() */
75 /* unicast/broadcast fan out limit */
78 int BroadcastRetransmitCount = 1;
80 /* -------------------------------------------------------------------------
81 * Function : BmfPError
82 * Description: Prints an error message at OLSR debug level 1.
83 * First the plug-in name is printed. Then (if format is not NULL
84 * and *format is not empty) the arguments are printed, followed
85 * by a colon and a blank. Then the message and a new-line.
86 * Input : format, arguments
90 * ------------------------------------------------------------------------- */
91 void BmfPError(const char* format, ...)
93 #define MAX_STR_DESC 255
94 char* strErr = strerror(errno);
95 char strDesc[MAX_STR_DESC];
97 /* Rely on short-circuit boolean evaluation */
98 if (format == NULL || *format == '\0')
100 olsr_printf(1, "%s: %s\n", PLUGIN_NAME_SHORT, strErr);
106 olsr_printf(1, "%s: ", PLUGIN_NAME_SHORT);
108 va_start(arglist, format);
109 vsnprintf(strDesc, MAX_STR_DESC, format, arglist);
112 strDesc[MAX_STR_DESC - 1] = '\0'; /* Ensures null termination */
114 olsr_printf(1, "%s: %s\n", strDesc, strErr);
118 /* -------------------------------------------------------------------------
119 * Function : MainAddressOf
120 * Description: Lookup the main address of a node
121 * Input : ip - IP address of the node
123 * Return : The main IP address of the node
125 * ------------------------------------------------------------------------- */
126 union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip)
128 union olsr_ip_addr* result;
130 result = mid_lookup_main_addr(ip);
136 } /* MainAddressOf */
138 /* -------------------------------------------------------------------------
139 * Function : ForwardPacket
140 * Description: Forward a raw IP packet
141 * Input : intf - the network interface on which to forward the packet. The
142 * packet will be forwarded on its 'capturing' socket.
143 * ipPacket - the IP packet to be forwarded
144 * ipPacketLen - the length of the IP packet to be forwarded
145 * debugInfo - string to use printing debugging information
149 * ------------------------------------------------------------------------- */
150 static void ForwardPacket(
151 struct TBmfInterface* intf,
152 unsigned char* ipPacket,
153 u_int16_t ipPacketLen,
154 const char* debugInfo)
157 struct sockaddr_ll dest;
161 guard.fd = intf->capturingSkfd;
162 guard.events = POLLOUT;
164 /* If the IP packet is a local broadcast packet,
165 * update its destination address to match the subnet of the network
166 * interface on which the packet is being sent. */
167 CheckAndUpdateLocalBroadcast(ipPacket, &intf->broadAddr);
169 memset(&dest, 0, sizeof(dest));
170 dest.sll_family = AF_PACKET;
171 dest.sll_protocol = htons(ETH_P_IP);
172 dest.sll_ifindex = if_nametoindex(intf->ifName);
173 dest.sll_halen = IFHWADDRLEN;
175 /* Use all-ones as destination MAC address. When the IP destination is
176 * a multicast address, the destination MAC address should normally also
177 * be a multicast address. E.g., when the destination IP is 224.0.0.1,
178 * the destination MAC should be 01:00:5e:00:00:01. However, it does not
179 * seem to matter when the destination MAC address is set to all-ones
181 memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
183 /* Daniele Lacamera: poll guard to avoid locking in sendto().
184 * Wait at most 2 polling periods. Since we're running in the context of the main
185 * OLSR thread, we should not wait too long. 2 polling periods is considered a
186 * reasonable time. */
187 pollret = poll (&guard, 1, 2 * olsr_cnf->pollrate * MSEC_PER_SEC);
190 BmfPError("sendto() on \"%s\": not ready to send pkt. pollret=%d\n", intf->ifName, pollret);
192 /* Apparently the network interface is jammed. Give up. */
196 /* Forward the BMF packet via the capturing socket */
197 nBytesWritten = sendto(
202 (struct sockaddr*) &dest,
204 if (nBytesWritten != ipPacketLen)
206 BmfPError("sendto() error forwarding pkt on \"%s\"", intf->ifName);
210 /* Increase counter */
211 intf->nBmfPacketsTx++;
215 "%s: --> %s \"%s\"\n",
219 } /* ForwardPacket */
221 /* -------------------------------------------------------------------------
222 * Function : EncapsulateAndForwardPacket
223 * Description: Encapsulate a captured raw IP packet and forward it
224 * Input : intf - the network interface on which to forward the packet
225 * encapsulationUdpData - The encapsulation header, followed by
226 * the encapsulated IP packet
227 * source - the source IP address of the BMF packet, or NULL if
228 * unknown or not applicable
229 * forwardedBy - the IP address of the node that forwarded the BMF
230 * packet, or NULL if unknown or not applicable
231 * forwardedTo - the IP address of the node to which the BMF packet
232 * was directed, or NULL if unknown or not applicable
236 * ------------------------------------------------------------------------- */
237 static void EncapsulateAndForwardPacket(
238 struct TBmfInterface* intf,
239 unsigned char* encapsulationUdpData,
240 union olsr_ip_addr* source,
241 union olsr_ip_addr* forwardedBy,
242 union olsr_ip_addr* forwardedTo)
244 /* Retrieve the number of bytes to be forwarded via the encapsulation socket */
245 u_int16_t udpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
247 /* The next destination(s) */
248 struct TBestNeighbors bestNeighborLinks;
249 struct link_entry* bestNeighbor;
251 int nPossibleNeighbors = 0;
252 struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
254 int sendUnicast; /* 0 = send broadcast; 1 = send unicast */
258 /* Find at most 'FanOutLimit' best neigbors to forward the packet to */
266 &nPossibleNeighbors);
268 if (nPossibleNeighbors <= 0)
272 "%s: --> not encap-forwarding on \"%s\": there is no neighbor that needs my retransmission\n",
278 /* Compose destination of encapsulation packet */
280 memset(&forwardTo, 0, sizeof(forwardTo));
281 forwardTo.sin_family = AF_INET;
282 forwardTo.sin_port = htons(BMF_ENCAP_PORT);
284 /* Start by filling in the local broadcast address. This may be overwritten later. */
285 forwardTo.sin_addr = intf->broadAddr.v4;
287 /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
288 * unicast packet (to the best neighbor).
289 * - But if the BMF mechanism is BM_BROADCAST,
290 * - send 'nPossibleNeighbors' unicast packets if there are up to
291 * 'FanOutLimit' possible neighbors,
292 * - if there are more than 'FanOutLimit' possible neighbors, then
293 * send a (WLAN-air-expensive, less reliable) broadcast packet. */
294 if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
296 /* One unicast packet to the best neighbor */
299 bestNeighborLinks.links[0] = bestNeighbor;
301 else /* BmfMechanism == BM_BROADCAST */
303 if (nPossibleNeighbors <= FanOutLimit)
305 /* 'nPossibleNeighbors' unicast packets */
306 nPacketsToSend = nPossibleNeighbors;
309 else /* nPossibleNeighbors > FanOutLimit */
311 /* One broadcast packet, possibly retransmitted as specified in the
312 * 'BroadcastRetransmitCount' plugin parameter */
313 nPacketsToSend = BroadcastRetransmitCount;
318 for (i = 0; i < nPacketsToSend; i++)
324 guard.fd = intf->encapsulatingSkfd;
325 guard.events = POLLOUT;
327 if (sendUnicast == 1)
329 /* For unicast, overwrite the local broadcast address which was filled in above */
330 forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
333 /* Daniele Lacamera: poll guard to avoid locking in sendto().
334 * Wait at most 2 polling periods. Since we're running in the context of the main
335 * OLSR thread, we should not wait too long. 2 polling periods is considered a
336 * reasonable time. */
337 pollret = poll (&guard, 1, 2 * olsr_cnf->pollrate * MSEC_PER_SEC);
340 BmfPError("sendto() on \"%s\": not ready to send pkt. pollret=%d\n", intf->ifName, pollret);
342 /* Apparently the network interface is jammed. Give up and return. */
346 /* Forward the BMF packet via the encapsulation socket */
347 nBytesWritten = sendto(
348 intf->encapsulatingSkfd,
349 encapsulationUdpData,
352 (struct sockaddr*) &forwardTo,
355 /* Evaluate and display result */
356 if (nBytesWritten != udpDataLen)
358 BmfPError("sendto() error forwarding encapsulated pkt on \"%s\"", intf->ifName);
360 } /* if (nBytesWritten != udpDataLen) */
362 /* Increase counter */
363 intf->nBmfPacketsTx++;
367 "%s: --> forwarded encapsulated packet on \"%s\" to %s\n",
370 inet_ntoa(forwardTo.sin_addr));
372 } /* EncapsulateAndForwardPacket */
374 /* -------------------------------------------------------------------------
375 * Function : BmfPacketCaptured
376 * Description: Handle a captured IP packet
377 * Input : intf - the network interface on which the packet was captured
378 * sllPkttype - the type of packet. Either PACKET_OUTGOING,
379 * PACKET_BROADCAST or PACKET_MULTICAST.
380 * encapsulationUdpData - space for the encapsulation header, followed by
381 * the captured IP packet
384 * Data Used : BmfInterfaces
385 * Notes : The IP packet is assumed to be captured on a socket of family
386 * PF_PACKET and type SOCK_DGRAM (cooked).
387 * ------------------------------------------------------------------------- */
388 static void BmfPacketCaptured(
389 struct TBmfInterface* intf,
390 unsigned char sllPkttype,
391 unsigned char* encapsulationUdpData)
393 union olsr_ip_addr src; /* Source IP address in captured packet */
394 union olsr_ip_addr dst; /* Destination IP address in captured packet */
395 union olsr_ip_addr* origIp; /* Main OLSR address of source of captured packet */
396 struct TBmfInterface* walker;
398 int isFromOlsrNeighbor;
400 unsigned char* ipPacket; /* The captured IP packet... */
401 u_int16_t ipPacketLen; /* ...and its length */
402 struct ip* ipHeader; /* The IP header inside the captured IP packet */
404 struct TEncapHeader* encapHdr;
406 struct ipaddr_str srcBuf, dstBuf;
408 ipHeader = GetIpHeader(encapsulationUdpData);
410 dst.v4 = ipHeader->ip_dst;
412 /* Only forward multicast packets. If configured, also forward local broadcast packets */
413 if (IsMulticast(&dst) ||
414 (EnableLocalBroadcast != 0 && ipequal(&dst, &intf->broadAddr)))
423 ipPacket = GetIpPacket(encapsulationUdpData);
425 /* Don't forward fragments of IP packets: there is no way to distinguish fragments
426 * of BMF encapsulation packets from other fragments.
427 * Well yes, there is the IP-ID, which can be kept in a list to relate a fragment
428 * to earlier sent BMF packets, but... sometimes the second fragment comes in earlier
429 * than the first fragment, so that the list is not yet up to date and the second
430 * fragment is not recognized as a BMF packet.
431 * Also, don't forward OLSR packets (UDP port 698) and BMF encapsulated packets */
432 if (IsIpFragment(ipPacket) || IsOlsrOrBmfPacket(ipPacket))
437 /* Increase counter */
438 intf->nBmfPacketsRx++;
440 /* Check if the frame is captured on an OLSR-enabled interface */
441 isFromOlsrIntf = (intf->olsrIntf != NULL);
443 /* Retrieve the length of the captured packet */
444 ipPacketLen = GetIpTotalLength(ipPacket);
446 src.v4 = ipHeader->ip_src;
450 "%s: %s pkt of %ld bytes captured on %s interface \"%s\": %s->%s\n",
452 sllPkttype == PACKET_OUTGOING ? "outgoing" : "incoming",
454 isFromOlsrIntf ? "OLSR" : "non-OLSR",
456 olsr_ip_to_string(&srcBuf, &src),
457 olsr_ip_to_string(&dstBuf, &dst));
459 /* Lookup main address of source in the MID table of OLSR */
460 origIp = MainAddressOf(&src);
462 /* Calculate packet fingerprint */
463 crc32 = PacketCrc32(ipPacket, ipPacketLen);
465 /* Check if this packet was seen recently */
466 if (CheckAndMarkRecentPacket(crc32))
468 /* Increase counter */
469 intf->nBmfPacketsRxDup++;
473 "%s: --> discarding: packet is duplicate\n",
478 /* Compose encapsulation header */
479 encapHdr = (struct TEncapHeader*) encapsulationUdpData;
480 memset (encapHdr, 0, ENCAP_HDR_LEN);
481 encapHdr->type = BMF_ENCAP_TYPE;
482 encapHdr->len = BMF_ENCAP_LEN;
483 encapHdr->reserved = 0;
484 encapHdr->crc32 = htonl(crc32);
486 /* Check if the frame is captured on an OLSR interface from an OLSR neighbor.
487 * TODO: get_best_link_to_neighbor() may be very CPU-expensive, a simpler call
488 * would do here (something like 'get_any_link_to_neighbor()'). */
490 (isFromOlsrIntf /* The frame is captured on an OLSR interface... */
491 && get_best_link_to_neighbor(origIp) != NULL); /* ...from an OLSR neighbor */
493 /* Check with OLSR if I am MPR for that neighbor */
494 iAmMpr = olsr_lookup_mprs_set(origIp) != NULL;
496 /* Check with each network interface what needs to be done on it */
497 for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
499 /* Is the forwarding interface OLSR-enabled? */
500 int isToOlsrIntf = (walker->olsrIntf != NULL);
502 /* Depending on certain conditions, we decide whether or not to forward
503 * the packet, and if it is forwarded, in which form (encapsulated
504 * or not, TTL decreased or not). These conditions are:
505 * - is the packet is coming in on an OLSR interface or not? (isFromOlsrIntf)
506 * - is the packet going out on an OLSR interface or not? (isToOlsrIntf)
507 * - if the packet if coming in on an OLSR interface:
508 * - is the node that forwarded the packet my OLSR-neighbor? (isFromOlsrNeighbor)
509 * - has the node that forwarded the packet selected me as MPR? (iAmMpr)
511 * Based on these conditions, the following cases can be distinguished:
513 * - Case 1: Packet coming in on an OLSR interface. What to
514 * do with it on an OLSR interface?
516 * - Case 1.1: If the forwarding node is an OLSR neighbor that has *not*
517 * selected me as MPR: don't forward the packet.
518 * - Case 1.2: If the forwarding node is an OLSR neighbor that has selected
519 * me as MPR: encapsulate and forward the packet.
520 * - Case 1.3: If the forwarding node is not an OLSR neighbor: encapsulate
521 * and forward the packet.
522 * NOTE: Case 1.3 is a special case. In the perfect world, we expect to
523 * see only OLSR-neighbors on OLSR-enabled interfaces. Sometimes, however,
524 * ignorant users will connect a host not running OLSR, to a LAN in
525 * which there are hosts running OLSR. Of course these ignorant users,
526 * expecting magic, want to see their multicast packets being forwarded
527 * through the network.
529 * - Case 2: Packet coming in on an OLSR interface. What to do with it on a
530 * non-OLSR interface?
531 * Answer: Forward it.
533 * - Case 3: Packet coming in on a non-OLSR interface. What to
534 * do with it on an OLSR interface?
535 * Answer: Encapsulate and forward it.
537 * - Case 4: Packet coming in on non-OLSR interface. What to do with it on a
538 * non-OLSR interface?
539 * Answer 1: nothing. Multicast routing between non-OLSR interfaces
540 * is to be done by other protocols (e.g. PIM, DVMRP).
541 * Answer 2 (better): Forward it.
544 if (isFromOlsrIntf && isToOlsrIntf)
546 /* Case 1: Forward from an OLSR interface to an OLSR interface */
548 if (isFromOlsrNeighbor && !iAmMpr)
553 struct ipaddr_str buf;
557 "%s: --> not encap-forwarding on \"%s\": I am not selected as MPR by neighbor %s\n",
560 olsr_ip_to_string(&buf, &src));
563 else if (sllPkttype == PACKET_OUTGOING && intf == walker)
567 "%s: --> not encap-forwarding on \"%s\": pkt was captured on that interface\n",
573 /* Case 1.2 and 1.3 */
574 EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
576 } /* if (isFromOlsrIntf && isToOlsrIntf) */
578 else if (isFromOlsrIntf && !isToOlsrIntf)
580 /* Case 2: Forward from OLSR interface to non-OLSR interface */
581 ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded to non-OLSR interface");
582 } /* else if (isFromOlsrIntf && !isToOlsrIntf) */
584 else if (!isFromOlsrIntf && isToOlsrIntf)
586 /* Case 3: Forward from a non-OLSR interface to an OLSR interface.
587 * Encapsulate and forward packet. */
588 EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
589 } /* else if (!isFromOlsrIntf && isToOlsrIntf) */
593 /* Case 4: Forward from non-OLSR interface to non-OLSR interface. */
595 /* Don't forward on interface on which packet was received */
600 "%s: --> not forwarding on \"%s\": pkt was captured on that interface\n",
607 ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface");
608 } /* if (intf == walker) */
611 } /* BmfPacketCaptured */
613 /* -------------------------------------------------------------------------
614 * Function : BmfEncapsulationPacketReceived
615 * Description: Handle a received BMF-encapsulation packet
616 * Input : intf - the network interface on which the packet was received
617 * forwardedBy - the IP node that forwarded the packet to me
618 * forwardedTo - the destination IP address of the encapsulation
619 * packet, in case the packet was received promiscuously.
620 * Pass NULL if the packet is received normally (unicast or
622 * encapsulationUdpData - the encapsulating IP UDP data, containting
623 * the BMF encapsulation header, followed by the encapsulated
627 * Data Used : BmfInterfaces
628 * ------------------------------------------------------------------------- */
629 static void BmfEncapsulationPacketReceived(
630 struct TBmfInterface* intf,
631 union olsr_ip_addr* forwardedBy,
632 union olsr_ip_addr* forwardedTo,
633 unsigned char* encapsulationUdpData)
635 int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */
636 unsigned char* ipPacket; /* The encapsulated IP packet */
637 u_int16_t ipPacketLen; /* Length of the encapsulated IP packet */
638 struct ip* ipHeader; /* IP header inside the encapsulated IP packet */
639 union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */
640 union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */
641 struct TEncapHeader* encapsulationHdr;
642 struct TBmfInterface* walker;
644 struct ipaddr_str mcSrcBuf, mcDstBuf, forwardedByBuf, forwardedToBuf;
646 /* Are we talking to ourselves? */
647 if (if_ifwithaddr(forwardedBy) != NULL)
652 /* Discard encapsulated packets received on a non-OLSR interface */
653 if (intf->olsrIntf == NULL)
658 /* Retrieve details about the encapsulated IP packet */
659 ipPacket = GetIpPacket(encapsulationUdpData);
660 ipPacketLen = GetIpTotalLength(ipPacket);
661 ipHeader = GetIpHeader(encapsulationUdpData);
663 mcSrc.v4 = ipHeader->ip_src;
664 mcDst.v4 = ipHeader->ip_dst;
666 /* Increase counter */
667 intf->nBmfPacketsRx++;
669 /* Beware: not possible to call olsr_ip_to_string more than 4 times in same printf */
672 "%s: encapsulated pkt of %ld bytes incoming on \"%s\": %s->%s, forwarded by %s to %s\n",
676 olsr_ip_to_string(&mcSrcBuf, &mcSrc),
677 olsr_ip_to_string(&mcDstBuf, &mcDst),
678 olsr_ip_to_string(&forwardedByBuf, forwardedBy),
679 forwardedTo != NULL ? olsr_ip_to_string(&forwardedToBuf, forwardedTo) : "me");
681 /* Get encapsulation header */
682 encapsulationHdr = (struct TEncapHeader*) encapsulationUdpData;
684 /* Verify correct format of BMF encapsulation header */
685 if (encapsulationHdr->type != BMF_ENCAP_TYPE ||
686 encapsulationHdr->len != BMF_ENCAP_LEN ||
687 ntohs(encapsulationHdr->reserved != 0))
691 "%s: --> discarding: format of BMF encapsulation header not recognized\n",
696 /* Check if this packet was seen recently */
697 if (CheckAndMarkRecentPacket(ntohl(encapsulationHdr->crc32)))
699 /* Increase counter */
700 intf->nBmfPacketsRxDup++;
704 "%s: --> discarding: packet is duplicate\n",
709 if (EtherTunTapFd >= 0)
711 /* Unpack the encapsulated IP packet and deliver it locally, by sending
712 * a copy into the local IP stack via the EtherTunTap interface */
714 union olsr_ip_addr broadAddr;
715 int nBytesToWrite, nBytesWritten;
716 unsigned char* bufferToWrite;
718 /* If the encapsulated IP packet is a local broadcast packet,
719 * update its destination address to match the subnet of the EtherTunTap
721 broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
722 CheckAndUpdateLocalBroadcast(ipPacket, &broadAddr);
724 bufferToWrite = ipPacket;
725 nBytesToWrite = ipPacketLen;
727 /* Write the packet into the EtherTunTap interface for local delivery */
728 nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite);
729 if (nBytesWritten != nBytesToWrite)
731 BmfPError("write() error forwarding encapsulated pkt on \"%s\"", EtherTunTapIfName);
737 "%s: --> unpacked and delivered locally on \"%s\"\n",
741 } /* if (EtherTunTapFd >= 0) */
743 /* Check if I am MPR for the forwarder */
744 iAmMpr = (olsr_lookup_mprs_set(MainAddressOf(forwardedBy)) != NULL);
746 /* Check with each network interface what needs to be done on it */
747 for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
749 /* What to do with the packet on a non-OLSR interface? Unpack
750 * encapsulated packet, and forward it.
752 * What to do with the packet on an OLSR interface? Forward it only
753 * if the forwarding node has selected us as MPR (iAmMpr).
755 * Note that the packet is always coming in on an OLSR interface, because
756 * it is an encapsulated BMF packet. */
758 /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
759 if (walker->olsrIntf == NULL)
761 ForwardPacket (walker, ipPacket, ipPacketLen, "unpacked and forwarded to non-OLSR interface");
762 } /* if (walker->olsrIntf == NULL) */
764 /* To an OLSR interface: forward the packet, but only if this node is
765 * selected as MPR by the forwarding node */
768 EncapsulateAndForwardPacket (
770 encapsulationUdpData,
774 } /* else if (iAmMpr) */
776 else /* walker->olsrIntf != NULL && !iAmMpr */
779 struct ipaddr_str buf;
781 /* 'walker' is an OLSR interface, but I am not selected as MPR. In that
782 * case, don't forward. */
785 "%s: --> not forwarding on \"%s\": I am not selected as MPR by %s\n",
788 olsr_ip_to_string(&buf, forwardedBy));
791 } /* BmfEncapsulationPacketReceived */
793 /* -------------------------------------------------------------------------
794 * Function : BmfTunPacketCaptured
795 * Description: Handle an IP packet, captured outgoing on the tuntap interface
796 * Input : encapsulationUdpData - space for the encapsulation header, followed by
797 * the captured outgoing IP packet
801 * Notes : The packet is assumed to be captured on a socket of family
802 * PF_PACKET and type SOCK_DGRAM (cooked).
803 * ------------------------------------------------------------------------- */
804 static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
806 union olsr_ip_addr srcIp;
807 union olsr_ip_addr dstIp;
808 union olsr_ip_addr broadAddr;
809 struct TBmfInterface* walker;
810 unsigned char* ipPacket;
811 u_int16_t ipPacketLen;
814 struct TEncapHeader* encapHdr;
816 struct ipaddr_str srcIpBuf, dstIpBuf;
818 ipPacket = GetIpPacket(encapsulationUdpData);
819 ipPacketLen = GetIpTotalLength(ipPacket);
820 ipHeader = GetIpHeader(encapsulationUdpData);
822 dstIp.v4 = ipHeader->ip_dst;
823 broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
825 /* Only forward multicast packets. If configured, also forward local broadcast packets */
826 if (IsMulticast(&dstIp) ||
827 (EnableLocalBroadcast != 0 && ipequal(&dstIp, &broadAddr)))
836 srcIp.v4 = ipHeader->ip_src;
840 "%s: outgoing pkt of %ld bytes captured on tuntap interface \"%s\": %s->%s\n",
844 olsr_ip_to_string(&srcIpBuf, &srcIp),
845 olsr_ip_to_string(&dstIpBuf, &dstIp));
847 /* Calculate packet fingerprint */
848 crc32 = PacketCrc32(ipPacket, ipPacketLen);
850 /* Check if this packet was seen recently */
851 if (CheckAndMarkRecentPacket(crc32))
855 "%s: --> discarding: packet is duplicate\n",
860 /* Compose encapsulation header */
861 encapHdr = (struct TEncapHeader*) encapsulationUdpData;
862 memset (encapHdr, 0, ENCAP_HDR_LEN);
863 encapHdr->type = BMF_ENCAP_TYPE;
864 encapHdr->len = BMF_ENCAP_LEN;
865 encapHdr->reserved = 0;
866 encapHdr->crc32 = htonl(crc32);
868 /* Check with each network interface what needs to be done on it */
869 for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
871 /* Is the forwarding interface OLSR-enabled? */
872 if (walker->olsrIntf != NULL)
874 /* On an OLSR interface: encapsulate and forward packet. */
875 EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
879 /* On a non-OLSR interface: what to do?
880 * Answer 1: nothing. Multicast routing between non-OLSR interfaces
881 * is to be done by other protocols (e.g. PIM, DVMRP).
882 * Answer 2 (better): Forward it. */
883 ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface");
886 } /* BmfTunPacketCaptured */
888 /* -------------------------------------------------------------------------
890 * Description: Wait (blocking) for IP packets, then call the handler for each
895 * Data Used : BmfInterfaces
896 * ------------------------------------------------------------------------- */
898 BMF_handle_captureFd(int skfd, void *data, unsigned int flags __attribute__ ((unused))) {
899 unsigned char rxBuffer[BMF_BUFFER_SIZE];
900 struct TBmfInterface* walker = data;
901 struct sockaddr_ll pktAddr;
902 socklen_t addrLen = sizeof(pktAddr);
904 unsigned char* ipPacket;
906 /* Receive the captured Ethernet frame, leaving space for the BMF
907 * encapsulation header */
908 ipPacket = GetIpPacket(rxBuffer);
912 BMF_BUFFER_SIZE - ENCAP_HDR_LEN,
914 (struct sockaddr*)&pktAddr,
918 BmfPError("recvfrom() error on \"%s\"", walker->ifName);
920 } /* if (nBytes < 0) */
922 /* Check if the number of received bytes is large enough for an IP
923 * packet which contains at least a minimum-size IP header.
924 * Note: There is an apparent bug in the packet socket implementation in
925 * combination with VLAN interfaces. On a VLAN interface, the value returned
926 * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
927 * returned on a non-VLAN interface, for the same ethernet frame. */
928 if (nBytes < (int)sizeof(struct ip))
932 "%s: captured frame too short (%d bytes) on \"%s\"\n",
939 if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
940 pktAddr.sll_pkttype == PACKET_MULTICAST ||
941 pktAddr.sll_pkttype == PACKET_BROADCAST)
943 /* A multicast or broadcast packet was captured */
945 BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer);
947 } /* if (pktAddr.sll_pkttype == ...) */
951 BMF_handle_listeningFd(int skfd, void *data, unsigned int flags __attribute__ ((unused))) {
952 unsigned char rxBuffer[BMF_BUFFER_SIZE];
953 struct TBmfInterface* walker = data;
954 struct sockaddr_ll pktAddr;
955 socklen_t addrLen = sizeof(pktAddr);
959 unsigned int headerLength;
960 struct udphdr* udpHeader;
962 union olsr_ip_addr forwardedBy;
963 union olsr_ip_addr forwardedTo;
965 /* Heard a BMF packet */
972 (struct sockaddr*)&pktAddr,
976 BmfPError("recvfrom() error on \"%s\"", walker->ifName);
978 } /* if (nBytes < 0) */
980 /* Check if the received packet is actually directed to another
982 if (pktAddr.sll_pkttype != PACKET_OTHERHOST)
984 /* No, the packet is directed to this node. In that case it will
985 * be, or will already have been received, via the encapsulating
986 * socket. Discard it here. */
988 } /* if (pktAddr.sll_pkttype ...) */
990 /* Check if the received packet is UDP - BMF port */
991 ipHeader = (struct ip*) ARM_NOWARN_ALIGN(rxBuffer);
992 if (ipHeader->ip_p != SOL_UDP)
998 /* Check if the number of received bytes is large enough for a minimal BMF
999 * encapsulation packet, at least:
1000 * - the IP header of the encapsulation IP packet
1001 * - the UDP header of the encapsulation IP packet
1002 * - the encapsulation header
1003 * - a minimum IP header inside the encapsulated packet
1004 * Note: on a VLAN interface, the value returned by 'recvfrom' may (but need
1005 * not) be 4 (bytes) larger than the value returned on a non-VLAN interface, for
1006 * the same ethernet frame. */
1007 headerLength = GetIpHeaderLength(rxBuffer);
1010 sizeof(struct udphdr) +
1013 if (minimumLength > BMF_BUFFER_SIZE) {
1014 olsr_printf(1, "%s: IP header length %u is too large\n",
1015 PLUGIN_NAME_SHORT, headerLength);
1018 if (nBytes < minimumLength)
1022 "%s: captured a too short encapsulation packet (%d bytes) on \"%s\"\n",
1030 udpHeader = (struct udphdr*) ARM_NOWARN_ALIGN((rxBuffer + headerLength));
1031 #if defined(__GLIBC__) || defined(__BIONIC__)
1032 destPort = ntohs(udpHeader->dest);
1034 destPort = ntohs(udpHeader->uh_dport);
1036 if (destPort != BMF_ENCAP_PORT)
1042 forwardedBy.v4 = ipHeader->ip_src;
1043 forwardedTo.v4 = ipHeader->ip_dst;
1044 BmfEncapsulationPacketReceived(
1048 rxBuffer + headerLength + sizeof(struct udphdr));
1053 BMF_handle_encapsulatingFd(int skfd, void *data, unsigned int flags __attribute__ ((unused))) {
1054 unsigned char rxBuffer[BMF_BUFFER_SIZE];
1055 struct TBmfInterface* walker = data;
1056 struct sockaddr_in from;
1057 socklen_t fromLen = sizeof(from);
1060 union olsr_ip_addr forwardedBy;
1062 /* An encapsulated packet was received */
1068 (struct sockaddr*)&from,
1072 BmfPError("recvfrom() error on \"%s\"", walker->ifName);
1075 } /* if (nBytes < 0) */
1077 forwardedBy.v4 = from.sin_addr;
1079 /* Check if the number of received bytes is large enough for a minimal BMF
1080 * encapsulation packet, at least:
1081 * - the encapsulation header
1082 * - a minimum IP header inside the encapsulated packet */
1086 if (nBytes < minimumLength)
1088 struct ipaddr_str buf;
1091 "%s: received a too short encapsulation packet (%d bytes) from %s on \"%s\"\n",
1094 olsr_ip_to_string(&buf, &forwardedBy),
1099 /* Unfortunately, the recvfrom call does not return the destination
1100 * of the encapsulation packet (the destination may be either the
1101 * my unicast or my local broadcast address). Therefore we fill in 'NULL'
1102 * for the 'forwardedTo' parameter. */
1103 BmfEncapsulationPacketReceived(walker, &forwardedBy, NULL, rxBuffer);
1107 BMF_handle_tuntapFd(int skfd __attribute__ ((unused)),
1108 void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused))) {
1109 unsigned char rxBuffer[BMF_BUFFER_SIZE];
1111 unsigned char* ipPacket;
1112 unsigned char* bufferToRead;
1113 size_t nBytesToRead;
1115 /* Receive the packet, leaving space for the BMF encapsulation header */
1116 ipPacket = GetIpPacket(rxBuffer);
1118 bufferToRead = ipPacket;
1119 nBytesToRead = BMF_BUFFER_SIZE - ENCAP_HDR_LEN;
1121 nBytes = read(EtherTunTapFd, bufferToRead, nBytesToRead);
1124 BmfPError("recvfrom() error on \"%s\"", EtherTunTapIfName);
1128 /* Check if the number of received bytes is large enough for an IP
1129 * packet which contains at least a minimum-size IP header */
1130 if (nBytes < (int)sizeof(struct ip))
1134 "%s: captured packet too short (%d bytes) on \"%s\"\n",
1141 BmfTunPacketCaptured(rxBuffer);
1144 /* -------------------------------------------------------------------------
1145 * Function : InterfaceChange
1146 * Description: Callback function passed to OLSRD for it to call whenever a
1147 * network interface has been added, removed or updated
1148 * Input : if_index - index of the interface
1149 * interf - the network interface to deal with
1150 * (might be NULL for non-OLSR interfaces)
1151 * action - indicates if the specified network interface was
1152 * added, removed or updated.
1155 * ------------------------------------------------------------------------- */
1156 void InterfaceChange(int if_index __attribute__((unused)), struct interface_olsr * interf,
1157 enum olsr_ifchg_flag action)
1159 if (interf == NULL) {
1164 case (IFCHG_IF_ADD):
1165 /* If the new interfaces is ready, completely restart BMF. In this way
1166 * the IP address for the BMF network interface is correctly re-evaluated,
1167 * and a default route for multicast traffic is (re)established.
1168 * Thanks to Daniele Lacamera for finding and solving this bug. */
1171 olsr_printf(1, "%s: interface %s added\n", PLUGIN_NAME_SHORT, interf->int_name);
1174 case (IFCHG_IF_REMOVE):
1175 /* We cannot just remove the interface, because the receive-thread is likely
1176 * to be waiting in select(...) for packets coming in via the interface.
1177 * Therefore we first close BMF (CloseBmf()), interrupting and kiling the
1178 * receive-thread so that it is safe to remove this (and all other)
1179 * interfaces. After that, BMF is re-started (InitBmf(interf)). */
1182 olsr_printf(1, "%s: interface %s removed\n", PLUGIN_NAME_SHORT, interf->int_name);
1185 case (IFCHG_IF_UPDATE):
1186 olsr_printf(1, "%s: interface %s updated\n", PLUGIN_NAME_SHORT, interf->int_name);
1192 "%s: interface %s: error - unknown action (%d)\n",
1194 interf->int_name, action);
1197 } /* InterfaceChange */
1200 /* -------------------------------------------------------------------------
1201 * Function : SetFanOutLimit
1202 * Description: Overrule the default fan out limit value (2)
1203 * Input : value - fan out limit value (0...MAX_UNICAST_NEIGHBORS)
1207 * Return : success (0) or fail (1)
1208 * Data Used : FanOutLimit
1209 * ------------------------------------------------------------------------- */
1212 void* data __attribute__((unused)),
1213 set_plugin_parameter_addon addon __attribute__((unused)))
1215 if (set_plugin_int(value, &FanOutLimit, addon) == 0)
1217 /* Extra check if within range */
1218 if (FanOutLimit >= 0 && FanOutLimit <= MAX_UNICAST_NEIGHBORS)
1226 /* -------------------------------------------------------------------------
1227 * Function : InitBmf
1228 * Description: Initialize the BMF plugin
1229 * Input : skipThisIntf - specifies which network interface should not
1230 * be enabled for BMF. Pass NULL if not applicable.
1232 * Return : fail (0) or success (1)
1233 * Data Used : BmfThreadRunning, BmfThread
1234 * ------------------------------------------------------------------------- */
1235 int InitBmf(struct interface_olsr * skipThisIntf)
1237 CreateBmfNetworkInterfaces(skipThisIntf);
1239 if (EtherTunTapFd >= 0)
1241 /* Deactivate IP spoof filter for EtherTunTap interface */
1242 DeactivateSpoofFilter();
1244 /* If the BMF network interface has a sensible IP address, it is a good idea
1245 * to route all multicast traffic through that interface */
1246 if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
1248 AddMulticastRoute();
1255 /* -------------------------------------------------------------------------
1256 * Function : CloseBmf
1257 * Description: Close the BMF plugin and clean up
1261 * Data Used : BmfThread
1262 * ------------------------------------------------------------------------- */
1265 if (EtherTunTapFd >= 0)
1267 /* If there is a multicast route, try to delete it first */
1268 DeleteMulticastRoute();
1270 /* Restore IP spoof filter for EtherTunTap interface */
1271 RestoreSpoofFilter();
1274 /* Clean up after the BmfThread has been killed */
1275 CloseBmfNetworkInterfaces();