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