Skip to content

Commit

Permalink
remote: osx manual interface selection work-around
Browse files Browse the repository at this point in the history
  • Loading branch information
guruofquality committed Oct 29, 2015
1 parent 11311b4 commit 43a5bef
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
2 changes: 2 additions & 0 deletions common/CMakeLists.txt
Expand Up @@ -29,6 +29,8 @@ CHECK_INCLUDE_FILES(netinet/tcp.h HAS_NETINET_TCP_H)
CHECK_INCLUDE_FILES(sys/types.h HAS_SYS_TYPES_H)
CHECK_INCLUDE_FILES(sys/socket.h HAS_SYS_SOCKET_H)
CHECK_INCLUDE_FILES(arpa/inet.h HAS_ARPA_INET_H)
CHECK_INCLUDE_FILES(ifaddrs.h HAS_IFADDRS_H)
CHECK_INCLUDE_FILES(net/if.h HAS_NET_IF_H)

#network libraries
if (WIN32)
Expand Down
46 changes: 45 additions & 1 deletion common/SoapyRPCSocket.cpp
Expand Up @@ -181,6 +181,38 @@ int SoapyRPCSocket::connect(const std::string &url)
return ret;
}

/*!
* OSX doesn't support automatic ipv6mr_interface = 0.
* The following code attempts to work around this issue
* by manually selecting a multicast capable interface.
*/
static int getDefaultIfaceIndex(void)
{
#ifdef __APPLE__

//find the first available multicast interfaces
int loIface = 0, enIface = 0;
struct ifaddrs *ifa = nullptr;
getifaddrs(&ifa);
while (ifa != nullptr)
{
const bool isUp = ((ifa->ifa_flags & IFF_UP) != 0);
const bool isLoopback = ((ifa->ifa_flags & IFF_LOOPBACK) != 0);
const bool isMulticast = ((ifa->ifa_flags & IFF_MULTICAST) != 0);
if (isUp and isLoopback and isMulticast and loIface == 0) loIface = if_nametoindex(ifa->ifa_name);
if (isUp and not isLoopback and isMulticast and enIface == 0) enIface = if_nametoindex(ifa->ifa_name);
ifa = ifa->ifa_next;
}
freeifaddrs(ifa);

//prefer discovered regular interface over loopback
if (enIface != 0) return enIface;
if (loIface != 0) return loIface;
#endif //__APPLE__

return 0;
}

int SoapyRPCSocket::multicastJoin(const std::string &group, const bool loop, const int ttl)
{
/*
Expand Down Expand Up @@ -257,11 +289,23 @@ int SoapyRPCSocket::multicastJoin(const std::string &group, const bool loop, con
return -1;
}

//setup IPV6_MULTICAST_IF
int iface = getDefaultIfaceIndex();
if (iface != 0)
{
ret = ::setsockopt(_sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (const char *)&iface, sizeof(iface));
if (ret != 0)
{
this->reportError("setsockopt(IPV6_MULTICAST_IF)");
return -1;
}
}

//setup IPV6_ADD_MEMBERSHIP
auto *addr_in6 = (const struct sockaddr_in6 *)addr.addr();
struct ipv6_mreq mreq6;
mreq6.ipv6mr_multiaddr = addr_in6->sin6_addr;
mreq6.ipv6mr_interface = 0;//local_addr_in6->sin6_scope_id;
mreq6.ipv6mr_interface = iface;
ret = ::setsockopt(_sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char *)&mreq6, sizeof(mreq6));
if (ret != 0)
{
Expand Down
10 changes: 10 additions & 0 deletions common/SoapySocketDefs.in.hpp
Expand Up @@ -63,6 +63,16 @@ typedef int socklen_t;
#include <arpa/inet.h> //inet_ntop
#endif //HAS_ARPA_INET_H

#cmakedefine HAS_IFADDRS_H
#ifdef HAS_IFADDRS_H
#include <ifaddrs.h> //getifaddrs
#endif //HAS_IFADDRS_H

#cmakedefine HAS_NET_IF_H
#ifdef HAS_NET_IF_H
#include <net/if.h> //if_nametoindex
#endif //HAS_NET_IF_H

/***********************************************************************
* htonll and ntohll for GCC
**********************************************************************/
Expand Down

0 comments on commit 43a5bef

Please sign in to comment.