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 <netinet/udp.h> /* struct udphdr */
54 #include <linux/if_ether.h> /* ETH_P_IP */
55 #include <linux/if_packet.h> /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */
56 #include <linux/if_tun.h> /* IFF_TAP */
57 #include <netinet/ip.h> /* struct ip */
58 #include <netinet/udp.h> /* SOL_UDP */
61 #include "olsr.h" /* olsr_printf() */
63 #include "defs.h" /* olsr_cnf */
64 #include "link_set.h" /* get_link_set() */
65 #include "tc_set.h" /* olsr_lookup_tc_entry(), olsr_lookup_tc_edge() */
66 #include "net_olsr.h" /* ipequal */
67 #include "lq_plugin.h"
68 #include "kernel_tunnel.h"
71 #include "Packet.h" /* IFHWADDRLEN */
72 #include "Bmf.h" /* PLUGIN_NAME, MainAddressOf() */
73 #include "Address.h" /* IsMulticast() */
75 /* List of network interface objects used by BMF plugin */
76 struct TBmfInterface* BmfInterfaces = NULL;
77 struct TBmfInterface* LastBmfInterface = NULL;
79 /* Highest-numbered open socket file descriptor. To be used as first
80 * parameter in calls to select(...). */
83 /* Set of socket file descriptors */
86 /* File descriptor of EtherTunTap interface */
87 int EtherTunTapFd = -1;
89 /* Network interface name of EtherTunTap interface. May be overruled by
90 * setting the plugin parameter "BmfInterface". */
91 char EtherTunTapIfName[IFNAMSIZ] = "bmf0";
93 /* The underlying mechanism to forward multicast packets. Either:
94 * - BM_BROADCAST: BMF uses the IP local broadcast as destination address
95 * - BM_UNICAST_PROMISCUOUS: BMF uses the IP address of the best neighbor as
96 * destination address. The other neighbors listen promiscuously. */
97 enum TBmfMechanism BmfMechanism = BM_BROADCAST;
99 #define ETHERTUNTAPIPNOTSET 0
101 /* The IP address of the BMF network interface in host byte order.
102 * May be overruled by setting the plugin parameter "BmfInterfaceIp". */
103 u_int32_t EtherTunTapIp = ETHERTUNTAPIPNOTSET;
105 /* 255.255.255.255 in host byte order. May be overruled by
106 * setting the plugin parameter "BmfInterfaceIp". */
107 u_int32_t EtherTunTapIpMask = 0xFFFFFFFF;
109 /* The IP broadcast address of the BMF network interface in host byte order.
110 * May be overruled by setting the plugin parameter "BmfinterfaceIp". */
111 u_int32_t EtherTunTapIpBroadcast = ETHERTUNTAPIPNOTSET;
113 /* Whether or not the BMF network interface must be marked as persistent */
114 int EtherTunTapPersistent = 1;
116 /* Whether or not the configuration has overruled the default IP
117 * configuration of the EtherTunTap interface */
118 int TunTapIpOverruled = 0;
120 /* Whether or not to capture packets on the OLSR-enabled
121 * interfaces (in promiscuous mode). May be overruled by setting the plugin
122 * parameter "CapturePacketsOnOlsrInterfaces" to "yes". */
123 int CapturePacketsOnOlsrInterfaces = 0;
125 /* -------------------------------------------------------------------------
126 * Function : SetBmfInterfaceName
127 * Description: Overrule the default network interface name ("bmf0") of the
128 * EtherTunTap interface
129 * Input : ifname - network interface name (e.g. "mybmf0")
133 * Return : success (0) or fail (1)
134 * Data Used : EtherTunTapIfName
135 * ------------------------------------------------------------------------- */
136 int SetBmfInterfaceName(
138 void* data __attribute__((unused)),
139 set_plugin_parameter_addon addon __attribute__((unused)))
141 strncpy(EtherTunTapIfName, ifname, IFNAMSIZ - 1);
142 EtherTunTapIfName[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
144 } /* SetBmfInterfaceName */
146 /* -------------------------------------------------------------------------
147 * Function : SetBmfInterfaceIp
148 * Description: Overrule the default IP address and prefix length
149 * ("10.255.255.253/30") of the EtherTunTap interface
150 * Input : ip - IP address string, followed by '/' and prefix length
154 * Return : success (0) or fail (1)
155 * Data Used : EtherTunTapIp, EtherTunTapIpMask, EtherTunTapIpBroadcast,
157 * ------------------------------------------------------------------------- */
158 int SetBmfInterfaceIp(
160 void* data __attribute__((unused)),
161 set_plugin_parameter_addon addon __attribute__((unused)))
163 #define IPV4_MAX_ADDRLEN 16
164 #define IPV4_MAX_PREFIXLEN 32
166 char ipAddr[IPV4_MAX_ADDRLEN];
167 struct in_addr sinaddr;
171 /* Inspired by function str2prefix_ipv4 as found in Quagga source
172 * file lib/prefix.c */
174 /* Find slash inside string. */
175 slashAt = strchr(ip, '/');
177 /* String doesn't contain slash. */
178 if (slashAt == NULL || slashAt - ip >= IPV4_MAX_ADDRLEN)
180 /* No prefix length specified, or IP address too long */
184 strncpy(ipAddr, ip, slashAt - ip);
185 *(ipAddr + (slashAt - ip)) = '\0';
186 if (inet_aton(ipAddr, &sinaddr) == 0)
188 /* Invalid address passed */
192 EtherTunTapIp = ntohl(sinaddr.s_addr);
194 /* Get prefix length. */
195 prefixLen = atoi(++slashAt);
196 if (prefixLen <= 0 || prefixLen > IPV4_MAX_PREFIXLEN)
201 /* Compose IP subnet mask in host byte order */
202 EtherTunTapIpMask = 0;
203 for (i = 0; i < prefixLen; i++)
205 EtherTunTapIpMask |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
208 /* Compose IP broadcast address in host byte order */
209 EtherTunTapIpBroadcast = EtherTunTapIp;
210 for (i = prefixLen; i < IPV4_MAX_PREFIXLEN; i++)
212 EtherTunTapIpBroadcast |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
215 TunTapIpOverruled = 1;
218 } /* SetBmfInterfaceIp */
220 /* -------------------------------------------------------------------------
221 * Function : SetBmfInterfacePersistent
222 * Description: Determine if the EtherTunTap interface must be marked
224 * Input : value - yes/true/1 or no/false/0
228 * Return : success (0) or fail (1)
229 * Data Used : EtherTunTapPersistent
230 * ------------------------------------------------------------------------- */
231 int SetBmfInterfacePersistent(
233 void* data __attribute__((unused)),
234 set_plugin_parameter_addon addon __attribute__((unused)))
236 if (strcasecmp(value, "yes") == 0 || strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) {
237 EtherTunTapPersistent = 1;
238 } else if (strcasecmp(value, "no") == 0 || strcasecmp(value, "false") == 0 || strcasecmp(value, "0") == 0) {
239 EtherTunTapPersistent = 0;
244 } /* SetBmfInterfacePersistent */
246 /* -------------------------------------------------------------------------
247 * Function : SetCapturePacketsOnOlsrInterfaces
248 * Description: Overrule the default setting, enabling or disabling the
249 * capturing of packets on OLSR-enabled interfaces.
250 * Input : enable - either "yes" or "no"
254 * Return : success (0) or fail (1)
256 * ------------------------------------------------------------------------- */
257 int SetCapturePacketsOnOlsrInterfaces(
259 void* data __attribute__((unused)),
260 set_plugin_parameter_addon addon __attribute__((unused)))
262 if (strcmp(enable, "yes") == 0)
264 CapturePacketsOnOlsrInterfaces = 1;
267 else if (strcmp(enable, "no") == 0)
269 CapturePacketsOnOlsrInterfaces = 0;
273 /* Value not recognized */
275 } /* SetCapturePacketsOnOlsrInterfaces */
277 /* -------------------------------------------------------------------------
278 * Function : SetBmfMechanism
279 * Description: Overrule the default BMF mechanism to either BM_BROADCAST or
280 * BM_UNICAST_PROMISCUOUS.
281 * Input : mechanism - either "Broadcast" or "UnicastPromiscuous"
285 * Return : success (0) or fail (1)
287 * ------------------------------------------------------------------------- */
289 const char* mechanism,
290 void* data __attribute__((unused)),
291 set_plugin_parameter_addon addon __attribute__((unused)))
293 if (strcmp(mechanism, "Broadcast") == 0)
295 BmfMechanism = BM_BROADCAST;
298 else if (strcmp(mechanism, "UnicastPromiscuous") == 0)
300 BmfMechanism = BM_UNICAST_PROMISCUOUS;
304 /* Value not recognized */
306 } /* SetBmfMechanism */
308 /* -------------------------------------------------------------------------
309 * Function : AddDescriptorToInputSet
310 * Description: Add a socket descriptor to the global set of socket file descriptors
311 * Input : skfd - socket file descriptor
314 * Data Used : HighestSkfd, InputSet
315 * Notes : Keeps track of the highest-numbered descriptor
316 * ------------------------------------------------------------------------- */
317 static void AddDescriptorToInputSet(int skfd)
319 /* Keep the highest-numbered descriptor */
320 if (skfd > HighestSkfd)
325 /* Add descriptor to input set */
326 FD_SET(skfd, &InputSet);
327 } /* AddDescriptorToInputSet */
329 /* To save the state of the IP spoof filter for the EtherTunTap interface */
330 static char EthTapSpoofState = '1';
332 /* -------------------------------------------------------------------------
333 * Function : DeactivateSpoofFilter
334 * Description: Deactivates the Linux anti-spoofing filter for the tuntap
338 * Return : fail (0) or success (1)
339 * Data Used : EtherTunTapIfName, EthTapSpoofState
340 * Notes : Saves the current filter state for later restoring
341 * ------------------------------------------------------------------------- */
342 int DeactivateSpoofFilter(void)
345 char procFile[FILENAME_MAX];
347 /* Generate the procfile name */
348 sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName);
350 /* Open procfile for reading */
351 procSpoof = fopen(procFile, "r");
352 if (procSpoof == NULL)
356 "WARNING! Could not open the %s file to check/disable the IP spoof filter!\n"
357 "Are you using the procfile filesystem?\n"
358 "Does your system support IPv4?\n"
359 "I will continue (in 3 sec) - but you should manually ensure that IP spoof\n"
360 "filtering is disabled!\n\n",
367 EthTapSpoofState = (char)fgetc(procSpoof);
370 /* Open procfile for writing */
371 procSpoof = fopen(procFile, "w");
372 if (procSpoof == NULL)
374 fprintf(stderr, "Could not open %s for writing!\n", procFile);
377 "I will continue (in 3 sec) - but you should manually ensure that IP"
378 " spoof filtering is disabled!\n\n");
383 syslog(LOG_INFO, "Writing \"0\" to %s", procFile);
384 fputs("0", procSpoof);
389 } /* DeactivateSpoofFilter */
391 /* -------------------------------------------------------------------------
392 * Function : RestoreSpoofFilter
393 * Description: Restores the Linux anti-spoofing filter setting for the tuntap
398 * Data Used : EtherTunTapIfName, EthTapSpoofState
399 * ------------------------------------------------------------------------- */
400 void RestoreSpoofFilter(void)
403 char procFile[FILENAME_MAX];
405 /* Generate the procfile name */
406 sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName);
408 /* Open procfile for writing */
409 procSpoof = fopen(procFile, "w");
410 if (procSpoof == NULL)
412 fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procFile);
416 syslog(LOG_INFO, "Resetting %s to %c\n", procFile, EthTapSpoofState);
418 fputc(EthTapSpoofState, procSpoof);
421 } /* RestoreSpoofFilter */
423 /* -------------------------------------------------------------------------
424 * Function : FindNeighbors
425 * Description: Find the neighbors on a network interface to forward a BMF
427 * Input : intf - the network interface
428 * source - the source IP address of the BMF packet, or NULL if
429 * unknown or not applicable
430 * forwardedBy - the IP address of the node that forwarded the BMF
431 * packet, or NULL if unknown or not applicable
432 * forwardedTo - the IP address of the node to which the BMF packet
433 * was directed, or NULL if unknown or not applicable
434 * Output : neighbors - list of (up to a number of 'FanOutLimit') neighbors.
435 * bestNeighbor - the best neighbor (in terms of lowest cost or ETX
437 * nPossibleNeighbors - number of found possible neighbors
438 * Data Used : FanOutLimit
439 * ------------------------------------------------------------------------- */
441 struct TBestNeighbors* neighbors,
442 struct link_entry** bestNeighbor,
443 struct TBmfInterface* intf,
444 union olsr_ip_addr* source,
445 union olsr_ip_addr* forwardedBy,
446 union olsr_ip_addr* forwardedTo,
447 int* nPossibleNeighbors)
450 struct ipaddr_str buf;
455 *bestNeighbor = NULL;
456 for (i = 0; i < MAX_UNICAST_NEIGHBORS; i++)
458 neighbors->links[i] = NULL;
460 *nPossibleNeighbors = 0;
462 /* handle the non-LQ case */
464 if (olsr_cnf->lq_level == 0)
466 struct link_entry* walker;
468 OLSR_FOR_ALL_LINK_ENTRIES(walker) {
469 union olsr_ip_addr* neighborMainIp;
471 /* Consider only links from the specified interface */
472 if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
479 "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
482 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
484 neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
486 /* Consider only neighbors with an IP address that differs from the
487 * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
488 if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
492 "%s: ----> not forwarding to %s: is source of pkt\n",
494 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
499 /* Rely on short-circuit boolean evaluation */
500 if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
504 "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
506 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
511 /* Rely on short-circuit boolean evaluation */
512 if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
516 "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
518 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
523 /* Found a candidate neighbor to direct our packet to */
525 /* In the non-LQ case, it is not possible to select neigbors
526 * by quality or cost. So just remember the first found link.
527 * TODO: come on, there must be something better than to simply
528 * select the first one found! */
529 if (*bestNeighbor == NULL)
531 *bestNeighbor = walker;
534 /* Fill the list with up to 'FanOutLimit' neighbors. If there
535 * are more neighbors, broadcast is used instead of unicast. In that
536 * case we do not need the list of neighbors. */
537 if (*nPossibleNeighbors < FanOutLimit)
539 neighbors->links[*nPossibleNeighbors] = walker;
542 *nPossibleNeighbors += 1;
543 } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
546 /* handle the LQ case */
549 #ifdef USING_THALES_LINK_COST_ROUTING
551 struct link_entry* walker;
552 float previousLinkCost = 2 * INFINITE_COST;
553 float bestLinkCost = 2 * INFINITE_COST;
555 if (forwardedBy != NULL)
557 /* Retrieve the cost of the link from 'forwardedBy' to myself */
558 struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
559 if (bestLinkFromForwarder != NULL)
561 previousLinkCost = bestLinkFromForwarder->link_cost;
565 for (walker = get_link_set(); walker != NULL; walker = walker->next)
567 union olsr_ip_addr* neighborMainIp;
568 struct link_entry* bestLinkToNeighbor;
569 struct tc_entry* tcLastHop;
571 /* Consider only links from the specified interface */
572 if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
579 "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
582 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
584 neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
586 /* Consider only neighbors with an IP address that differs from the
587 * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
588 if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
592 "%s: ----> not forwarding to %s: is source of pkt\n",
594 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
599 /* Rely on short-circuit boolean evaluation */
600 if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
604 "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
606 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
611 /* Rely on short-circuit boolean evaluation */
612 if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
616 "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
618 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
623 /* Found a candidate neighbor to direct our packet to */
625 if (walker->link_cost >= INFINITE_COST)
629 "%s: ----> not forwarding to %s: link is timing out\n",
631 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
636 /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
639 "%s: ----> forwarding pkt to %s will cost %5.2f\n",
641 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
644 /* If the candidate neighbor is best reached via another interface, then skip
645 * the candidate neighbor; the candidate neighbor has been / will be selected via that
646 * other interface. */
647 bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
649 if (walker != bestLinkToNeighbor)
651 if (bestLinkToNeighbor == NULL)
655 "%s: ----> not forwarding to %s: no link found\n",
657 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
661 struct interface_olsr * bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
665 "%s: ----> not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %5.2f\n",
667 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
669 bestLinkToNeighbor->link_cost);
675 if (forwardedBy != NULL)
679 "%s: ----> 2-hop path from %s via me to %s will cost %5.2f\n",
681 olsr_ip_to_string(&forwardedByBuf, forwardedBy),
682 olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
683 previousLinkCost + walker->link_cost);
686 /* Check the topology table whether the 'forwardedBy' node is itself a direct
687 * neighbor of the candidate neighbor, at a lower cost than the 2-hop route
688 * via myself. If so, we do not need to forward the BMF packet to the candidate
689 * neighbor, because the 'forwardedBy' node will forward the packet. */
690 if (forwardedBy != NULL)
692 tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
693 if (tcLastHop != NULL)
695 struct tc_edge_entry* tc_edge;
697 tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
699 /* We are not interested in dead-end or dying edges. */
700 if (tc_edge != NULL && (tc_edge->flags & OLSR_TC_EDGE_DOWN) == 0)
702 if (previousLinkCost + walker->link_cost > tc_edge->link_cost)
705 struct ipaddr_str neighbor_iface_buf, forw_buf;
706 olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
710 "%s: ----> not forwarding to %s: I am not an MPR between %s and %s, direct link costs %5.2f\n",
712 neighbor_iface_buf.buf,
713 olsr_ip_to_string(&forw_buf, forwardedBy),
714 neighbor_iface_buf.buf,
723 /* Remember the best neighbor. If all are very bad, remember none. */
724 if (walker->link_cost < bestLinkCost)
726 *bestNeighbor = walker;
727 bestLinkCost = walker->link_cost;
730 /* Fill the list with up to 'FanOutLimit' neighbors. If there
731 * are more neighbors, broadcast is used instead of unicast. In that
732 * case we do not need the list of neighbors. */
733 if (*nPossibleNeighbors < FanOutLimit)
735 neighbors->links[*nPossibleNeighbors] = walker;
738 *nPossibleNeighbors += 1;
742 #else /* USING_THALES_LINK_COST_ROUTING */
744 struct link_entry* walker;
745 olsr_linkcost previousLinkEtx = LINK_COST_BROKEN;
746 olsr_linkcost bestEtx = LINK_COST_BROKEN;
748 if (forwardedBy != NULL)
750 /* Retrieve the cost of the link from 'forwardedBy' to myself */
751 struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
752 if (bestLinkFromForwarder != NULL)
754 previousLinkEtx = bestLinkFromForwarder->linkcost;
758 OLSR_FOR_ALL_LINK_ENTRIES(walker) {
759 union olsr_ip_addr* neighborMainIp;
760 struct link_entry* bestLinkToNeighbor;
761 struct tc_entry* tcLastHop;
764 /* Consider only links from the specified interface */
765 if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
772 "%s: ----> considering forwarding pkt on \"%s\" to %s\n",
775 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
777 neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
779 /* Consider only neighbors with an IP address that differs from the
780 * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
781 if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
785 "%s: ----> not forwarding to %s: is source of pkt\n",
787 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
792 /* Rely on short-circuit boolean evaluation */
793 if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
797 "%s: ----> not forwarding to %s: is the node that forwarded the pkt\n",
799 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
804 /* Rely on short-circuit boolean evaluation */
805 if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
809 "%s: ----> not forwarding to %s: is the node to which the pkt was forwarded\n",
811 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
816 /* Found a candidate neighbor to direct our packet to */
818 /* Calculate the link quality (ETX) of the link to the found neighbor */
819 currEtx = walker->linkcost;
821 if (currEtx >= LINK_COST_BROKEN)
825 "%s: ----> not forwarding to %s: link is timing out\n",
827 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
832 /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
835 "%s: ----> forwarding pkt to %s will cost ETX %5.2f\n",
837 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
840 /* If the candidate neighbor is best reached via another interface, then skip
841 * the candidate neighbor; the candidate neighbor has been / will be selected via that
842 * other interface. */
843 bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
845 if (walker != bestLinkToNeighbor)
847 if (bestLinkToNeighbor == NULL)
851 "%s: ----> not forwarding to %s: no link found\n",
853 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
858 struct interface_olsr * bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
859 struct lqtextbuffer lqbuffer;
863 "%s: ----> not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %s\n",
865 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
866 bestIntf ? bestIntf->int_name : "NULL",
867 get_linkcost_text(bestLinkToNeighbor->linkcost, false, &lqbuffer));
873 if (forwardedBy != NULL)
876 struct ipaddr_str forwardedByBuf, niaBuf;
877 struct lqtextbuffer lqbuffer;
881 "%s: ----> 2-hop path from %s via me to %s will cost ETX %s\n",
883 olsr_ip_to_string(&forwardedByBuf, forwardedBy),
884 olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
885 get_linkcost_text(previousLinkEtx + currEtx, true, &lqbuffer));
888 /* Check the topology table whether the 'forwardedBy' node is itself a direct
889 * neighbor of the candidate neighbor, at a lower cost than the 2-hop route
890 * via myself. If so, we do not need to forward the BMF packet to the candidate
891 * neighbor, because the 'forwardedBy' node will forward the packet. */
892 if (forwardedBy != NULL)
894 tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
895 if (tcLastHop != NULL)
897 struct tc_edge_entry* tc_edge;
899 tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
901 /* We are not interested in dead-end edges. */
903 olsr_linkcost tcEtx = tc_edge->cost;
905 if (previousLinkEtx + currEtx > tcEtx)
908 struct ipaddr_str neighbor_iface_buf, forw_buf;
909 struct lqtextbuffer lqbuffer;
910 olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
914 "%s: ----> not forwarding to %s: I am not an MPR between %s and %s, direct link costs %s\n",
916 neighbor_iface_buf.buf,
917 olsr_ip_to_string(&forw_buf, forwardedBy),
918 neighbor_iface_buf.buf,
919 get_linkcost_text(tcEtx, false, &lqbuffer));
927 /* Remember the best neighbor. If all are very bad, remember none. */
928 if (currEtx < bestEtx)
930 *bestNeighbor = walker;
934 /* Fill the list with up to 'FanOutLimit' neighbors. If there
935 * are more neighbors, broadcast is used instead of unicast. In that
936 * case we do not need the list of neighbors. */
937 if (*nPossibleNeighbors < FanOutLimit)
939 neighbors->links[*nPossibleNeighbors] = walker;
942 *nPossibleNeighbors += 1;
943 } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
945 #endif /* USING_THALES_LINK_COST_ROUTING */
949 /* Display the result of the neighbor search */
950 if (*nPossibleNeighbors == 0)
954 "%s: ----> no suitable neighbor found to forward to on \"%s\"\n",
962 "%s: ----> %d neighbors found on \"%s\"; best neighbor to forward to: %s\n",
966 olsr_ip_to_string(&buf, &(*bestNeighbor)->neighbor_iface_addr));
969 } /* FindNeighbors */
971 /* -------------------------------------------------------------------------
972 * Function : CreateCaptureSocket
973 * Description: Create socket for promiscuously capturing multicast IP traffic
974 * Input : ifname - network interface (e.g. "eth0")
976 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
978 * Notes : The socket is a cooked IP packet socket, bound to the specified
980 * ------------------------------------------------------------------------- */
981 static int CreateCaptureSocket(const char* ifName)
983 int ifIndex = if_nametoindex(ifName);
984 struct packet_mreq mreq;
986 struct sockaddr_ll bindTo;
988 /* Open cooked IP packet socket */
989 int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
992 BmfPError("socket(PF_PACKET) error");
996 /* Set interface to promiscuous mode */
997 memset(&mreq, 0, sizeof(struct packet_mreq));
998 mreq.mr_ifindex = ifIndex;
999 mreq.mr_type = PACKET_MR_PROMISC;
1000 if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
1002 BmfPError("setsockopt(PACKET_MR_PROMISC) error");
1007 /* Get hardware (MAC) address */
1008 memset(&req, 0, sizeof(struct ifreq));
1009 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
1010 req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
1011 if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
1013 BmfPError("error retrieving MAC address");
1018 /* Bind the socket to the specified interface */
1019 memset(&bindTo, 0, sizeof(bindTo));
1020 bindTo.sll_family = AF_PACKET;
1021 bindTo.sll_protocol = htons(ETH_P_IP);
1022 bindTo.sll_ifindex = ifIndex;
1023 memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
1024 bindTo.sll_halen = IFHWADDRLEN;
1026 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
1028 BmfPError("bind() error");
1033 /* Set socket to blocking operation */
1034 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1036 BmfPError("fcntl() error");
1041 AddDescriptorToInputSet(skfd);
1044 } /* CreateCaptureSocket */
1046 /* -------------------------------------------------------------------------
1047 * Function : CreateListeningSocket
1048 * Description: Create socket for promiscuously listening to BMF packets.
1049 * Used only when 'BmfMechanism' is BM_UNICAST_PROMISCUOUS
1050 * Input : ifname - network interface (e.g. "eth0")
1052 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
1054 * Notes : The socket is a cooked IP packet socket, bound to the specified
1056 * ------------------------------------------------------------------------- */
1057 static int CreateListeningSocket(const char* ifName)
1059 int ifIndex = if_nametoindex(ifName);
1060 struct packet_mreq mreq;
1062 struct sockaddr_ll bindTo;
1064 /* Open cooked IP packet socket */
1065 int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
1068 BmfPError("socket(PF_PACKET) error");
1072 /* Set interface to promiscuous mode */
1073 memset(&mreq, 0, sizeof(struct packet_mreq));
1074 mreq.mr_ifindex = ifIndex;
1075 mreq.mr_type = PACKET_MR_PROMISC;
1076 if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
1078 BmfPError("setsockopt(PACKET_MR_PROMISC) error");
1083 /* Get hardware (MAC) address */
1084 memset(&req, 0, sizeof(struct ifreq));
1085 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
1086 req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
1087 if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
1089 BmfPError("error retrieving MAC address");
1094 /* Bind the socket to the specified interface */
1095 memset(&bindTo, 0, sizeof(bindTo));
1096 bindTo.sll_family = AF_PACKET;
1097 bindTo.sll_protocol = htons(ETH_P_IP);
1098 bindTo.sll_ifindex = ifIndex;
1099 memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
1100 bindTo.sll_halen = IFHWADDRLEN;
1102 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
1104 BmfPError("bind() error");
1109 /* Set socket to blocking operation */
1110 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1112 BmfPError("fcntl() error");
1117 AddDescriptorToInputSet(skfd);
1120 } /* CreateListeningSocket */
1122 /* -------------------------------------------------------------------------
1123 * Function : CreateEncapsulateSocket
1124 * Description: Create a socket for sending and receiving encapsulated
1126 * Input : ifname - network interface (e.g. "eth0")
1128 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
1130 * Notes : The socket is an UDP (datagram) over IP socket, bound to the
1131 * specified network interface
1132 * ------------------------------------------------------------------------- */
1133 static int CreateEncapsulateSocket(const char* ifName)
1136 struct sockaddr_in bindTo;
1138 /* Open UDP-IP socket */
1139 int skfd = socket(PF_INET, SOCK_DGRAM, 0);
1142 BmfPError("socket(PF_INET) error");
1146 /* Enable sending to broadcast addresses */
1147 if (setsockopt(skfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
1149 BmfPError("setsockopt(SO_BROADCAST) error");
1154 /* Bind to the specific network interfaces indicated by ifName. */
1155 /* When using Kernel 2.6 this must happer prior to the port binding! */
1156 if (setsockopt(skfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, strlen(ifName) + 1) < 0)
1158 BmfPError("setsockopt(SO_BINDTODEVICE) error");
1163 /* Bind to BMF port */
1164 memset(&bindTo, 0, sizeof(bindTo));
1165 bindTo.sin_family = AF_INET;
1166 bindTo.sin_port = htons(BMF_ENCAP_PORT);
1167 bindTo.sin_addr.s_addr = htonl(INADDR_ANY);
1169 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
1171 BmfPError("bind() error");
1176 /* Set socket to blocking operation */
1177 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1179 BmfPError("fcntl() error");
1184 AddDescriptorToInputSet(skfd);
1187 } /* CreateEncapsulateSocket */
1189 /* -------------------------------------------------------------------------
1190 * Function : CreateLocalEtherTunTap
1191 * Description: Creates and brings up an EtherTunTap interface
1194 * Return : the socket file descriptor (>= 0), or -1 in case of failure
1195 * Data Used : EtherTunTapIfName - name used for the tuntap interface (e.g.
1199 * EtherTunTapIpBroadcast
1201 * Note : Order dependency: call this function only if BmfInterfaces
1202 * is filled with a list of network interfaces.
1203 * ------------------------------------------------------------------------- */
1204 static int CreateLocalEtherTunTap(void)
1206 static const char * deviceName = OS_TUNNEL_PATH;
1212 etfd = open(deviceName, O_RDWR | O_NONBLOCK);
1215 BmfPError("error opening %s", deviceName);
1219 memset(&ifreq, 0, sizeof(ifreq));
1220 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1221 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1223 /* Specify the IFF_TUN flag for IP packets.
1224 * Specify IFF_NO_PI for not receiving extra meta packet information. */
1225 ifreq.ifr_flags = IFF_TUN;
1226 ifreq.ifr_flags |= IFF_NO_PI;
1228 if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0)
1230 BmfPError("ioctl(TUNSETIFF) error on %s", deviceName);
1235 memset(&ifreq, 0, sizeof(ifreq));
1236 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1237 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1238 ifreq.ifr_addr.sa_family = AF_INET;
1240 ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1243 BmfPError("socket(PF_INET) error on %s", deviceName);
1248 /* Give the EtherTunTap interface an IP address.
1249 * The default IP address is the address of the first OLSR interface;
1250 * the default netmask is 255.255.255.255 . Having an all-ones netmask prevents
1251 * automatic entry of the BMF network interface in the routing table. */
1252 if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
1254 struct TBmfInterface* nextBmfIf = BmfInterfaces;
1255 while (nextBmfIf != NULL)
1257 struct TBmfInterface* bmfIf = nextBmfIf;
1258 nextBmfIf = bmfIf->next;
1260 if (bmfIf->olsrIntf != NULL)
1262 EtherTunTapIp = ntohl(bmfIf->intAddr.v4.s_addr);
1263 EtherTunTapIpBroadcast = EtherTunTapIp;
1268 if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
1270 /* No IP address configured for BMF network interface, and no OLSR interface found to
1271 * copy IP address from. Fall back to default: 10.255.255.253 . */
1272 EtherTunTapIp = ETHERTUNTAPDEFAULTIP;
1275 ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_addr))->sin_addr.s_addr = htonl(EtherTunTapIp);
1276 ioctlres = ioctl(ioctlSkfd, SIOCSIFADDR, &ifreq);
1280 ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_netmask))->sin_addr.s_addr = htonl(EtherTunTapIpMask);
1281 ioctlres = ioctl(ioctlSkfd, SIOCSIFNETMASK, &ifreq);
1284 /* Set broadcast IP */
1285 ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifreq.ifr_broadaddr))->sin_addr.s_addr = htonl(EtherTunTapIpBroadcast);
1286 ioctlres = ioctl(ioctlSkfd, SIOCSIFBRDADDR, &ifreq);
1289 /* Bring EtherTunTap interface up (if not already) */
1290 ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
1293 ifreq.ifr_flags |= (IFF_UP | IFF_RUNNING | IFF_BROADCAST);
1294 ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
1302 /* Any of the above ioctl() calls failed */
1303 BmfPError("error bringing up EtherTunTap interface \"%s\"", EtherTunTapIfName);
1308 } /* if (ioctlres < 0) */
1310 /* Set the multicast flag on the interface */
1311 memset(&ifreq, 0, sizeof(ifreq));
1312 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1313 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1315 ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
1318 ifreq.ifr_flags |= IFF_MULTICAST;
1319 ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
1323 /* Any of the two above ioctl() calls failed */
1324 BmfPError("error setting multicast flag on EtherTunTap interface \"%s\"", EtherTunTapIfName);
1326 /* Continue anyway */
1329 /* Use ioctl to make the tuntap persistent. Otherwise it will disappear
1330 * when this program exits. That is not desirable, since a multicast
1331 * daemon (e.g. mrouted) may be using the tuntap interface. */
1332 if (ioctl(etfd, TUNSETPERSIST, EtherTunTapPersistent ? (void *)&ifreq : NULL) < 0)
1334 BmfPError("error making EtherTunTap interface \"%s\" %spersistent", EtherTunTapIfName, !EtherTunTapPersistent ? "non-" : "");
1336 /* Continue anyway */
1339 OLSR_PRINTF(8, "%s: opened 1 socket on \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
1341 AddDescriptorToInputSet(etfd);
1343 /* If the user configured a specific IP address for the BMF network interface,
1344 * help the user and advertise the IP address of the BMF network interface
1345 * on the OLSR network via HNA */
1346 if (TunTapIpOverruled != 0)
1348 union olsr_ip_addr temp_net;
1350 temp_net.v4.s_addr = htonl(EtherTunTapIp);
1351 ip_prefix_list_add(&olsr_cnf->hna_entries, &temp_net, 32);
1357 } /* CreateLocalEtherTunTap */
1359 /* -------------------------------------------------------------------------
1360 * Function : CreateInterface
1361 * Description: Create a new TBmfInterface object and adds it to the global
1362 * BmfInterfaces list
1363 * Input : ifName - name of the network interface (e.g. "eth0")
1364 * : olsrIntf - OLSR interface object of the network interface, or
1365 * NULL if the network interface is not OLSR-enabled
1367 * Return : the number of opened sockets
1368 * Data Used : BmfInterfaces, LastBmfInterface
1369 * ------------------------------------------------------------------------- */
1370 static int CreateInterface(
1372 struct interface_olsr * olsrIntf)
1374 int capturingSkfd = -1;
1375 int encapsulatingSkfd = -1;
1376 int listeningSkfd = -1;
1380 struct TBmfInterface* newIf = malloc(sizeof(struct TBmfInterface));
1382 assert(ifName != NULL);
1389 if (olsrIntf != NULL)
1391 /* On OLSR-enabled interfaces, create socket for encapsulating and forwarding
1392 * multicast packets */
1393 encapsulatingSkfd = CreateEncapsulateSocket(ifName);
1394 if (encapsulatingSkfd < 0)
1402 /* Create socket for capturing and sending of multicast packets on
1403 * non-OLSR interfaces, and on OLSR-interfaces if configured. */
1404 if ((olsrIntf == NULL) || (CapturePacketsOnOlsrInterfaces != 0))
1406 capturingSkfd = CreateCaptureSocket(ifName);
1407 if (capturingSkfd < 0)
1409 if (encapsulatingSkfd >= 0) {
1410 close(encapsulatingSkfd);
1419 /* Create promiscuous mode listening interface if BMF uses IP unicast
1420 * as underlying forwarding mechanism */
1421 if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
1423 listeningSkfd = CreateListeningSocket(ifName);
1424 if (listeningSkfd < 0)
1426 if (encapsulatingSkfd >= 0) {
1427 close(encapsulatingSkfd); /* no problem if 'encapsulatingSkfd' is -1 */
1436 /* For ioctl operations on the network interface, use either capturingSkfd
1437 * or encapsulatingSkfd, whichever is available */
1438 ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd;
1440 /* Retrieve the MAC address of the interface. */
1441 memset(&ifr, 0, sizeof(struct ifreq));
1442 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1443 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1444 if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0)
1446 BmfPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
1447 if (capturingSkfd >= 0) {
1448 close(capturingSkfd);
1450 if (encapsulatingSkfd >= 0) {
1451 close(encapsulatingSkfd);
1457 /* add listeners to sockets */
1458 if (capturingSkfd != -1) {
1459 add_olsr_socket(capturingSkfd, NULL, BMF_handle_captureFd, newIf, SP_IMM_READ);
1461 if (encapsulatingSkfd != -1) {
1462 add_olsr_socket(encapsulatingSkfd, NULL, BMF_handle_encapsulatingFd, newIf, SP_IMM_READ);
1464 if (listeningSkfd != -1) {
1465 add_olsr_socket(listeningSkfd, NULL, BMF_handle_listeningFd, newIf, SP_IMM_READ);
1467 /* Copy data into TBmfInterface object */
1468 newIf->capturingSkfd = capturingSkfd;
1469 newIf->encapsulatingSkfd = encapsulatingSkfd;
1470 newIf->listeningSkfd = listeningSkfd;
1471 memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1472 memcpy(newIf->ifName, ifName, IFNAMSIZ);
1473 newIf->olsrIntf = olsrIntf;
1474 if (olsrIntf != NULL)
1476 /* For an OLSR-interface, copy the interface address and broadcast
1477 * address from the OLSR interface object. Downcast to correct sockaddr
1479 newIf->intAddr.v4 = ((struct sockaddr_in *)&olsrIntf->int_addr)->sin_addr;
1480 newIf->broadAddr.v4 = ((struct sockaddr_in *)&olsrIntf->int_broadaddr)->sin_addr;
1484 /* For a non-OLSR interface, retrieve the IP address ourselves */
1485 memset(&ifr, 0, sizeof(struct ifreq));
1486 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1487 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1488 if (ioctl(ioctlSkfd, SIOCGIFADDR, &ifr) < 0)
1490 BmfPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
1492 newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
1496 /* Downcast to correct sockaddr subtype */
1497 newIf->intAddr.v4 = ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&ifr.ifr_addr))->sin_addr;
1500 /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
1501 memset(&ifr, 0, sizeof(struct ifreq));
1502 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1503 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1504 if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0)
1506 BmfPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
1508 newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
1512 /* Downcast to correct sockaddr subtype */
1513 newIf->broadAddr.v4 = ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&ifr.ifr_broadaddr))->sin_addr;
1517 /* Reset counters */
1518 newIf->nBmfPacketsRx = 0;
1519 newIf->nBmfPacketsRxDup = 0;
1520 newIf->nBmfPacketsTx = 0;
1522 /* Add new TBmfInterface object to global list. OLSR interfaces are
1523 * added at the front of the list, non-OLSR interfaces at the back. */
1524 if (BmfInterfaces == NULL)
1526 /* First TBmfInterface object in list */
1528 BmfInterfaces = newIf;
1529 LastBmfInterface = newIf;
1531 else if (olsrIntf != NULL)
1533 /* Add new TBmfInterface object at front of list */
1534 newIf->next = BmfInterfaces;
1535 BmfInterfaces = newIf;
1539 /* Add new TBmfInterface object at back of list */
1541 LastBmfInterface->next= newIf;
1542 LastBmfInterface = newIf;
1547 "%s: opened %d socket%s on %s interface \"%s\"\n",
1550 nOpened == 1 ? "" : "s",
1551 olsrIntf != NULL ? "OLSR" : "non-OLSR",
1555 } /* CreateInterface */
1557 /* -------------------------------------------------------------------------
1558 * Function : CreateBmfNetworkInterfaces
1559 * Description: Create a list of TBmfInterface objects, one for each network
1560 * interface on which BMF runs
1561 * Input : skipThisIntf - network interface to skip, if seen
1563 * Return : fail (-1) or success (0)
1565 * ------------------------------------------------------------------------- */
1566 int CreateBmfNetworkInterfaces(struct interface_olsr * skipThisIntf)
1573 int nOpenedSockets = 0;
1575 /* Clear input descriptor set */
1578 skfd = socket(PF_INET, SOCK_DGRAM, 0);
1581 BmfPError("no inet socket available to retrieve interface list");
1585 /* Retrieve the network interface configuration list */
1589 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
1590 ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
1592 if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
1594 BmfPError("ioctl(SIOCGIFCONF) error");
1600 if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs)
1602 /* Assume it overflowed; double the space and try again */
1604 assert(numreqs < 1024);
1605 continue; /* for (;;) */
1607 break; /* for (;;) */
1612 /* For each item in the interface configuration list... */
1614 for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++)
1616 struct interface_olsr * olsrIntf;
1617 union olsr_ip_addr ipAddr;
1619 /* Skip the BMF network interface itself */
1620 if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
1622 continue; /* for (n = ...) */
1625 /* ...find the OLSR interface structure, if any */
1626 ipAddr.v4 = ((struct sockaddr_in*) ARM_NOWARN_ALIGN(&ifr->ifr_addr))->sin_addr;
1627 olsrIntf = if_ifwithaddr(&ipAddr);
1629 if (skipThisIntf != NULL && olsrIntf == skipThisIntf)
1631 continue; /* for (n = ...) */
1634 if (olsrIntf == NULL && ! IsNonOlsrBmfIf(ifr->ifr_name))
1636 /* Interface is neither OLSR interface, nor specified as non-OLSR BMF
1637 * interface in the BMF plugin parameter list */
1638 continue; /* for (n = ...) */
1641 nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
1643 } /* for (n = ...) */
1647 /* Create the BMF network interface */
1648 EtherTunTapFd = CreateLocalEtherTunTap();
1649 if (EtherTunTapFd >= 0)
1651 add_olsr_socket(EtherTunTapFd, NULL, BMF_handle_tuntapFd, NULL, SP_IMM_READ);
1655 if (BmfInterfaces == NULL)
1657 olsr_printf(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
1661 olsr_printf(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
1664 } /* CreateBmfNetworkInterfaces */
1666 /* -------------------------------------------------------------------------
1667 * Function : CloseBmfNetworkInterfaces
1668 * Description: Closes every socket on each network interface used by BMF
1672 * Data Used : BmfInterfaces, LastBmfInterface
1674 * - the local EtherTunTap interface (e.g. "tun0" or "tap0")
1675 * - for each BMF-enabled interface, the socket used for
1676 * capturing multicast packets
1677 * - for each OLSR-enabled interface, the socket used for
1678 * encapsulating packets
1679 * Also restores the network state to the situation before BMF
1681 * ------------------------------------------------------------------------- */
1682 void CloseBmfNetworkInterfaces(void)
1685 u_int32_t totalOlsrBmfPacketsRx = 0;
1686 u_int32_t totalOlsrBmfPacketsRxDup = 0;
1687 u_int32_t totalOlsrBmfPacketsTx = 0;
1688 u_int32_t totalNonOlsrBmfPacketsRx = 0;
1689 u_int32_t totalNonOlsrBmfPacketsRxDup = 0;
1690 u_int32_t totalNonOlsrBmfPacketsTx = 0;
1692 /* Close all opened sockets */
1693 struct TBmfInterface* nextBmfIf = BmfInterfaces;
1694 while (nextBmfIf != NULL)
1696 struct TBmfInterface* bmfIf = nextBmfIf;
1697 nextBmfIf = bmfIf->next;
1699 if (bmfIf->capturingSkfd >= 0)
1701 close(bmfIf->capturingSkfd);
1702 remove_olsr_socket(bmfIf->capturingSkfd, NULL, BMF_handle_captureFd);
1705 if (bmfIf->encapsulatingSkfd >= 0)
1707 close(bmfIf->encapsulatingSkfd);
1708 remove_olsr_socket(bmfIf->encapsulatingSkfd, NULL, BMF_handle_encapsulatingFd);
1711 if (bmfIf->listeningSkfd >= 0)
1713 close(bmfIf->listeningSkfd);
1714 remove_olsr_socket(bmfIf->listeningSkfd, NULL, BMF_handle_listeningFd);
1720 "%s: %s interface \"%s\": RX pkts %d (%d dups); TX pkts %d\n",
1722 bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
1724 bmfIf->nBmfPacketsRx,
1725 bmfIf->nBmfPacketsRxDup,
1726 bmfIf->nBmfPacketsTx);
1730 "%s: closed %s interface \"%s\"\n",
1732 bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
1736 if (bmfIf->olsrIntf != NULL)
1738 totalOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
1739 totalOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
1740 totalOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
1744 totalNonOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
1745 totalNonOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
1746 totalNonOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
1752 if (EtherTunTapFd >= 0)
1754 close(EtherTunTapFd);
1755 remove_olsr_socket(EtherTunTapFd, NULL, BMF_handle_tuntapFd);
1758 OLSR_PRINTF(7, "%s: closed \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
1761 BmfInterfaces = NULL;
1762 LastBmfInterface = NULL;
1764 /* Re-initialize the IP address for the BMF network interface. Thanks to
1765 * Daniele Lacamera for finding and solving this bug. */
1766 EtherTunTapIp = ETHERTUNTAPIPNOTSET;
1768 olsr_printf(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
1772 "%s: total all OLSR interfaces : RX pkts %d (%d dups); TX pkts %d\n",
1774 totalOlsrBmfPacketsRx,
1775 totalOlsrBmfPacketsRxDup,
1776 totalOlsrBmfPacketsTx);
1779 "%s: total all non-OLSR interfaces: RX pkts %d (%d dups); TX pkts %d\n",
1781 totalNonOlsrBmfPacketsRx,
1782 totalNonOlsrBmfPacketsRxDup,
1783 totalNonOlsrBmfPacketsTx);
1784 } /* CloseBmfNetworkInterfaces */
1786 #define MAX_NON_OLSR_IFS 32
1787 static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
1788 static int nNonOlsrIfs = 0;
1790 /* -------------------------------------------------------------------------
1791 * Function : AddNonOlsrBmfIf
1792 * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
1793 * network interfaces
1794 * Input : ifName - network interface (e.g. "eth0")
1798 * Return : success (0) or fail (1)
1799 * Data Used : NonOlsrIfNames
1800 * ------------------------------------------------------------------------- */
1801 int AddNonOlsrBmfIf(
1803 void* data __attribute__((unused)),
1804 set_plugin_parameter_addon addon __attribute__((unused)))
1806 assert(ifName != NULL);
1808 if (nNonOlsrIfs >= MAX_NON_OLSR_IFS)
1812 "%s: too many non-OLSR interfaces specified, maximum is %d\n",
1818 strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
1819 NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1822 } /* AddNonOlsrBmfIf */
1824 /* -------------------------------------------------------------------------
1825 * Function : IsNonOlsrBmfIf
1826 * Description: Checks if a network interface is OLSR-enabled
1827 * Input : ifName - network interface (e.g. "eth0")
1829 * Return : true (1) or false (0)
1830 * Data Used : NonOlsrIfNames
1831 * ------------------------------------------------------------------------- */
1832 int IsNonOlsrBmfIf(const char* ifName)
1836 assert(ifName != NULL);
1838 for (i = 0; i < nNonOlsrIfs; i++)
1840 if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0) return 1;
1843 } /* IsNonOlsrBmfIf */
1845 /* -------------------------------------------------------------------------
1846 * Function : CheckAndUpdateLocalBroadcast
1847 * Description: For an IP packet, check if the destination address is not a
1848 * multicast address. If it is not, the packet is assumed to be
1849 * a local broadcast packet. In that case, set the destination
1850 * address of the IP packet to the passed broadcast address.
1851 * Input : ipPacket - the IP packet
1852 * broadAddr - the broadcast address to fill in
1856 * Notes : See also RFC1141
1857 * ------------------------------------------------------------------------- */
1858 void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* broadAddr)
1861 union olsr_ip_addr destIp;
1863 assert(ipPacket != NULL && broadAddr != NULL);
1865 iph = (struct iphdr*) ARM_NOWARN_ALIGN(ipPacket);
1866 destIp.v4.s_addr = iph->daddr;
1867 if (! IsMulticast(&destIp))
1869 u_int32_t origDaddr, newDaddr;
1872 origDaddr = ntohl(iph->daddr);
1874 iph->daddr = broadAddr->v4.s_addr;
1875 newDaddr = ntohl(iph->daddr);
1877 /* Re-calculate IP header checksum for new destination */
1878 check = ntohs(iph->check);
1880 check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
1881 check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
1884 check = check + (check >> 16);
1886 iph->check = htons(check);
1888 if (iph->protocol == SOL_UDP)
1890 /* Re-calculate UDP/IP checksum for new destination */
1892 int ipHeaderLen = GetIpHeaderLength(ipPacket);
1893 struct udphdr* udph = (struct udphdr*) ARM_NOWARN_ALIGN((ipPacket + ipHeaderLen));
1895 /* RFC 1624, Eq. 3: HC' = ~(~HC - m + m') */
1897 #if defined(__GLIBC__) or defined(__BIONIC__)
1898 check = ntohs(udph->check);
1900 check = ntohs(udph->uh_sum);
1903 check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
1904 check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
1907 check = check + (check >> 16);
1909 #if defined(__GLIBC__) or defined(__BIONIC__)
1910 udph->check = htons(check);
1912 udph->uh_sum = htons(check);
1916 } /* CheckAndUpdateLocalBroadcast */
1918 /* -------------------------------------------------------------------------
1919 * Function : AddMulticastRoute
1920 * Description: Insert a route to all multicast addresses in the kernel
1921 * routing table. The route will be via the BMF network interface.
1926 * ------------------------------------------------------------------------- */
1927 void AddMulticastRoute(void)
1929 struct rtentry kernel_route;
1930 int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1933 BmfPError("socket(PF_INET) error");
1937 memset(&kernel_route, 0, sizeof(struct rtentry));
1939 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sa_family = AF_INET;
1940 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_gateway))->sa_family = AF_INET;
1941 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sa_family = AF_INET;
1944 ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sin_addr.s_addr = htonl(0xE0000000);
1945 ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sin_addr.s_addr = htonl(0xF0000000);
1947 kernel_route.rt_metric = 0;
1948 kernel_route.rt_flags = RTF_UP;
1950 kernel_route.rt_dev = EtherTunTapIfName;
1952 if (ioctl(ioctlSkfd, SIOCADDRT, &kernel_route) < 0)
1954 BmfPError("error setting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
1956 /* Continue anyway */
1959 } /* AddMulticastRoute */
1961 /* -------------------------------------------------------------------------
1962 * Function : DeleteMulticastRoute
1963 * Description: Delete the route to all multicast addresses from the kernel
1969 * ------------------------------------------------------------------------- */
1970 void DeleteMulticastRoute(void)
1972 if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
1974 struct rtentry kernel_route;
1975 int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1978 BmfPError("socket(PF_INET) error");
1982 memset(&kernel_route, 0, sizeof(struct rtentry));
1984 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sa_family = AF_INET;
1985 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_gateway))->sa_family = AF_INET;
1986 ((struct sockaddr *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sa_family = AF_INET;
1989 ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_dst))->sin_addr.s_addr = htonl(0xE0000000);
1990 ((struct sockaddr_in *) ARM_NOWARN_ALIGN(&kernel_route.rt_genmask))->sin_addr.s_addr = htonl(0xF0000000);
1992 kernel_route.rt_metric = 0;
1993 kernel_route.rt_flags = RTF_UP;
1995 kernel_route.rt_dev = EtherTunTapIfName;
1997 if (ioctl(ioctlSkfd, SIOCDELRT, &kernel_route) < 0)
1999 BmfPError("error deleting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
2001 /* Continue anyway */
2005 } /* DeleteMulticastRoute */