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