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"
69 #include "Packet.h" /* IFHWADDRLEN */
70 #include "Bmf.h" /* PLUGIN_NAME, MainAddressOf() */
71 #include "Address.h" /* IsMulticast() */
73 /* List of network interface objects used by BMF plugin */
74 struct TBmfInterface* BmfInterfaces = NULL;
75 struct TBmfInterface* LastBmfInterface = NULL;
77 /* Highest-numbered open socket file descriptor. To be used as first
78 * parameter in calls to select(...). */
81 /* Set of socket file descriptors */
84 /* File descriptor of EtherTunTap interface */
85 int EtherTunTapFd = -1;
87 /* Network interface name of EtherTunTap interface. May be overruled by
88 * setting the plugin parameter "BmfInterface". */
89 char EtherTunTapIfName[IFNAMSIZ] = "bmf0";
91 /* The underlying mechanism to forward multicast packets. Either:
92 * - BM_BROADCAST: BMF uses the IP local broadcast as destination address
93 * - BM_UNICAST_PROMISCUOUS: BMF uses the IP address of the best neighbor as
94 * destination address. The other neighbors listen promiscuously. */
95 enum TBmfMechanism BmfMechanism = BM_BROADCAST;
97 #define ETHERTUNTAPIPNOTSET 0
99 /* The IP address of the BMF network interface in host byte order.
100 * May be overruled by setting the plugin parameter "BmfInterfaceIp". */
101 u_int32_t EtherTunTapIp = ETHERTUNTAPIPNOTSET;
103 /* 255.255.255.255 in host byte order. May be overruled by
104 * setting the plugin parameter "BmfInterfaceIp". */
105 u_int32_t EtherTunTapIpMask = 0xFFFFFFFF;
107 /* The IP broadcast address of the BMF network interface in host byte order.
108 * May be overruled by setting the plugin parameter "BmfinterfaceIp". */
109 u_int32_t EtherTunTapIpBroadcast = ETHERTUNTAPIPNOTSET;
111 /* Whether or not the configuration has overruled the default IP
112 * configuration of the EtherTunTap interface */
113 int TunTapIpOverruled = 0;
115 /* Whether or not to capture packets on the OLSR-enabled
116 * interfaces (in promiscuous mode). May be overruled by setting the plugin
117 * parameter "CapturePacketsOnOlsrInterfaces" to "yes". */
118 int CapturePacketsOnOlsrInterfaces = 0;
120 /* -------------------------------------------------------------------------
121 * Function : SetBmfInterfaceName
122 * Description: Overrule the default network interface name ("bmf0") of the
123 * EtherTunTap interface
124 * Input : ifname - network interface name (e.g. "mybmf0")
128 * Return : success (0) or fail (1)
129 * Data Used : EtherTunTapIfName
130 * ------------------------------------------------------------------------- */
131 int SetBmfInterfaceName(
133 void* data __attribute__((unused)),
134 set_plugin_parameter_addon addon __attribute__((unused)))
136 strncpy(EtherTunTapIfName, ifname, IFNAMSIZ - 1);
137 EtherTunTapIfName[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
139 } /* SetBmfInterfaceName */
141 /* -------------------------------------------------------------------------
142 * Function : SetBmfInterfaceIp
143 * Description: Overrule the default IP address and prefix length
144 * ("10.255.255.253/30") of the EtherTunTap interface
145 * Input : ip - IP address string, followed by '/' and prefix length
149 * Return : success (0) or fail (1)
150 * Data Used : EtherTunTapIp, EtherTunTapIpMask, EtherTunTapIpBroadcast,
152 * ------------------------------------------------------------------------- */
153 int SetBmfInterfaceIp(
155 void* data __attribute__((unused)),
156 set_plugin_parameter_addon addon __attribute__((unused)))
158 #define IPV4_MAX_ADDRLEN 16
159 #define IPV4_MAX_PREFIXLEN 32
161 char ipAddr[IPV4_MAX_ADDRLEN];
162 struct in_addr sinaddr;
166 /* Inspired by function str2prefix_ipv4 as found in Quagga source
167 * file lib/prefix.c */
169 /* Find slash inside string. */
170 slashAt = strchr(ip, '/');
172 /* String doesn't contain slash. */
173 if (slashAt == NULL || slashAt - ip >= IPV4_MAX_ADDRLEN)
175 /* No prefix length specified, or IP address too long */
179 strncpy(ipAddr, ip, slashAt - ip);
180 *(ipAddr + (slashAt - ip)) = '\0';
181 if (inet_aton(ipAddr, &sinaddr) == 0)
183 /* Invalid address passed */
187 EtherTunTapIp = ntohl(sinaddr.s_addr);
189 /* Get prefix length. */
190 prefixLen = atoi(++slashAt);
191 if (prefixLen <= 0 || prefixLen > IPV4_MAX_PREFIXLEN)
196 /* Compose IP subnet mask in host byte order */
197 EtherTunTapIpMask = 0;
198 for (i = 0; i < prefixLen; i++)
200 EtherTunTapIpMask |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
203 /* Compose IP broadcast address in host byte order */
204 EtherTunTapIpBroadcast = EtherTunTapIp;
205 for (i = prefixLen; i < IPV4_MAX_PREFIXLEN; i++)
207 EtherTunTapIpBroadcast |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
210 TunTapIpOverruled = 1;
213 } /* SetBmfInterfaceIp */
215 /* -------------------------------------------------------------------------
216 * Function : SetCapturePacketsOnOlsrInterfaces
217 * Description: Overrule the default setting, enabling or disabling the
218 * capturing of packets on OLSR-enabled interfaces.
219 * Input : enable - either "yes" or "no"
223 * Return : success (0) or fail (1)
225 * ------------------------------------------------------------------------- */
226 int SetCapturePacketsOnOlsrInterfaces(
228 void* data __attribute__((unused)),
229 set_plugin_parameter_addon addon __attribute__((unused)))
231 if (strcmp(enable, "yes") == 0)
233 CapturePacketsOnOlsrInterfaces = 1;
236 else if (strcmp(enable, "no") == 0)
238 CapturePacketsOnOlsrInterfaces = 0;
242 /* Value not recognized */
244 } /* SetCapturePacketsOnOlsrInterfaces */
246 /* -------------------------------------------------------------------------
247 * Function : SetBmfMechanism
248 * Description: Overrule the default BMF mechanism to either BM_BROADCAST or
249 * BM_UNICAST_PROMISCUOUS.
250 * Input : mechanism - either "Broadcast" or "UnicastPromiscuous"
254 * Return : success (0) or fail (1)
256 * ------------------------------------------------------------------------- */
258 const char* mechanism,
259 void* data __attribute__((unused)),
260 set_plugin_parameter_addon addon __attribute__((unused)))
262 if (strcmp(mechanism, "Broadcast") == 0)
264 BmfMechanism = BM_BROADCAST;
267 else if (strcmp(mechanism, "UnicastPromiscuous") == 0)
269 BmfMechanism = BM_UNICAST_PROMISCUOUS;
273 /* Value not recognized */
275 } /* SetBmfMechanism */
277 /* -------------------------------------------------------------------------
278 * Function : AddDescriptorToInputSet
279 * Description: Add a socket descriptor to the global set of socket file descriptors
280 * Input : skfd - socket file descriptor
283 * Data Used : HighestSkfd, InputSet
284 * Notes : Keeps track of the highest-numbered descriptor
285 * ------------------------------------------------------------------------- */
286 static void AddDescriptorToInputSet(int skfd)
288 /* Keep the highest-numbered descriptor */
289 if (skfd > HighestSkfd)
294 /* Add descriptor to input set */
295 FD_SET(skfd, &InputSet);
296 } /* AddDescriptorToInputSet */
298 /* To save the state of the IP spoof filter for the EtherTunTap interface */
299 static char EthTapSpoofState = '1';
301 /* -------------------------------------------------------------------------
302 * Function : DeactivateSpoofFilter
303 * Description: Deactivates the Linux anti-spoofing filter for the tuntap
307 * Return : fail (0) or success (1)
308 * Data Used : EtherTunTapIfName, EthTapSpoofState
309 * Notes : Saves the current filter state for later restoring
310 * ------------------------------------------------------------------------- */
311 int DeactivateSpoofFilter(void)
314 char procFile[FILENAME_MAX];
316 /* Generate the procfile name */
317 sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName);
319 /* Open procfile for reading */
320 procSpoof = fopen(procFile, "r");
321 if (procSpoof == NULL)
325 "WARNING! Could not open the %s file to check/disable the IP spoof filter!\n"
326 "Are you using the procfile filesystem?\n"
327 "Does your system support IPv4?\n"
328 "I will continue (in 3 sec) - but you should manually ensure that IP spoof\n"
329 "filtering is disabled!\n\n",
336 EthTapSpoofState = fgetc(procSpoof);
339 /* Open procfile for writing */
340 procSpoof = fopen(procFile, "w");
341 if (procSpoof == NULL)
343 fprintf(stderr, "Could not open %s for writing!\n", procFile);
346 "I will continue (in 3 sec) - but you should manually ensure that IP"
347 " spoof filtering is disabled!\n\n");
352 syslog(LOG_INFO, "Writing \"0\" to %s", procFile);
353 fputs("0", procSpoof);
358 } /* DeactivateSpoofFilter */
360 /* -------------------------------------------------------------------------
361 * Function : RestoreSpoofFilter
362 * Description: Restores the Linux anti-spoofing filter setting for the tuntap
367 * Data Used : EtherTunTapIfName, EthTapSpoofState
368 * ------------------------------------------------------------------------- */
369 void RestoreSpoofFilter(void)
372 char procFile[FILENAME_MAX];
374 /* Generate the procfile name */
375 sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName);
377 /* Open procfile for writing */
378 procSpoof = fopen(procFile, "w");
379 if (procSpoof == NULL)
381 fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procFile);
385 syslog(LOG_INFO, "Resetting %s to %c\n", procFile, EthTapSpoofState);
387 fputc(EthTapSpoofState, procSpoof);
390 } /* RestoreSpoofFilter */
392 /* -------------------------------------------------------------------------
393 * Function : FindNeighbors
394 * Description: Find the neighbors on a network interface to forward a BMF
396 * Input : intf - the network interface
397 * source - the source IP address of the BMF packet
398 * forwardedBy - the IP address of the node that forwarded the BMF
400 * forwardedTo - the IP address of the node to which the BMF packet
402 * Output : neighbors - list of (up to a number of 'FanOutLimit') neighbors.
403 * bestNeighbor - the best neighbor (in terms of lowest cost or ETX
405 * nPossibleNeighbors - number of found possible neighbors
406 * Data Used : FanOutLimit
407 * ------------------------------------------------------------------------- */
409 struct TBestNeighbors* neighbors,
410 struct link_entry** bestNeighbor,
411 struct TBmfInterface* intf,
412 union olsr_ip_addr* source,
413 union olsr_ip_addr* forwardedBy,
414 union olsr_ip_addr* forwardedTo,
415 int* nPossibleNeighbors)
418 struct ipaddr_str buf;
423 *bestNeighbor = NULL;
424 for (i = 0; i < MAX_UNICAST_NEIGHBORS; i++)
426 neighbors->links[i] = NULL;
428 *nPossibleNeighbors = 0;
430 /* handle the non-LQ case */
432 if (olsr_cnf->lq_level == 0)
434 struct link_entry* walker;
436 /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
437 OLSR_FOR_ALL_LINK_ENTRIES(walker) {
438 union olsr_ip_addr* neighborMainIp;
440 /* Consider only links from the specified interface */
441 if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
448 "%s: ----> Considering forwarding pkt on \"%s\" to %s\n",
451 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
453 neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
455 /* Consider only neighbors with an IP address that differs from the
456 * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
457 if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
461 "%s: ----> Not forwarding to %s: is source of pkt\n",
463 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
468 /* Rely on short-circuit boolean evaluation */
469 if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
473 "%s: ----> Not forwarding to %s: is the node that forwarded the pkt\n",
475 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
480 /* Rely on short-circuit boolean evaluation */
481 if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
485 "%s: ----> Not forwarding to %s: is the node to which the pkt was forwarded\n",
487 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
492 /* Found a candidate neighbor to direct our packet to */
494 /* In the non-LQ case, it is not possible to select neigbors
495 * by quality or cost. So just remember the first found link.
496 * TODO: come on, there must be something better than to simply
497 * select the first one found! */
498 if (*bestNeighbor == NULL)
500 *bestNeighbor = walker;
503 /* Fill the list with up to 'FanOutLimit' neighbors. If there
504 * are more neighbors, broadcast is used instead of unicast. In that
505 * case we do not need the list of neighbors. */
506 if (*nPossibleNeighbors < FanOutLimit)
508 neighbors->links[*nPossibleNeighbors] = walker;
511 *nPossibleNeighbors += 1;
512 } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
515 /* handle the LQ case */
518 #ifdef USING_THALES_LINK_COST_ROUTING
520 struct link_entry* walker;
521 float previousLinkCost = 2 * INFINITE_COST;
522 float bestLinkCost = 2 * INFINITE_COST;
524 if (forwardedBy != NULL)
526 /* Retrieve the cost of the link from 'forwardedBy' to myself */
527 struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
528 if (bestLinkFromForwarder != NULL)
530 previousLinkCost = bestLinkFromForwarder->link_cost;
534 /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
535 for (walker = get_link_set(); walker != NULL; walker = walker->next)
537 union olsr_ip_addr* neighborMainIp;
538 struct link_entry* bestLinkToNeighbor;
539 struct tc_entry* tcLastHop;
541 /* Consider only links from the specified interface */
542 if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
549 "%s: ----> Considering forwarding pkt on \"%s\" to %s\n",
552 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
554 neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
556 /* Consider only neighbors with an IP address that differs from the
557 * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
558 if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
562 "%s: ----> Not forwarding to %s: is source of pkt\n",
564 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
569 /* Rely on short-circuit boolean evaluation */
570 if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
574 "%s: ----> Not forwarding to %s: is the node that forwarded the pkt\n",
576 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
581 /* Rely on short-circuit boolean evaluation */
582 if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
586 "%s: ----> Not forwarding to %s: is the node to which the pkt was forwarded\n",
588 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
593 /* Found a candidate neighbor to direct our packet to */
595 if (walker->link_cost >= INFINITE_COST)
599 "%s: ----> Not forwarding to %s: link is timing out\n",
601 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
606 /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
609 "%s: ----> Forwarding pkt to %s will cost %5.2f\n",
611 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
614 /* If the candidate neighbor is best reached via another interface, then skip
615 * the candidate neighbor; the candidate neighbor has been / will be selected via that
617 * Assumption: olsr_mutex has been grabbed for safe access to OLSR data. */
618 bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
620 if (walker != bestLinkToNeighbor)
622 if (bestLinkToNeighbor == NULL)
626 "%s: ----> Not forwarding to %s: no link found\n",
628 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
632 struct interface* bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
636 "%s: ----> Not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %5.2f\n",
638 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
640 bestLinkToNeighbor->link_cost);
646 if (forwardedBy != NULL)
650 "%s: ----> 2-hop path from %s via me to %s will cost %5.2f\n",
652 olsr_ip_to_string(&forwardedByBuf, forwardedBy),
653 olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
654 previousLinkCost + walker->link_cost);
657 /* Check the topology table whether the 'forwardedBy' node is itself a direct
658 * neighbor of the candidate neighbor, at a lower cost than the 2-hop route
659 * via myself. If so, we do not need to forward the BMF packet to the candidate
660 * neighbor, because the 'forwardedBy' node will forward the packet. */
661 if (forwardedBy != NULL)
663 /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
664 tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
665 if (tcLastHop != NULL)
667 struct tc_edge_entry* tc_edge;
669 /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
670 tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
672 /* We are not interested in dead-end or dying edges. */
673 if (tc_edge != NULL && (tc_edge->flags & OLSR_TC_EDGE_DOWN) == 0)
675 if (previousLinkCost + walker->link_cost > tc_edge->link_cost)
678 struct ipaddr_str neighbor_iface_buf, forw_buf;
679 olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
683 "%s: ----> Not forwarding to %s: I am not an MPR between %s and %s, direct link costs %5.2f\n",
685 neighbor_iface_buf.buf,
686 olsr_ip_to_string(&forw_buf, forwardedBy),
687 neighbor_iface_buf.buf,
696 /* Remember the best neighbor. If all are very bad, remember none. */
697 if (walker->link_cost < bestLinkCost)
699 *bestNeighbor = walker;
700 bestLinkCost = walker->link_cost;
703 /* Fill the list with up to 'FanOutLimit' neighbors. If there
704 * are more neighbors, broadcast is used instead of unicast. In that
705 * case we do not need the list of neighbors. */
706 if (*nPossibleNeighbors < FanOutLimit)
708 neighbors->links[*nPossibleNeighbors] = walker;
711 *nPossibleNeighbors += 1;
715 #else /* USING_THALES_LINK_COST_ROUTING */
717 struct link_entry* walker;
718 olsr_linkcost previousLinkEtx = LINK_COST_BROKEN;
719 olsr_linkcost bestEtx = LINK_COST_BROKEN;
721 if (forwardedBy != NULL)
723 /* Retrieve the cost of the link from 'forwardedBy' to myself */
724 struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
725 if (bestLinkFromForwarder != NULL)
727 previousLinkEtx = bestLinkFromForwarder->linkcost;
731 /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
732 OLSR_FOR_ALL_LINK_ENTRIES(walker) {
733 union olsr_ip_addr* neighborMainIp;
734 struct link_entry* bestLinkToNeighbor;
735 struct tc_entry* tcLastHop;
738 /* Consider only links from the specified interface */
739 if (! ipequal(&intf->intAddr, &walker->local_iface_addr))
746 "%s: ----> Considering forwarding pkt on \"%s\" to %s\n",
749 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
751 neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
753 /* Consider only neighbors with an IP address that differs from the
754 * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
755 if (source != NULL && ipequal(neighborMainIp, MainAddressOf(source)))
759 "%s: ----> Not forwarding to %s: is source of pkt\n",
761 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
766 /* Rely on short-circuit boolean evaluation */
767 if (forwardedBy != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedBy)))
771 "%s: ----> Not forwarding to %s: is the node that forwarded the pkt\n",
773 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
778 /* Rely on short-circuit boolean evaluation */
779 if (forwardedTo != NULL && ipequal(neighborMainIp, MainAddressOf(forwardedTo)))
783 "%s: ----> Not forwarding to %s: is the node to which the pkt was forwarded\n",
785 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
790 /* Found a candidate neighbor to direct our packet to */
792 /* Calculate the link quality (ETX) of the link to the found neighbor */
793 currEtx = walker->linkcost;
795 if (currEtx >= LINK_COST_BROKEN)
799 "%s: ----> Not forwarding to %s: link is timing out\n",
801 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
806 /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
809 "%s: ----> Forwarding pkt to %s will cost ETX %5.2f\n",
811 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
814 /* If the candidate neighbor is best reached via another interface, then skip
815 * the candidate neighbor; the candidate neighbor has been / will be selected via that
817 * Assumption: olsr_mutex has been grabbed for safe access to OLSR data. */
818 bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
820 if (walker != bestLinkToNeighbor)
822 if (bestLinkToNeighbor == NULL)
826 "%s: ----> Not forwarding to %s: no link found\n",
828 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
833 struct interface* bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
834 struct lqtextbuffer lqbuffer;
838 "%s: ----> Not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %s\n",
840 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
842 get_linkcost_text(bestLinkToNeighbor->linkcost, false, &lqbuffer));
848 if (forwardedBy != NULL)
851 struct ipaddr_str forwardedByBuf, niaBuf;
852 struct lqtextbuffer lqbuffer;
856 "%s: ----> 2-hop path from %s via me to %s will cost ETX %s\n",
858 olsr_ip_to_string(&forwardedByBuf, forwardedBy),
859 olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
860 get_linkcost_text(previousLinkEtx + currEtx, true, &lqbuffer));
863 /* Check the topology table whether the 'forwardedBy' node is itself a direct
864 * neighbor of the candidate neighbor, at a lower cost than the 2-hop route
865 * via myself. If so, we do not need to forward the BMF packet to the candidate
866 * neighbor, because the 'forwardedBy' node will forward the packet. */
867 if (forwardedBy != NULL)
869 /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
870 tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
871 if (tcLastHop != NULL)
873 struct tc_edge_entry* tc_edge;
875 /* Assumption: olsr_mutex has been grabbed for safe access to OLSR data */
876 tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
878 /* We are not interested in dead-end edges. */
880 olsr_linkcost tcEtx = tc_edge->cost;
882 if (previousLinkEtx + currEtx > tcEtx)
885 struct ipaddr_str neighbor_iface_buf, forw_buf;
886 struct lqtextbuffer lqbuffer;
887 olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
891 "%s: ----> Not forwarding to %s: I am not an MPR between %s and %s, direct link costs %s\n",
893 neighbor_iface_buf.buf,
894 olsr_ip_to_string(&forw_buf, forwardedBy),
895 neighbor_iface_buf.buf,
896 get_linkcost_text(tcEtx, false, &lqbuffer));
904 /* Remember the best neighbor. If all are very bad, remember none. */
905 if (currEtx < bestEtx)
907 *bestNeighbor = walker;
911 /* Fill the list with up to 'FanOutLimit' neighbors. If there
912 * are more neighbors, broadcast is used instead of unicast. In that
913 * case we do not need the list of neighbors. */
914 if (*nPossibleNeighbors < FanOutLimit)
916 neighbors->links[*nPossibleNeighbors] = walker;
919 *nPossibleNeighbors += 1;
920 } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
922 #endif /* USING_THALES_LINK_COST_ROUTING */
926 /* Display the result of the neighbor search */
927 if (*nPossibleNeighbors == 0)
931 "%s: ----> No suitable neighbor found to forward to on \"%s\"\n",
939 "%s: ----> %d neighbors found on \"%s\"; best neighbor to forward to: %s\n",
943 olsr_ip_to_string(&buf, &(*bestNeighbor)->neighbor_iface_addr));
946 } /* FindNeighbors */
948 /* -------------------------------------------------------------------------
949 * Function : CreateCaptureSocket
950 * Description: Create socket for promiscuously capturing multicast IP traffic
951 * Input : ifname - network interface (e.g. "eth0")
953 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
955 * Notes : The socket is a cooked IP packet socket, bound to the specified
957 * ------------------------------------------------------------------------- */
958 static int CreateCaptureSocket(const char* ifName)
960 int ifIndex = if_nametoindex(ifName);
961 struct packet_mreq mreq;
963 struct sockaddr_ll bindTo;
965 /* Open cooked IP packet socket */
966 int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
969 BmfPError("socket(PF_PACKET) error");
973 /* Set interface to promiscuous mode */
974 memset(&mreq, 0, sizeof(struct packet_mreq));
975 mreq.mr_ifindex = ifIndex;
976 mreq.mr_type = PACKET_MR_PROMISC;
977 if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
979 BmfPError("setsockopt(PACKET_MR_PROMISC) error");
984 /* Get hardware (MAC) address */
985 memset(&req, 0, sizeof(struct ifreq));
986 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
987 req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
988 if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
990 BmfPError("error retrieving MAC address");
995 /* Bind the socket to the specified interface */
996 memset(&bindTo, 0, sizeof(bindTo));
997 bindTo.sll_family = AF_PACKET;
998 bindTo.sll_protocol = htons(ETH_P_IP);
999 bindTo.sll_ifindex = ifIndex;
1000 memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
1001 bindTo.sll_halen = IFHWADDRLEN;
1003 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
1005 BmfPError("bind() error");
1010 /* Set socket to blocking operation */
1011 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1013 BmfPError("fcntl() error");
1018 AddDescriptorToInputSet(skfd);
1021 } /* CreateCaptureSocket */
1023 /* -------------------------------------------------------------------------
1024 * Function : CreateListeningSocket
1025 * Description: Create socket for promiscuously listening to BMF packets.
1026 * Used only when 'BmfMechanism' is BM_UNICAST_PROMISCUOUS
1027 * Input : ifname - network interface (e.g. "eth0")
1029 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
1031 * Notes : The socket is a cooked IP packet socket, bound to the specified
1033 * ------------------------------------------------------------------------- */
1034 static int CreateListeningSocket(const char* ifName)
1036 int ifIndex = if_nametoindex(ifName);
1037 struct packet_mreq mreq;
1039 struct sockaddr_ll bindTo;
1041 /* Open cooked IP packet socket */
1042 int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
1045 BmfPError("socket(PF_PACKET) error");
1049 /* Set interface to promiscuous mode */
1050 memset(&mreq, 0, sizeof(struct packet_mreq));
1051 mreq.mr_ifindex = ifIndex;
1052 mreq.mr_type = PACKET_MR_PROMISC;
1053 if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
1055 BmfPError("setsockopt(PACKET_MR_PROMISC) error");
1060 /* Get hardware (MAC) address */
1061 memset(&req, 0, sizeof(struct ifreq));
1062 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
1063 req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
1064 if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
1066 BmfPError("error retrieving MAC address");
1071 /* Bind the socket to the specified interface */
1072 memset(&bindTo, 0, sizeof(bindTo));
1073 bindTo.sll_family = AF_PACKET;
1074 bindTo.sll_protocol = htons(ETH_P_IP);
1075 bindTo.sll_ifindex = ifIndex;
1076 memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
1077 bindTo.sll_halen = IFHWADDRLEN;
1079 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
1081 BmfPError("bind() error");
1086 /* Set socket to blocking operation */
1087 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1089 BmfPError("fcntl() error");
1094 AddDescriptorToInputSet(skfd);
1097 } /* CreateListeningSocket */
1099 /* -------------------------------------------------------------------------
1100 * Function : CreateEncapsulateSocket
1101 * Description: Create a socket for sending and receiving encapsulated
1103 * Input : ifname - network interface (e.g. "eth0")
1105 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
1107 * Notes : The socket is an UDP (datagram) over IP socket, bound to the
1108 * specified network interface
1109 * ------------------------------------------------------------------------- */
1110 static int CreateEncapsulateSocket(const char* ifName)
1113 struct sockaddr_in bindTo;
1115 /* Open UDP-IP socket */
1116 int skfd = socket(PF_INET, SOCK_DGRAM, 0);
1119 BmfPError("socket(PF_INET) error");
1123 /* Enable sending to broadcast addresses */
1124 if (setsockopt(skfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
1126 BmfPError("setsockopt(SO_BROADCAST) error");
1131 /* Bind to the specific network interfaces indicated by ifName. */
1132 /* When using Kernel 2.6 this must happer prior to the port binding! */
1133 if (setsockopt(skfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, strlen(ifName) + 1) < 0)
1135 BmfPError("setsockopt(SO_BINDTODEVICE) error");
1140 /* Bind to BMF port */
1141 memset(&bindTo, 0, sizeof(bindTo));
1142 bindTo.sin_family = AF_INET;
1143 bindTo.sin_port = htons(BMF_ENCAP_PORT);
1144 bindTo.sin_addr.s_addr = htonl(INADDR_ANY);
1146 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
1148 BmfPError("bind() error");
1153 /* Set socket to blocking operation */
1154 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
1156 BmfPError("fcntl() error");
1161 AddDescriptorToInputSet(skfd);
1164 } /* CreateEncapsulateSocket */
1166 /* -------------------------------------------------------------------------
1167 * Function : CreateLocalEtherTunTap
1168 * Description: Creates and brings up an EtherTunTap interface
1171 * Return : the socket file descriptor (>= 0), or -1 in case of failure
1172 * Data Used : EtherTunTapIfName - name used for the tuntap interface (e.g.
1176 * EtherTunTapIpBroadcast
1178 * Note : Order dependency: call this function only if BmfInterfaces
1179 * is filled with a list of network interfaces.
1180 * ------------------------------------------------------------------------- */
1181 static int CreateLocalEtherTunTap(void)
1183 static const char deviceName[] = "/dev/net/tun";
1185 union olsr_sockaddr sock;
1190 etfd = open(deviceName, O_RDWR | O_NONBLOCK);
1193 BmfPError("error opening %s", deviceName);
1197 memset(&ifreq, 0, sizeof(ifreq));
1198 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1199 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1201 /* Specify the IFF_TUN flag for IP packets.
1202 * Specify IFF_NO_PI for not receiving extra meta packet information. */
1203 ifreq.ifr_flags = IFF_TUN;
1204 ifreq.ifr_flags |= IFF_NO_PI;
1206 if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0)
1208 BmfPError("ioctl(TUNSETIFF) error on %s", deviceName);
1213 memset(&ifreq, 0, sizeof(ifreq));
1214 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1215 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1216 ifreq.ifr_addr.sa_family = AF_INET;
1218 ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1221 BmfPError("socket(PF_INET) error on %s", deviceName);
1226 /* Give the EtherTunTap interface an IP address.
1227 * The default IP address is the address of the first OLSR interface;
1228 * the default netmask is 255.255.255.255 . Having an all-ones netmask prevents
1229 * automatic entry of the BMF network interface in the routing table. */
1230 if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
1232 struct TBmfInterface* nextBmfIf = BmfInterfaces;
1233 while (nextBmfIf != NULL)
1235 struct TBmfInterface* bmfIf = nextBmfIf;
1236 nextBmfIf = bmfIf->next;
1238 if (bmfIf->olsrIntf != NULL)
1240 EtherTunTapIp = ntohl(bmfIf->intAddr.v4.s_addr);
1241 EtherTunTapIpBroadcast = EtherTunTapIp;
1246 if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
1248 /* No IP address configured for BMF network interface, and no OLSR interface found to
1249 * copy IP address from. Fall back to default: 10.255.255.253 . */
1250 EtherTunTapIp = ETHERTUNTAPDEFAULTIP;
1253 memset(&sock, 0, sizeof(sock));
1254 sock.in4.sin_family = AF_INET;
1256 sock.in4.sin_addr.s_addr = htonl(EtherTunTapIp);
1257 ifreq.ifr_addr = sock.in;
1258 ioctlres = ioctl(ioctlSkfd, SIOCSIFADDR, &ifreq);
1262 sock.in4.sin_addr.s_addr = htonl(EtherTunTapIpMask);
1263 ifreq.ifr_netmask = sock.in;
1264 ioctlres = ioctl(ioctlSkfd, SIOCSIFNETMASK, &ifreq);
1267 /* Set broadcast IP */
1268 sock.in4.sin_addr.s_addr = htonl(EtherTunTapIpBroadcast);
1269 ifreq.ifr_broadaddr = sock.in;
1270 ioctlres = ioctl(ioctlSkfd, SIOCSIFBRDADDR, &ifreq);
1273 /* Bring EtherTunTap interface up (if not already) */
1274 ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
1277 ifreq.ifr_flags |= (IFF_UP | IFF_RUNNING | IFF_BROADCAST);
1278 ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
1286 /* Any of the above ioctl() calls failed */
1287 BmfPError("error bringing up EtherTunTap interface \"%s\"", EtherTunTapIfName);
1292 } /* if (ioctlres < 0) */
1294 /* Set the multicast flag on the interface */
1295 memset(&ifreq, 0, sizeof(ifreq));
1296 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
1297 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1299 ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
1302 ifreq.ifr_flags |= IFF_MULTICAST;
1303 ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
1307 /* Any of the two above ioctl() calls failed */
1308 BmfPError("error setting multicast flag on EtherTunTap interface \"%s\"", EtherTunTapIfName);
1310 /* Continue anyway */
1313 /* Use ioctl to make the tuntap persistent. Otherwise it will disappear
1314 * when this program exits. That is not desirable, since a multicast
1315 * daemon (e.g. mrouted) may be using the tuntap interface. */
1316 if (ioctl(etfd, TUNSETPERSIST, (void *)&ifreq) < 0)
1318 BmfPError("error making EtherTunTap interface \"%s\" persistent", EtherTunTapIfName);
1320 /* Continue anyway */
1323 OLSR_PRINTF(8, "%s: opened 1 socket on \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
1325 AddDescriptorToInputSet(etfd);
1327 /* If the user configured a specific IP address for the BMF network interface,
1328 * help the user and advertise the IP address of the BMF network interface
1329 * on the OLSR network via HNA */
1330 if (TunTapIpOverruled != 0)
1332 union olsr_ip_addr temp_net;
1334 temp_net.v4.s_addr = htonl(EtherTunTapIp);
1335 ip_prefix_list_add(&olsr_cnf->hna_entries, &temp_net, 32);
1341 } /* CreateLocalEtherTunTap */
1343 /* -------------------------------------------------------------------------
1344 * Function : CreateInterface
1345 * Description: Create a new TBmfInterface object and adds it to the global
1346 * BmfInterfaces list
1347 * Input : ifName - name of the network interface (e.g. "eth0")
1348 * : olsrIntf - OLSR interface object of the network interface, or
1349 * NULL if the network interface is not OLSR-enabled
1351 * Return : the number of opened sockets
1352 * Data Used : BmfInterfaces, LastBmfInterface
1353 * ------------------------------------------------------------------------- */
1354 static int CreateInterface(
1356 struct interface* olsrIntf)
1358 int capturingSkfd = -1;
1359 int encapsulatingSkfd = -1;
1360 int listeningSkfd = -1;
1364 struct TBmfInterface* newIf = malloc(sizeof(struct TBmfInterface));
1366 assert(ifName != NULL);
1373 if (olsrIntf != NULL)
1375 /* On OLSR-enabled interfaces, create socket for encapsulating and forwarding
1376 * multicast packets */
1377 encapsulatingSkfd = CreateEncapsulateSocket(ifName);
1378 if (encapsulatingSkfd < 0)
1386 /* Create socket for capturing and sending of multicast packets on
1387 * non-OLSR interfaces, and on OLSR-interfaces if configured. */
1388 if ((olsrIntf == NULL) || (CapturePacketsOnOlsrInterfaces != 0))
1390 capturingSkfd = CreateCaptureSocket(ifName);
1391 if (capturingSkfd < 0)
1393 close(encapsulatingSkfd);
1401 /* Create promiscuous mode listening interface if BMF uses IP unicast
1402 * as underlying forwarding mechanism */
1403 if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
1405 listeningSkfd = CreateListeningSocket(ifName);
1406 if (listeningSkfd < 0)
1408 close(listeningSkfd);
1409 close(encapsulatingSkfd); /* no problem if 'encapsulatingSkfd' is -1 */
1417 /* For ioctl operations on the network interface, use either capturingSkfd
1418 * or encapsulatingSkfd, whichever is available */
1419 ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd;
1421 /* Retrieve the MAC address of the interface. */
1422 memset(&ifr, 0, sizeof(struct ifreq));
1423 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1424 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1425 if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0)
1427 BmfPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
1428 close(capturingSkfd);
1429 close(encapsulatingSkfd);
1434 /* Copy data into TBmfInterface object */
1435 newIf->capturingSkfd = capturingSkfd;
1436 newIf->encapsulatingSkfd = encapsulatingSkfd;
1437 newIf->listeningSkfd = listeningSkfd;
1438 memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1439 memcpy(newIf->ifName, ifName, IFNAMSIZ);
1440 newIf->olsrIntf = olsrIntf;
1441 if (olsrIntf != NULL)
1443 /* For an OLSR-interface, copy the interface address and broadcast
1444 * address from the OLSR interface object. Downcast to correct sockaddr
1446 newIf->intAddr.v4 = ((struct sockaddr_in *)&olsrIntf->int_addr)->sin_addr;
1447 newIf->broadAddr.v4 = ((struct sockaddr_in *)&olsrIntf->int_broadaddr)->sin_addr;
1451 /* For a non-OLSR interface, retrieve the IP address ourselves */
1452 memset(&ifr, 0, sizeof(struct ifreq));
1453 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1454 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1455 if (ioctl(ioctlSkfd, SIOCGIFADDR, &ifr) < 0)
1457 BmfPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
1459 newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
1463 /* Downcast to correct sockaddr subtype */
1464 newIf->intAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
1467 /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
1468 memset(&ifr, 0, sizeof(struct ifreq));
1469 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1470 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1471 if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0)
1473 BmfPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
1475 newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
1479 /* Downcast to correct sockaddr subtype */
1480 newIf->broadAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr;
1484 /* Reset counters */
1485 newIf->nBmfPacketsRx = 0;
1486 newIf->nBmfPacketsRxDup = 0;
1487 newIf->nBmfPacketsTx = 0;
1489 /* Add new TBmfInterface object to global list. OLSR interfaces are
1490 * added at the front of the list, non-OLSR interfaces at the back. */
1491 if (BmfInterfaces == NULL)
1493 /* First TBmfInterface object in list */
1495 BmfInterfaces = newIf;
1496 LastBmfInterface = newIf;
1498 else if (olsrIntf != NULL)
1500 /* Add new TBmfInterface object at front of list */
1501 newIf->next = BmfInterfaces;
1502 BmfInterfaces = newIf;
1506 /* Add new TBmfInterface object at back of list */
1508 LastBmfInterface->next= newIf;
1509 LastBmfInterface = newIf;
1514 "%s: opened %d socket%s on %s interface \"%s\"\n",
1517 nOpened == 1 ? "" : "s",
1518 olsrIntf != NULL ? "OLSR" : "non-OLSR",
1522 } /* CreateInterface */
1524 /* -------------------------------------------------------------------------
1525 * Function : CreateBmfNetworkInterfaces
1526 * Description: Create a list of TBmfInterface objects, one for each network
1527 * interface on which BMF runs
1528 * Input : skipThisIntf - network interface to skip, if seen
1530 * Return : fail (-1) or success (0)
1532 * ------------------------------------------------------------------------- */
1533 int CreateBmfNetworkInterfaces(struct interface* skipThisIntf)
1540 int nOpenedSockets = 0;
1542 /* Clear input descriptor set */
1545 skfd = socket(PF_INET, SOCK_DGRAM, 0);
1548 BmfPError("no inet socket available to retrieve interface list");
1552 /* Retrieve the network interface configuration list */
1556 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
1557 ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
1559 if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
1561 BmfPError("ioctl(SIOCGIFCONF) error");
1567 if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs)
1569 /* Assume it overflowed; double the space and try again */
1571 assert(numreqs < 1024);
1572 continue; /* for (;;) */
1574 break; /* for (;;) */
1579 /* For each item in the interface configuration list... */
1581 for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++)
1583 struct interface* olsrIntf;
1584 union olsr_ip_addr ipAddr;
1586 /* Skip the BMF network interface itself */
1587 if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
1589 continue; /* for (n = ...) */
1592 /* ...find the OLSR interface structure, if any */
1593 ipAddr.v4 = ((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr;
1594 olsrIntf = if_ifwithaddr(&ipAddr);
1596 if (skipThisIntf != NULL && olsrIntf == skipThisIntf)
1598 continue; /* for (n = ...) */
1601 if (olsrIntf == NULL && ! IsNonOlsrBmfIf(ifr->ifr_name))
1603 /* Interface is neither OLSR interface, nor specified as non-OLSR BMF
1604 * interface in the BMF plugin parameter list */
1605 continue; /* for (n = ...) */
1608 nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
1610 } /* for (n = ...) */
1614 /* Create the BMF network interface */
1615 EtherTunTapFd = CreateLocalEtherTunTap();
1616 if (EtherTunTapFd >= 0)
1621 if (BmfInterfaces == NULL)
1623 olsr_printf(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
1627 olsr_printf(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
1630 } /* CreateBmfNetworkInterfaces */
1632 /* -------------------------------------------------------------------------
1633 * Function : CloseBmfNetworkInterfaces
1634 * Description: Closes every socket on each network interface used by BMF
1638 * Data Used : BmfInterfaces, LastBmfInterface
1640 * - the local EtherTunTap interface (e.g. "tun0" or "tap0")
1641 * - for each BMF-enabled interface, the socket used for
1642 * capturing multicast packets
1643 * - for each OLSR-enabled interface, the socket used for
1644 * encapsulating packets
1645 * Also restores the network state to the situation before BMF
1647 * ------------------------------------------------------------------------- */
1648 void CloseBmfNetworkInterfaces(void)
1651 u_int32_t totalOlsrBmfPacketsRx = 0;
1652 u_int32_t totalOlsrBmfPacketsRxDup = 0;
1653 u_int32_t totalOlsrBmfPacketsTx = 0;
1654 u_int32_t totalNonOlsrBmfPacketsRx = 0;
1655 u_int32_t totalNonOlsrBmfPacketsRxDup = 0;
1656 u_int32_t totalNonOlsrBmfPacketsTx = 0;
1658 /* Close all opened sockets */
1659 struct TBmfInterface* nextBmfIf = BmfInterfaces;
1660 while (nextBmfIf != NULL)
1662 struct TBmfInterface* bmfIf = nextBmfIf;
1663 nextBmfIf = bmfIf->next;
1665 if (bmfIf->capturingSkfd >= 0)
1667 close(bmfIf->capturingSkfd);
1670 if (bmfIf->encapsulatingSkfd >= 0)
1672 close(bmfIf->encapsulatingSkfd);
1678 "%s: %s interface \"%s\": RX pkts %d (%d dups); TX pkts %d\n",
1680 bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
1682 bmfIf->nBmfPacketsRx,
1683 bmfIf->nBmfPacketsRxDup,
1684 bmfIf->nBmfPacketsTx);
1688 "%s: closed %s interface \"%s\"\n",
1690 bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
1694 if (bmfIf->olsrIntf != NULL)
1696 totalOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
1697 totalOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
1698 totalOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
1702 totalNonOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
1703 totalNonOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
1704 totalNonOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
1710 if (EtherTunTapFd >= 0)
1712 close(EtherTunTapFd);
1715 OLSR_PRINTF(7, "%s: closed \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName);
1718 BmfInterfaces = NULL;
1719 LastBmfInterface = NULL;
1721 /* Re-initialize the IP address for the BMF network interface. Thanks to
1722 * Daniele Lacamera for finding and solving this bug. */
1723 EtherTunTapIp = ETHERTUNTAPIPNOTSET;
1725 olsr_printf(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
1729 "%s: Total all OLSR interfaces : RX pkts %d (%d dups); TX pkts %d\n",
1731 totalOlsrBmfPacketsRx,
1732 totalOlsrBmfPacketsRxDup,
1733 totalOlsrBmfPacketsTx);
1736 "%s: Total all non-OLSR interfaces: RX pkts %d (%d dups); TX pkts %d\n",
1738 totalNonOlsrBmfPacketsRx,
1739 totalNonOlsrBmfPacketsRxDup,
1740 totalNonOlsrBmfPacketsTx);
1741 } /* CloseBmfNetworkInterfaces */
1743 #define MAX_NON_OLSR_IFS 32
1744 static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
1745 static int nNonOlsrIfs = 0;
1747 /* -------------------------------------------------------------------------
1748 * Function : AddNonOlsrBmfIf
1749 * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
1750 * network interfaces
1751 * Input : ifName - network interface (e.g. "eth0")
1755 * Return : success (0) or fail (1)
1756 * Data Used : NonOlsrIfNames
1757 * ------------------------------------------------------------------------- */
1758 int AddNonOlsrBmfIf(
1760 void* data __attribute__((unused)),
1761 set_plugin_parameter_addon addon __attribute__((unused)))
1763 assert(ifName != NULL);
1765 if (nNonOlsrIfs >= MAX_NON_OLSR_IFS)
1769 "%s: too many non-OLSR interfaces specified, maximum is %d\n",
1775 strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
1776 NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1779 } /* AddNonOlsrBmfIf */
1781 /* -------------------------------------------------------------------------
1782 * Function : IsNonOlsrBmfIf
1783 * Description: Checks if a network interface is OLSR-enabled
1784 * Input : ifName - network interface (e.g. "eth0")
1786 * Return : true (1) or false (0)
1787 * Data Used : NonOlsrIfNames
1788 * ------------------------------------------------------------------------- */
1789 int IsNonOlsrBmfIf(const char* ifName)
1793 assert(ifName != NULL);
1795 for (i = 0; i < nNonOlsrIfs; i++)
1797 if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0) return 1;
1800 } /* IsNonOlsrBmfIf */
1802 /* -------------------------------------------------------------------------
1803 * Function : CheckAndUpdateLocalBroadcast
1804 * Description: For an IP packet, check if the destination address is not a
1805 * multicast address. If it is not, the packet is assumed to be
1806 * a local broadcast packet. In that case, set the destination
1807 * address of the IP packet to the passed broadcast address.
1808 * Input : ipPacket - the IP packet
1809 * broadAddr - the broadcast address to fill in
1813 * Notes : See also RFC1141
1814 * ------------------------------------------------------------------------- */
1815 void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* broadAddr)
1818 union olsr_ip_addr destIp;
1820 assert(ipPacket != NULL && broadAddr != NULL);
1822 iph = (struct iphdr*) ipPacket;
1823 destIp.v4.s_addr = iph->daddr;
1824 if (! IsMulticast(&destIp))
1826 u_int32_t origDaddr, newDaddr;
1829 origDaddr = ntohl(iph->daddr);
1831 iph->daddr = broadAddr->v4.s_addr;
1832 newDaddr = ntohl(iph->daddr);
1834 /* Re-calculate IP header checksum for new destination */
1835 check = ntohs(iph->check);
1837 check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
1838 check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
1841 check = check + (check >> 16);
1843 iph->check = htons(check);
1845 if (iph->protocol == SOL_UDP)
1847 /* Re-calculate UDP/IP checksum for new destination */
1849 int ipHeaderLen = GetIpHeaderLength(ipPacket);
1850 struct udphdr* udph = (struct udphdr*) (ipPacket + ipHeaderLen);
1852 /* RFC 1624, Eq. 3: HC' = ~(~HC - m + m') */
1854 check = ntohs(udph->check);
1856 check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
1857 check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
1860 check = check + (check >> 16);
1862 udph->check = htons(check);
1865 } /* CheckAndUpdateLocalBroadcast */
1867 /* -------------------------------------------------------------------------
1868 * Function : AddMulticastRoute
1869 * Description: Insert a route to all multicast addresses in the kernel
1870 * routing table. The route will be via the BMF network interface.
1875 * ------------------------------------------------------------------------- */
1876 void AddMulticastRoute(void)
1878 struct rtentry kernel_route;
1879 union olsr_sockaddr sock;
1881 int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1884 BmfPError("socket(PF_INET) error");
1888 memset(&kernel_route, 0, sizeof(struct rtentry));
1890 kernel_route.rt_gateway.sa_family = AF_INET;
1893 memset(&sock, 0, sizeof(sock));
1894 sock.in4.sin_family = AF_INET;
1896 sock.in4.sin_addr.s_addr = htonl(0xE0000000);
1897 kernel_route.rt_dst = sock.in;
1899 sock.in4.sin_addr.s_addr = htonl(0xF0000000);
1900 kernel_route.rt_genmask = sock.in;
1902 kernel_route.rt_metric = 0;
1903 kernel_route.rt_flags = RTF_UP;
1905 kernel_route.rt_dev = EtherTunTapIfName;
1907 if (ioctl(ioctlSkfd, SIOCADDRT, &kernel_route) < 0)
1909 BmfPError("error setting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
1911 /* Continue anyway */
1914 } /* AddMulticastRoute */
1916 /* -------------------------------------------------------------------------
1917 * Function : DeleteMulticastRoute
1918 * Description: Delete the route to all multicast addresses from the kernel
1924 * ------------------------------------------------------------------------- */
1925 void DeleteMulticastRoute(void)
1927 if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
1929 struct rtentry kernel_route;
1930 union olsr_sockaddr sock;
1932 int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1935 BmfPError("socket(PF_INET) error");
1939 memset(&kernel_route, 0, sizeof(struct rtentry));
1941 kernel_route.rt_gateway.sa_family = AF_INET;
1944 memset(&sock, 0, sizeof(sock));
1945 sock.in4.sin_family = AF_INET;
1947 sock.in4.sin_addr.s_addr = htonl(0xE0000000);
1948 kernel_route.rt_dst = sock.in;
1950 sock.in4.sin_addr.s_addr = htonl(0xF0000000);
1951 kernel_route.rt_genmask = sock.in;
1953 kernel_route.rt_metric = 0;
1954 kernel_route.rt_flags = RTF_UP;
1956 kernel_route.rt_dev = EtherTunTapIfName;
1958 if (ioctl(ioctlSkfd, SIOCDELRT, &kernel_route) < 0)
1960 BmfPError("error deleting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
1962 /* Continue anyway */
1966 } /* DeleteMulticastRoute */