|
reSIProcate/rutil
9694
|
00001 #ifdef HAVE_CONFIG_H 00002 #include "config.h" 00003 #endif 00004 00005 #include <Winsock2.h> 00006 #include <Iphlpapi.h> 00007 00008 #include "rutil/GenericIPAddress.hxx" 00009 #include "rutil/WinCompat.hxx" 00010 #include "rutil/DnsUtil.hxx" 00011 #include "rutil/Log.hxx" 00012 #include "rutil/Logger.hxx" 00013 #include "rutil/WinLeakCheck.hxx" 00014 00015 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT 00016 00017 00018 static char* ConvertLPWSTRToLPSTR(LPWSTR lpwszStrIn) 00019 { 00020 LPSTR pszOut = NULL; 00021 if (lpwszStrIn != NULL) 00022 { 00023 int nInputStrLen = (int)wcslen(lpwszStrIn); 00024 00025 // Double NULL Termination 00026 int nOutputStrLen = WideCharToMultiByte (CP_ACP, 0, lpwszStrIn, nInputStrLen, NULL, 0, 0, 0) + 2; 00027 pszOut = new char [nOutputStrLen]; 00028 00029 if (pszOut) 00030 { 00031 memset (pszOut, 0x00, nOutputStrLen); 00032 WideCharToMultiByte(CP_ACP, 0, lpwszStrIn, nInputStrLen, pszOut, nOutputStrLen, 0, 0); 00033 } 00034 } 00035 return pszOut; 00036 } 00037 00038 using namespace resip; 00039 00040 class WinCompatInstanceCleaner 00041 { 00042 public: 00043 ~WinCompatInstanceCleaner() { WinCompat::destroyInstance(); } 00044 } winCompatInstanceCleaner; 00045 00046 WinCompat::Exception::Exception(const Data& msg, const Data& file, const int line) : 00047 BaseException(msg,file,line) 00048 { 00049 } 00050 00051 00052 WinCompat::Version 00053 WinCompat::getVersion() 00054 { 00055 #ifdef UNDER_CE 00056 #define OSVERSIONINFOEX OSVERSIONINFO 00057 #endif 00058 OSVERSIONINFOEX osvi; 00059 BOOL bOsVersionInfoEx; 00060 00061 // Try calling GetVersionEx using the OSVERSIONINFOEX structure. 00062 // If that fails, try using the OSVERSIONINFO structure. 00063 00064 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); 00065 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 00066 00067 if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) ) 00068 { 00069 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); 00070 if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) 00071 { 00072 return WindowsUnknown; 00073 } 00074 } 00075 00076 switch (osvi.dwPlatformId) 00077 { 00078 // Test for the Windows NT product family. 00079 case VER_PLATFORM_WIN32_NT: 00080 00081 // Test for the specific product family. 00082 if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 ) 00083 { 00084 return WinCompat::Windows2003Server; 00085 } 00086 else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 ) 00087 { 00088 return WinCompat::WindowsXP; 00089 } 00090 else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 ) 00091 { 00092 return WinCompat::Windows2000; 00093 } 00094 else if ( osvi.dwMajorVersion <= 4 ) 00095 { 00096 return WinCompat::WindowsNT; 00097 } 00098 break; 00099 00100 // Test for the Windows 95 product family. 00101 case VER_PLATFORM_WIN32_WINDOWS: 00102 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) 00103 { 00104 return WinCompat::Windows95; 00105 } 00106 else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) 00107 { 00108 if ( osvi.szCSDVersion[1] == 'A' ) 00109 { 00110 return WinCompat::Windows98SE; 00111 } 00112 else 00113 { 00114 return WinCompat::Windows98; 00115 } 00116 } 00117 else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) 00118 { 00119 return WinCompat::WindowsME; 00120 } 00121 break; 00122 00123 default: 00124 return WinCompat::WindowsUnknown; 00125 } 00126 00127 return WinCompat::WindowsUnknown; 00128 } 00129 00130 00131 WinCompat* WinCompat::mInstance = 0; 00132 00133 00134 WinCompat * 00135 WinCompat::instance() 00136 { 00137 static Mutex mutex; 00138 if (!mInstance) 00139 { 00140 Lock lock(mutex); 00141 if (!mInstance) 00142 { 00143 mInstance = new WinCompat(); 00144 } 00145 } 00146 return mInstance; 00147 } 00148 00149 00150 WinCompat::WinCompat() : 00151 getBestInterfaceEx(0), 00152 getAdaptersAddresses(0), 00153 getAdaptersInfo(0), 00154 loadLibraryWithIPv4Failed(false), 00155 loadLibraryWithIPv6Failed(false), 00156 hLib(0) 00157 { 00158 00159 // Note: IPHLPAPI has been known to conflict with some thirdparty DLL's. 00160 // If you don't care about Win95/98/Me as your target system - then 00161 // you can define NO_IPHLPAPI so that you are not required to link with this 00162 // library. (SLG) 00163 #if !defined (NO_IPHLPAPI) 00164 // check to see if the GetAdaptersAddresses() is in the IPHLPAPI library 00165 HINSTANCE hLib = LoadLibrary(TEXT("iphlpapi.dll")); 00166 if (hLib == NULL) 00167 { 00168 loadLibraryWithIPv6Failed = true; 00169 loadLibraryWithIPv4Failed = true; 00170 return; 00171 } 00172 00173 getBestInterfaceEx = (GetBestInterfaceExProc) GetProcAddress(hLib, TEXT("GetBestInterfaceEx")); 00174 getAdaptersAddresses = (GetAdaptersAddressesProc) GetProcAddress(hLib, TEXT("GetAdaptersAddresses")); 00175 getAdaptersInfo = (GetAdaptersInfoProc) GetProcAddress(hLib, TEXT("GetAdaptersInfo")); 00176 if (getAdaptersAddresses == NULL || getBestInterfaceEx == NULL) 00177 { 00178 loadLibraryWithIPv6Failed = true; 00179 } 00180 if (getAdaptersInfo == NULL) 00181 { 00182 loadLibraryWithIPv4Failed = true; 00183 } 00184 #else 00185 loadLibraryWithIPv6Failed = true; 00186 loadLibraryWithIPv4Failed = true; 00187 #endif 00188 } 00189 00190 void WinCompat::destroyInstance() 00191 { 00192 delete mInstance; 00193 mInstance = 0; 00194 } 00195 00196 WinCompat::~WinCompat() 00197 { 00198 if(hLib != NULL) 00199 { 00200 FreeLibrary(hLib); 00201 } 00202 } 00203 00204 00205 #if !defined(NO_IPHLPAPI) 00206 // !slg! - This function is horribly slow (upto 200ms) and can cause serious performance issues for servers. 00207 // We should consider finding more efficient APIs, or caching some of the results. 00208 GenericIPAddress 00209 WinCompat::determineSourceInterfaceWithIPv6(const GenericIPAddress& destination) 00210 { 00211 if (instance()->loadLibraryWithIPv6Failed) 00212 { 00213 throw Exception("Library iphlpapi.dll with IPv6 support not available", __FILE__,__LINE__); 00214 } 00215 00216 // Obtain the size of the structure 00217 IP_ADAPTER_ADDRESSES *pAdapterAddresses; 00218 DWORD dwRet, dwSize; 00219 DWORD flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER; 00220 unsigned short family = destination.isVersion6() ? AF_INET6 : AF_INET; 00221 dwRet = (instance()->getAdaptersAddresses)(family, flags, NULL, NULL, &dwSize); 00222 if (dwRet == ERROR_BUFFER_OVERFLOW) // expected error 00223 { 00224 // Allocate memory 00225 pAdapterAddresses = (IP_ADAPTER_ADDRESSES *) LocalAlloc(LMEM_ZEROINIT,dwSize); 00226 if (pAdapterAddresses == NULL) 00227 { 00228 throw Exception("Can't find source address for destination", __FILE__,__LINE__); 00229 } 00230 00231 // Obtain network adapter information (IPv6) 00232 dwRet = (instance()->getAdaptersAddresses)(family, flags, NULL, pAdapterAddresses, &dwSize); 00233 if (dwRet != ERROR_SUCCESS) 00234 { 00235 LocalFree(pAdapterAddresses); 00236 throw Exception("Can't find source address for destination", __FILE__,__LINE__); 00237 } 00238 } 00239 00240 // Check if this address is a local address - this also avoids returning 00241 // the loopback address that can cause havoc if the registrar and user agent are on the same box 00242 IP_ADAPTER_ADDRESSES *AI; 00243 int i; 00244 for (i = 0, AI = pAdapterAddresses; AI != NULL; AI = AI->Next, i++) 00245 { 00246 PIP_ADAPTER_UNICAST_ADDRESS defaultAdaptorAddress = 0; 00247 for (PIP_ADAPTER_UNICAST_ADDRESS unicast = AI->FirstUnicastAddress; 00248 unicast; unicast = unicast->Next) 00249 { 00250 if (unicast->Address.lpSockaddr->sa_family != family) 00251 continue; 00252 00253 // Store first address of matching family as the Adaptors default address 00254 if(!defaultAdaptorAddress) defaultAdaptorAddress = unicast; 00255 00256 if (family == AF_INET && 00257 reinterpret_cast<const struct sockaddr_in*>(unicast->Address.lpSockaddr)->sin_addr.S_un.S_addr == 00258 destination.v4Address.sin_addr.S_un.S_addr) 00259 { 00260 // Return default address for NIC. Note: We could also just return the destination, 00261 // however returning the default address for NIC is beneficial in cases where the 00262 // co-located registrar supports redundancy via a Virtual IP address. 00263 GenericIPAddress ipaddress(*defaultAdaptorAddress->Address.lpSockaddr); 00264 LocalFree(pAdapterAddresses); 00265 return(ipaddress); 00266 } 00267 #ifdef USE_IPV6 00268 else if (family == AF_INET6 && 00269 memcmp(&(reinterpret_cast<const struct sockaddr_in6*>(unicast->Address.lpSockaddr)->sin6_addr), 00270 &(reinterpret_cast<const struct sockaddr_in6*>(&destination.address)->sin6_addr), 00271 sizeof(IN6_ADDR)) == 0) 00272 { 00273 // explicitly cast to sockaddr_in6, to use that version of GenericIPAddress' ctor. If we don't, then compiler 00274 // defaults to ctor for sockaddr_in (at least under Win32), which will truncate the lower-bits of the IPv6 address. 00275 const struct sockaddr_in6* psa = reinterpret_cast<const struct sockaddr_in6*>(defaultAdaptorAddress->Address.lpSockaddr); 00276 00277 // Return default address for NIC. Note: We could also just return the destination, 00278 // however returning the default address for NIC is beneficial in cases where the 00279 // co-located registrar supports redundancy via a Virtual IP address. 00280 GenericIPAddress ipaddress(*psa); 00281 LocalFree(pAdapterAddresses); 00282 return(ipaddress); 00283 } 00284 #endif 00285 } 00286 } 00287 00288 // Not a local address, get the best interface from the OS 00289 DWORD dwBestIfIndex; 00290 const sockaddr* saddr = &destination.address; 00291 if ((instance()->getBestInterfaceEx)((sockaddr *)saddr, &dwBestIfIndex) != NO_ERROR) 00292 { 00293 LocalFree(pAdapterAddresses); 00294 throw Exception("Can't find source address for destination", __FILE__,__LINE__); 00295 } 00296 00297 for (i = 0, AI = pAdapterAddresses; AI != NULL; AI = AI->Next, i++) 00298 { 00299 for (PIP_ADAPTER_UNICAST_ADDRESS unicast = AI->FirstUnicastAddress; 00300 unicast; unicast = unicast->Next) 00301 { 00302 if (unicast->Address.lpSockaddr->sa_family != saddr->sa_family) 00303 continue; 00304 if (saddr->sa_family == AF_INET && AI->IfIndex == dwBestIfIndex) 00305 { 00306 GenericIPAddress ipaddress(*unicast->Address.lpSockaddr); 00307 LocalFree(pAdapterAddresses); 00308 return(ipaddress); 00309 } 00310 #ifdef USE_IPV6 00311 else if (saddr->sa_family == AF_INET6 && AI->Ipv6IfIndex == dwBestIfIndex) 00312 { 00313 // explicitly cast to sockaddr_in6, to use that version of GenericIPAddress' ctor. If we don't, then compiler 00314 // defaults to ctor for sockaddr_in (at least under Win32), which will truncate the lower-bits of the IPv6 address. 00315 const struct sockaddr_in6* psa = reinterpret_cast<const struct sockaddr_in6*>(unicast->Address.lpSockaddr); 00316 GenericIPAddress ipaddress(*psa); 00317 LocalFree(pAdapterAddresses); 00318 return(ipaddress); 00319 } 00320 #endif 00321 } 00322 } 00323 LocalFree(pAdapterAddresses); 00324 throw Exception("Can't find source address for destination", __FILE__,__LINE__); 00325 00326 return GenericIPAddress(); 00327 } 00328 00329 00330 GenericIPAddress 00331 WinCompat::determineSourceInterfaceWithoutIPv6(const GenericIPAddress& destination) 00332 { 00333 if (instance()->loadLibraryWithIPv4Failed) 00334 { 00335 throw Exception("Library iphlpapi.dll not available", __FILE__,__LINE__); 00336 } 00337 00338 struct sockaddr_in sourceIP; 00339 memset(&sourceIP, 0, sizeof(sockaddr_in)); 00340 sourceIP.sin_family = AF_INET; 00341 00342 // look throught the local ip address - first we want to see if the address is local, if 00343 // not then we want to look for the Best route 00344 PMIB_IPADDRTABLE pIpAddrTable = NULL; 00345 ULONG addrSize = 0; 00346 00347 // allocate the space 00348 if (ERROR_INSUFFICIENT_BUFFER == GetIpAddrTable(NULL, &addrSize, FALSE)) 00349 { 00350 pIpAddrTable = (PMIB_IPADDRTABLE) new char [addrSize]; 00351 } 00352 else 00353 { 00354 throw Exception("Can't find source address for destination", __FILE__,__LINE__); 00355 } 00356 00357 if (NO_ERROR != GetIpAddrTable(pIpAddrTable, &addrSize, FALSE)) 00358 { 00359 delete [] (char *) pIpAddrTable; 00360 return GenericIPAddress(sourceIP); 00361 } 00362 00363 // Check if address is local or not 00364 DWORD i = 0; 00365 for(i = 0; i <pIpAddrTable->dwNumEntries; i++) 00366 { 00367 if(pIpAddrTable->table[i].dwAddr == 00368 destination.v4Address.sin_addr.S_un.S_addr) 00369 { 00370 // Address is local - no need to find best route - this also avoids returning 00371 // 127.0.0.1 that can cause havoc if the registrar and user agent are on the same box 00372 // Return default address for NIC. Note: We could also just return the destination, 00373 // however returning the default address for NIC is beneficial in cases where the 00374 // co-located registrar supports redundancy via a Virtual IP address. 00375 DWORD dwNicIndex = pIpAddrTable->table[i].dwIndex; 00376 for(DWORD j = 0; j <pIpAddrTable->dwNumEntries; j++) 00377 { 00378 if(pIpAddrTable->table[j].dwIndex == dwNicIndex) // Default address is first address found for NIC 00379 { 00380 sourceIP.sin_addr.s_addr = pIpAddrTable->table[j].dwAddr; 00381 delete [] (char *) pIpAddrTable; 00382 return GenericIPAddress(sourceIP); 00383 } 00384 } 00385 } 00386 } 00387 00388 // try to figure the best route to the destination 00389 MIB_IPFORWARDROW bestRoute; 00390 memset(&bestRoute, 0, sizeof(bestRoute)); 00391 const sockaddr_in& sin = (const sockaddr_in&)destination.address; 00392 if (NO_ERROR != GetBestRoute(sin.sin_addr.s_addr, 0, &bestRoute)) 00393 { 00394 delete [] (char *) pIpAddrTable; 00395 throw Exception("Can't find source address for destination", __FILE__,__LINE__); 00396 } 00397 00398 // look throught the local ip address to find one that match the best route. 00399 enum ENICEntryPreference {ENICUnknown = 0, ENextHopNotWithinNICSubnet, ENICSubnetIsAll1s, ENICServicesNextHop}; 00400 ENICEntryPreference eCurrSelection = ENICUnknown; 00401 00402 // try to find a match 00403 for (i=0; i<pIpAddrTable->dwNumEntries; i++) 00404 { 00405 MIB_IPADDRROW &entry = pIpAddrTable->table[i]; 00406 00407 ULONG addr = pIpAddrTable->table[i].dwAddr; 00408 ULONG gw = bestRoute.dwForwardNextHop; 00409 if(entry.dwIndex == bestRoute.dwForwardIfIndex) // Note: there MAY be > 1 entry with the same index, see AddIPAddress. 00410 { 00411 if( (entry.dwAddr & entry.dwMask) == (bestRoute.dwForwardNextHop & entry.dwMask) ) 00412 { 00413 sourceIP.sin_addr.s_addr = entry.dwAddr; 00414 eCurrSelection = ENICServicesNextHop; 00415 break; 00416 } 00417 else if (entry.dwMask == 0xffffffff && eCurrSelection < ENICSubnetIsAll1s) 00418 { 00419 sourceIP.sin_addr.s_addr = entry.dwAddr; 00420 eCurrSelection = ENICSubnetIsAll1s; // Lucent/Avaya VPN has Subnet Mask of 255.255.255.255. Illegal perhaps but we should use 00421 // if cannot find one that serves next hop. 00422 } 00423 else if (eCurrSelection < ENextHopNotWithinNICSubnet) 00424 { 00425 sourceIP.sin_addr.s_addr = entry.dwAddr; 00426 eCurrSelection = ENextHopNotWithinNICSubnet; // should use if nothing else works since bestRoute told us to use this NIC. 00427 } 00428 } 00429 } 00430 00431 if (eCurrSelection != ENICServicesNextHop) 00432 { 00433 // rarely happens but it does. We would fail before with the old code, let's see what the ip table looks like. 00434 in_addr subnet, netMask, nextHop; 00435 subnet.s_addr = bestRoute.dwForwardDest; 00436 netMask.s_addr = bestRoute.dwForwardMask; 00437 nextHop.s_addr = bestRoute.dwForwardNextHop; 00438 // best-route 00439 DebugLog(<< "Best Route - subnet=" <<DnsUtil::inet_ntop(subnet) 00440 <<" net-mask=" <<DnsUtil::inet_ntop(netMask) 00441 <<" next-hop=" <<DnsUtil::inet_ntop(nextHop) 00442 <<" if-index=" <<bestRoute.dwForwardIfIndex ); 00443 // ip-table 00444 for (i=0; i<pIpAddrTable->dwNumEntries; i++) 00445 { 00446 MIB_IPADDRROW & entry = pIpAddrTable->table[i]; 00447 in_addr nicIP, nicMask; 00448 nicIP.s_addr = entry.dwAddr; 00449 nicMask.s_addr = entry.dwMask; 00450 DebugLog(<<"IP Table entry " <<i+1 <<'/' <<pIpAddrTable->dwNumEntries <<" if-index=" <<entry.dwIndex 00451 <<" NIC IP=" <<DnsUtil::inet_ntop(nicIP) 00452 <<" NIC Mask=" <<DnsUtil::inet_ntop(nicMask) ); 00453 } 00454 } 00455 00456 delete [] (char *) pIpAddrTable; 00457 return GenericIPAddress(sourceIP); 00458 } 00459 #endif // !defined(NO_IPHLPAPI) 00460 00461 GenericIPAddress 00462 WinCompat::determineSourceInterface(const GenericIPAddress& destination) 00463 { 00464 // Note: IPHLPAPI has been known to conflict with some thirdparty DLL's. 00465 // If you don't care about Win95/98/Me as your target system - then 00466 // you can define NO_IPHLPAPI so that you are not required to link with this 00467 // library. (SLG) 00468 00469 #if !defined(NO_IPHLPAPI) 00470 00471 if(destination.isVersion6()) 00472 { 00473 return determineSourceInterfaceWithIPv6(destination); 00474 } 00475 else 00476 { 00477 return determineSourceInterfaceWithoutIPv6(destination); 00478 } 00479 00480 #else 00481 assert(0); 00482 #endif 00483 return GenericIPAddress(); 00484 } 00485 00486 00487 std::list<std::pair<Data,Data> > 00488 WinCompat::getInterfaces(const Data& matching) 00489 { 00490 if (instance()->loadLibraryWithIPv6Failed) 00491 { 00492 if (instance()->loadLibraryWithIPv4Failed) 00493 { 00494 throw Exception("Library iphlpapi.dll not available", __FILE__,__LINE__); 00495 } 00496 00497 // Do IPV4 only lookup - useful for Windows versions less than W2k3 and WinXp 00498 // Note: This query does not include the Loopback Adapter 00499 PIP_ADAPTER_INFO pAdaptersInfo=NULL; 00500 std::list<std::pair<Data,Data> > results; 00501 DWORD dwRet, dwSize=0; 00502 dwRet = (instance()->getAdaptersInfo)(pAdaptersInfo, &dwSize); 00503 if (dwRet == ERROR_BUFFER_OVERFLOW) // expected error 00504 { 00505 // Allocate memory 00506 pAdaptersInfo = (PIP_ADAPTER_INFO) LocalAlloc(LMEM_ZEROINIT,dwSize); 00507 if (pAdaptersInfo == NULL) 00508 { 00509 throw Exception("Can't query for adapters info - LocalAlloc error", __FILE__,__LINE__); 00510 } 00511 dwRet = (instance()->getAdaptersInfo)(pAdaptersInfo, &dwSize); 00512 if (dwRet != ERROR_SUCCESS) 00513 { 00514 LocalFree(pAdaptersInfo); 00515 throw Exception("Can't query for adapters info - GetAdaptersInfo", __FILE__,__LINE__); 00516 } 00517 else 00518 { 00519 IP_ADAPTER_INFO *AI; 00520 int i; 00521 for (i = 0, AI = pAdaptersInfo; AI != NULL; AI = AI->Next, i++) 00522 { 00523 //Data name(AI->AdapterName); 00524 Data name(AI->Description); 00525 if(matching == Data::Empty || name == matching) 00526 { 00527 for (const IP_ADDR_STRING *addr=&AI->IpAddressList; addr; addr = addr->Next) 00528 { 00529 results.push_back(std::make_pair(name, Data(addr->IpAddress.String))); 00530 } 00531 } 00532 } 00533 LocalFree(pAdaptersInfo); 00534 } 00535 } 00536 return results; 00537 } 00538 00539 // Use IPV6 compatible query 00540 // Note: This query includes the Loopback Adapter 00541 // Obtain the size of the structure 00542 IP_ADAPTER_ADDRESSES *pAdapterAddresses; 00543 std::list<std::pair<Data,Data> > results; 00544 DWORD dwRet, dwSize=0; 00545 DWORD flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER; 00546 dwRet = (instance()->getAdaptersAddresses)(AF_UNSPEC, flags, NULL, NULL, &dwSize); 00547 if (dwRet == ERROR_BUFFER_OVERFLOW) // expected error 00548 { 00549 // Allocate memory 00550 pAdapterAddresses = (IP_ADAPTER_ADDRESSES *) LocalAlloc(LMEM_ZEROINIT,dwSize); 00551 if (pAdapterAddresses == NULL) 00552 { 00553 throw Exception("Can't query for adapter addresses - LocalAlloc error", __FILE__,__LINE__); 00554 } 00555 00556 // Obtain network adapter information (IPv6) 00557 dwRet = (instance()->getAdaptersAddresses)(AF_UNSPEC, flags, NULL, pAdapterAddresses, &dwSize); 00558 if (dwRet != ERROR_SUCCESS) 00559 { 00560 LocalFree(pAdapterAddresses); 00561 throw Exception("Can't query for adapter addresses - GetAdapterAddresses", __FILE__,__LINE__); 00562 } 00563 else 00564 { 00565 IP_ADAPTER_ADDRESSES *AI; 00566 int i; 00567 for (i = 0, AI = pAdapterAddresses; AI != NULL; AI = AI->Next, i++) 00568 { 00569 if (AI->FirstUnicastAddress != NULL) 00570 { 00571 LPSTR pszSimpleCharStringFromLPWSTR = ConvertLPWSTRToLPSTR(AI->FriendlyName); 00572 Data name(pszSimpleCharStringFromLPWSTR); 00573 delete [] pszSimpleCharStringFromLPWSTR; 00574 00575 if(matching == Data::Empty || name == matching) 00576 { 00577 for (PIP_ADAPTER_UNICAST_ADDRESS unicast = AI->FirstUnicastAddress; 00578 unicast; unicast = unicast->Next) 00579 { 00580 #ifndef USE_IPV6 00581 // otherwise we would get 0.0.0.0 for AF_INET6 addresses 00582 if (unicast->Address.lpSockaddr->sa_family != AF_INET) continue; 00583 #endif 00584 results.push_back(std::make_pair(name, DnsUtil::inet_ntop(*unicast->Address.lpSockaddr))); 00585 } 00586 } 00587 } 00588 } 00589 LocalFree(pAdapterAddresses); 00590 } 00591 } 00592 return results; 00593 } 00594 00595 00596 /* ==================================================================== 00597 * The Vovida Software License, Version 1.0 00598 * 00599 * Copyright (c) 2000-2005 Vovida Networks, Inc. All rights reserved. 00600 * 00601 * Redistribution and use in source and binary forms, with or without 00602 * modification, are permitted provided that the following conditions 00603 * are met: 00604 * 00605 * 1. Redistributions of source code must retain the above copyright 00606 * notice, this list of conditions and the following disclaimer. 00607 * 00608 * 2. Redistributions in binary form must reproduce the above copyright 00609 * notice, this list of conditions and the following disclaimer in 00610 * the documentation and/or other materials provided with the 00611 * distribution. 00612 * 00613 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00614 * and "Vovida Open Communication Application Library (VOCAL)" must 00615 * not be used to endorse or promote products derived from this 00616 * software without prior written permission. For written 00617 * permission, please contact vocal@vovida.org. 00618 * 00619 * 4. Products derived from this software may not be called "VOCAL", nor 00620 * may "VOCAL" appear in their name, without prior written 00621 * permission of Vovida Networks, Inc. 00622 * 00623 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00624 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00625 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00626 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00627 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00628 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00629 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00630 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00631 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00632 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00633 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00634 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00635 * DAMAGE. 00636 * 00637 * ==================================================================== 00638 * 00639 * This software consists of voluntary contributions made by Vovida 00640 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00641 * Inc. For more information on Vovida Networks, Inc., please see 00642 * <http://www.vovida.org/>. 00643 * 00644 */
1.7.5.1