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