Convert some plugins to new logger
[olsrd.git] / lib / bmf / src / Bmf.c
1 /*
2  * OLSR Basic Multicast Forwarding (BMF) plugin.
3  * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
4  * Written by Erik Tromp.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of 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.
20  *
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.
31  */
32
33 /* -------------------------------------------------------------------------
34  * File       : Bmf.c
35  * Description: Multicast forwarding functions
36  * Created    : 29 Jun 2006
37  *
38  * ------------------------------------------------------------------------- */
39
40 #define _MULTI_THREADED
41
42 #include "Bmf.h"
43
44 /* System includes */
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 */
57 #include <unistd.h> /* close() */
58
59 /* OLSRD includes */
60 #include "plugin_util.h" /* set_plugin_int */
61 #include "defs.h" /* olsr_cnf, OLSR_PRINTF */
62 #include "ipcalc.h"
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 */
68 #include "olsr_logging.h"
69
70 /* BMF includes */
71 #include "NetworkInterfaces.h" /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
72 #include "Address.h" /* IsMulticast() */
73 #include "Packet.h" /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */
74 #include "PacketHistory.h" /* InitPacketHistory() */
75
76 static pthread_t BmfThread;
77 static int BmfThreadRunning = 0;
78
79 /* unicast/broadcast fan out limit */
80 int FanOutLimit = 2;
81
82 int BroadcastRetransmitCount = 1;
83
84 /* -------------------------------------------------------------------------
85  * Function   : MainAddressOf
86  * Description: Lookup the main address of a node
87  * Input      : ip - IP address of the node
88  * Output     : none
89  * Return     : The main IP address of the node
90  * Data Used  : none
91  * ------------------------------------------------------------------------- */
92 union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip)
93 {
94   union olsr_ip_addr* result;
95
96   /* TODO: mid_lookup_main_addr() is not thread-safe! */
97   result = olsr_lookup_main_addr_by_alias(ip);
98   if (result == NULL)
99   {
100     result = ip;
101   }
102   return result;
103 } /* MainAddressOf */
104
105 /* -------------------------------------------------------------------------
106  * Function   : EncapsulateAndForwardPacket
107  * Description: Encapsulate a captured raw IP packet and forward it
108  * Input      : intf - the network interface on which to forward the packet
109  *              encapsulationUdpData - The encapsulation header, followed by
110  *                the encapsulated IP packet
111  * Output     : none
112  * Return     : none
113  * Data Used  : none
114  * ------------------------------------------------------------------------- */
115 static void EncapsulateAndForwardPacket(
116   struct TBmfInterface* intf,
117   unsigned char* encapsulationUdpData)
118 {
119   /* The packet */
120   u_int16_t udpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
121
122   /* The next destination(s) */
123   struct TBestNeighbors bestNeighborLinks;
124   struct link_entry* bestNeighbor;
125
126   int nPossibleNeighbors = 0;
127   struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
128   int nPacketsToSend;
129   int sendUnicast; /* 0 = send broadcast; 1 = send unicast */
130
131   int i;
132
133   /* Find at most 'FanOutLimit' best neigbors to forward the packet to */
134   FindNeighbors(&bestNeighborLinks, &bestNeighbor, intf, NULL, NULL, NULL, &nPossibleNeighbors);
135
136   if (nPossibleNeighbors <= 0)
137   {
138     OLSR_DEBUG(
139       LOG_PLUGINS,
140       "BMF: not encap-forwarding on \"%s\": there is no neighbor that needs my retransmission\n",
141       intf->ifName);
142     return;
143   }
144
145   /* Compose destination of encapsulation packet */
146
147   memset(&forwardTo, 0, sizeof(forwardTo));
148   forwardTo.sin_family = AF_INET;
149   forwardTo.sin_port = htons(BMF_ENCAP_PORT);
150
151   /* Start by filling in the local broadcast address. This may be overwritten later. */
152   forwardTo.sin_addr = intf->broadAddr.v4;
153
154   /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
155    *   unicast packet (to the best neighbor).
156    * - But if the BMF mechanism is BM_BROADCAST,
157    *   - send 'nPossibleNeighbors' unicast packets if there are up to
158    *     'FanOutLimit' possible neighbors,
159    *   - if there are more than 'FanOutLimit' possible neighbors, then
160    *     send a (WLAN-air-expensive, less reliable) broadcast packet. */
161   if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
162   {
163     /* One unicast packet to the best neighbor */
164     nPacketsToSend = 1;
165     sendUnicast = 1;
166     bestNeighborLinks.links[0] = bestNeighbor;
167   }
168   else /* BmfMechanism == BM_BROADCAST */
169   {
170     if (nPossibleNeighbors <= FanOutLimit)
171     {
172       /* 'nPossibleNeighbors' unicast packets */
173       nPacketsToSend = nPossibleNeighbors;
174       sendUnicast = 1;
175     }
176     else /* nPossibleNeighbors > FanOutLimit */
177     {
178       /* One broadcast packet, possibly retransmitted as specified in the
179        * 'BroadcastRetransmitCount' plugin parameter */
180       nPacketsToSend = BroadcastRetransmitCount;
181       sendUnicast = 0;
182     } /* if */
183   } /* if */
184
185   for (i = 0; i < nPacketsToSend; i++)
186   {
187     int nBytesWritten;
188
189     if (sendUnicast == 1)
190     {
191       /* For unicast, overwrite the local broadcast address which was filled in above */
192       forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
193     }
194
195     /* Forward the BMF packet via the encapsulation socket */
196     nBytesWritten = sendto(
197       intf->encapsulatingSkfd,
198       encapsulationUdpData,
199       udpDataLen,
200       MSG_DONTROUTE,
201       (struct sockaddr*) &forwardTo,
202       sizeof(forwardTo));
203
204     /* Evaluate and display result */
205     if (nBytesWritten != udpDataLen)
206     {
207       OLSR_WARN(LOG_PLUGINS, "BMF: sendto() error forwarding pkt on \"%s\"", intf->ifName);
208     }
209     else
210     {
211       /* Increase counter */
212       intf->nBmfPacketsTx++;
213
214       OLSR_DEBUG(
215         LOG_PLUGINS,
216         "BMF: encapsulated and forwarded on \"%s\" to %s\n",
217         intf->ifName,
218         inet_ntoa(forwardTo.sin_addr));
219     } /* if (nBytesWritten != udpDataLen) */
220   } /* for */
221 } /* EncapsulateAndForwardPacket */
222
223 /* -------------------------------------------------------------------------
224  * Function   : BmfPacketCaptured
225  * Description: Handle a captured IP packet
226  * Input      : intf - the network interface on which the packet was captured
227  *              sllPkttype - the type of packet. Either PACKET_OUTGOING,
228  *                PACKET_BROADCAST or PACKET_MULTICAST.
229  *              encapsulationUdpData - space for the encapsulation header, followed by
230  *                the captured IP packet
231  * Output     : none
232  * Return     : none
233  * Data Used  : BmfInterfaces
234  * Notes      : The IP packet is assumed to be captured on a socket of family
235  *              PF_PACKET and type SOCK_DGRAM (cooked).
236  * ------------------------------------------------------------------------- */
237 static void BmfPacketCaptured(
238   struct TBmfInterface* intf,
239   unsigned char sllPkttype,
240   unsigned char* encapsulationUdpData)
241 {
242   union olsr_ip_addr src; /* Source IP address in captured packet */
243   union olsr_ip_addr dst; /* Destination IP address in captured packet */
244   union olsr_ip_addr* origIp; /* Main OLSR address of source of captured packet */
245   struct TBmfInterface* walker;
246   int isFromOlsrIntf;
247   int isFromOlsrNeighbor;
248   int iAmMpr;
249   unsigned char* ipPacket; /* The captured IP packet... */
250   u_int16_t ipPacketLen; /* ...and its length */
251   struct ip* ipHeader; /* The IP header inside the captured IP packet */
252   u_int32_t crc32;
253   struct TEncapHeader* encapHdr;
254   struct ipaddr_str srcBuf, dstBuf;
255   ipHeader = GetIpHeader(encapsulationUdpData);
256
257   dst.v4 = ipHeader->ip_dst;
258
259   /* Only forward multicast packets. If configured, also forward local broadcast packets */
260   if (IsMulticast(&dst) ||
261       (EnableLocalBroadcast != 0 && olsr_ipcmp(&dst, &intf->broadAddr) == 0))
262   {
263     /* continue */
264   }
265   else
266   {
267     return;
268   }
269
270   ipPacket = GetIpPacket(encapsulationUdpData);
271
272   /* Don't forward fragments of IP packets: there is no way to distinguish fragments
273    * of BMF encapsulation packets from other fragments.
274    * Well yes, there is the IP-ID, which can be kept in a list to relate a fragment
275    * to earlier sent BMF packets, but... sometimes the second fragment comes in earlier
276    * than the first fragment, so that the list is not yet up to date and the second
277    * fragment is not recognized as a BMF packet.
278    * Also, don't forward OLSR packets (UDP port 698) and BMF encapsulated packets */
279   if (IsIpFragment(ipPacket) || IsOlsrOrBmfPacket(ipPacket))
280   {
281     return;
282   }
283
284   /* Increase counter */
285   intf->nBmfPacketsRx++;
286
287   /* Check if the frame is captured on an OLSR-enabled interface */
288   isFromOlsrIntf = (intf->olsrIntf != NULL);
289
290   /* Retrieve the length of the captured packet */
291   ipPacketLen = GetIpTotalLength(ipPacket);
292
293   src.v4 = ipHeader->ip_src;
294
295   OLSR_DEBUG(
296     LOG_PLUGINS,
297     "BMF: %s pkt of %ld bytes captured on %s interface \"%s\": %s->%s\n",
298     sllPkttype == PACKET_OUTGOING ? "outgoing" : "incoming",
299     (long)ipPacketLen,
300     isFromOlsrIntf ? "OLSR" : "non-OLSR",
301     intf->ifName,
302     olsr_ip_to_string(&srcBuf, &src),
303     olsr_ip_to_string(&dstBuf, &dst));
304
305   /* Lookup main address of source in the MID table of OLSR */
306   origIp = MainAddressOf(&src);
307
308   /* Calculate packet fingerprint */
309   crc32 = PacketCrc32(ipPacket, ipPacketLen);
310
311   /* Check if this packet was seen recently */
312   if (CheckAndMarkRecentPacket(crc32))
313   {
314     /* Increase counter */
315     intf->nBmfPacketsRxDup++;
316
317     OLSR_DEBUG(LOG_PLUGINS, "BMF: discarding: packet is duplicate\n");
318     return;
319   }
320
321   /* Compose encapsulation header */
322   encapHdr = (struct TEncapHeader*) encapsulationUdpData;
323   memset (encapHdr, 0, ENCAP_HDR_LEN);
324   encapHdr->type = BMF_ENCAP_TYPE;
325   encapHdr->len = BMF_ENCAP_LEN;
326   encapHdr->reserved = 0;
327   encapHdr->crc32 = htonl(crc32);
328
329   /* Check if the frame is captured on an OLSR interface from an OLSR neighbor.
330    * TODO1: get_best_link_to_neighbor() is not thread-safe.
331    * TODO2: get_best_link_to_neighbor() may be very CPU-expensive, a simpler call
332    * would do here (something like 'get_any_link_to_neighbor()'). */
333   isFromOlsrNeighbor =
334     (isFromOlsrIntf /* The frame is captured on an OLSR interface... */
335     && get_best_link_to_neighbor(origIp) != NULL); /* ...from an OLSR neighbor */
336
337   /* Check with OLSR if I am MPR for that neighbor */
338   /* TODO: olsr_lookup_mprs_set() is not thread-safe! */
339   iAmMpr = olsr_lookup_mprs_set(origIp) != NULL;
340
341   /* Check with each network interface what needs to be done on it */
342   for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
343   {
344     /* Is the forwarding interface OLSR-enabled? */
345     int isToOlsrIntf = (walker->olsrIntf != NULL);
346
347     /* Depending on certain conditions, we decide whether or not to forward
348      * the packet, and if it is forwarded, in which form (encapsulated
349      * or not, TTL decreased or not). These conditions are:
350      * - is the packet is coming in on an OLSR interface or not? (isFromOlsrIntf)
351      * - is the packet going out on an OLSR interface or not? (isToOlsrIntf)
352      * - if the packet if coming in on an OLSR interface:
353      *   - is the node that forwarded the packet my OLSR-neighbor? (isFromOlsrNeighbor)
354      *   - has the node that forwarded the packet selected me as MPR? (iAmMpr)
355      *
356      * Based on these conditions, the following cases can be distinguished:
357      *
358      * - Case 1: Packet coming in on an OLSR interface. What to
359      *   do with it on an OLSR interface?
360      *   Answer:
361      *   - Case 1.1: If the forwarding node is an OLSR neighbor that has *not*
362      *     selected me as MPR: don't forward the packet.
363      *   - Case 1.2: If the forwarding node is an OLSR neighbor that has selected
364      *     me as MPR: encapsulate and forward the packet.
365      *   - Case 1.3: If the forwarding node is not an OLSR neighbor: encapsulate
366      *     and forward the packet.
367      *     NOTE: Case 1.3 is a special case. In the perfect world, we expect to
368      *     see only OLSR-neighbors on OLSR-enabled interfaces. Sometimes, however,
369      *     ignorant users will connect a host not running OLSR, to a LAN in
370      *     which there are hosts running OLSR. Of course these ignorant users,
371      *     expecting magic, want to see their multicast packets being forwarded
372      *     through the network.
373      *
374      * - Case 2: Packet coming in on an OLSR interface. What to do with it on a
375      *   non-OLSR interface?
376      *   Answer: Forward it.
377      *
378      * - Case 3: Packet coming in on a non-OLSR interface. What to
379      *   do with it on an OLSR interface?
380      *   Answer: Encapsulate and forward it.
381      *
382      * - Case 4: Packet coming in on non-OLSR interface. What to do with it on a
383      *   non-OLSR interface?
384      *   Answer 1: nothing. Multicast routing between non-OLSR interfaces
385      *   is to be done by other protocols (e.g. PIM, DVMRP).
386      *   Answer 2 (better): Forward it.
387      */
388
389     if (isFromOlsrIntf && isToOlsrIntf)
390     {
391       /* Case 1: Forward from an OLSR interface to an OLSR interface */
392
393       if (isFromOlsrNeighbor && !iAmMpr)
394       {
395         /* Case 1.1 */
396         {
397           struct ipaddr_str buf;
398           OLSR_DEBUG(
399             LOG_PLUGINS,
400             "BMF: not encap-forwarding on \"%s\": I am not selected as MPR by neighbor %s\n",
401             walker->ifName,
402             olsr_ip_to_string(&buf, &src));
403         }
404       }
405       else if (sllPkttype == PACKET_OUTGOING && intf == walker)
406       {
407         OLSR_DEBUG(
408           LOG_PLUGINS,
409           "BMF: not encap-forwarding on \"%s\": pkt was captured on that interface\n",
410           walker->ifName);
411       }
412       else
413       {
414         /* Case 1.2 and 1.3 */
415         EncapsulateAndForwardPacket(walker, encapsulationUdpData);
416       }
417     } /* if (isFromOlsrIntf && isToOlsrIntf) */
418
419     else if (isFromOlsrIntf && !isToOlsrIntf)
420     {
421       /* Case 2: Forward from OLSR interface to non-OLSR interface */
422
423       int nBytesWritten;
424       struct sockaddr_ll dest;
425
426       /* If the encapsulated IP packet is a local broadcast packet,
427        * update its destination address to match the subnet of the network
428        * interface on which the packet is being sent. */
429       CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
430
431       memset(&dest, 0, sizeof(dest));
432       dest.sll_family = AF_PACKET;
433       dest.sll_protocol = htons(ETH_P_IP);
434       dest.sll_ifindex = if_nametoindex(walker->ifName);
435       dest.sll_halen = IFHWADDRLEN;
436
437       /* Use all-ones as destination MAC address. When the IP destination is
438        * a multicast address, the destination MAC address should normally also
439        * be a multicast address. E.g., when the destination IP is 224.0.0.1,
440        * the destination MAC should be 01:00:5e:00:00:01. However, it does not
441        * seem to matter when the destination MAC address is set to all-ones
442        * in that case. */
443       memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
444
445       nBytesWritten = sendto(
446         walker->capturingSkfd,
447         ipPacket,
448         ipPacketLen,
449         0,
450         (struct sockaddr*) &dest,
451         sizeof(dest));
452       if (nBytesWritten != ipPacketLen)
453       {
454         OLSR_WARN(LOG_PLUGINS, "BMF: sendto() error forwarding pkt on \"%s\"", walker->ifName);
455       }
456       else
457       {
458         /* Increase counter */
459         walker->nBmfPacketsTx++;
460
461         OLSR_WARN(LOG_PLUGINS, "BMF: forwarded on \"%s\"\n", walker->ifName);
462       }
463     } /* else if (isFromOlsrIntf && !isToOlsrIntf) */
464
465     else if (!isFromOlsrIntf && isToOlsrIntf)
466     {
467       /* Case 3: Forward from a non-OLSR interface to an OLSR interface.
468        * Encapsulate and forward packet. */
469
470       EncapsulateAndForwardPacket(walker, encapsulationUdpData);
471     } /* else if (!isFromOlsrIntf && isToOlsrIntf) */
472
473     else
474     {
475       /* Case 4: Forward from non-OLSR interface to non-OLSR interface. */
476
477       /* Don't forward on interface on which packet was received */
478       if (intf == walker)
479       {
480         OLSR_DEBUG(
481           LOG_PLUGINS,
482           "not forwarding on \"%s\": pkt was captured on that interface\n",
483           walker->ifName);
484       }
485
486       else
487       {
488         int nBytesWritten;
489         struct sockaddr_ll dest;
490
491         /* If the encapsulated IP packet is a local broadcast packet,
492          * update its destination address to match the subnet of the network
493          * interface on which the packet is being sent. */
494         CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
495
496         memset(&dest, 0, sizeof(dest));
497         dest.sll_family = AF_PACKET;
498         dest.sll_protocol = htons(ETH_P_IP);
499         dest.sll_ifindex = if_nametoindex(walker->ifName);
500         dest.sll_halen = IFHWADDRLEN;
501
502         /* Use all-ones as destination MAC address. When the IP destination is
503          * a multicast address, the destination MAC address should normally also
504          * be a multicast address. E.g., when the destination IP is 224.0.0.1,
505          * the destination MAC should be 01:00:5e:00:00:01. However, it does not
506          * seem to matter when the destination MAC address is set to all-ones
507          * in that case. */
508         memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
509
510         nBytesWritten = sendto(
511           walker->capturingSkfd,
512           ipPacket,
513           ipPacketLen,
514           0,
515           (struct sockaddr*) &dest,
516           sizeof(dest));
517         if (nBytesWritten != ipPacketLen)
518         {
519           OLSR_WARN(LOG_PLUGINS, "BMF: sendto() error forwarding pkt on \"%s\"", walker->ifName);
520         }
521         else
522         {
523           /* Increase counter */
524           walker->nBmfPacketsTx++;
525
526           OLSR_DEBUG(
527             LOG_PLUGINS,
528             "BMF: forwarded from non-OLSR on non-OLSR \"%s\"\n",
529             walker->ifName);
530         }
531       } /* if (intf == walker) */
532     } /* if */
533   } /* for */
534 } /* BmfPacketCaptured */
535
536 /* -------------------------------------------------------------------------
537  * Function   : BmfEncapsulationPacketReceived
538  * Description: Handle a received BMF-encapsulation packet
539  * Input      : intf - the network interface on which the packet was received
540  *              forwardedBy - the IP node that forwarded the packet to me
541  *              forwardedTo - the destination IP address of the encapsulation
542  *                packet, in case the packet was received promiscuously.
543  *                Pass NULL if the packet is received normally (unicast or
544  *                broadcast).
545  *              encapsulationUdpData - the encapsulating IP UDP data, containting
546  *                the BMF encapsulation header, followed by the encapsulated
547  *                IP packet
548  * Output     : none
549  * Return     : none
550  * Data Used  : BmfInterfaces
551  * ------------------------------------------------------------------------- */
552 static void BmfEncapsulationPacketReceived(
553   struct TBmfInterface* intf,
554   union olsr_ip_addr* forwardedBy,
555   union olsr_ip_addr* forwardedTo,
556   unsigned char* encapsulationUdpData)
557 {
558   int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */
559   struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */
560   unsigned char* ipPacket; /* The encapsulated IP packet */
561   u_int16_t ipPacketLen; /* Length of the encapsulated IP packet */
562   struct ip* ipHeader; /* IP header inside the encapsulated IP packet */
563   union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */
564   union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */
565   struct TEncapHeader* encapsulationHdr;
566   u_int16_t encapsulationUdpDataLen;
567   struct TBmfInterface* walker;
568   struct ipaddr_str mcSrcBuf, mcDstBuf, forwardedByBuf, forwardedToBuf;
569   /* Are we talking to ourselves? */
570   if (if_ifwithaddr(forwardedBy) != NULL)
571   {
572     return;
573   }
574
575   /* Discard encapsulated packets received on a non-OLSR interface */
576   if (intf->olsrIntf == NULL)
577   {
578     return;
579   }
580
581   /* Retrieve details about the encapsulated IP packet */
582   ipPacket = GetIpPacket(encapsulationUdpData);
583   ipPacketLen = GetIpTotalLength(ipPacket);
584   ipHeader = GetIpHeader(encapsulationUdpData);
585
586   mcSrc.v4 = ipHeader->ip_src;
587   mcDst.v4 = ipHeader->ip_dst;
588
589   /* Increase counter */
590   intf->nBmfPacketsRx++;
591
592   OLSR_DEBUG(
593     LOG_PLUGINS,
594     "BMF: encapsulated pkt of %ld bytes incoming on \"%s\": %s->%s, forwarded by %s to %s\n",
595     (long)ipPacketLen,
596     intf->ifName,
597     olsr_ip_to_string(&mcSrcBuf, &mcSrc),
598     olsr_ip_to_string(&mcDstBuf, &mcDst),
599     olsr_ip_to_string(&forwardedByBuf, forwardedBy),
600     forwardedTo != NULL ? olsr_ip_to_string(&forwardedToBuf, forwardedTo) : "me");
601
602   /* Get encapsulation header */
603   encapsulationHdr = (struct TEncapHeader*) encapsulationUdpData;
604
605   /* Verify correct format of BMF encapsulation header */
606   if (encapsulationHdr->type != BMF_ENCAP_TYPE ||
607       encapsulationHdr->len != BMF_ENCAP_LEN ||
608       ntohs(encapsulationHdr->reserved != 0))
609   {
610     OLSR_DEBUG(
611       LOG_PLUGINS,
612       "%s: --> discarding: format of BMF encapsulation header not recognized\n",
613       PLUGIN_NAME_SHORT);
614     return;
615   }
616
617   /* Check if this packet was seen recently */
618   if (CheckAndMarkRecentPacket(ntohl(encapsulationHdr->crc32)))
619   {
620     /* Increase counter */
621     intf->nBmfPacketsRxDup++;
622
623     OLSR_DEBUG(LOG_PLUGINS, "BMF: discarding: packet is duplicate\n");
624     return;
625   }
626
627   if (EtherTunTapFd >= 0)
628   {
629     /* Unpack the encapsulated IP packet and deliver it locally, by sending
630      * a copy into the local IP stack via the EtherTunTap interface */
631
632     union olsr_ip_addr broadAddr;
633     int nBytesToWrite, nBytesWritten;
634     unsigned char* bufferToWrite;
635
636     /* If the encapsulated IP packet is a local broadcast packet,
637      * update its destination address to match the subnet of the EtherTunTap
638      * interface */
639     broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
640     CheckAndUpdateLocalBroadcast(ipPacket, &broadAddr);
641
642     bufferToWrite = ipPacket;
643     nBytesToWrite = ipPacketLen;
644
645     /* Write the packet into the EtherTunTap interface for local delivery */
646     nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite);
647     if (nBytesWritten != nBytesToWrite)
648     {
649       OLSR_WARN(LOG_PLUGINS, "BMF: write() error forwarding encapsulated pkt on \"%s\"", EtherTunTapIfName);
650     }
651     else
652     {
653       OLSR_DEBUG(LOG_PLUGINS, "BMF: unpacked and delivered locally on \"%s\"\n", EtherTunTapIfName);
654     }
655   } /* if (EtherTunTapFd >= 0) */
656
657   /* Check if I am MPR for the forwarder */
658   /* TODO: olsr_lookup_mprs_set() is not thread-safe! */
659   iAmMpr = (olsr_lookup_mprs_set(MainAddressOf(forwardedBy)) != NULL);
660
661   /* Compose destination address for next hop */
662   memset(&forwardTo, 0, sizeof(forwardTo));
663   forwardTo.sin_family = AF_INET;
664   forwardTo.sin_port = htons(BMF_ENCAP_PORT);
665
666   /* Retrieve the number of bytes to be forwarded via the encapsulation socket */
667   encapsulationUdpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);
668
669   /* Check with each network interface what needs to be done on it */
670   for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
671   {
672     /* What to do with the packet on a non-OLSR interface? Unpack
673      * encapsulated packet, and forward it.
674      *
675      * What to do with the packet on an OLSR interface? Forward it only
676      * if the forwarding node has selected us as MPR (iAmMpr).
677      *
678      * Note that the packet is always coming in on an OLSR interface, because
679      * it is an encapsulated BMF packet. */
680
681     /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
682     if (walker->olsrIntf == NULL)
683     {
684       int nBytesWritten;
685       struct sockaddr_ll dest;
686
687       /* If the encapsulated IP packet is a local broadcast packet,
688        * update its destination address to match the subnet of the network
689        * interface on which the packet is being sent. */
690       CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
691
692       memset(&dest, 0, sizeof(dest));
693       dest.sll_family = AF_PACKET;
694       dest.sll_protocol = htons(ETH_P_IP);
695       dest.sll_ifindex = if_nametoindex(walker->ifName);
696       dest.sll_halen = IFHWADDRLEN;
697
698       /* Use all-ones as destination MAC address. When the IP destination is
699        * a multicast address, the destination MAC address should normally also
700        * be a multicast address. E.g., when the destination IP is 224.0.0.1,
701        * the destination MAC should be 01:00:5e:00:00:01. However, it does not
702        * seem to matter when the destination MAC address is set to all-ones
703        * in that case. */
704       memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
705
706       nBytesWritten = sendto(
707         walker->capturingSkfd,
708         ipPacket,
709         ipPacketLen,
710         0,
711         (struct sockaddr*) &dest,
712         sizeof(dest));
713       if (nBytesWritten != ipPacketLen)
714       {
715         OLSR_WARN(LOG_PLUGINS, "BMF: sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);
716       }
717       else
718       {
719         /* Increase counter */
720         walker->nBmfPacketsTx++;
721
722         OLSR_DEBUG(
723           LOG_PLUGINS,
724           "unpacked and forwarded on \"%s\"\n",
725           walker->ifName);
726       }
727     } /* if (walker->olsrIntf == NULL) */
728
729     /* To an OLSR interface: forward the packet, but only if this node is
730      * selected as MPR by the forwarding node */
731     else if (iAmMpr)
732     {
733       struct TBestNeighbors bestNeighborLinks;
734       struct link_entry* bestNeighbor;
735       int nPossibleNeighbors;
736       int nPacketsToSend;
737       int sendUnicast; /* 0 = send broadcast; 1 = send unicast */
738       int i;
739
740       /* Retrieve at most two best neigbors to forward the packet to */
741       FindNeighbors(
742         &bestNeighborLinks,
743         &bestNeighbor,
744         walker,
745         &mcSrc,
746         forwardedBy,
747         forwardedTo,
748         &nPossibleNeighbors);
749
750       if (nPossibleNeighbors <= 0)
751       {
752         OLSR_DEBUG(
753           LOG_PLUGINS,
754           "not forwarding on \"%s\": there is no neighbor that needs my retransmission\n",
755           walker->ifName);
756
757         continue; /* for */
758       }
759
760       /* Compose destination of encapsulation packet.
761        * Start by filling in the local broadcast address. This may be overwritten later. */
762       forwardTo.sin_addr = walker->broadAddr.v4;
763
764       /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one
765        *   unicast packet (to the best neighbor).
766        * - But if the BMF mechanism is BM_BROADCAST,
767        *   - send 'nPossibleNeighbors' unicast packets if there are up to
768        *     'FanOutLimit' possible neighbors,
769        *   - if there are more than 'FanOutLimit' possible neighbors, then
770        *     send a (WLAN-air-expensive, less reliable) broadcast packet. */
771       if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
772       {
773         /* One unicast packet to the best neighbor */
774         nPacketsToSend = 1;
775         sendUnicast = 1;
776         bestNeighborLinks.links[0] = bestNeighbor;
777       }
778       else /* BmfMechanism == BM_BROADCAST */
779       {
780         if (nPossibleNeighbors <= FanOutLimit)
781         {
782           /* 'nPossibleNeighbors' unicast packets */
783           nPacketsToSend = nPossibleNeighbors;
784           sendUnicast = 1;
785         }
786         else /* nPossibleNeighbors > FanOutLimit */
787         {
788           /* One broadcast packet, possibly retransmitted as specified in the
789            * 'BroadcastRetransmitCount' plugin parameter */
790           nPacketsToSend = BroadcastRetransmitCount;
791           sendUnicast = 0;
792         } /* if */
793       } /* if */
794
795       for (i = 0; i < nPacketsToSend; i++)
796       {
797         int nBytesWritten;
798
799         if (sendUnicast)
800         {
801           /* For unicast, overwrite the local broadcast address which was filled in above */
802           forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4;
803         }
804
805         /* Forward the BMF packet via the encapsulation socket */
806         nBytesWritten = sendto(
807           walker->encapsulatingSkfd,
808           encapsulationUdpData,
809           encapsulationUdpDataLen,
810           MSG_DONTROUTE,
811           (struct sockaddr*) &forwardTo,
812           sizeof(forwardTo));
813
814         /* Evaluate and display result */
815         if (nBytesWritten != encapsulationUdpDataLen)
816         {
817           OLSR_WARN(LOG_PLUGINS, "sendto() error forwarding encapsulated pkt on \"%s\"", walker->ifName);
818         }
819         else
820         {
821           /* Increase counter */
822           walker->nBmfPacketsTx++;
823
824           OLSR_DEBUG(
825             LOG_PLUGINS,
826             "forwarded on \"%s\" to %s\n",
827             walker->ifName,
828             inet_ntoa(forwardTo.sin_addr));
829         } /* if */
830       } /* for */
831     }  /* else if (iAmMpr) */
832
833     else /* walker->olsrIntf != NULL && !iAmMpr */
834     {
835       struct ipaddr_str buf;
836       /* 'walker' is an OLSR interface, but I am not selected as MPR. In that
837        * case, don't forward. */
838       OLSR_DEBUG(
839         LOG_PLUGINS,
840         "not forwarding on \"%s\": I am not selected as MPR by %s\n",
841         walker->ifName,
842         olsr_ip_to_string(&buf, forwardedBy));
843     } /* else */
844   } /* for */
845 } /* BmfEncapsulationPacketReceived */
846
847 /* -------------------------------------------------------------------------
848  * Function   : BmfTunPacketCaptured
849  * Description: Handle an IP packet, captured outgoing on the tuntap interface
850  * Input      : encapsulationUdpData - space for the encapsulation header, followed by
851  *                the captured outgoing IP packet
852  * Output     : none
853  * Return     : none
854  * Data Used  : none
855  * Notes      : The packet is assumed to be captured on a socket of family
856  *              PF_PACKET and type SOCK_DGRAM (cooked).
857  * ------------------------------------------------------------------------- */
858 static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
859 {
860   union olsr_ip_addr srcIp;
861   union olsr_ip_addr dstIp;
862   union olsr_ip_addr broadAddr;
863   struct TBmfInterface* walker;
864   unsigned char* ipPacket;
865   u_int16_t ipPacketLen;
866   struct ip* ipHeader;
867   u_int32_t crc32;
868   struct TEncapHeader* encapHdr;
869   struct ipaddr_str srcIpBuf, dstIpBuf;
870   ipPacket = GetIpPacket(encapsulationUdpData);
871   ipPacketLen = GetIpTotalLength(ipPacket);
872   ipHeader = GetIpHeader(encapsulationUdpData);
873
874   dstIp.v4 = ipHeader->ip_dst;
875   broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
876
877   /* Only forward multicast packets. If configured, also forward local broadcast packets */
878   if (IsMulticast(&dstIp) ||
879       (EnableLocalBroadcast != 0 && olsr_ipcmp(&dstIp, &broadAddr) == 0))
880   {
881     /* continue */
882   }
883   else
884   {
885     return;
886   }
887
888   srcIp.v4 = ipHeader->ip_src;
889
890   OLSR_DEBUG(
891     LOG_PLUGINS,
892     "outgoing pkt of %ld bytes captured on tuntap interface \"%s\": %s->%s\n",
893     (long)ipPacketLen,
894     EtherTunTapIfName,
895     olsr_ip_to_string(&srcIpBuf, &srcIp),
896     olsr_ip_to_string(&dstIpBuf, &dstIp));
897
898   /* Calculate packet fingerprint */
899   crc32 = PacketCrc32(ipPacket, ipPacketLen);
900
901   /* Check if this packet was seen recently */
902   if (CheckAndMarkRecentPacket(crc32))
903   {
904     OLSR_DEBUG(LOG_PLUGINS, "discarding: packet is duplicate\n");
905     return;
906   }
907
908   /* Compose encapsulation header */
909   encapHdr = (struct TEncapHeader*) encapsulationUdpData;
910   memset (encapHdr, 0, ENCAP_HDR_LEN);
911   encapHdr->type = BMF_ENCAP_TYPE;
912   encapHdr->len = BMF_ENCAP_LEN;
913   encapHdr->reserved = 0;
914   encapHdr->crc32 = htonl(crc32);
915
916   /* Check with each network interface what needs to be done on it */
917   for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
918   {
919     /* Is the forwarding interface OLSR-enabled? */
920     if (walker->olsrIntf != NULL)
921     {
922       /* On an OLSR interface: encapsulate and forward packet. */
923
924       EncapsulateAndForwardPacket(walker, encapsulationUdpData);
925     }
926     else
927     {
928       /* On a non-OLSR interface: what to do?
929        * Answer 1: nothing. Multicast routing between non-OLSR interfaces
930        * is to be done by other protocols (e.g. PIM, DVMRP).
931        * Answer 2 (better): Forward it. */
932
933       int nBytesWritten;
934       struct sockaddr_ll dest;
935
936       /* If the encapsulated IP packet is a local broadcast packet,
937        * update its destination address to match the subnet of the network
938        * interface on which the packet is being sent. */
939       CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr);
940
941       memset(&dest, 0, sizeof(dest));
942       dest.sll_family = AF_PACKET;
943       dest.sll_protocol = htons(ETH_P_IP);
944       dest.sll_ifindex = if_nametoindex(walker->ifName);
945       dest.sll_halen = IFHWADDRLEN;
946
947       /* Use all-ones as destination MAC address. When the IP destination is
948        * a multicast address, the destination MAC address should normally also
949        * be a multicast address. E.g., when the destination IP is 224.0.0.1,
950        * the destination MAC should be 01:00:5e:00:00:01. However, it does not
951        * seem to matter when the destination MAC address is set to all-ones
952        * in that case. */
953       memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
954
955       nBytesWritten = sendto(
956         walker->capturingSkfd,
957         ipPacket,
958         ipPacketLen,
959         0,
960         (struct sockaddr*) &dest,
961         sizeof(dest));
962       if (nBytesWritten != ipPacketLen)
963       {
964         OLSR_WARN(LOG_PLUGINS, "sendto() error forwarding pkt on \"%s\"", walker->ifName);
965       }
966       else
967       {
968         /* Increase counter */
969         walker->nBmfPacketsTx++;
970
971         OLSR_DEBUG(
972           LOG_PLUGINS,
973           "forwarded from non-OLSR to non-OLSR \"%s\"\n",
974           walker->ifName);
975       } /* if */
976     } /* if */
977   } /* for */
978 } /* BmfTunPacketCaptured */
979
980 /* -------------------------------------------------------------------------
981  * Function   : DoBmf
982  * Description: Wait (blocking) for IP packets, then call the handler for each
983  *              received packet
984  * Input      : none
985  * Output     : none
986  * Return     : none
987  * Data Used  : BmfInterfaces
988  * ------------------------------------------------------------------------- */
989 static void DoBmf(void)
990 {
991   int nFdBitsSet;
992   unsigned char rxBuffer[BMF_BUFFER_SIZE];
993   fd_set rxFdSet;
994
995   assert(HighestSkfd >= 0);
996
997   /* Make a local copy of the set of file descriptors that select() can
998    * modify to indicate which descriptors actually changed status */
999   rxFdSet = InputSet;
1000
1001   /* Wait (blocking) for packets received on any of the sockets.
1002    * NOTE: don't use a timeout (last parameter). It causes a high system CPU load! */
1003   nFdBitsSet = select(HighestSkfd + 1, &rxFdSet, NULL, NULL, NULL);
1004   if (nFdBitsSet < 0)
1005   {
1006     if (errno != EINTR)
1007     {
1008       OLSR_WARN(LOG_PLUGINS, "select() error");
1009     }
1010     return;
1011   }
1012
1013   while (nFdBitsSet > 0)
1014   {
1015     struct TBmfInterface* walker;
1016
1017     /* Check if a packet was received on the capturing socket (if any)
1018      * of each network interface */
1019     for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
1020     {
1021       int skfd = walker->capturingSkfd;
1022       if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
1023       {
1024         struct sockaddr_ll pktAddr;
1025         socklen_t addrLen = sizeof(pktAddr);
1026         int nBytes;
1027         unsigned char* ipPacket;
1028
1029         /* A packet was captured. */
1030
1031         nFdBitsSet--;
1032
1033         /* Receive the captured Ethernet frame, leaving space for the BMF
1034          * encapsulation header */
1035         ipPacket = GetIpPacket(rxBuffer);
1036         nBytes = recvfrom(
1037           skfd,
1038           ipPacket,
1039           BMF_BUFFER_SIZE - ENCAP_HDR_LEN,
1040           0,
1041           (struct sockaddr*)&pktAddr,
1042           &addrLen);
1043         if (nBytes < 0)
1044         {
1045           OLSR_WARN(LOG_PLUGINS, "recvfrom() error on \"%s\"", walker->ifName);
1046
1047           continue; /* for */
1048         } /* if (nBytes < 0) */
1049
1050         /* Check if the number of received bytes is large enough for an IP
1051          * packet which contains at least a minimum-size IP header.
1052          * Note: There is an apparent bug in the packet socket implementation in
1053          * combination with VLAN interfaces. On a VLAN interface, the value returned
1054          * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value
1055          * returned on a non-VLAN interface, for the same ethernet frame. */
1056         if (nBytes < (int)sizeof(struct ip))
1057         {
1058           OLSR_DEBUG(
1059             LOG_PLUGINS,
1060             "captured frame too short (%d bytes) on \"%s\"\n",
1061             nBytes,
1062             walker->ifName);
1063
1064           continue; /* for */
1065         }
1066
1067         if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
1068             pktAddr.sll_pkttype == PACKET_MULTICAST ||
1069             pktAddr.sll_pkttype == PACKET_BROADCAST)
1070         {
1071           /* A multicast or broadcast packet was captured */
1072
1073           BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer);
1074
1075         } /* if (pktAddr.sll_pkttype == ...) */
1076       } /* if (skfd >= 0 && (FD_ISSET...)) */
1077     } /* for */
1078
1079     /* Check if a BMF encapsulation packet was received on the listening
1080      * socket (if any) of each network interface */
1081     for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
1082     {
1083       int skfd = walker->listeningSkfd;
1084       if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
1085       {
1086         struct sockaddr_ll pktAddr;
1087         socklen_t addrLen = sizeof(pktAddr);
1088         int nBytes;
1089         int minimumLength;
1090         struct ip* ipHeader;
1091         struct udphdr* udpHeader;
1092         u_int16_t destPort;
1093         union olsr_ip_addr forwardedBy;
1094         union olsr_ip_addr forwardedTo;
1095
1096         /* Heard a BMF packet */
1097
1098         nFdBitsSet--;
1099
1100         nBytes = recvfrom(
1101           skfd,
1102           rxBuffer,
1103           BMF_BUFFER_SIZE,
1104           0,
1105           (struct sockaddr*)&pktAddr,
1106           &addrLen);
1107         if (nBytes < 0)
1108         {
1109           OLSR_WARN(LOG_PLUGINS, "recvfrom() error on \"%s\"", walker->ifName);
1110
1111           continue; /* for */
1112         } /* if (nBytes < 0) */
1113
1114         /* Check if the received packet is actually directed to another
1115          * node on the LAN */
1116         if (pktAddr.sll_pkttype != PACKET_OTHERHOST)
1117         {
1118           /* No, the packet is directed to this node. In that case it will
1119            * be, or will already have been received, via the encapsulating
1120            * socket. Discard it here. */
1121           continue; /* for */
1122         } /* if (pktAddr.sll_pkttype ...) */
1123
1124         /* Check if the received packet is UDP - BMF port */
1125         ipHeader = (struct ip*)rxBuffer;
1126         if (ipHeader->ip_p != SOL_UDP)
1127         {
1128           /* Not UDP */
1129           continue; /* for */
1130         }
1131
1132         udpHeader = (struct udphdr*)(rxBuffer + GetIpHeaderLength(rxBuffer));
1133         destPort = ntohs(udpHeader->dest);
1134         if (destPort != BMF_ENCAP_PORT)
1135         {
1136           /* Not BMF */
1137           continue; /* for */
1138         }
1139
1140         /* Check if the number of received bytes is large enough for a minimal BMF
1141          * encapsulation packet, at least:
1142          * - the IP header of the encapsulation IP packet
1143          * - the UDP header of the encapsulation IP packet
1144          * - the encapsulation header
1145          * - a minimum IP header inside the encapsulated packet
1146          * Note: on a VLAN interface, the value returned by 'recvfrom' may (but need
1147          * not) be 4 (bytes) larger than the value returned on a non-VLAN interface, for
1148          * the same ethernet frame. */
1149         minimumLength =
1150           GetIpHeaderLength(rxBuffer) +
1151           sizeof(struct udphdr) +
1152           ENCAP_HDR_LEN +
1153           sizeof(struct ip);
1154         if (nBytes < minimumLength)
1155         {
1156           OLSR_DEBUG(
1157             LOG_PLUGINS,
1158             "captured a too short encapsulation packet (%d bytes) on \"%s\"\n",
1159             nBytes,
1160             walker->ifName);
1161
1162           continue; /* for */
1163         }
1164
1165         forwardedBy.v4 = ipHeader->ip_src;
1166         forwardedTo.v4 = ipHeader->ip_dst;
1167         BmfEncapsulationPacketReceived(
1168           walker,
1169           &forwardedBy,
1170           &forwardedTo,
1171           rxBuffer + GetIpHeaderLength(rxBuffer) + sizeof(struct udphdr));
1172
1173       } /* if (skfd >= 0 && (FD_ISSET...)) */
1174     } /* for */
1175
1176     /* Check if a packet was received on the encapsulating socket (if any)
1177      * of each network interface */
1178     for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
1179     {
1180       int skfd = walker->encapsulatingSkfd;
1181       if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet)))
1182       {
1183         struct sockaddr_in from;
1184         socklen_t fromLen = sizeof(from);
1185         int nBytes;
1186         int minimumLength;
1187         union olsr_ip_addr forwardedBy;
1188
1189         /* An encapsulated packet was received */
1190
1191         nFdBitsSet--;
1192
1193         nBytes = recvfrom(
1194           skfd,
1195           rxBuffer,
1196           BMF_BUFFER_SIZE,
1197           0,
1198           (struct sockaddr*)&from,
1199           &fromLen);
1200         if (nBytes < 0)
1201         {
1202           OLSR_WARN(LOG_PLUGINS, "recvfrom() error on \"%s\"", walker->ifName);
1203
1204           continue; /* for */
1205         } /* if (nBytes < 0) */
1206
1207         forwardedBy.v4 = from.sin_addr;
1208
1209         /* Check if the number of received bytes is large enough for a minimal BMF
1210          * encapsulation packet, at least:
1211          * - the encapsulation header
1212          * - a minimum IP header inside the encapsulated packet */
1213         minimumLength =
1214           ENCAP_HDR_LEN +
1215           sizeof(struct ip);
1216         if (nBytes < minimumLength)
1217         {
1218           struct ipaddr_str buf;
1219           OLSR_DEBUG(
1220             LOG_PLUGINS,
1221             "received a too short encapsulation packet (%d bytes) from %s on \"%s\"\n",
1222             nBytes,
1223             olsr_ip_to_string(&buf, &forwardedBy),
1224             walker->ifName);
1225
1226           continue; /* for */
1227         }
1228
1229         /* Unfortunately, the recvfrom call does not return the destination
1230          * of the encapsulation packet (the destination may be either the
1231          * my unicast or my local broadcast address). Therefore we fill in 'NULL'
1232          * for the 'forwardedTo' parameter. */
1233         BmfEncapsulationPacketReceived(walker, &forwardedBy, NULL, rxBuffer);
1234
1235       } /* if (skfd >= 0 && (FD_ISSET...)) */
1236     } /* for */
1237
1238     if (nFdBitsSet > 0 && FD_ISSET(EtherTunTapFd, &rxFdSet))
1239     {
1240       /* Check if an application has sent a packet out via the tuntap
1241        * network interface */
1242
1243       int nBytes;
1244       unsigned char* ipPacket;
1245       unsigned char* bufferToRead;
1246       size_t nBytesToRead;
1247
1248       nFdBitsSet--;
1249
1250       /* Receive the packet, leaving space for the BMF encapsulation header */
1251       ipPacket = GetIpPacket(rxBuffer);
1252
1253       bufferToRead = ipPacket;
1254       nBytesToRead = BMF_BUFFER_SIZE - ENCAP_HDR_LEN;
1255
1256       nBytes = read(EtherTunTapFd, bufferToRead, nBytesToRead);
1257
1258       if (nBytes < 0)
1259       {
1260         OLSR_WARN(LOG_PLUGINS, "recvfrom() error on \"%s\"", EtherTunTapIfName);
1261       }
1262       else
1263       {
1264         /* Check if the number of received bytes is large enough for an IP
1265          * packet which contains at least a minimum-size IP header */
1266         if (nBytes < (int)sizeof(struct ip))
1267         {
1268           OLSR_DEBUG(
1269             LOG_PLUGINS,
1270             "captured packet too short (%d bytes) on \"%s\"\n",
1271             nBytes,
1272             EtherTunTapIfName);
1273         }
1274         else
1275         {
1276           /* An outbound packet was captured */
1277
1278           BmfTunPacketCaptured(rxBuffer);
1279
1280         } /* if (nBytes < ... */
1281       } /* if (nBytes < 0) */
1282     } /* if (nFdBitsSet > 0 && ... */
1283   } /* while (nFdBitsSet > 0) */
1284 } /* DoBmf */
1285
1286 /* -------------------------------------------------------------------------
1287  * Function   : BmfSignalHandler
1288  * Description: Signal handler function
1289  * Input      : signo - signal being handled
1290  * Output     : none
1291  * Return     : none
1292  * Data Used  : BmfThreadRunning
1293  * ------------------------------------------------------------------------- */
1294 static void BmfSignalHandler(int signo __attribute__((unused)))
1295 {
1296   BmfThreadRunning = 0;
1297 } /* BmfSignalHandler */
1298
1299 /* -------------------------------------------------------------------------
1300  * Function   : BmfRun
1301  * Description: Receiver thread function
1302  * Input      : useless - not used
1303  * Output     : none
1304  * Return     : not used
1305  * Data Used  : BmfThreadRunning
1306  * Notes      : Another thread can gracefully stop this thread by sending
1307  *              a SIGALRM signal.
1308  * ------------------------------------------------------------------------- */
1309 static void* BmfRun(void* useless __attribute__((unused)))
1310 {
1311   /* Mask all signals except SIGALRM */
1312   sigset_t blockedSigs;
1313   sigfillset(&blockedSigs);
1314   sigdelset(&blockedSigs, SIGALRM);
1315   if (pthread_sigmask(SIG_BLOCK, &blockedSigs, NULL) != 0)
1316   {
1317     OLSR_WARN(LOG_PLUGINS, "pthread_sigmask() error");
1318   }
1319
1320   /* Set up the signal handler for the process: use SIGALRM to terminate
1321    * the BMF thread. Only if a signal handler is specified, does a blocking
1322    * system call return with errno set to EINTR; if a signal hander is not
1323    * specified, any system call in which the thread may be waiting will not
1324    * return. Note that the BMF thread is usually blocked in the select()
1325    * function (see DoBmf()). */
1326   if (signal(SIGALRM, BmfSignalHandler) == SIG_ERR)
1327   {
1328     OLSR_WARN(LOG_PLUGINS, "signal() error");
1329   }
1330
1331   /* Call the thread function until flagged to exit */
1332   while (BmfThreadRunning != 0)
1333   {
1334     DoBmf();
1335   }
1336
1337   return NULL;
1338 } /* BmfRun */
1339
1340 /* -------------------------------------------------------------------------
1341  * Function   : InterfaceChange
1342  * Description: Callback function passed to OLSRD for it to call whenever a
1343  *              network interface has been added, removed or updated
1344  * Input      : interf - the network interface to deal with
1345  *              action - indicates if the specified network interface was
1346  *                added, removed or updated.
1347  * Output     : none
1348  * Return     : always 0
1349  * Data Used  : none
1350  * ------------------------------------------------------------------------- */
1351 int InterfaceChange(struct interface* interf, int action)
1352 {
1353   switch (action)
1354   {
1355   case (IFCHG_IF_ADD):
1356     AddInterface(interf);
1357     OLSR_DEBUG(LOG_PLUGINS, "interface %s added\n", interf->int_name);
1358     break;
1359
1360   case (IFCHG_IF_REMOVE):
1361     /* We cannot just remove the interface, because the receive-thread is likely
1362      * to be waiting in select(...) for packets coming in via the interface.
1363      * Therefore we first close BMF (CloseBmf()), interrupting and kiling the
1364      * receive-thread so that it is safe to remove this (and all other)
1365      * interfaces. After that, BMF is re-started (InitBmf(interf)). */
1366     CloseBmf();
1367     InitBmf(interf);
1368     OLSR_DEBUG(LOG_PLUGINS, "interface %s removed\n", interf->int_name);
1369     break;
1370
1371   case (IFCHG_IF_UPDATE):
1372     OLSR_DEBUG(LOG_PLUGINS, "interface %s updated\n", interf->int_name);
1373     break;
1374
1375   default:
1376     OLSR_WARN(
1377       LOG_PLUGINS,
1378       "interface %s: error - unknown action (%d)\n",
1379       interf->int_name, action);
1380     break;
1381   }
1382
1383   return 0;
1384 } /* InterfaceChange */
1385
1386
1387 /* -------------------------------------------------------------------------
1388  * Function   : SetFanOutLimit
1389  * Description: Overrule the default fan out limit value (2)
1390  * Input      : value - fan out limit value (1...MAX_UNICAST_NEIGHBORS)
1391  *              data - not used
1392  *              addon - not used
1393  * Output     : none
1394  * Return     : success (0) or fail (1)
1395  * Data Used  : FanOutLimit
1396  * ------------------------------------------------------------------------- */
1397 int SetFanOutLimit(
1398   const char* value,
1399   void* data __attribute__((unused)),
1400   set_plugin_parameter_addon addon __attribute__((unused)))
1401 {
1402   if (set_plugin_int(value, &FanOutLimit, addon) == 0)
1403   {
1404     /* Extra check if within range */
1405     if (FanOutLimit >= 1 && FanOutLimit <= MAX_UNICAST_NEIGHBORS)
1406     {
1407       return 0;
1408     }
1409   }
1410   return 1;
1411 }
1412
1413 /* -------------------------------------------------------------------------
1414  * Function   : InitBmf
1415  * Description: Initialize the BMF plugin
1416  * Input      : skipThisIntf - specifies which network interface should not
1417  *              be enabled for BMF. Pass NULL if not applicable.
1418  * Output     : none
1419  * Return     : fail (0) or success (1)
1420  * Data Used  : BmfThreadRunning, BmfThread
1421  * ------------------------------------------------------------------------- */
1422 int InitBmf(struct interface* skipThisIntf)
1423 {
1424   CreateBmfNetworkInterfaces(skipThisIntf);
1425
1426   /* Start running the multicast packet processing thread */
1427   BmfThreadRunning = 1;
1428   if (pthread_create(&BmfThread, NULL, BmfRun, NULL) != 0)
1429   {
1430     OLSR_WARN(LOG_PLUGINS, "pthread_create() error");
1431     return 0;
1432   }
1433
1434   if (EtherTunTapFd >= 0)
1435   {
1436     /* Deactivate IP spoof filter for EtherTunTap interface */
1437     DeactivateSpoofFilter();
1438
1439     /* If the BMF network interface has a sensible IP address, it is a good idea
1440      * to route all multicast traffic through that interface */
1441     if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
1442     {
1443       AddMulticastRoute();
1444     }
1445   }
1446
1447   return 1;
1448 } /* InitBmf */
1449
1450 /* -------------------------------------------------------------------------
1451  * Function   : CloseBmf
1452  * Description: Close the BMF plugin and clean up
1453  * Input      : none
1454  * Output     : none
1455  * Return     : none
1456  * Data Used  : BmfThread
1457  * ------------------------------------------------------------------------- */
1458 void CloseBmf(void)
1459 {
1460   if (EtherTunTapFd >= 0)
1461   {
1462     /* If there is a multicast route, try to delete it first */
1463     DeleteMulticastRoute();
1464
1465     /* Restore IP spoof filter for EtherTunTap interface */
1466     RestoreSpoofFilter();
1467   }
1468
1469   if (BmfThreadRunning)
1470   {
1471     /* Signal BmfThread to exit */
1472     /* Strangely enough, all running threads receive the SIGALRM signal. But only the
1473      * BMF thread is affected by this signal, having specified a handler for this
1474      * signal in its thread entry function BmfRun(...). */
1475     if (pthread_kill(BmfThread, SIGALRM) != 0)
1476     {
1477       OLSR_WARN(LOG_PLUGINS, "pthread_kill() error");
1478     }
1479
1480     /* Wait for BmfThread to acknowledge */
1481     if (pthread_join(BmfThread, NULL) != 0)
1482     {
1483       OLSR_WARN(LOG_PLUGINS, "pthread_join() error");
1484     }
1485   }
1486
1487   /* Clean up after the BmfThread has been killed */
1488   CloseBmfNetworkInterfaces();
1489 } /* CloseBmf */
1490
1491
1492 /*
1493  * Local Variables:
1494  * c-basic-offset: 2
1495  * indent-tabs-mode: nil
1496  * End:
1497  */