00001
00002
00003
00004
00005
00006
00007
00008 #include "dds/DCPS/RTPS/GuidGenerator.h"
00009
00010 #include "dds/DCPS/GuidUtils.h"
00011
00012 #include "dds/DdsDcpsGuidTypeSupportImpl.h"
00013
00014 #include "ace/OS_NS_unistd.h"
00015 #include "ace/OS_NS_stdlib.h"
00016 #include "ace/OS_NS_netdb.h"
00017 #include "ace/OS_NS_sys_socket.h"
00018 #include "ace/OS_NS_sys_time.h"
00019
00020 #include "ace/os_include/net/os_if.h"
00021
00022 #include <cstring>
00023
00024 #ifdef ACE_LINUX
00025 # include <sys/types.h>
00026 # include <ifaddrs.h>
00027 #endif
00028
00029 #if defined ACE_WIN32 && !defined ACE_HAS_WINCE
00030 # include <winsock2.h>
00031 # include <iphlpapi.h>
00032 # include "ace/Version.h"
00033
00034 # if ACE_MAJOR_VERSION == 6 && ACE_MINOR_VERSION == 0 && defined _MSC_VER
00035 # pragma comment(lib, "IPHlpApi.Lib")
00036 # endif
00037 #endif
00038
00039 #ifdef ACE_VXWORKS
00040 # include "ace/os_include/sys/os_sysctl.h"
00041 # include <net/route.h>
00042 #endif
00043
00044 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
00045
00046 namespace OpenDDS {
00047 namespace RTPS {
00048
00049 GuidGenerator::GuidGenerator()
00050 : pid_(ACE_OS::getpid()),
00051 counter_(0)
00052 {
00053
00054 if (pid_ == -1) {
00055 unsigned seed = static_cast<unsigned>(ACE_OS::gettimeofday().usec());
00056 pid_ = static_cast<pid_t>(ACE_OS::rand_r(&seed));
00057 }
00058
00059 ACE_OS::macaddr_node_t macaddress;
00060 const int result = ACE_OS::getmacaddress(&macaddress);
00061
00062 if (-1 != result) {
00063 ACE_OS::memcpy(node_id_, macaddress.node, NODE_ID_SIZE);
00064 } else {
00065 for (int i = 0; i < NODE_ID_SIZE; ++i) {
00066 node_id_[i] = static_cast<unsigned char>(ACE_OS::rand());
00067 }
00068 }
00069 }
00070
00071 ACE_UINT16
00072 GuidGenerator::getCount()
00073 {
00074 ACE_Guard<ACE_SYNCH_MUTEX> guard(counter_lock_);
00075 return counter_++;
00076 }
00077
00078 int
00079 GuidGenerator::interfaceName(const char* iface)
00080 {
00081 if (interface_name_ == iface) {
00082 return 0;
00083 }
00084 interface_name_ = iface;
00085
00086 #if defined ACE_WIN32 && !defined ACE_HAS_WINCE
00087 ULONG size;
00088 if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, 0, &size)
00089 != ERROR_BUFFER_OVERFLOW) {
00090 return -1;
00091 }
00092 ACE_Allocator* const alloc = DCPS::SafetyProfilePool::instance();
00093 IP_ADAPTER_ADDRESSES* const addrs =
00094 static_cast<IP_ADAPTER_ADDRESSES*>(alloc->malloc(size));
00095 if (!addrs) {
00096 return -1;
00097 }
00098 if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, addrs, &size) != NO_ERROR) {
00099 alloc->free(addrs);
00100 return -1;
00101 }
00102
00103 bool found = false;
00104 for (IP_ADAPTER_ADDRESSES* iter = addrs; iter && !found; iter = iter->Next) {
00105 if (ACE_Wide_To_Ascii(iter->FriendlyName).char_rep() == interface_name_) {
00106 std::memcpy(node_id_, iter->PhysicalAddress,
00107 std::min(static_cast<size_t>(iter->PhysicalAddressLength),
00108 sizeof node_id_));
00109 found = true;
00110 }
00111 }
00112
00113 alloc->free(addrs);
00114 return found ? 0 : -1;
00115 #elif defined ACE_LINUX || defined __ANDROID_API__
00116 ifreq ifr;
00117
00118
00119 if (std::strlen(iface) >= sizeof(ifr.ifr_name)) {
00120 ACE_ERROR((LM_ERROR,
00121 ACE_TEXT("Interface name %C exceeds max allowable length, must be < %d."),
00122 iface, IFNAMSIZ));
00123 return -1;
00124 }
00125 std::strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
00126 const ACE_HANDLE h = ACE_OS::socket(PF_INET, SOCK_DGRAM, 0);
00127 if (h == ACE_INVALID_HANDLE) {
00128 return -1;
00129 }
00130 if (ACE_OS::ioctl(h, SIOCGIFHWADDR, &ifr) < 0) {
00131 ACE_OS::close(h);
00132 return -1;
00133 }
00134 ACE_OS::close(h);
00135 std::memcpy(node_id_, ifr.ifr_addr.sa_data, sizeof node_id_);
00136 return 0;
00137 #elif defined ACE_HAS_SIOCGIFCONF || defined ACE_HAS_MAC_OSX
00138 const ACE_HANDLE h = ACE_OS::socket(AF_INET, SOCK_DGRAM, 0);
00139 if (h == ACE_INVALID_HANDLE) {
00140 return -1;
00141 }
00142
00143 const int BUFFERSIZE = 4000;
00144 char buffer[BUFFERSIZE];
00145 ifconf ifc;
00146 ifc.ifc_len = BUFFERSIZE;
00147 ifc.ifc_buf = buffer;
00148
00149 if (ACE_OS::ioctl(h, SIOCGIFCONF, &ifc) < 0) {
00150 ACE_OS::close(h);
00151 return -1;
00152 }
00153
00154 bool found = false;
00155 for (const char* ptr = buffer; !found && ptr < buffer + ifc.ifc_len;) {
00156 const ifreq* ifr = reinterpret_cast<const ifreq*>(ptr);
00157 if (ifr->ifr_addr.sa_family == AF_LINK && ifr->ifr_name == interface_name_) {
00158 const sockaddr_dl* sdl =
00159 reinterpret_cast<const sockaddr_dl*>(&ifr->ifr_addr);
00160 std::memcpy(node_id_, LLADDR(sdl), sizeof node_id_);
00161 found = true;
00162 }
00163
00164 ptr += sizeof ifr->ifr_name + std::max(sizeof ifr->ifr_addr,
00165 static_cast<size_t>(ifr->ifr_addr.sa_len));
00166 }
00167
00168 ACE_OS::close(h);
00169 return found ? 0 : -1;
00170 #elif defined ACE_VXWORKS
00171 int name[] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
00172 static const size_t name_elts = sizeof name / sizeof name[0];
00173
00174 size_t result_sz = 0u;
00175 if (sysctl(name, name_elts, 0, &result_sz, 0, 0u) != 0) {
00176 return -1;
00177 }
00178
00179 ACE_Allocator* const alloc = DCPS::SafetyProfilePool::instance();
00180 char* const result = static_cast<char*>(alloc->malloc(result_sz));
00181
00182 if (sysctl(name, name_elts, result, &result_sz, 0, 0u) != 0) {
00183 alloc->free(result);
00184 return -1;
00185 }
00186
00187 for (size_t pos = 0, n; pos + sizeof(if_msghdr) < result_sz; pos += n) {
00188 if_msghdr* const hdr = reinterpret_cast<if_msghdr*>(result + pos);
00189 n = hdr->ifm_msglen;
00190 sockaddr_dl* const addr =
00191 reinterpret_cast<sockaddr_dl*>(result + pos + sizeof(if_msghdr));
00192
00193 if (hdr->ifm_type == RTM_IFINFO && (hdr->ifm_addrs & RTA_IFP)
00194 && std::memcmp(addr->sdl_data, iface, addr->sdl_nlen) == 0
00195 && addr->sdl_alen >= sizeof node_id_) {
00196 std::memcpy(node_id_, LLADDR(addr), sizeof node_id_);
00197 alloc->free(result);
00198 return 0;
00199 }
00200
00201 while (pos + n < result_sz) {
00202 if_msghdr* const nxt = reinterpret_cast<if_msghdr*>(result + pos + n);
00203 if (nxt->ifm_type != RTM_NEWADDR) {
00204 break;
00205 }
00206 n += nxt->ifm_msglen;
00207 }
00208 }
00209
00210 alloc->free(result);
00211 return -1;
00212 #else
00213 return -1;
00214 #endif
00215 }
00216
00217 void
00218 GuidGenerator::populate(DCPS::GUID_t &container)
00219 {
00220 container.guidPrefix[0] = DCPS::VENDORID_OCI[0];
00221 container.guidPrefix[1] = DCPS::VENDORID_OCI[1];
00222
00223 const ACE_UINT16 count = getCount();
00224 ACE_OS::memcpy(&container.guidPrefix[2], node_id_, NODE_ID_SIZE);
00225 container.guidPrefix[8] = static_cast<CORBA::Octet>(pid_ >> 8);
00226 container.guidPrefix[9] = static_cast<CORBA::Octet>(pid_ & 0xFF);
00227 container.guidPrefix[10] = static_cast<CORBA::Octet>(count >> 8);
00228 container.guidPrefix[11] = static_cast<CORBA::Octet>(count & 0xFF);
00229 }
00230
00231 }
00232 }
00233
00234 OPENDDS_END_VERSIONED_NAMESPACE_DECL