summaryrefslogtreecommitdiff
path: root/cpp/src/Ice/Network.cpp
diff options
context:
space:
mode:
authorDwayne Boone <dwayne@zeroc.com>2005-09-30 13:43:13 +0000
committerDwayne Boone <dwayne@zeroc.com>2005-09-30 13:43:13 +0000
commit8e89205f5f3e9846c25c815f0de5cbde1d14ccf6 (patch)
treea0d95f534d47ec523dec84660ec7537972e005eb /cpp/src/Ice/Network.cpp
parentFix (diff)
downloadice-8e89205f5f3e9846c25c815f0de5cbde1d14ccf6.tar.bz2
ice-8e89205f5f3e9846c25c815f0de5cbde1d14ccf6.tar.xz
ice-8e89205f5f3e9846c25c815f0de5cbde1d14ccf6.zip
Add method to get all local addresses
Diffstat (limited to 'cpp/src/Ice/Network.cpp')
-rw-r--r--cpp/src/Ice/Network.cpp214
1 files changed, 157 insertions, 57 deletions
diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp
index 3d1fddf7536..2794896173c 100644
--- a/cpp/src/Ice/Network.cpp
+++ b/cpp/src/Ice/Network.cpp
@@ -11,11 +11,18 @@
#include <Ice/Network.h>
#include <Ice/LocalException.h>
-#ifdef _WIN32
+#if defined(_WIN32)
# include <winsock2.h>
+#elif defined(__linux) || defined(__APPLE__) || defined(__FreeBSD__)
+# include <ifaddrs.h>
+#else
+# include <sys/ioctl.h>
+# include <net/if.h>
+# ifdef __sun
+# include <sys/sockio.h>
+# endif
#endif
-
using namespace std;
using namespace Ice;
using namespace IceInternal;
@@ -1319,83 +1326,177 @@ IceInternal::addrToString(const struct sockaddr_in& addr)
return s.str();
}
-#ifdef _WIN32
vector<struct sockaddr_in>
IceInternal::getLocalAddresses()
{
vector<struct sockaddr_in> result;
- try
- {
- SOCKET fd = createSocket(false);
- vector<unsigned char> buffer;
- buffer.resize(1024);
- unsigned long len = 0;
- DWORD rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, &buffer[0], buffer.size(), &len, 0, 0);
- if(rs == SOCKET_ERROR)
- {
- //
- // If the buffer wasn't big enough, resize it to the
- // required length and try again.
- //
- if(getSocketErrno() == WSAEFAULT)
- {
- buffer.resize(len);
- rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, &buffer[0], buffer.size(), &len, 0, 0);
- }
+#if defined(_WIN32)
+ SOCKET fd = createSocket(false);
- if(rs == SOCKET_ERROR)
- {
- closeSocketNoThrow(fd);
- SocketException ex(__FILE__, __LINE__);
- ex.error = getSocketErrno();
- throw ex;
- }
+ vector<unsigned char> buffer;
+ buffer.resize(1024);
+ unsigned long len = 0;
+ DWORD rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, &buffer[0], buffer.size(), &len, 0, 0);
+ if(rs == SOCKET_ERROR)
+ {
+ //
+ // If the buffer wasn't big enough, resize it to the
+ // required length and try again.
+ //
+ if(getSocketErrno() == WSAEFAULT)
+ {
+ buffer.resize(len);
+ rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, &buffer[0], buffer.size(), &len, 0, 0);
}
+
+ if(rs == SOCKET_ERROR)
+ {
+ closeSocketNoThrow(fd);
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = getSocketErrno();
+ throw ex;
+ }
+ }
- //
- // Add the local interface addresses.
- //
- SOCKET_ADDRESS_LIST* addrs = reinterpret_cast<SOCKET_ADDRESS_LIST*>(&buffer[0]);
- for (int i = 0; i < addrs->iAddressCount; ++i)
- {
- result.push_back(*reinterpret_cast<struct sockaddr_in*>(addrs->Address[i].lpSockaddr));
- }
+ //
+ // Add the local interface addresses.
+ //
+ SOCKET_ADDRESS_LIST* addrs = reinterpret_cast<SOCKET_ADDRESS_LIST*>(&buffer[0]);
+ for (int i = 0; i < addrs->iAddressCount; ++i)
+ {
+ result.push_back(*reinterpret_cast<struct sockaddr_in*>(addrs->Address[i].lpSockaddr));
+ }
+
+ //
+ // Add the loopback interface address.
+ //
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(0);
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ result.push_back(addr);
- //
- // Add the loopback interface address.
- //
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(0);
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- result.push_back(addr);
+ closeSocket(fd);
+#elif defined(__linux) || defined(__APPLE__) || defined(__FreeBSD__)
+ struct ifaddrs* ifap;
+ if(::getifaddrs(&ifap) == SOCKET_ERROR)
+ {
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = getSocketErrno();
+ throw ex;
+ }
- closeSocket(fd);
+ struct ifaddrs* curr = ifap;
+ while(curr != 0)
+ {
+ if(curr->ifa_addr && curr->ifa_addr->sa_family == AF_INET)
+ {
+ struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(curr->ifa_addr);
+ if(addr->sin_addr.s_addr != 0)
+ {
+ result.push_back(*addr);
+ }
}
- catch(const Ice::LocalException&)
+
+ curr = curr->ifa_next;
+ }
+
+ ::freeifaddrs(ifap);
+#else
+ SOCKET fd = createSocket(false);
+
+#ifdef _AIX
+ int cmd = CSIOCGIFCONF;
+#else
+ int cmd = SIOCGIFCONF;
+#endif
+ struct ifconf ifc;
+ int numaddrs = 10;
+ int old_ifc_len = 0;
+
+ //
+ // Need to call ioctl multiple times since we do not know up front
+ // how many addresses there will be, and thus how large a buffer we need.
+ // We keep increasing the buffer size until subsequent calls return
+ // the same length, meaning we have all the addresses.
+ //
+ while(true)
{
- //
- // TODO: Warning?
- //
+ int bufsize = numaddrs * sizeof(struct ifreq);
+ ifc.ifc_len = bufsize;
+ ifc.ifc_buf = (char*)malloc(bufsize);
+
+ int rs = ioctl(fd, cmd, &ifc);
+ if(rs == SOCKET_ERROR)
+ {
+ closeSocketNoThrow(fd);
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = getSocketErrno();
+ throw ex;
+ }
+ else if(ifc.ifc_len == old_ifc_len)
+ {
+ //
+ // Returned same length twice in a row, finished.
+ //
+ break;
+ }
+ else
+ {
+ old_ifc_len = ifc.ifc_len;
+ }
+
+ numaddrs += 10;
+ free(ifc.ifc_buf);
}
+
+ numaddrs = ifc.ifc_len / sizeof(struct ifreq);
+ struct ifreq* ifr = ifc.ifc_req;
+ for(int i = 0; i < numaddrs; ++i)
+ {
+ if(ifr[i].ifr_addr.sa_family == AF_INET)
+ {
+ struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(&ifr[i].ifr_addr);
+ if(addr->sin_addr.s_addr != 0)
+ {
+ result.push_back(*addr);
+ }
+ }
+ }
+
+ free(ifc.ifc_buf);
+ closeSocket(fd);
+#endif
+
return result;
}
+#ifdef _WIN32
bool
IceInternal::isLocalAddress(const struct sockaddr_in& addr)
{
struct sockaddr_in addr0 = addr;
addr0.sin_port = htons(0); // Local interface addresses have the port set to 0.
- vector<struct sockaddr_in> localAddrs = getLocalAddresses();
- for(vector<struct sockaddr_in>::const_iterator p = localAddrs.begin(); p != localAddrs.end(); ++p)
+
+ try
{
- if(compareAddress(addr0, *p))
- {
- return true;
- }
+ vector<struct sockaddr_in> localAddrs = getLocalAddresses();
+ for(vector<struct sockaddr_in>::const_iterator p = localAddrs.begin(); p != localAddrs.end(); ++p)
+ {
+ if(compareAddress(addr0, *p))
+ {
+ return true;
+ }
+ }
+ }
+ catch(const Ice.LocalException&)
+ {
+ //
+ // TODO: Warning?
+ //
}
return false;
}
@@ -1421,5 +1522,4 @@ IceInternal::isPeerLocal(SOCKET fd)
}
return isLocalAddress(remoteAddr);
}
-
#endif