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 */
58 #include <stdlib.h> /* atoi, malloc */
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 "olsr_ip_prefix_list.h"
69 #include "olsr_logging.h"
72 #include "Packet.h" /* IFHWADDRLEN */
73 #include "Bmf.h" /* PLUGIN_NAME, MainAddressOf() */
74 #include "Address.h" /* IsMulticast() */
76 /* List of network interface objects used by BMF plugin */
77 struct TBmfInterface* BmfInterfaces = NULL;
78 struct TBmfInterface* LastBmfInterface = NULL;
80 /* Highest-numbered open socket file descriptor. To be used as first
81 * parameter in calls to select(...). */
84 /* Set of socket file descriptors */
87 /* File descriptor of EtherTunTap interface */
88 int EtherTunTapFd = -1;
90 /* Network interface name of EtherTunTap interface. May be overruled by
91 * setting the plugin parameter "BmfInterface". */
92 char EtherTunTapIfName[IFNAMSIZ] = "bmf0";
94 /* The underlying mechanism to forward multicast packets. Either:
95 * - BM_BROADCAST: BMF uses the IP local broadcast as destination address
96 * - BM_UNICAST_PROMISCUOUS: BMF uses the IP address of the best neighbor as
97 * destination address. The other neighbors listen promiscuously. */
98 enum TBmfMechanism BmfMechanism = BM_BROADCAST;
100 #define ETHERTUNTAPIPNOTSET 0
102 /* The IP address of the BMF network interface in host byte order.
103 * May be overruled by setting the plugin parameter "BmfInterfaceIp". */
104 u_int32_t EtherTunTapIp = ETHERTUNTAPIPNOTSET;
106 /* 255.255.255.255 in host byte order. May be overruled by
107 * setting the plugin parameter "BmfInterfaceIp". */
108 u_int32_t EtherTunTapIpMask = 0xFFFFFFFF;
110 /* The IP broadcast address of the BMF network interface in host byte order.
111 * May be overruled by setting the plugin parameter "BmfinterfaceIp". */
112 u_int32_t EtherTunTapIpBroadcast = ETHERTUNTAPIPNOTSET;
114 /* Whether or not the configuration has overruled the default IP
115 * configuration of the EtherTunTap interface */
116 int TunTapIpOverruled = 0;
118 /* Whether or not to capture packets on the OLSR-enabled
119 * interfaces (in promiscuous mode). May be overruled by setting the plugin
120 * parameter "CapturePacketsOnOlsrInterfaces" to "yes". */
121 int CapturePacketsOnOlsrInterfaces = 0;
123 /* -------------------------------------------------------------------------
124 * Function : SetBmfInterfaceName
125 * Description: Overrule the default network interface name ("bmf0") of the
126 * EtherTunTap interface
127 * Input : ifname - network interface name (e.g. "mybmf0")
131 * Return : success (0) or fail (1)
132 * Data Used : EtherTunTapIfName
133 * ------------------------------------------------------------------------- */
134 int SetBmfInterfaceName(
136 void* data __attribute__((unused)),
137 set_plugin_parameter_addon addon __attribute__((unused)))
139 strncpy(EtherTunTapIfName, ifname, IFNAMSIZ - 1);
140 EtherTunTapIfName[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
142 } /* SetBmfInterfaceName */
144 /* -------------------------------------------------------------------------
145 * Function : SetBmfInterfaceIp
146 * Description: Overrule the default IP address and prefix length
147 * ("10.255.255.253/30") of the EtherTunTap interface
148 * Input : ip - IP address string, followed by '/' and prefix length
152 * Return : success (0) or fail (1)
153 * Data Used : EtherTunTapIp, EtherTunTapIpMask, EtherTunTapIpBroadcast,
155 * ------------------------------------------------------------------------- */
156 int SetBmfInterfaceIp(
158 void* data __attribute__((unused)),
159 set_plugin_parameter_addon addon __attribute__((unused)))
161 #define IPV4_MAX_ADDRLEN 16
162 #define IPV4_MAX_PREFIXLEN 32
164 char ipAddr[IPV4_MAX_ADDRLEN];
165 struct in_addr sinaddr;
169 /* Inspired by function str2prefix_ipv4 as found in Quagga source
170 * file lib/prefix.c */
172 /* Find slash inside string. */
173 slashAt = strchr(ip, '/');
175 /* String doesn't contain slash. */
176 if (slashAt == NULL || slashAt - ip >= IPV4_MAX_ADDRLEN)
178 /* No prefix length specified, or IP address too long */
182 strncpy(ipAddr, ip, slashAt - ip);
183 *(ipAddr + (slashAt - ip)) = '\0';
184 if (inet_aton(ipAddr, &sinaddr) == 0)
186 /* Invalid address passed */
190 EtherTunTapIp = ntohl(sinaddr.s_addr);
192 /* Get prefix length. */
193 prefixLen = atoi(++slashAt);
194 if (prefixLen <= 0 || prefixLen > IPV4_MAX_PREFIXLEN)
199 /* Compose IP subnet mask in host byte order */
200 EtherTunTapIpMask = 0;
201 for (i = 0; i < prefixLen; i++)
203 EtherTunTapIpMask |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
206 /* Compose IP broadcast address in host byte order */
207 EtherTunTapIpBroadcast = EtherTunTapIp;
208 for (i = prefixLen; i < IPV4_MAX_PREFIXLEN; i++)
210 EtherTunTapIpBroadcast |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i));
213 TunTapIpOverruled = 1;
216 } /* SetBmfInterfaceIp */
218 /* -------------------------------------------------------------------------
219 * Function : SetCapturePacketsOnOlsrInterfaces
220 * Description: Overrule the default setting, enabling or disabling the
221 * capturing of packets on OLSR-enabled interfaces.
222 * Input : enable - either "yes" or "no"
226 * Return : success (0) or fail (1)
228 * ------------------------------------------------------------------------- */
229 int SetCapturePacketsOnOlsrInterfaces(
231 void* data __attribute__((unused)),
232 set_plugin_parameter_addon addon __attribute__((unused)))
234 if (strcmp(enable, "yes") == 0)
236 CapturePacketsOnOlsrInterfaces = 1;
239 else if (strcmp(enable, "no") == 0)
241 CapturePacketsOnOlsrInterfaces = 0;
245 /* Value not recognized */
247 } /* SetCapturePacketsOnOlsrInterfaces */
249 /* -------------------------------------------------------------------------
250 * Function : SetBmfMechanism
251 * Description: Overrule the default BMF mechanism to either BM_BROADCAST or
252 * BM_UNICAST_PROMISCUOUS.
253 * Input : mechanism - either "Broadcast" or "UnicastPromiscuous"
257 * Return : success (0) or fail (1)
259 * ------------------------------------------------------------------------- */
261 const char* mechanism,
262 void* data __attribute__((unused)),
263 set_plugin_parameter_addon addon __attribute__((unused)))
265 if (strcmp(mechanism, "Broadcast") == 0)
267 BmfMechanism = BM_BROADCAST;
270 else if (strcmp(mechanism, "UnicastPromiscuous") == 0)
272 BmfMechanism = BM_UNICAST_PROMISCUOUS;
276 /* Value not recognized */
278 } /* SetBmfMechanism */
280 /* -------------------------------------------------------------------------
281 * Function : AddDescriptorToInputSet
282 * Description: Add a socket descriptor to the global set of socket file descriptors
283 * Input : skfd - socket file descriptor
286 * Data Used : HighestSkfd, InputSet
287 * Notes : Keeps track of the highest-numbered descriptor
288 * ------------------------------------------------------------------------- */
289 static void AddDescriptorToInputSet(int skfd)
291 /* Keep the highest-numbered descriptor */
292 if (skfd > HighestSkfd)
297 /* Add descriptor to input set */
298 FD_SET(skfd, &InputSet);
299 } /* AddDescriptorToInputSet */
301 /* To save the state of the IP spoof filter for the EtherTunTap interface */
302 static char EthTapSpoofState = '1';
304 /* -------------------------------------------------------------------------
305 * Function : DeactivateSpoofFilter
306 * Description: Deactivates the Linux anti-spoofing filter for the tuntap
310 * Return : fail (0) or success (1)
311 * Data Used : EtherTunTapIfName, EthTapSpoofState
312 * Notes : Saves the current filter state for later restoring
313 * ------------------------------------------------------------------------- */
314 int DeactivateSpoofFilter(void)
317 char procFile[FILENAME_MAX];
319 /* Generate the procfile name */
320 sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName);
322 /* Open procfile for reading */
323 procSpoof = fopen(procFile, "r");
324 if (procSpoof == NULL)
328 "WARNING! Could not open the %s file to check/disable the IP spoof filter!\n"
329 "Are you using the procfile filesystem?\n"
330 "Does your system support IPv4?\n"
331 "I will continue (in 3 sec) - but you should manually ensure that IP spoof\n"
332 "filtering is disabled!\n\n",
339 EthTapSpoofState = fgetc(procSpoof);
342 /* Open procfile for writing */
343 procSpoof = fopen(procFile, "w");
344 if (procSpoof == NULL)
346 OLSR_WARN(LOG_PLUGINS, "Could not open %s for writing!\n"
347 "I will continue (in 3 sec) - but you should manually ensure that IP"
348 " spoof filtering is disabled!\n\n", 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 OLSR_WARN(LOG_PLUGINS, "Could not open %s for writing!\nSettings not restored!\n", procFile);
385 fputc(EthTapSpoofState, procSpoof);
388 } /* RestoreSpoofFilter */
390 /* -------------------------------------------------------------------------
391 * Function : FindNeighbors
392 * Description: Find the neighbors on a network interface to forward a BMF
394 * Input : intf - the network interface
395 * source - the source IP address of the BMF packet
396 * forwardedBy - the IP address of the node that forwarded the BMF
398 * forwardedTo - the IP address of the node to which the BMF packet
400 * Output : neighbors - list of (up to a number of 'FanOutLimit') neighbors.
401 * bestNeighbor - the best neighbor (in terms of lowest cost or ETX
403 * nPossibleNeighbors - number of found possible neighbors
404 * Data Used : FanOutLimit
405 * ------------------------------------------------------------------------- */
407 struct TBestNeighbors* neighbors,
408 struct link_entry** bestNeighbor,
409 struct TBmfInterface* intf,
410 union olsr_ip_addr* source,
411 union olsr_ip_addr* forwardedBy,
412 union olsr_ip_addr* forwardedTo,
413 int* nPossibleNeighbors)
415 struct link_entry* walker;
416 olsr_linkcost previousLinkEtx = LINK_COST_BROKEN;
417 olsr_linkcost bestEtx = LINK_COST_BROKEN;
422 *bestNeighbor = NULL;
423 for (i = 0; i < MAX_UNICAST_NEIGHBORS; i++)
425 neighbors->links[i] = NULL;
427 *nPossibleNeighbors = 0;
429 if (forwardedBy != NULL)
431 /* Retrieve the cost of the link from 'forwardedBy' to myself */
432 struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy);
433 if (bestLinkFromForwarder != NULL)
435 previousLinkEtx = bestLinkFromForwarder->linkcost;
439 OLSR_FOR_ALL_LINK_ENTRIES(walker) {
440 struct ipaddr_str buf;
441 union olsr_ip_addr* neighborMainIp;
442 struct link_entry* bestLinkToNeighbor;
443 struct tc_entry* tcLastHop;
446 /* Consider only links from the specified interface */
447 if (olsr_ipcmp(&intf->intAddr, &walker->local_iface_addr) != 0)
454 "Considering forwarding pkt on \"%s\" to %s\n",
456 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
458 neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr);
460 /* Consider only neighbors with an IP address that differs from the
461 * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */
462 if (source != NULL && olsr_ipcmp(neighborMainIp, MainAddressOf(source)) == 0)
466 "Not forwarding to %s: is source of pkt\n",
467 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
472 /* Rely on short-circuit boolean evaluation */
473 if (forwardedBy != NULL && olsr_ipcmp(neighborMainIp, MainAddressOf(forwardedBy)) == 0)
477 "Not forwarding to %s: is the node that forwarded the pkt\n",
478 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
483 /* Rely on short-circuit boolean evaluation */
484 if (forwardedTo != NULL && olsr_ipcmp(neighborMainIp, MainAddressOf(forwardedTo)) == 0)
488 "Not forwarding to %s: is the node to which the pkt was forwarded\n",
489 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
494 /* Found a candidate neighbor to direct our packet to */
496 /* Calculate the link quality (ETX) of the link to the found neighbor */
497 currEtx = walker->linkcost;
499 if (currEtx >= LINK_COST_BROKEN)
503 "Not forwarding to %s: link is timing out\n",
504 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
509 /* Compare costs to check if the candidate neighbor is best reached via 'intf' */
512 "Forwarding pkt to %s will cost ETX %5.2f\n",
513 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
517 * If the candidate neighbor is best reached via another interface, then skip
518 * the candidate neighbor; the candidate neighbor has been / will be selected via that
521 bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr);
523 if (walker != bestLinkToNeighbor)
525 if (bestLinkToNeighbor == NULL)
529 "Not forwarding to %s: no link found\n",
530 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr));
534 #if !defined REMOVE_DEBUG
535 struct interface* bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr);
536 struct lqtextbuffer lqbuffer;
540 "Not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %s\n",
541 olsr_ip_to_string(&buf, &walker->neighbor_iface_addr),
543 get_linkcost_text(bestLinkToNeighbor->linkcost, false, &lqbuffer));
549 if (forwardedBy != NULL)
551 #if !defined REMOVE_DEBUG
552 struct ipaddr_str forwardedByBuf, niaBuf;
553 struct lqtextbuffer lqbuffer;
557 "2-hop path from %s via me to %s will cost ETX %s\n",
558 olsr_ip_to_string(&forwardedByBuf, forwardedBy),
559 olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr),
560 get_linkcost_text(previousLinkEtx + currEtx, true, &lqbuffer));
563 /* Check the topology table whether the 'forwardedBy' node is itself a direct
564 * neighbor of the candidate neighbor, at a lower cost than the 2-hop route
565 * via myself. If so, we do not need to forward the BMF packet to the candidate
566 * neighbor, because the 'forwardedBy' node will forward the packet. */
567 if (forwardedBy != NULL)
569 tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy));
570 if (tcLastHop != NULL)
572 struct tc_edge_entry* tc_edge;
574 tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr));
576 /* We are not interested in dead-end edges. */
578 olsr_linkcost tcEtx = tc_edge->cost;
580 if (previousLinkEtx + currEtx > tcEtx)
582 #if !defined REMOVE_DEBUG
583 struct ipaddr_str neighbor_iface_buf, forw_buf;
584 struct lqtextbuffer lqbuffer;
585 olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr);
589 "Not forwarding to %s: I am not an MPR between %s and %s, direct link costs %s\n",
590 neighbor_iface_buf.buf,
591 olsr_ip_to_string(&forw_buf, forwardedBy),
592 neighbor_iface_buf.buf,
593 get_linkcost_text(tcEtx, false, &lqbuffer));
601 /* Remember the best neighbor. If all are very bad, remember none. */
602 if (currEtx < bestEtx)
604 *bestNeighbor = walker;
608 /* Fill the list with up to 'FanOutLimit' neighbors. If there
609 * are more neighbors, broadcast is used instead of unicast. In that
610 * case we do not need the list of neighbors. */
611 if (*nPossibleNeighbors < FanOutLimit)
613 neighbors->links[*nPossibleNeighbors] = walker;
616 *nPossibleNeighbors += 1;
617 } OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
619 /* Display the result of the neighbor search */
620 if (*nPossibleNeighbors == 0)
624 "No suitable neighbor found to forward to on \"%s\"\n",
629 struct ipaddr_str buf;
632 "%d neighbors found on \"%s\"; best neighbor to forward to: %s\n",
635 olsr_ip_to_string(&buf, &(*bestNeighbor)->neighbor_iface_addr));
638 } /* FindNeighbors */
640 /* -------------------------------------------------------------------------
641 * Function : CreateCaptureSocket
642 * Description: Create socket for promiscuously capturing multicast IP traffic
643 * Input : ifname - network interface (e.g. "eth0")
645 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
647 * Notes : The socket is a cooked IP packet socket, bound to the specified
649 * ------------------------------------------------------------------------- */
650 static int CreateCaptureSocket(const char* ifName)
652 int ifIndex = if_nametoindex(ifName);
653 struct packet_mreq mreq;
655 struct sockaddr_ll bindTo;
657 /* Open cooked IP packet socket */
658 int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
661 OLSR_WARN(LOG_PLUGINS, "socket(PF_PACKET) error");
665 /* Set interface to promiscuous mode */
666 memset(&mreq, 0, sizeof(struct packet_mreq));
667 mreq.mr_ifindex = ifIndex;
668 mreq.mr_type = PACKET_MR_PROMISC;
669 if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
671 OLSR_WARN(LOG_PLUGINS, "setsockopt(PACKET_MR_PROMISC) error");
676 /* Get hardware (MAC) address */
677 memset(&req, 0, sizeof(struct ifreq));
678 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
679 req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
680 if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
682 OLSR_WARN(LOG_PLUGINS, "error retrieving MAC address");
687 /* Bind the socket to the specified interface */
688 memset(&bindTo, 0, sizeof(bindTo));
689 bindTo.sll_family = AF_PACKET;
690 bindTo.sll_protocol = htons(ETH_P_IP);
691 bindTo.sll_ifindex = ifIndex;
692 memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
693 bindTo.sll_halen = IFHWADDRLEN;
695 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
697 OLSR_WARN(LOG_PLUGINS, "bind() error");
702 /* Set socket to blocking operation */
703 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
705 OLSR_WARN(LOG_PLUGINS, "fcntl() error");
710 AddDescriptorToInputSet(skfd);
713 } /* CreateCaptureSocket */
715 /* -------------------------------------------------------------------------
716 * Function : CreateListeningSocket
717 * Description: Create socket for promiscuously listening to BMF packets.
718 * Used only when 'BmfMechanism' is BM_UNICAST_PROMISCUOUS
719 * Input : ifname - network interface (e.g. "eth0")
721 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
723 * Notes : The socket is a cooked IP packet socket, bound to the specified
725 * ------------------------------------------------------------------------- */
726 static int CreateListeningSocket(const char* ifName)
728 int ifIndex = if_nametoindex(ifName);
729 struct packet_mreq mreq;
731 struct sockaddr_ll bindTo;
733 /* Open cooked IP packet socket */
734 int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
737 OLSR_WARN(LOG_PLUGINS, "socket(PF_PACKET) error");
741 /* Set interface to promiscuous mode */
742 memset(&mreq, 0, sizeof(struct packet_mreq));
743 mreq.mr_ifindex = ifIndex;
744 mreq.mr_type = PACKET_MR_PROMISC;
745 if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
747 OLSR_WARN(LOG_PLUGINS, "setsockopt(PACKET_MR_PROMISC) error");
752 /* Get hardware (MAC) address */
753 memset(&req, 0, sizeof(struct ifreq));
754 strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
755 req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */
756 if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
758 OLSR_WARN(LOG_PLUGINS, "error retrieving MAC address");
763 /* Bind the socket to the specified interface */
764 memset(&bindTo, 0, sizeof(bindTo));
765 bindTo.sll_family = AF_PACKET;
766 bindTo.sll_protocol = htons(ETH_P_IP);
767 bindTo.sll_ifindex = ifIndex;
768 memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
769 bindTo.sll_halen = IFHWADDRLEN;
771 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
773 OLSR_WARN(LOG_PLUGINS, "bind() error");
778 /* Set socket to blocking operation */
779 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
781 OLSR_WARN(LOG_PLUGINS, "fcntl() error");
786 AddDescriptorToInputSet(skfd);
789 } /* CreateListeningSocket */
791 /* -------------------------------------------------------------------------
792 * Function : CreateEncapsulateSocket
793 * Description: Create a socket for sending and receiving encapsulated
795 * Input : ifname - network interface (e.g. "eth0")
797 * Return : the socket descriptor ( >= 0), or -1 if an error occurred
799 * Notes : The socket is an UDP (datagram) over IP socket, bound to the
800 * specified network interface
801 * ------------------------------------------------------------------------- */
802 static int CreateEncapsulateSocket(const char* ifName)
805 struct sockaddr_in bindTo;
807 /* Open UDP-IP socket */
808 int skfd = socket(PF_INET, SOCK_DGRAM, 0);
811 OLSR_WARN(LOG_PLUGINS, "socket(PF_INET) error");
815 /* Enable sending to broadcast addresses */
816 if (setsockopt(skfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
818 OLSR_WARN(LOG_PLUGINS, "setsockopt(SO_BROADCAST) error");
823 /* Bind to the specific network interfaces indicated by ifName. */
824 /* When using Kernel 2.6 this must happer prior to the port binding! */
825 if (setsockopt(skfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, strlen(ifName) + 1) < 0)
827 OLSR_WARN(LOG_PLUGINS, "setsockopt(SO_BINDTODEVICE) error");
832 /* Bind to BMF port */
833 memset(&bindTo, 0, sizeof(bindTo));
834 bindTo.sin_family = AF_INET;
835 bindTo.sin_port = htons(BMF_ENCAP_PORT);
836 bindTo.sin_addr.s_addr = htonl(INADDR_ANY);
838 if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0)
840 OLSR_WARN(LOG_PLUGINS, "bind() error");
845 /* Set socket to blocking operation */
846 if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
848 OLSR_WARN(LOG_PLUGINS, "fcntl() error");
853 AddDescriptorToInputSet(skfd);
856 } /* CreateEncapsulateSocket */
858 /* -------------------------------------------------------------------------
859 * Function : CreateLocalEtherTunTap
860 * Description: Creates and brings up an EtherTunTap interface
863 * Return : the socket file descriptor (>= 0), or -1 in case of failure
864 * Data Used : EtherTunTapIfName - name used for the tuntap interface (e.g.
868 * EtherTunTapIpBroadcast
870 * Note : Order dependency: call this function only if BmfInterfaces
871 * is filled with a list of network interfaces.
872 * ------------------------------------------------------------------------- */
873 static int CreateLocalEtherTunTap(void)
875 static const char deviceName[] = "/dev/net/tun";
881 etfd = open(deviceName, O_RDWR | O_NONBLOCK);
884 OLSR_WARN(LOG_PLUGINS, "error opening %s", deviceName);
888 memset(&ifreq, 0, sizeof(ifreq));
889 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
890 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
892 /* Specify the IFF_TUN flag for IP packets.
893 * Specify IFF_NO_PI for not receiving extra meta packet information. */
894 ifreq.ifr_flags = IFF_TUN;
895 ifreq.ifr_flags |= IFF_NO_PI;
897 if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0)
899 OLSR_WARN(LOG_PLUGINS, "ioctl(TUNSETIFF) error on %s", deviceName);
904 memset(&ifreq, 0, sizeof(ifreq));
905 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
906 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
907 ifreq.ifr_addr.sa_family = AF_INET;
909 ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
912 OLSR_WARN(LOG_PLUGINS, "socket(PF_INET) error on %s", deviceName);
917 /* Give the EtherTunTap interface an IP address.
918 * The default IP address is the address of the first OLSR interface;
919 * the default netmask is 255.255.255.255 . Having an all-ones netmask prevents
920 * automatic entry of the BMF network interface in the routing table. */
921 if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
923 struct TBmfInterface* nextBmfIf = BmfInterfaces;
924 while (nextBmfIf != NULL)
926 struct TBmfInterface* bmfIf = nextBmfIf;
927 nextBmfIf = bmfIf->next;
929 if (bmfIf->olsrIntf != NULL)
931 EtherTunTapIp = ntohl(bmfIf->intAddr.v4.s_addr);
932 EtherTunTapIpBroadcast = EtherTunTapIp;
937 if (EtherTunTapIp == ETHERTUNTAPIPNOTSET)
939 /* No IP address configured for BMF network interface, and no OLSR interface found to
940 * copy IP address from. Fall back to default: 10.255.255.253 . */
941 EtherTunTapIp = ETHERTUNTAPDEFAULTIP;
944 ((struct sockaddr_in*)&ifreq.ifr_addr)->sin_addr.s_addr = htonl(EtherTunTapIp);
945 ioctlres = ioctl(ioctlSkfd, SIOCSIFADDR, &ifreq);
949 ((struct sockaddr_in*)&ifreq.ifr_netmask)->sin_addr.s_addr = htonl(EtherTunTapIpMask);
950 ioctlres = ioctl(ioctlSkfd, SIOCSIFNETMASK, &ifreq);
953 /* Set broadcast IP */
954 ((struct sockaddr_in*)&ifreq.ifr_broadaddr)->sin_addr.s_addr = htonl(EtherTunTapIpBroadcast);
955 ioctlres = ioctl(ioctlSkfd, SIOCSIFBRDADDR, &ifreq);
958 /* Bring EtherTunTap interface up (if not already) */
959 ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
962 ifreq.ifr_flags |= (IFF_UP | IFF_RUNNING | IFF_BROADCAST);
963 ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
971 /* Any of the above ioctl() calls failed */
972 OLSR_WARN(LOG_PLUGINS, "error bringing up EtherTunTap interface \"%s\"", EtherTunTapIfName);
977 } /* if (ioctlres < 0) */
979 /* Set the multicast flag on the interface */
980 memset(&ifreq, 0, sizeof(ifreq));
981 strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1);
982 ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
984 ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq);
987 ifreq.ifr_flags |= IFF_MULTICAST;
988 ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq);
992 /* Any of the two above ioctl() calls failed */
993 OLSR_WARN(LOG_PLUGINS, "error setting multicast flag on EtherTunTap interface \"%s\"", EtherTunTapIfName);
995 /* Continue anyway */
998 /* Use ioctl to make the tuntap persistent. Otherwise it will disappear
999 * when this program exits. That is not desirable, since a multicast
1000 * daemon (e.g. mrouted) may be using the tuntap interface. */
1001 if (ioctl(etfd, TUNSETPERSIST, (void *)&ifreq) < 0)
1003 OLSR_WARN(LOG_PLUGINS, "error making EtherTunTap interface \"%s\" persistent", EtherTunTapIfName);
1005 /* Continue anyway */
1008 OLSR_DEBUG(LOG_PLUGINS, "opened 1 socket on \"%s\"\n", EtherTunTapIfName);
1010 AddDescriptorToInputSet(etfd);
1012 /* If the user configured a specific IP address for the BMF network interface,
1013 * help the user and advertise the IP address of the BMF network interface
1014 * on the OLSR network via HNA */
1015 if (TunTapIpOverruled != 0)
1017 union olsr_ip_addr temp_net;
1019 temp_net.v4.s_addr = htonl(EtherTunTapIp);
1020 ip_prefix_list_add(&olsr_cnf->hna_entries, &temp_net, 32);
1026 } /* CreateLocalEtherTunTap */
1028 /* -------------------------------------------------------------------------
1029 * Function : CreateInterface
1030 * Description: Create a new TBmfInterface object and adds it to the global
1031 * BmfInterfaces list
1032 * Input : ifName - name of the network interface (e.g. "eth0")
1033 * : olsrIntf - OLSR interface object of the network interface, or
1034 * NULL if the network interface is not OLSR-enabled
1036 * Return : the number of opened sockets
1037 * Data Used : BmfInterfaces, LastBmfInterface
1038 * ------------------------------------------------------------------------- */
1039 static int CreateInterface(
1041 struct interface* olsrIntf)
1043 int capturingSkfd = -1;
1044 int encapsulatingSkfd = -1;
1045 int listeningSkfd = -1;
1049 struct TBmfInterface* newIf = malloc(sizeof(struct TBmfInterface));
1051 assert(ifName != NULL);
1058 if (olsrIntf != NULL)
1060 /* On OLSR-enabled interfaces, create socket for encapsulating and forwarding
1061 * multicast packets */
1062 encapsulatingSkfd = CreateEncapsulateSocket(ifName);
1063 if (encapsulatingSkfd < 0)
1071 /* Create socket for capturing and sending of multicast packets on
1072 * non-OLSR interfaces, and on OLSR-interfaces if configured. */
1073 if ((olsrIntf == NULL) || (CapturePacketsOnOlsrInterfaces != 0))
1075 capturingSkfd = CreateCaptureSocket(ifName);
1076 if (capturingSkfd < 0)
1078 close(encapsulatingSkfd);
1086 /* Create promiscuous mode listening interface if BMF uses IP unicast
1087 * as underlying forwarding mechanism */
1088 if (BmfMechanism == BM_UNICAST_PROMISCUOUS)
1090 listeningSkfd = CreateListeningSocket(ifName);
1091 if (listeningSkfd < 0)
1093 close(listeningSkfd);
1094 close(encapsulatingSkfd); /* no problem if 'encapsulatingSkfd' is -1 */
1102 /* For ioctl operations on the network interface, use either capturingSkfd
1103 * or encapsulatingSkfd, whichever is available */
1104 ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd;
1106 /* Retrieve the MAC address of the interface. */
1107 memset(&ifr, 0, sizeof(struct ifreq));
1108 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1109 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1110 if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0)
1112 OLSR_WARN(LOG_PLUGINS, "ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
1113 close(capturingSkfd);
1114 close(encapsulatingSkfd);
1119 /* Copy data into TBmfInterface object */
1120 newIf->capturingSkfd = capturingSkfd;
1121 newIf->encapsulatingSkfd = encapsulatingSkfd;
1122 newIf->listeningSkfd = listeningSkfd;
1123 memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
1124 memcpy(newIf->ifName, ifName, IFNAMSIZ);
1125 newIf->olsrIntf = olsrIntf;
1126 if (olsrIntf != NULL)
1128 /* For an OLSR-interface, copy the interface address and broadcast
1129 * address from the OLSR interface object. Downcast to correct sockaddr
1131 newIf->intAddr.v4 = olsrIntf->int_addr.sin_addr;
1132 newIf->broadAddr.v4 = olsrIntf->int_broadaddr.sin_addr;
1136 /* For a non-OLSR interface, retrieve the IP address ourselves */
1137 memset(&ifr, 0, sizeof(struct ifreq));
1138 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1139 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1140 if (ioctl(ioctlSkfd, SIOCGIFADDR, &ifr) < 0)
1142 OLSR_WARN(LOG_PLUGINS, "ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
1144 newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
1148 /* Downcast to correct sockaddr subtype */
1149 newIf->intAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
1152 /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
1153 memset(&ifr, 0, sizeof(struct ifreq));
1154 strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
1155 ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1156 if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0)
1158 OLSR_WARN(LOG_PLUGINS, "ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
1160 newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
1164 /* Downcast to correct sockaddr subtype */
1165 newIf->broadAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr;
1169 /* Initialize fragment history table */
1170 memset(&newIf->fragmentHistory, 0, sizeof(newIf->fragmentHistory));
1171 newIf->nextFragmentHistoryEntry = 0;
1173 /* Reset counters */
1174 newIf->nBmfPacketsRx = 0;
1175 newIf->nBmfPacketsRxDup = 0;
1176 newIf->nBmfPacketsTx = 0;
1178 /* Add new TBmfInterface object to global list. OLSR interfaces are
1179 * added at the front of the list, non-OLSR interfaces at the back. */
1180 if (BmfInterfaces == NULL)
1182 /* First TBmfInterface object in list */
1183 BmfInterfaces = newIf;
1184 LastBmfInterface = newIf;
1186 else if (olsrIntf != NULL)
1188 /* Add new TBmfInterface object at front of list */
1189 newIf->next = BmfInterfaces;
1190 BmfInterfaces = newIf;
1194 /* Add new TBmfInterface object at back of list */
1196 LastBmfInterface->next= newIf;
1197 LastBmfInterface = newIf;
1202 "opened %d socket%s on %s interface \"%s\"\n",
1204 nOpened == 1 ? "" : "s",
1205 olsrIntf != NULL ? "OLSR" : "non-OLSR",
1209 } /* CreateInterface */
1211 /* -------------------------------------------------------------------------
1212 * Function : CreateBmfNetworkInterfaces
1213 * Description: Create a list of TBmfInterface objects, one for each network
1214 * interface on which BMF runs
1215 * Input : skipThisIntf - network interface to skip, if seen
1217 * Return : fail (-1) or success (0)
1219 * ------------------------------------------------------------------------- */
1220 int CreateBmfNetworkInterfaces(struct interface* skipThisIntf)
1227 int nOpenedSockets = 0;
1229 /* Clear input descriptor set */
1232 skfd = socket(PF_INET, SOCK_DGRAM, 0);
1235 OLSR_WARN(LOG_PLUGINS, "no inet socket available to retrieve interface list");
1239 /* Retrieve the network interface configuration list */
1243 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
1244 ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
1246 if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
1248 OLSR_WARN(LOG_PLUGINS, "ioctl(SIOCGIFCONF) error");
1254 if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs)
1256 /* Assume it overflowed; double the space and try again */
1258 assert(numreqs < 1024);
1259 continue; /* for (;;) */
1261 break; /* for (;;) */
1266 /* For each item in the interface configuration list... */
1268 for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++)
1270 struct interface* olsrIntf;
1271 union olsr_ip_addr ipAddr;
1273 /* Skip the BMF network interface itself */
1274 if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
1276 continue; /* for (n = ...) */
1279 /* ...find the OLSR interface structure, if any */
1280 ipAddr.v4 = ((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr;
1281 olsrIntf = if_ifwithaddr(&ipAddr);
1283 if (skipThisIntf != NULL && olsrIntf == skipThisIntf)
1285 continue; /* for (n = ...) */
1288 if (olsrIntf == NULL && ! IsNonOlsrBmfIf(ifr->ifr_name))
1290 /* Interface is neither OLSR interface, nor specified as non-OLSR BMF
1291 * interface in the BMF plugin parameter list */
1292 continue; /* for (n = ...) */
1295 nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
1297 } /* for (n = ...) */
1301 /* Create the BMF network interface */
1302 EtherTunTapFd = CreateLocalEtherTunTap();
1303 if (EtherTunTapFd >= 0)
1308 if (BmfInterfaces == NULL)
1310 OLSR_WARN(LOG_PLUGINS, "could not initialize any network interface\n");
1314 OLSR_WARN(LOG_PLUGINS, "opened %d sockets\n", nOpenedSockets);
1317 } /* CreateBmfNetworkInterfaces */
1319 /* -------------------------------------------------------------------------
1320 * Function : AddInterface
1321 * Description: Add an OLSR-enabled network interface to the list of BMF-enabled
1322 * network interfaces
1323 * Input : newIntf - network interface to add
1327 * ------------------------------------------------------------------------- */
1328 void AddInterface(struct interface* newIntf)
1332 assert(newIntf != NULL);
1334 nOpened = CreateInterface(newIntf->int_name, newIntf);
1336 OLSR_DEBUG(LOG_PLUGINS, "opened %d sockets\n", nOpened);
1337 } /* AddInterface */
1339 /* -------------------------------------------------------------------------
1340 * Function : CloseBmfNetworkInterfaces
1341 * Description: Closes every socket on each network interface used by BMF
1347 * - the local EtherTunTap interface (e.g. "tun0" or "tap0")
1348 * - for each BMF-enabled interface, the socket used for
1349 * capturing multicast packets
1350 * - for each OLSR-enabled interface, the socket used for
1351 * encapsulating packets
1352 * Also restores the network state to the situation before BMF
1354 * ------------------------------------------------------------------------- */
1355 void CloseBmfNetworkInterfaces(void)
1358 u_int32_t totalOlsrBmfPacketsRx = 0;
1359 u_int32_t totalOlsrBmfPacketsRxDup = 0;
1360 u_int32_t totalOlsrBmfPacketsTx = 0;
1361 u_int32_t totalNonOlsrBmfPacketsRx = 0;
1362 u_int32_t totalNonOlsrBmfPacketsRxDup = 0;
1363 u_int32_t totalNonOlsrBmfPacketsTx = 0;
1365 /* Close all opened sockets */
1366 struct TBmfInterface* nextBmfIf = BmfInterfaces;
1367 while (nextBmfIf != NULL)
1369 struct TBmfInterface* bmfIf = nextBmfIf;
1370 nextBmfIf = bmfIf->next;
1372 if (bmfIf->capturingSkfd >= 0)
1374 close(bmfIf->capturingSkfd);
1377 if (bmfIf->encapsulatingSkfd >= 0)
1379 close(bmfIf->encapsulatingSkfd);
1385 "%s interface \"%s\": RX pkts %u (%u dups); TX pkts %u\n",
1386 bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
1388 bmfIf->nBmfPacketsRx,
1389 bmfIf->nBmfPacketsRxDup,
1390 bmfIf->nBmfPacketsTx);
1394 "closed %s interface \"%s\"\n",
1395 bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR",
1399 if (bmfIf->olsrIntf != NULL)
1401 totalOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
1402 totalOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
1403 totalOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
1407 totalNonOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx;
1408 totalNonOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup;
1409 totalNonOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx;
1415 if (EtherTunTapFd >= 0)
1417 close(EtherTunTapFd);
1420 OLSR_DEBUG(LOG_PLUGINS, "closed \"%s\"\n", EtherTunTapIfName);
1423 BmfInterfaces = NULL;
1425 OLSR_DEBUG(LOG_PLUGINS, "closed %d sockets\n", nClosed);
1429 "Total all OLSR interfaces : RX pkts %u (%u dups); TX pkts %u\n",
1430 totalOlsrBmfPacketsRx,
1431 totalOlsrBmfPacketsRxDup,
1432 totalOlsrBmfPacketsTx);
1435 "Total all non-OLSR interfaces: RX pkts %u (%u dups); TX pkts %u\n",
1436 totalNonOlsrBmfPacketsRx,
1437 totalNonOlsrBmfPacketsRxDup,
1438 totalNonOlsrBmfPacketsTx);
1439 } /* CloseBmfNetworkInterfaces */
1441 #define MAX_NON_OLSR_IFS 32
1442 static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
1443 static int nNonOlsrIfs = 0;
1445 /* -------------------------------------------------------------------------
1446 * Function : AddNonOlsrBmfIf
1447 * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
1448 * network interfaces
1449 * Input : ifName - network interface (e.g. "eth0")
1453 * Return : success (0) or fail (1)
1454 * Data Used : NonOlsrIfNames
1455 * ------------------------------------------------------------------------- */
1456 int AddNonOlsrBmfIf(
1458 void* data __attribute__((unused)),
1459 set_plugin_parameter_addon addon __attribute__((unused)))
1461 assert(ifName != NULL);
1463 if (nNonOlsrIfs >= MAX_NON_OLSR_IFS)
1467 "too many non-OLSR interfaces specified, maximum is %d\n",
1472 strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
1473 NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0'; /* Ensures null termination */
1476 } /* AddNonOlsrBmfIf */
1478 /* -------------------------------------------------------------------------
1479 * Function : IsNonOlsrBmfIf
1480 * Description: Checks if a network interface is OLSR-enabled
1481 * Input : ifName - network interface (e.g. "eth0")
1483 * Return : true (1) or false (0)
1484 * Data Used : NonOlsrIfNames
1485 * ------------------------------------------------------------------------- */
1486 int IsNonOlsrBmfIf(const char* ifName)
1490 assert(ifName != NULL);
1492 for (i = 0; i < nNonOlsrIfs; i++)
1494 if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0) return 1;
1497 } /* IsNonOlsrBmfIf */
1499 /* -------------------------------------------------------------------------
1500 * Function : CheckAndUpdateLocalBroadcast
1501 * Description: For an IP packet, check if the destination address is not a
1502 * multicast address. If it is not, the packet is assumed to be
1503 * a local broadcast packet. In that case, set the destination
1504 * address of the IP packet to the passed broadcast address.
1505 * Input : ipPacket - the IP packet
1506 * broadAddr - the broadcast address to fill in
1510 * Notes : See also RFC1141
1511 * ------------------------------------------------------------------------- */
1512 void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* broadAddr)
1515 union olsr_ip_addr destIp;
1517 assert(ipPacket != NULL && broadAddr != NULL);
1519 iph = (struct iphdr*) ipPacket;
1520 destIp.v4.s_addr = iph->daddr;
1521 if (! IsMulticast(&destIp))
1523 u_int32_t origDaddr, newDaddr;
1526 origDaddr = ntohl(iph->daddr);
1528 iph->daddr = broadAddr->v4.s_addr;
1529 newDaddr = ntohl(iph->daddr);
1531 /* Re-calculate IP header checksum for new destination */
1532 check = ntohs(iph->check);
1534 check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
1535 check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
1538 check = check + (check >> 16);
1540 iph->check = htons(check);
1542 if (iph->protocol == SOL_UDP)
1544 /* Re-calculate UDP/IP checksum for new destination */
1546 int ipHeaderLen = GetIpHeaderLength(ipPacket);
1547 struct udphdr* udph = (struct udphdr*) (ipPacket + ipHeaderLen);
1549 /* RFC 1624, Eq. 3: HC' = ~(~HC - m + m') */
1551 check = ntohs(udph->check);
1553 check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF));
1554 check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF));
1557 check = check + (check >> 16);
1559 udph->check = htons(check);
1562 } /* CheckAndUpdateLocalBroadcast */
1564 /* -------------------------------------------------------------------------
1565 * Function : AddMulticastRoute
1566 * Description: Insert a route to all multicast addresses in the kernel
1567 * routing table. The route will be via the BMF network interface.
1572 * ------------------------------------------------------------------------- */
1573 void AddMulticastRoute(void)
1575 struct rtentry kernel_route;
1576 int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1579 OLSR_WARN(LOG_PLUGINS, "socket(PF_INET) error");
1583 memset(&kernel_route, 0, sizeof(struct rtentry));
1585 ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
1586 ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
1587 ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
1590 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = htonl(0xE0000000);
1591 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = htonl(0xF0000000);
1593 kernel_route.rt_metric = 0;
1594 kernel_route.rt_flags = RTF_UP;
1596 kernel_route.rt_dev = EtherTunTapIfName;
1598 if (ioctl(ioctlSkfd, SIOCADDRT, &kernel_route) < 0)
1600 OLSR_WARN(LOG_PLUGINS, "error setting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
1602 /* Continue anyway */
1605 } /* AddMulticastRoute */
1607 /* -------------------------------------------------------------------------
1608 * Function : DeleteMulticastRoute
1609 * Description: Delete the route to all multicast addresses from the kernel
1615 * ------------------------------------------------------------------------- */
1616 void DeleteMulticastRoute(void)
1618 if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP)
1620 struct rtentry kernel_route;
1621 int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0);
1624 OLSR_WARN(LOG_PLUGINS, "socket(PF_INET) error");
1628 memset(&kernel_route, 0, sizeof(struct rtentry));
1630 ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;
1631 ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;
1632 ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;
1635 ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = htonl(0xE0000000);
1636 ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = htonl(0xF0000000);
1638 kernel_route.rt_metric = 0;
1639 kernel_route.rt_flags = RTF_UP;
1641 kernel_route.rt_dev = EtherTunTapIfName;
1643 if (ioctl(ioctlSkfd, SIOCDELRT, &kernel_route) < 0)
1645 OLSR_WARN(LOG_PLUGINS, "error deleting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName);
1647 /* Continue anyway */
1651 } /* DeleteMulticastRoute */
1656 * indent-tabs-mode: nil