2 * OLSR Basic Multicast Forwarding (BMF) plugin.
3 * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands.
4 * Written by Erik Tromp.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
33 /* -------------------------------------------------------------------------
34 * File : NetworkInterfaces.c
35 * Description: Functions to open and close sockets
36 * Created : 29 Jun 2006
38 * ------------------------------------------------------------------------- */
40 #include "NetworkInterfaces.h"
43 #include <stddef.h> /* NULL */
44 #include <syslog.h> /* syslog() */
45 #include <string.h> /* strerror(), strchr(), strcmp() */
46 #include <errno.h> /* errno */
47 #include <unistd.h> /* close() */
48 #include <sys/ioctl.h> /* ioctl() */
49 #include <fcntl.h> /* fcntl() */
50 #include <assert.h> /* assert() */
51 #include <net/if.h> /* socket(), ifreq, if_indextoname(), if_nametoindex() */
52 #include <netinet/in.h> /* htons() */
53 #include <linux/if_ether.h> /* ETH_P_IP */
54 #include <linux/if_packet.h> /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */
55 #include <linux/if_tun.h> /* IFF_TAP */
56 #include <netinet/ip.h> /* struct ip */
57 #include <netinet/udp.h> /* SOL_UDP */
60 #include "olsr.h" /* olsr_printf() */
62 #include "defs.h" /* olsr_cnf */
63 #include "link_set.h" /* get_link_set() */
64 #include "tc_set.h" /* olsr_lookup_tc_entry(), olsr_lookup_tc_edge() */
65 #include "net_olsr.h" /* ipequal */
66 #include "lq_plugin.h"
67 #include "kernel_tunnel.h"
70 #include "Packet.h" /* IFHWADDRLEN */
71 #include "Bmf.h" /* PLUGIN_NAME, MainAddressOf() */
72 #include "Address.h" /* IsMulticast() */
74 /* List of network interface objects used by BMF plugin */
75 struct TBmfInterface* BmfInterfaces = NULL;
76 struct TBmfInterface* LastBmfInterface = NULL;
78 /* Highest-numbered open socket file descriptor. To be used as first
79 * parameter in calls to select(...). */
82 /* Set of socket file descriptors */
85 /* File descriptor of EtherTunTap interface */
86 int EtherTunTapFd = -1;
88 /* Network interface name of EtherTunTap interface. May be overruled by
89 * setting the plugin parameter "BmfInterface". */
90 char EtherTunTapIfName[IFNAMSIZ] = "bmf0";
92 /* The underlying mechanism to forward multicast packets. Either:
93 * - BM_BROADCAST: BMF uses the IP local broadcast as destination address
94 * - BM_UNICAST_PROMISCUOUS: BMF uses the IP address of the best neighbor as
95 * destination address. The other neighbors listen promiscuously. */
96 enum TBmfMechanism BmfMechanism = BM_BROADCAST;
98 #define ETHERTUNTAPIPNOTSET 0
100 /* The IP address of the BMF network interface in host byte order.
101 * May be overruled by setting the plugin parameter "BmfInterfaceIp". */
102 u_int32_t EtherTunTapIp = ETHERTUNTAPIPNOTSET;
104 /* 255.255.255.255 in host byte order. May be overruled by
105 * setting the plugin parameter "BmfInterfaceIp". */
106 u_int32_t EtherTunTapIpMask = 0xFFFFFFFF;
108 /* The IP broadcast address of the BMF network interface in host byte order.
109 * May be overruled by setting the plugin parameter "BmfinterfaceIp". */
110 u_int32_t EtherTunTapIpBroadcast = ETHERTUNTAPIPNOTSET;
112 /* Whether or not the BMF network interface must be marked as persistent */
113 int EtherTunTapPersistent = 1;
115 /* Whether or not the configuration has overruled the default IP
116 * configuration of the EtherTunTap interface */
117 int TunTapIpOverruled = 0;
119 /* Whether or not to capture packets on the OLSR-enabled
120 * interfaces (in promiscuous mode). May be overruled by setting the plugin
121 * parameter "CapturePacketsOnOlsrInterfaces" to "yes". */
122 int CapturePacketsOnOlsrInterfaces = 0;
124 /* -------------------------------------------------------------------------
125 * Function : SetBmfInterfaceName
126 * Description: Overrule the default network interface name ("bmf0") of the
127 * EtherTunTap interface
128 * Input : ifname - network interface name (e.g. "mybmf0")
132 * Return : success (0) or fail (1)
133 * Data Used : EtherTunTapIfName
134 * ------------------------------------------------------------------------- */
135 int SetBmfInterfaceName(
137 void* data __attribute__((unused)),
138 set_plugin_parameter_addon addon __attribute__((unused)))
140 strncpy(EtherTunTapIfName, ifname, IFNAMSIZ - 1);
141 EtherTunTapIfName[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
143 } /* SetBmfInterfaceName */
145 /* -------------------------------------------------------------------------
146 * Function : SetBmfInterfaceIp
147 * Description: Overrule the default IP address and prefix length
148 * ("10.255.255.253/30") of the EtherTunTap interface
149 * Input : ip - IP address string, followed by '/' and prefix length
153 * Return : success (0) or fail (1)
154 * Data Used : EtherTunTapIp, EtherTunTapIpMask, EtherTunTapIpBroadcast,
156 * ------------------------------------------------------------------------- */
157 int SetBmfInterfaceIp(
159 void* data __attribute__((unused)),
160 set_plugin_parameter_addon addon __attribute__((unused)))
162 #define IPV4_MAX_ADDRLEN 16
163 #define IPV4_MAX_PREFIXLEN 32
165 char ipAddr[IPV4_MAX_ADDRLEN];
166 struct in_addr sinaddr;
170 /* Inspired by function str2prefix_ipv4 as found in Quagga source
171 * file lib/prefix.c */
173 /* Find slash inside string. */
174 slashAt = strchr(ip, '/');
176 /* String doesn't contain slash. */
177 if (slashAt == NULL || slashAt - ip >= IPV4_MAX_ADDRLEN)
179 /* No prefix length specified, or IP address too long */
183 strncpy(ipAddr, ip, slashAt - ip);
184 *(ipAddr + (slashAt - ip)) = '\0';
185 if (inet_aton(ipAddr, &sinaddr) == 0)
187 /* Invalid address passed */
191 EtherTunTapIp = ntohl(sinaddr.s_addr);
193 /* Get prefix length. */
194 prefixLen = atoi(++slashAt);
195 if (prefixLen <= 0 || prefixLen > IPV4_MAX_PREFIXLEN)
200 /* Compose IP subnet mask in host byte order */
201 EtherTunTapIpMask = 0;
202 for (i = 0; i < prefixLen; i++)
204 EtherTunTapIpMask |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
207 /* Compose IP broadcast address in host byte order */
208 EtherTunTapIpBroadcast = EtherTunTapIp;
209 for (i = prefixLen; i < IPV4_MAX_PREFIXLEN; i++)
211 EtherTunTapIpBroadcast |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
214 TunTapIpOverruled = 1;
217 } /* SetBmfInterfaceIp */
219 /* -------------------------------------------------------------------------
220 * Function : SetBmfInterfacePersistent
221 * Description: Determine if the EtherTunTap interface must be marked
223 * Input : value - yes/true/1 or no/false/0
227 * Return : success (0) or fail (1)
228 * Data Used : EtherTunTapPersistent
229 * ------------------------------------------------------------------------- */
230 int SetBmfInterfacePersistent(
232 void* data __attribute__((unused)),
233 set_plugin_parameter_addon addon __attribute__((unused)))
235 if (strcasecmp(value, "yes") == 0 || strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) {
236 EtherTunTapPersistent = 1;
237 } else if (strcasecmp(value, "no") == 0 || strcasecmp(value, "false") == 0 || strcasecmp(value, "0") == 0) {
238 EtherTunTapPersistent = 0;
243 } /* SetBmfInterfacePersistent */
245 /* -------------------------------------------------------------------------
246 * Function : SetCapturePacketsOnOlsrInterfaces
247 * Description: Overrule the default setting, enabling or disabling the
248 * capturing of packets on OLSR-enabled interfaces.
249 * Input : enable - either "yes" or "no"
253 * Return : success (0) or fail (1)
255 * ------------------------------------------------------------------------- */
256 int SetCapturePacketsOnOlsrInterfaces(
258 void* data __attribute__((unused)),
259 set_plugin_parameter_addon addon __attribute__((unused)))
261 if (strcmp(enable, "yes") == 0)
263 CapturePacketsOnOlsrInterfaces = 1;
266 else if (strcmp(enable, "no") == 0)
268 CapturePacketsOnOlsrInterfaces = 0;
272 /* Value not recognized */
274 } /* SetCapturePacketsOnOlsrInterfaces */
276 /* -------------------------------------------------------------------------
277 * Function : SetBmfMechanism
278 * Description: Overrule the default BMF mechanism to either BM_BROADCAST or
279 * BM_UNICAST_PROMISCUOUS.
280 * Input : mechanism - either "Broadcast" or "UnicastPromiscuous"
284 * Return : success (0) or fail (1)
286 * ------------------------------------------------------------------------- */
288 const char* mechanism,
289 void* data __attribute__((unused)),
290 set_plugin_parameter_addon addon __attribute__((unused)))
292 if (strcmp(mechanism, "Broadcast") == 0)
294 BmfMechanism = BM_BROADCAST;
297 else if (strcmp(mechanism, "UnicastPromiscuous") == 0)
299 BmfMechanism = BM_UNICAST_PROMISCUOUS;
303 /* Value not recognized */
305 } /* SetBmfMechanism */
307 /* -------------------------------------------------------------------------
308 * Function : AddDescriptorToInputSet
309 * Description: Add a socket descriptor to the global set of socket file descriptors
310 * Input : skfd - socket file descriptor
313 * Data Used : HighestSkfd, InputSet
314 * Notes : Keeps track of the highest-numbered descriptor
315 * ------------------------------------------------------------------------- */
316 static void AddDescriptorToInputSet(int skfd)
318 /* Keep the highest-numbered descriptor */
319 if (skfd > HighestSkfd)
324 /* Add descriptor to input set */
325 FD_SET(skfd, &InputSet);
326 } /* AddDescriptorToInputSet */
328 /* To save the state of the IP spoof filter for the EtherTunTap interface */
329 static char EthTapSpoofState = '1';
331 /* -------------------------------------------------------------------------
332 * Function : DeactivateSpoofFilter
333 * Description: Deactivates the Linux anti-spoofing filter for the tuntap
337 * Return : fail (0) or success (1)
338 * Data Used : EtherTunTapIfName, EthTapSpoofState
339 * Notes : Saves the current filter state for later restoring
340 * ------------------------------------------------------------------------- */
341 int DeactivateSpoofFilter(void)
344 char procFile[FILENAME_MAX];
346 /* Generate the procfile name */
347 sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName);
349 /* Open procfile for reading */
350 procSpoof = fopen(procFile, "r");
351 if (procSpoof == NULL)
355 "WARNING! Could not open the %s file to check/disable the IP spoof filter!\n"
356 "Are you using the procfile filesystem?\n"
357 "Does your system support IPv4?\n"
358 "I will continue (in 3 sec) - but you should manually ensure that IP spoof\n"
359 "filtering is disabled!\n\n",
366 EthTapSpoofState = (char)fgetc(procSpoof);
369 /* Open procfile for writing */
370 procSpoof = fopen(procFile, "w");
371 if (procSpoof == NULL)
373 fprintf(stderr, "Could not open %s for writing!\n", procFile);
376 "I will continue (in 3 sec) - but you should manually ensure that IP"
377 " spoof filtering is disabled!\n\n");
382 syslog(LOG_INFO, "Writing \"0\" to %s", procFile);
383 fputs("0", procSpoof);
388 } /* DeactivateSpoofFilter */
390 /* -------------------------------------------------------------------------
391 * Function : RestoreSpoofFilter
392 * Description: Restores the Linux anti-spoofing filter setting for the tuntap
397 * Data Used : EtherTunTapIfName, EthTapSpoofState
398 * ------------------------------------------------------------------------- */
399 void RestoreSpoofFilter(void)
402 char procFile[FILENAME_MAX];
404 /* Generate the procfile name */
405 sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName);
407 /* Open procfile for writing */
408 procSpoof = fopen(procFile, "w");
409 if (procSpoof == NULL)
411 fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procFile);
415 syslog(LOG_INFO, "Resetting %s to %c\n", procFile, EthTapSpoofState);
417 fputc(EthTapSpoofState, procSpoof);
420 } /* RestoreSpoofFilter */
422 /* -------------------------------------------------------------------------
423 * Function : FindNeighbors
424 * Description: Find the neighbors on a network interface to forward a BMF
426 * Input : intf - the network interface
427 * source - the source IP address of the BMF packet, or NULL if
428 * unknown or not applicable
429 * forwardedBy - the IP address of the node that forwarded the BMF
430 * packet, or NULL if unknown or not applicable
431 * forwardedTo - the IP address of the node to which the BMF packet
432 * was directed, or NULL if unknown or not applicable
433 * Output : neighbors - list of (up to a number of 'FanOutLimit') neighbors.
434 * bestNeighbor - the best neighbor (in terms of lowest cost or ETX
436 * nPossibleNeighbors - number of found possible neighbors
437 * Data Used : FanOutLimit
438 * ------------------------------------------------------------------------- */
440 struct TBestNeighbors* neighbors,
441 struct link_entry** bestNeighbor,
442 struct TBmfInterface* intf,
443 union olsr_ip_addr* source,
444 union olsr_ip_addr* forwardedBy,
445 union olsr_ip_addr* forwardedTo,
446 int* nPossibleNeighbors)
449 struct ipaddr_str buf;
454 *bestNeighbor = NULL;
455 for (i = 0; i < MAX_UNICAST_NEIGHBORS; i++)
457 neighbors->links[i] = NULL;
459 *nPossibleNeighbors = 0;
461 /* handle the non-LQ case */
463 if (olsr_cnf->lq_level == 0)
465 struct link_entry* walker;
467 OLSR_FOR_ALL_LINK_ENTRIES(walker) {
468 union olsr_ip_addr* neighborMainIp;
470 /* Consider only links from the specified interface */
471 if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
478 "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
481 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
483 neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
485 /* Consider only neighbors with an IP address that differs from the
486 * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
487 if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
491 "%s: ----> not forwarding to %s: is source of pkt\n",
493 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
498 /* Rely on short-circuit boolean evaluation */
499 if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
503 "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
505 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
510 /* Rely on short-circuit boolean evaluation */
511 if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
515 "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
517 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
522 /* Found a candidate neighbor to direct our packet to */
524 /* In the non-LQ case, it is not possible to select neigbors
525 * by quality or cost. So just remember the first found link.
526 * TODO: come on, there must be something better than to simply
527 * select the first one found! */
528 if (*bestNeighbor == NULL)
530 *bestNeighbor = walker;
533 /* Fill the list with up to 'FanOutLimit' neighbors. If there
534 * are more neighbors, broadcast is used instead of unicast. In that
535 * case we do not need the list of neighbors. */
536 if (*nPossibleNeighbors < FanOutLimit)
538 neighbors->links[*nPossibleNeighbors] = walker;
541 *nPossibleNeighbors += 1;
542 } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
545 /* handle the LQ case */
548 #ifdef USING_THALES_LINK_COST_ROUTING
550 struct link_entry* walker;
551 float previousLinkCost = 2 * INFINITE_COST;
552 float bestLinkCost = 2 * INFINITE_COST;
554 if (forwardedBy != NULL)
556 /* Retrieve the cost of the link from 'forwardedBy' to myself */
557 struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
558 if (bestLinkFromForwarder != NULL)
560 previousLinkCost = bestLinkFromForwarder->link_cost;
564 for (walker = get_link_set(); walker != NULL; walker = walker->next)
566 union olsr_ip_addr* neighborMainIp;
567 struct link_entry* bestLinkToNeighbor;
568 struct tc_entry* tcLastHop;
570 /* Consider only links from the specified interface */
571 if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
578 "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
581 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
583 neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
585 /* Consider only neighbors with an IP address that differs from the
586 * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
587 if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
591 "%s: ----> not forwarding to %s: is source of pkt\n",
593 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
598 /* Rely on short-circuit boolean evaluation */
599 if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
603 "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
605 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
610 /* Rely on short-circuit boolean evaluation */
611 if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
615 "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
617 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
622 /* Found a candidate neighbor to direct our packet to */
624 if (walker->link_cost >= INFINITE_COST)
628 "%s: ----> not forwarding to %s: link is timing out\n",
630 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
635 /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
638 "%s: ----> forwarding pkt to %s will cost %5.2f\n",
640 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
643 /* If the candidate neighbor is best reached via another interface, then skip
644 * the candidate neighbor; the candidate neighbor has been / will be selected via that
645 * other interface. */
646 bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
648 if (walker != bestLinkToNeighbor)
650 if (bestLinkToNeighbor == NULL)
654 "%s: ----> not forwarding to %s: no link found\n",
656 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
660 struct interface_olsr * bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
664 "%s: ----> not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %5.2f\n",
666 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
668 bestLinkToNeighbor->link_cost);
674 if (forwardedBy != NULL)
678 "%s: ----> 2-hop path from %s via me to %s will cost %5.2f\n",
680 olsr_ip_to_string(&forwardedByBuf, forwardedBy),
681 olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
682 previousLinkCost + walker->link_cost);
685 /* Check the topology table whether the 'forwardedBy' node is itself a direct
686 * neighbor of the candidate neighbor, at a lower cost than the 2-hop route
687 * via myself. If so, we do not need to forward the BMF packet to the candidate
688 * neighbor, because the 'forwardedBy' node will forward the packet. */
689 if (forwardedBy != NULL)
691 tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
692 if (tcLastHop != NULL)
694 struct tc_edge_entry* tc_edge;
696 tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
698 /* We are not interested in dead-end or dying edges. */
699 if (tc_edge != NULL && (tc_edge->flags & OLSR_TC_EDGE_DOWN) == 0)
701 if (previousLinkCost + walker->link_cost > tc_edge->link_cost)
704 struct ipaddr_str neighbor_iface_buf, forw_buf;
705 olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
709 "%s: ----> not forwarding to %s: I am not an MPR between %s and %s, direct link costs %5.2f\n",
711 neighbor_iface_buf.buf,
712 olsr_ip_to_string(&forw_buf, forwardedBy),
713 neighbor_iface_buf.buf,
722 /* Remember the best neighbor. If all are very bad, remember none. */
723 if (walker->link_cost < bestLinkCost)
725 *bestNeighbor = walker;
726 bestLinkCost = walker->link_cost;
729 /* Fill the list with up to 'FanOutLimit' neighbors. If there
730 * are more neighbors, broadcast is used instead of unicast. In that
731 * case we do not need the list of neighbors. */
732 if (*nPossibleNeighbors < FanOutLimit)
734 neighbors->links[*nPossibleNeighbors] = walker;
737 *nPossibleNeighbors += 1;
741 #else /* USING_THALES_LINK_COST_ROUTING */
743 struct link_entry* walker;
744 olsr_linkcost previousLinkEtx = LINK_COST_BROKEN;
745 olsr_linkcost bestEtx = LINK_COST_BROKEN;
747 if (forwardedBy != NULL)
749 /* Retrieve the cost of the link from 'forwardedBy' to myself */
750 struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
751 if (bestLinkFromForwarder != NULL)
753 previousLinkEtx = bestLinkFromForwarder->linkcost;
757 OLSR_FOR_ALL_LINK_ENTRIES(walker) {
758 union olsr_ip_addr* neighborMainIp;
759 struct link_entry* bestLinkToNeighbor;
760 struct tc_entry* tcLastHop;
763 /* Consider only links from the specified interface */
764 if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
771 "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
774 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
776 neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
778 /* Consider only neighbors with an IP address that differs from the
779 * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
780 if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
784 "%s: ----> not forwarding to %s: is source of pkt\n",
786 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
791 /* Rely on short-circuit boolean evaluation */
792 if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
796 "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
798 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
803 /* Rely on short-circuit boolean evaluation */
804 if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
808 "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
810 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
815 /* Found a candidate neighbor to direct our packet to */
817 /* Calculate the link quality (ETX) of the link to the found neighbor */
818 currEtx = walker->linkcost;
820 if (currEtx >= LINK_COST_BROKEN)
824 "%s: ----> not forwarding to %s: link is timing out\n",
826 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
831 /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
834 "%s: ----> forwarding pkt to %s will cost ETX %5.2f\n",
836 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
839 /* If the candidate neighbor is best reached via another interface, then skip
840 * the candidate neighbor; the candidate neighbor has been / will be selected via that
841 * other interface. */
842 bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
844 if (walker != bestLinkToNeighbor)
846 if (bestLinkToNeighbor == NULL)
850 "%s: ----> not forwarding to %s: no link found\n",
852 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
857 struct interface_olsr * bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
858 struct lqtextbuffer lqbuffer;
862 "%s: ----> not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %s\n",
864 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
865 bestIntf ? bestIntf->int_name : "NULL",
866 get_linkcost_text(bestLinkToNeighbor->linkcost, false, &lqbuffer));
872 if (forwardedBy != NULL)
875 struct ipaddr_str forwardedByBuf, niaBuf;
876 struct lqtextbuffer lqbuffer;
880 "%s: ----> 2-hop path from %s via me to %s will cost ETX %s\n",
882 olsr_ip_to_string(&forwardedByBuf, forwardedBy),
883 olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
884 get_linkcost_text(previousLinkEtx + currEtx, true, &lqbuffer));
887 /* Check the topology table whether the 'forwardedBy' node is itself a direct
888 * neighbor of the candidate neighbor, at a lower cost than the 2-hop route
889 * via myself. If so, we do not need to forward the BMF packet to the candidate
890 * neighbor, because the 'forwardedBy' node will forward the packet. */
891 if (forwardedBy != NULL)
893 tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
894 if (tcLastHop != NULL)
896 struct tc_edge_entry* tc_edge;
898 tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
900 /* We are not interested in dead-end edges. */
902 olsr_linkcost tcEtx = tc_edge->cost;
904 if (previousLinkEtx + currEtx > tcEtx)
907 struct ipaddr_str neighbor_iface_buf, forw_buf;
908 struct lqtextbuffer lqbuffer;
909 olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
913 "%s: ----> not forwarding to %s: I am not an MPR between %s and %s, direct link costs %s\n",
915 neighbor_iface_buf.buf,
916 olsr_ip_to_string(&forw_buf, forwardedBy),
917 neighbor_iface_buf.buf,
918 get_linkcost_text(tcEtx, false, &lqbuffer));
926 /* Remember the best neighbor. If all are very bad, remember none. */
927 if (currEtx < bestEtx)
929 *bestNeighbor = walker;
933 /* Fill the list with up to 'FanOutLimit' neighbors. If there
934 * are more neighbors, broadcast is used instead of unicast. In that
935 * case we do not need the list of neighbors. */
936 if (*nPossibleNeighbors < FanOutLimit)
938 neighbors->links[*nPossibleNeighbors] = walker;
941 *nPossibleNeighbors += 1;
942 } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
944 #endif /* USING_THALES_LINK_COST_ROUTING */
948 /* Display the result of the neighbor search */
949 if (*nPossibleNeighbors == 0)
953 "%s: ----> no suitable neighbor found to forward to on \"%s\"\n",
961 "%s: ----> %d neighbors found on \"%s\"; best neighbor to forward to: %s\n",
965 olsr_ip_to_string(&buf, &(*bestNeighbor)->neighbor_iface_addr));
968 } /* FindNeighbors */
970 /* -------------------------------------------------------------------------
971 * Function : CreateCaptureSocket
972 * Description: Create socket for promiscuously capturing multicast IP traffic
973 * Input : ifname - network interface (e.g. "eth0")
975 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
977 * Notes : The socket is a cooked IP packet socket, bound to the specified
979 * ------------------------------------------------------------------------- */
980 static int CreateCaptureSocket(const char* ifName)
982 int ifIndex = if_nametoindex(ifName);
983 struct packet_mreq mreq;
985 struct sockaddr_ll bindTo;
987 /* Open cooked IP packet socket */
988 int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
991 BmfPError("socket(PF_PACKET) error");
995 /* Set interface to promiscuous mode */
996 memset(&mreq, 0, sizeof(struct packet_mreq));
997 mreq.mr_ifindex = ifIndex;
998 mreq.mr_type = PACKET_MR_PROMISC;
999 if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
1001 BmfPError("setsockopt(PACKET_MR_PROMISC) error");
1006 /* Get hardware (MAC) address */
1007 memset(&req, 0, sizeof(struct ifreq));
1008 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
1009 req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
1010 if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
1012 BmfPError("error retrieving MAC address");
1017 /* Bind the socket to the specified interface */
1018 memset(&bindTo, 0, sizeof(bindTo));
1019 bindTo.sll_family = AF_PACKET;
1020 bindTo.sll_protocol = htons(ETH_P_IP);
1021 bindTo.sll_ifindex = ifIndex;
1022 memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
1023 bindTo.sll_halen = IFHWADDRLEN;
1025 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
1027 BmfPError("bind() error");
1032 /* Set socket to blocking operation */
1033 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1035 BmfPError("fcntl() error");
1040 AddDescriptorToInputSet(skfd);
1043 } /* CreateCaptureSocket */
1045 /* -------------------------------------------------------------------------
1046 * Function : CreateListeningSocket
1047 * Description: Create socket for promiscuously listening to BMF packets.
1048 * Used only when 'BmfMechanism' is BM_UNICAST_PROMISCUOUS
1049 * Input : ifname - network interface (e.g. "eth0")
1051 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
1053 * Notes : The socket is a cooked IP packet socket, bound to the specified
1055 * ------------------------------------------------------------------------- */
1056 static int CreateListeningSocket(const char* ifName)
1058 int ifIndex = if_nametoindex(ifName);
1059 struct packet_mreq mreq;
1061 struct sockaddr_ll bindTo;
1063 /* Open cooked IP packet socket */
1064 int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
1067 BmfPError("socket(PF_PACKET) error");
1071 /* Set interface to promiscuous mode */
1072 memset(&mreq, 0, sizeof(struct packet_mreq));
1073 mreq.mr_ifindex = ifIndex;
1074 mreq.mr_type = PACKET_MR_PROMISC;
1075 if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
1077 BmfPError("setsockopt(PACKET_MR_PROMISC) error");
1082 /* Get hardware (MAC) address */
1083 memset(&req, 0, sizeof(struct ifreq));
1084 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
1085 req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
1086 if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
1088 BmfPError("error retrieving MAC address");
1093 /* Bind the socket to the specified interface */
1094 memset(&bindTo, 0, sizeof(bindTo));
1095 bindTo.sll_family = AF_PACKET;
1096 bindTo.sll_protocol = htons(ETH_P_IP);
1097 bindTo.sll_ifindex = ifIndex;
1098 memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
1099 bindTo.sll_halen = IFHWADDRLEN;
1101 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
1103 BmfPError("bind() error");
1108 /* Set socket to blocking operation */
1109 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1111 BmfPError("fcntl() error");
1116 AddDescriptorToInputSet(skfd);
1119 } /* CreateListeningSocket */
1121 /* -------------------------------------------------------------------------
1122 * Function : CreateEncapsulateSocket
1123 * Description: Create a socket for sending and receiving encapsulated
1125 * Input : ifname - network interface (e.g. "eth0")
1127 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
1129 * Notes : The socket is an UDP (datagram) over IP socket, bound to the
1130 * specified network interface
1131 * ------------------------------------------------------------------------- */
1132 static int CreateEncapsulateSocket(const char* ifName)
1135 struct sockaddr_in bindTo;
1137 /* Open UDP-IP socket */
1138 int skfd = socket(PF_INET, SOCK_DGRAM, 0);
1141 BmfPError("socket(PF_INET) error");
1145 /* Enable sending to broadcast addresses */
1146 if (setsockopt(skfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
1148 BmfPError("setsockopt(SO_BROADCAST) error");
1153 /* Bind to the specific network interfaces indicated by ifName. */
1154 /* When using Kernel 2.6 this must happer prior to the port binding! */
1155 if (setsockopt(skfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, strlen(ifName) + 1) < 0)
1157 BmfPError("setsockopt(SO_BINDTODEVICE) error");
1162 /* Bind to BMF port */
1163 memset(&bindTo, 0, sizeof(bindTo));
1164 bindTo.sin_family = AF_INET;
1165 bindTo.sin_port = htons(BMF_ENCAP_PORT);
1166 bindTo.sin_addr.s_addr = htonl(INADDR_ANY);
1168 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
1170 BmfPError("bind() error");
1175 /* Set socket to blocking operation */
1176 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1178 BmfPError("fcntl() error");
1183 AddDescriptorToInputSet(skfd);
1186 } /* CreateEncapsulateSocket */
1188 /* -------------------------------------------------------------------------
1189 * Function : CreateLocalEtherTunTap
1190 * Description: Creates and brings up an EtherTunTap interface
1193 * Return : the socket file descriptor (>= 0), or -1 in case of failure
1194 * Data Used : EtherTunTapIfName - name used for the tuntap interface (e.g.
1198 * EtherTunTapIpBroadcast
1200 * Note : Order dependency: call this function only if BmfInterfaces
1201 * is filled with a list of network interfaces.
1202 * ------------------------------------------------------------------------- */
1203 static int CreateLocalEtherTunTap(void)
1205 static const char * deviceName = OS_TUNNEL_PATH;
1211 etfd = open(deviceName, O_RDWR | O_NONBLOCK);
1214 BmfPError("error opening %s", deviceName);
1218 memset(&ifreq, 0, sizeof(ifreq));
1219 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1220 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1222 /* Specify the IFF_TUN flag for IP packets.
1223 * Specify IFF_NO_PI for not receiving extra meta packet information. */
1224 ifreq.ifr_flags = IFF_TUN;
1225 ifreq.ifr_flags |= IFF_NO_PI;
1227 if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0)
1229 BmfPError("ioctl(TUNSETIFF) error on %s", deviceName);
1234 memset(&ifreq, 0, sizeof(ifreq));
1235 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1236 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1237 ifreq.ifr_addr.sa_family = AF_INET;
1239 ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1242 BmfPError("socket(PF_INET) error on %s", deviceName);
1247 /* Give the EtherTunTap interface an IP address.
1248 * The default IP address is the address of the first OLSR interface;
1249 * the default netmask is 255.255.255.255 . Having an all-ones netmask prevents
1250 * automatic entry of the BMF network interface in the routing table. */
1251 if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
1253 struct TBmfInterface* nextBmfIf = BmfInterfaces;
1254 while (nextBmfIf != NULL)
1256 struct TBmfInterface* bmfIf = nextBmfIf;
1257 nextBmfIf = bmfIf->next;
1259 if (bmfIf->olsrIntf != NULL)
1261 EtherTunTapIp = ntohl(bmfIf->intAddr.v4.s_addr);
1262 EtherTunTapIpBroadcast = EtherTunTapIp;
1267 if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
1269 /* No IP address configured for BMF network interface, and no OLSR interface found to
1270 * copy IP address from. Fall back to default: 10.255.255.253 . */
1271 EtherTunTapIp = ETHERTUNTAPDEFAULTIP;
1274 ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_addr))->sin_addr.s_addr = htonl(EtherTunTapIp);
1275 ioctlres = ioctl(ioctlSkfd, SIOCSIFADDR, &ifreq);
1279 ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_netmask))->sin_addr.s_addr = htonl(EtherTunTapIpMask);
1280 ioctlres = ioctl(ioctlSkfd, SIOCSIFNETMASK, &ifreq);
1283 /* Set broadcast IP */
1284 ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_broadaddr))->sin_addr.s_addr = htonl(EtherTunTapIpBroadcast);
1285 ioctlres = ioctl(ioctlSkfd, SIOCSIFBRDADDR, &ifreq);
1288 /* Bring EtherTunTap interface up (if not already) */
1289 ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
1292 ifreq.ifr_flags |= (IFF_UP | IFF_RUNNING | IFF_BROADCAST);
1293 ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
1301 /* Any of the above ioctl() calls failed */
1302 BmfPError("error bringing up EtherTunTap interface \"%s\"", EtherTunTapIfName);
1307 } /* if (ioctlres < 0) */
1309 /* Set the multicast flag on the interface */
1310 memset(&ifreq, 0, sizeof(ifreq));
1311 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1312 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1314 ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
1317 ifreq.ifr_flags |= IFF_MULTICAST;
1318 ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
1322 /* Any of the two above ioctl() calls failed */
1323 BmfPError("error setting multicast flag on EtherTunTap interface \"%s\"", EtherTunTapIfName);
1325 /* Continue anyway */
1328 /* Use ioctl to make the tuntap persistent. Otherwise it will disappear
1329 * when this program exits. That is not desirable, since a multicast
1330 * daemon (e.g. mrouted) may be using the tuntap interface. */
1331 if (ioctl(etfd, TUNSETPERSIST, EtherTunTapPersistent ? (void *)&ifreq : NULL) < 0)
1333 BmfPError("error making EtherTunTap interface \"%s\" %spersistent", EtherTunTapIfName, !EtherTunTapPersistent ? "non-" : "");
1335 /* Continue anyway */
1338 OLSR_PRINTF(8, "%s: opened 1 socket on \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
1340 AddDescriptorToInputSet(etfd);
1342 /* If the user configured a specific IP address for the BMF network interface,
1343 * help the user and advertise the IP address of the BMF network interface
1344 * on the OLSR network via HNA */
1345 if (TunTapIpOverruled != 0)
1347 union olsr_ip_addr temp_net;
1349 temp_net.v4.s_addr = htonl(EtherTunTapIp);
1350 ip_prefix_list_add(&olsr_cnf->hna_entries, &temp_net, 32);
1356 } /* CreateLocalEtherTunTap */
1358 /* -------------------------------------------------------------------------
1359 * Function : CreateInterface
1360 * Description: Create a new TBmfInterface object and adds it to the global
1361 * BmfInterfaces list
1362 * Input : ifName - name of the network interface (e.g. "eth0")
1363 * : olsrIntf - OLSR interface object of the network interface, or
1364 * NULL if the network interface is not OLSR-enabled
1366 * Return : the number of opened sockets
1367 * Data Used : BmfInterfaces, LastBmfInterface
1368 * ------------------------------------------------------------------------- */
1369 static int CreateInterface(
1371 struct interface_olsr * olsrIntf)
1373 int capturingSkfd = -1;
1374 int encapsulatingSkfd = -1;
1375 int listeningSkfd = -1;
1379 struct TBmfInterface* newIf = malloc(sizeof(struct TBmfInterface));
1381 assert(ifName != NULL);
1388 if (olsrIntf != NULL)
1390 /* On OLSR-enabled interfaces, create socket for encapsulating and forwarding
1391 * multicast packets */
1392 encapsulatingSkfd = CreateEncapsulateSocket(ifName);
1393 if (encapsulatingSkfd < 0)
1401 /* Create socket for capturing and sending of multicast packets on
1402 * non-OLSR interfaces, and on OLSR-interfaces if configured. */
1403 if ((olsrIntf == NULL) || (CapturePacketsOnOlsrInterfaces != 0))
1405 capturingSkfd = CreateCaptureSocket(ifName);
1406 if (capturingSkfd < 0)
1408 if (encapsulatingSkfd >= 0) {
1409 close(encapsulatingSkfd);
1418 /* Create promiscuous mode listening interface if BMF uses IP unicast
1419 * as underlying forwarding mechanism */
1420 if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
1422 listeningSkfd = CreateListeningSocket(ifName);
1423 if (listeningSkfd < 0)
1425 if (encapsulatingSkfd >= 0) {
1426 close(encapsulatingSkfd); /* no problem if 'encapsulatingSkfd' is -1 */
1435 /* For ioctl operations on the network interface, use either capturingSkfd
1436 * or encapsulatingSkfd, whichever is available */
1437 ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd;
1439 /* Retrieve the MAC address of the interface. */
1440 memset(&ifr, 0, sizeof(struct ifreq));
1441 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1442 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1443 if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0)
1445 BmfPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
1446 if (capturingSkfd >= 0) {
1447 close(capturingSkfd);
1449 if (encapsulatingSkfd >= 0) {
1450 close(encapsulatingSkfd);
1456 /* add listeners to sockets */
1457 if (capturingSkfd != -1) {
1458 add_olsr_socket(capturingSkfd, NULL, BMF_handle_captureFd, newIf, SP_IMM_READ);
1460 if (encapsulatingSkfd != -1) {
1461 add_olsr_socket(encapsulatingSkfd, NULL, BMF_handle_encapsulatingFd, newIf, SP_IMM_READ);
1463 if (listeningSkfd != -1) {
1464 add_olsr_socket(listeningSkfd, NULL, BMF_handle_listeningFd, newIf, SP_IMM_READ);
1466 /* Copy data into TBmfInterface object */
1467 newIf->capturingSkfd = capturingSkfd;
1468 newIf->encapsulatingSkfd = encapsulatingSkfd;
1469 newIf->listeningSkfd = listeningSkfd;
1470 memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1471 memcpy(newIf->ifName, ifName, IFNAMSIZ);
1472 newIf->olsrIntf = olsrIntf;
1473 if (olsrIntf != NULL)
1475 /* For an OLSR-interface, copy the interface address and broadcast
1476 * address from the OLSR interface object. Downcast to correct sockaddr
1478 newIf->intAddr.v4 = ((struct sockaddr_in *)&olsrIntf->int_addr)->sin_addr;
1479 newIf->broadAddr.v4 = ((struct sockaddr_in *)&olsrIntf->int_broadaddr)->sin_addr;
1483 /* For a non-OLSR interface, retrieve the IP address ourselves */
1484 memset(&ifr, 0, sizeof(struct ifreq));
1485 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1486 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1487 if (ioctl(ioctlSkfd, SIOCGIFADDR, &ifr) < 0)
1489 BmfPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
1491 newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
1495 /* Downcast to correct sockaddr subtype */
1496 newIf->intAddr.v4 = ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&ifr.ifr_addr))->sin_addr;
1499 /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
1500 memset(&ifr, 0, sizeof(struct ifreq));
1501 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1502 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1503 if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0)
1505 BmfPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
1507 newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
1511 /* Downcast to correct sockaddr subtype */
1512 newIf->broadAddr.v4 = ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr))->sin_addr;
1516 /* Reset counters */
1517 newIf->nBmfPacketsRx = 0;
1518 newIf->nBmfPacketsRxDup = 0;
1519 newIf->nBmfPacketsTx = 0;
1521 /* Add new TBmfInterface object to global list. OLSR interfaces are
1522 * added at the front of the list, non-OLSR interfaces at the back. */
1523 if (BmfInterfaces == NULL)
1525 /* First TBmfInterface object in list */
1527 BmfInterfaces = newIf;
1528 LastBmfInterface = newIf;
1530 else if (olsrIntf != NULL)
1532 /* Add new TBmfInterface object at front of list */
1533 newIf->next = BmfInterfaces;
1534 BmfInterfaces = newIf;
1538 /* Add new TBmfInterface object at back of list */
1540 LastBmfInterface->next= newIf;
1541 LastBmfInterface = newIf;
1546 "%s: opened %d socket%s on %s interface \"%s\"\n",
1549 nOpened == 1 ? "" : "s",
1550 olsrIntf != NULL ? "OLSR" : "non-OLSR",
1554 } /* CreateInterface */
1556 /* -------------------------------------------------------------------------
1557 * Function : CreateBmfNetworkInterfaces
1558 * Description: Create a list of TBmfInterface objects, one for each network
1559 * interface on which BMF runs
1560 * Input : skipThisIntf - network interface to skip, if seen
1562 * Return : fail (-1) or success (0)
1564 * ------------------------------------------------------------------------- */
1565 int CreateBmfNetworkInterfaces(struct interface_olsr * skipThisIntf)
1572 int nOpenedSockets = 0;
1574 /* Clear input descriptor set */
1577 skfd = socket(PF_INET, SOCK_DGRAM, 0);
1580 BmfPError("no inet socket available to retrieve interface list");
1584 /* Retrieve the network interface configuration list */
1588 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
1589 ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
1591 if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
1593 BmfPError("ioctl(SIOCGIFCONF) error");
1599 if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs)
1601 /* Assume it overflowed; double the space and try again */
1603 assert(numreqs < 1024);
1604 continue; /* for (;;) */
1606 break; /* for (;;) */
1611 /* For each item in the interface configuration list... */
1613 for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++)
1615 struct interface_olsr * olsrIntf;
1616 union olsr_ip_addr ipAddr;
1618 /* Skip the BMF network interface itself */
1619 if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
1621 continue; /* for (n = ...) */
1624 /* ...find the OLSR interface structure, if any */
1625 ipAddr.v4 = ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifr->ifr_addr))->sin_addr;
1626 olsrIntf = if_ifwithaddr(&ipAddr);
1628 if (skipThisIntf != NULL && olsrIntf == skipThisIntf)
1630 continue; /* for (n = ...) */
1633 if (olsrIntf == NULL && ! IsNonOlsrBmfIf(ifr->ifr_name))
1635 /* Interface is neither OLSR interface, nor specified as non-OLSR BMF
1636 * interface in the BMF plugin parameter list */
1637 continue; /* for (n = ...) */
1640 nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
1642 } /* for (n = ...) */
1646 /* Create the BMF network interface */
1647 EtherTunTapFd = CreateLocalEtherTunTap();
1648 if (EtherTunTapFd >= 0)
1650 add_olsr_socket(EtherTunTapFd, NULL, BMF_handle_tuntapFd, NULL, SP_IMM_READ);
1654 if (BmfInterfaces == NULL)
1656 olsr_printf(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
1660 olsr_printf(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
1663 } /* CreateBmfNetworkInterfaces */
1665 /* -------------------------------------------------------------------------
1666 * Function : CloseBmfNetworkInterfaces
1667 * Description: Closes every socket on each network interface used by BMF
1671 * Data Used : BmfInterfaces, LastBmfInterface
1673 * - the local EtherTunTap interface (e.g. "tun0" or "tap0")
1674 * - for each BMF-enabled interface, the socket used for
1675 * capturing multicast packets
1676 * - for each OLSR-enabled interface, the socket used for
1677 * encapsulating packets
1678 * Also restores the network state to the situation before BMF
1680 * ------------------------------------------------------------------------- */
1681 void CloseBmfNetworkInterfaces(void)
1684 u_int32_t totalOlsrBmfPacketsRx = 0;
1685 u_int32_t totalOlsrBmfPacketsRxDup = 0;
1686 u_int32_t totalOlsrBmfPacketsTx = 0;
1687 u_int32_t totalNonOlsrBmfPacketsRx = 0;
1688 u_int32_t totalNonOlsrBmfPacketsRxDup = 0;
1689 u_int32_t totalNonOlsrBmfPacketsTx = 0;
1691 /* Close all opened sockets */
1692 struct TBmfInterface* nextBmfIf = BmfInterfaces;
1693 while (nextBmfIf != NULL)
1695 struct TBmfInterface* bmfIf = nextBmfIf;
1696 nextBmfIf = bmfIf->next;
1698 if (bmfIf->capturingSkfd >= 0)
1700 close(bmfIf->capturingSkfd);
1701 remove_olsr_socket(bmfIf->capturingSkfd, NULL, BMF_handle_captureFd);
1704 if (bmfIf->encapsulatingSkfd >= 0)
1706 close(bmfIf->encapsulatingSkfd);
1707 remove_olsr_socket(bmfIf->encapsulatingSkfd, NULL, BMF_handle_encapsulatingFd);
1710 if (bmfIf->listeningSkfd >= 0)
1712 close(bmfIf->listeningSkfd);
1713 remove_olsr_socket(bmfIf->listeningSkfd, NULL, BMF_handle_listeningFd);
1719 "%s: %s interface \"%s\": RX pkts %d (%d dups); TX pkts %d\n",
1721 bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
1723 bmfIf->nBmfPacketsRx,
1724 bmfIf->nBmfPacketsRxDup,
1725 bmfIf->nBmfPacketsTx);
1729 "%s: closed %s interface \"%s\"\n",
1731 bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
1735 if (bmfIf->olsrIntf != NULL)
1737 totalOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
1738 totalOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
1739 totalOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
1743 totalNonOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
1744 totalNonOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
1745 totalNonOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
1751 if (EtherTunTapFd >= 0)
1753 close(EtherTunTapFd);
1754 remove_olsr_socket(EtherTunTapFd, NULL, BMF_handle_tuntapFd);
1757 OLSR_PRINTF(7, "%s: closed \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
1760 BmfInterfaces = NULL;
1761 LastBmfInterface = NULL;
1763 /* Re-initialize the IP address for the BMF network interface. Thanks to
1764 * Daniele Lacamera for finding and solving this bug. */
1765 EtherTunTapIp = ETHERTUNTAPIPNOTSET;
1767 olsr_printf(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
1771 "%s: total all OLSR interfaces : RX pkts %d (%d dups); TX pkts %d\n",
1773 totalOlsrBmfPacketsRx,
1774 totalOlsrBmfPacketsRxDup,
1775 totalOlsrBmfPacketsTx);
1778 "%s: total all non-OLSR interfaces: RX pkts %d (%d dups); TX pkts %d\n",
1780 totalNonOlsrBmfPacketsRx,
1781 totalNonOlsrBmfPacketsRxDup,
1782 totalNonOlsrBmfPacketsTx);
1783 } /* CloseBmfNetworkInterfaces */
1785 #define MAX_NON_OLSR_IFS 32
1786 static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
1787 static int nNonOlsrIfs = 0;
1789 /* -------------------------------------------------------------------------
1790 * Function : AddNonOlsrBmfIf
1791 * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
1792 * network interfaces
1793 * Input : ifName - network interface (e.g. "eth0")
1797 * Return : success (0) or fail (1)
1798 * Data Used : NonOlsrIfNames
1799 * ------------------------------------------------------------------------- */
1800 int AddNonOlsrBmfIf(
1802 void* data __attribute__((unused)),
1803 set_plugin_parameter_addon addon __attribute__((unused)))
1805 assert(ifName != NULL);
1807 if (nNonOlsrIfs >= MAX_NON_OLSR_IFS)
1811 "%s: too many non-OLSR interfaces specified, maximum is %d\n",
1817 strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
1818 NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1821 } /* AddNonOlsrBmfIf */
1823 /* -------------------------------------------------------------------------
1824 * Function : IsNonOlsrBmfIf
1825 * Description: Checks if a network interface is OLSR-enabled
1826 * Input : ifName - network interface (e.g. "eth0")
1828 * Return : true (1) or false (0)
1829 * Data Used : NonOlsrIfNames
1830 * ------------------------------------------------------------------------- */
1831 int IsNonOlsrBmfIf(const char* ifName)
1835 assert(ifName != NULL);
1837 for (i = 0; i < nNonOlsrIfs; i++)
1839 if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0) return 1;
1842 } /* IsNonOlsrBmfIf */
1844 /* -------------------------------------------------------------------------
1845 * Function : CheckAndUpdateLocalBroadcast
1846 * Description: For an IP packet, check if the destination address is not a
1847 * multicast address. If it is not, the packet is assumed to be
1848 * a local broadcast packet. In that case, set the destination
1849 * address of the IP packet to the passed broadcast address.
1850 * Input : ipPacket - the IP packet
1851 * broadAddr - the broadcast address to fill in
1855 * Notes : See also RFC1141
1856 * ------------------------------------------------------------------------- */
1857 void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* broadAddr)
1860 union olsr_ip_addr destIp;
1862 assert(ipPacket != NULL && broadAddr != NULL);
1864 iph = (struct iphdr*) ARM_NOWARN_ALIGN(ipPacket);
1865 destIp.v4.s_addr = iph->daddr;
1866 if (! IsMulticast(&destIp))
1868 u_int32_t origDaddr, newDaddr;
1871 origDaddr = ntohl(iph->daddr);
1873 iph->daddr = broadAddr->v4.s_addr;
1874 newDaddr = ntohl(iph->daddr);
1876 /* Re-calculate IP header checksum for new destination */
1877 check = ntohs(iph->check);
1879 check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
1880 check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
1883 check = check + (check >> 16);
1885 iph->check = htons(check);
1887 if (iph->protocol == SOL_UDP)
1889 /* Re-calculate UDP/IP checksum for new destination */
1891 int ipHeaderLen = GetIpHeaderLength(ipPacket);
1892 struct udphdr* udph = (struct udphdr*) ARM_NOWARN_ALIGN((ipPacket + ipHeaderLen));
1894 /* RFC 1624, Eq. 3: HC' = ~(~HC - m + m') */
1896 check = ntohs(udph->check);
1898 check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
1899 check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
1902 check = check + (check >> 16);
1904 udph->check = htons(check);
1907 } /* CheckAndUpdateLocalBroadcast */
1909 /* -------------------------------------------------------------------------
1910 * Function : AddMulticastRoute
1911 * Description: Insert a route to all multicast addresses in the kernel
1912 * routing table. The route will be via the BMF network interface.
1917 * ------------------------------------------------------------------------- */
1918 void AddMulticastRoute(void)
1920 struct rtentry kernel_route;
1921 int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1924 BmfPError("socket(PF_INET) error");
1928 memset(&kernel_route, 0, sizeof(struct rtentry));
1930 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sa_family = AF_INET;
1931 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_gateway))->sa_family = AF_INET;
1932 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sa_family = AF_INET;
1935 ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sin_addr.s_addr = htonl(0xE0000000);
1936 ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sin_addr.s_addr = htonl(0xF0000000);
1938 kernel_route.rt_metric = 0;
1939 kernel_route.rt_flags = RTF_UP;
1941 kernel_route.rt_dev = EtherTunTapIfName;
1943 if (ioctl(ioctlSkfd, SIOCADDRT, &kernel_route) < 0)
1945 BmfPError("error setting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
1947 /* Continue anyway */
1950 } /* AddMulticastRoute */
1952 /* -------------------------------------------------------------------------
1953 * Function : DeleteMulticastRoute
1954 * Description: Delete the route to all multicast addresses from the kernel
1960 * ------------------------------------------------------------------------- */
1961 void DeleteMulticastRoute(void)
1963 if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
1965 struct rtentry kernel_route;
1966 int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1969 BmfPError("socket(PF_INET) error");
1973 memset(&kernel_route, 0, sizeof(struct rtentry));
1975 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sa_family = AF_INET;
1976 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_gateway))->sa_family = AF_INET;
1977 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sa_family = AF_INET;
1980 ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sin_addr.s_addr = htonl(0xE0000000);
1981 ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sin_addr.s_addr = htonl(0xF0000000);
1983 kernel_route.rt_metric = 0;
1984 kernel_route.rt_flags = RTF_UP;
1986 kernel_route.rt_dev = EtherTunTapIfName;
1988 if (ioctl(ioctlSkfd, SIOCDELRT, &kernel_route) < 0)
1990 BmfPError("error deleting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
1992 /* Continue anyway */
1996 } /* DeleteMulticastRoute */