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