diff --git a/Foundation/src/Environment_UNIX.cpp b/Foundation/src/Environment_UNIX.cpp index f10409920..c526de6cf 100644 --- a/Foundation/src/Environment_UNIX.cpp +++ b/Foundation/src/Environment_UNIX.cpp @@ -36,6 +36,7 @@ #include "Poco/Environment_UNIX.h" #include "Poco/Exception.h" +#include "Poco/Buffer.h" #include #include #include @@ -167,11 +168,11 @@ namespace Poco { void EnvironmentImpl::nodeIdImpl(NodeId& id) { + std::memset(&id, 0, sizeof(id)); struct ifaddrs* ifaphead; int rc = getifaddrs(&ifaphead); - if (rc) throw SystemException("cannot get network adapter list"); + if (rc) return; - bool foundAdapter = false; for (struct ifaddrs* ifap = ifaphead; ifap; ifap = ifap->ifa_next) { if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_LINK) @@ -182,13 +183,11 @@ void EnvironmentImpl::nodeIdImpl(NodeId& id) if (ap && alen > 0) { std::memcpy(&id, ap, sizeof(id)); - foundAdapter = true; break; } } } freeifaddrs(ifaphead); - if (!foundAdapter) throw SystemException("cannot determine MAC address (no suitable network adapter found)"); } @@ -203,6 +202,11 @@ void EnvironmentImpl::nodeIdImpl(NodeId& id) #include #include #include +#ifndef __CYGWIN__ +#include +#else // workaround for Cygwin, which does not have if_arp.h +#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */ +#endif #include #include @@ -212,17 +216,56 @@ namespace Poco { void EnvironmentImpl::nodeIdImpl(NodeId& id) { - struct ifreq ifr; + std::memset(&id, 0, sizeof(id)); + int sock = socket(PF_INET, SOCK_DGRAM, 0); + if (sock == -1) return; - int s = socket(PF_INET, SOCK_DGRAM, 0); - if (s == -1) throw SystemException("cannot open socket"); - - std::strcpy(ifr.ifr_name, "eth0"); - int rc = ioctl(s, SIOCGIFHWADDR, &ifr); - close(s); - if (rc < 0) throw SystemException("cannot get MAC address"); - struct sockaddr* sa = reinterpret_cast(&ifr.ifr_addr); - std::memcpy(&id, sa->sa_data, sizeof(id)); + // the following code is loosely based + // on W. Richard Stevens, UNIX Network Programming, pp 434ff. + int lastlen = 0; + int len = 100*sizeof(struct ifreq); + struct ifconf ifc; + char* buf = 0; + for (;;) + { + buf = new char[len]; + ifc.ifc_len = len; + ifc.ifc_buf = buf; + if (::ioctl(sock, SIOCGIFCONF, &ifc) < 0) + { + if (errno != EINVAL || lastlen != 0) + { + close(sock); + delete [] buf; + return; + } + } + else + { + if (ifc.ifc_len == lastlen) + break; + lastlen = ifc.ifc_len; + } + len += 10*sizeof(struct ifreq); + delete [] buf; + } + for (const char* ptr = buf; ptr < buf + ifc.ifc_len;) + { + const struct ifreq* ifr = reinterpret_cast(ptr); + int rc = ioctl(sock, SIOCGIFHWADDR, ifr); + if (rc != -1) + { + const struct sockaddr* sa = reinterpret_cast(&ifr->ifr_hwaddr); + if (sa->sa_family == ARPHRD_ETHER) + { + std::memcpy(&id, sa->sa_data, sizeof(id)); + break; + } + } + ptr += sizeof(struct ifreq); + } + close(sock); + delete [] buf; } @@ -253,15 +296,16 @@ namespace Poco { void EnvironmentImpl::nodeIdImpl(NodeId& id) { + std::memset(&id, 0, sizeof(id)); char name[MAXHOSTNAMELEN]; if (gethostname(name, sizeof(name))) - throw SystemException("cannot get host name"); + return; struct hostent* pHost = gethostbyname(name); - if (!pHost) throw SystemException("cannot get host IP address"); + if (!pHost) return; int s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (s == -1) throw SystemException("cannot open socket"); + if (s == -1) return; struct arpreq ar; std::memset(&ar, 0, sizeof(ar)); @@ -270,7 +314,7 @@ void EnvironmentImpl::nodeIdImpl(NodeId& id) std::memcpy(&pAddr->sin_addr, *pHost->h_addr_list, sizeof(struct in_addr)); int rc = ioctl(s, SIOCGARP, &ar); close(s); - if (rc < 0) throw SystemException("cannot get MAC address"); + if (rc < 0) return; std::memcpy(&id, ar.arp_ha.sa_data, sizeof(id)); } diff --git a/Foundation/src/Environment_VMS.cpp b/Foundation/src/Environment_VMS.cpp index fc468d792..511e2eb84 100644 --- a/Foundation/src/Environment_VMS.cpp +++ b/Foundation/src/Environment_VMS.cpp @@ -123,15 +123,16 @@ std::string EnvironmentImpl::nodeNameImpl() void EnvironmentImpl::nodeIdImpl(NodeId& id) { + std::memset(&id, 0, sizeof(id)); char name[MAXHOSTNAMELEN]; if (gethostname(name, sizeof(name))) - throw SystemException("cannot get host name"); - + return; + struct hostent* pHost = gethostbyname(name); - if (!pHost) throw SystemException("cannot get host IP address"); + if (!pHost) return; int s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (s == -1) throw SystemException("cannot open socket"); + if (s == -1) return; struct arpreq ar; std::memset(&ar, 0, sizeof(ar)); @@ -140,7 +141,7 @@ void EnvironmentImpl::nodeIdImpl(NodeId& id) std::memcpy(&pAddr->sin_addr, *pHost->h_addr_list, sizeof(struct in_addr)); int rc = ioctl(s, SIOCGARP, &ar); close(s); - if (rc < 0) throw SystemException("cannot get MAC address"); + if (rc < 0) return; std::memcpy(&id, ar.arp_ha.sa_data, sizeof(id)); } diff --git a/Foundation/src/Environment_WIN32.cpp b/Foundation/src/Environment_WIN32.cpp index c787582d2..5e7ea6d9e 100644 --- a/Foundation/src/Environment_WIN32.cpp +++ b/Foundation/src/Environment_WIN32.cpp @@ -148,6 +148,8 @@ std::string EnvironmentImpl::nodeNameImpl() void EnvironmentImpl::nodeIdImpl(NodeId& id) { + std::memset(&id, 0, sizeof(id)); + PIP_ADAPTER_INFO pAdapterInfo; PIP_ADAPTER_INFO pAdapter = 0; ULONG len = sizeof(IP_ADAPTER_INFO); @@ -162,31 +164,21 @@ void EnvironmentImpl::nodeIdImpl(NodeId& id) } else if (rc != ERROR_SUCCESS) { - throw SystemException("cannot get network adapter list"); + return; } - try + if (GetAdaptersInfo(pAdapterInfo, &len) == NO_ERROR) { + pAdapter = pAdapterInfo; bool found = false; - if (GetAdaptersInfo(pAdapterInfo, &len) == NO_ERROR) + while (pAdapter && !found) { - pAdapter = pAdapterInfo; - while (pAdapter && !found) + if (pAdapter->Type == MIB_IF_TYPE_ETHERNET && pAdapter->AddressLength == sizeof(id)) { - if (pAdapter->Type == MIB_IF_TYPE_ETHERNET && pAdapter->AddressLength == sizeof(id)) - { - std::memcpy(&id, pAdapter->Address, pAdapter->AddressLength); - found = true; - } - pAdapter = pAdapter->Next; + found = true; + std::memcpy(&id, pAdapter->Address, pAdapter->AddressLength); } + pAdapter = pAdapter->Next; } - else throw SystemException("cannot get network adapter list"); - if (!found) throw SystemException("no Ethernet adapter found"); - } - catch (Exception&) - { - delete [] reinterpret_cast(pAdapterInfo); - throw; } delete [] reinterpret_cast(pAdapterInfo); } diff --git a/Foundation/src/Environment_WIN32U.cpp b/Foundation/src/Environment_WIN32U.cpp index f249ece24..2c083c17c 100644 --- a/Foundation/src/Environment_WIN32U.cpp +++ b/Foundation/src/Environment_WIN32U.cpp @@ -162,6 +162,8 @@ std::string EnvironmentImpl::nodeNameImpl() void EnvironmentImpl::nodeIdImpl(NodeId& id) { + std::memset(&id, 0, sizeof(id)); + PIP_ADAPTER_INFO pAdapterInfo; PIP_ADAPTER_INFO pAdapter = 0; ULONG len = sizeof(IP_ADAPTER_INFO); @@ -176,31 +178,21 @@ void EnvironmentImpl::nodeIdImpl(NodeId& id) } else if (rc != ERROR_SUCCESS) { - throw SystemException("cannot get network adapter list"); + return; } - try + if (GetAdaptersInfo(pAdapterInfo, &len) == NO_ERROR) { + pAdapter = pAdapterInfo; bool found = false; - if (GetAdaptersInfo(pAdapterInfo, &len) == NO_ERROR) + while (pAdapter && !found) { - pAdapter = pAdapterInfo; - while (pAdapter && !found) + if (pAdapter->Type == MIB_IF_TYPE_ETHERNET && pAdapter->AddressLength == sizeof(id)) { - if (pAdapter->Type == MIB_IF_TYPE_ETHERNET && pAdapter->AddressLength == sizeof(id)) - { - std::memcpy(&id, pAdapter->Address, pAdapter->AddressLength); - found = true; - } - pAdapter = pAdapter->Next; + found = true; + std::memcpy(&id, pAdapter->Address, pAdapter->AddressLength); } + pAdapter = pAdapter->Next; } - else throw SystemException("cannot get network adapter list"); - if (!found) throw SystemException("no Ethernet adapter found"); - } - catch (Exception&) - { - delete [] reinterpret_cast(pAdapterInfo); - throw; } delete [] reinterpret_cast(pAdapterInfo); }