Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

477 lines
12 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. Module Name:
  4. ipname.cxx
  5. Abstract:
  6. Miscellaneous helper routines to resolve names to IP Addresses.
  7. Author:
  8. Gopal Parupudi <GopalP>
  9. Notes:
  10. a. Class IP_ADDRESS_RESOLVER cloned from RPC Runtime Transport sources
  11. (rpc\runtime\trans\winnt\common\wstrans.cxx).
  12. Revision History:
  13. GopalP 10/13/1997 Start.
  14. --*/
  15. #include <precomp.hxx>
  16. #define BACKSLASH ((SENS_CHAR) '\\')
  17. #define HTTP_PREFIX1 (SENS_STRING("http://"))
  18. #define HTTP_PREFIX2 (SENS_STRING("http:\\\\"))
  19. #define HTTP_PREFIX_LEN 7
  20. BOOL
  21. GetNetBIOSName(
  22. IN TCHAR *ActualName,
  23. IN OUT TCHAR *SanitizedName,
  24. IN SIZE_T cchName
  25. )
  26. /*++
  27. Routine Description:
  28. Sanitize the name of the destination to make it more suitable for
  29. name resolution.
  30. Arguments:
  31. ActualName - Original Name of the destination.
  32. SanitizedName - On return, this contains the sanitized version of the
  33. Actual Name. Memory is allocated by the caller.
  34. Return Value:
  35. TRUE, if successful.
  36. FALSE, if the address if the address in invalid.
  37. --*/
  38. {
  39. TCHAR *pchTemp;
  40. //
  41. // Remove the leading \\ characters, if present.
  42. //
  43. pchTemp = ActualName;
  44. if (*pchTemp == BACKSLASH)
  45. {
  46. // Check for another slash
  47. if (*++pchTemp == BACKSLASH)
  48. {
  49. if (NULL != _tcschr(++pchTemp, BACKSLASH))
  50. {
  51. // Found yet another slash!
  52. return FALSE;
  53. }
  54. StringCchCopy(SanitizedName, cchName, pchTemp);
  55. return TRUE;
  56. }
  57. else
  58. {
  59. return FALSE;
  60. }
  61. }
  62. //
  63. // Remove the "http://" prefix, if present.
  64. //
  65. pchTemp = ActualName;
  66. if ( (_tcsnicmp(HTTP_PREFIX1, ActualName, HTTP_PREFIX_LEN) == 0)
  67. || (_tcsnicmp(HTTP_PREFIX2, ActualName, HTTP_PREFIX_LEN) == 0))
  68. {
  69. StringCchCopy(SanitizedName, cchName, (pchTemp + HTTP_PREFIX_LEN));
  70. return TRUE;
  71. }
  72. StringCchCopy(SanitizedName, cchName, pchTemp);
  73. return TRUE;
  74. }
  75. DWORD
  76. ResolveName(
  77. IN TCHAR *lpszDestination,
  78. OUT LPDWORD lpdwIpAddr
  79. )
  80. /*++
  81. Routine Description:
  82. Resolve the destination name to its IP Address.
  83. Arguments:
  84. lpszDestination - Name of the destination of interest.
  85. lpdwIpAddr - On success, this contains the IP Address of the destination.
  86. Note:
  87. Since this function depends on Winsock2 being loaded, there are 2 different
  88. implementations - one for Win9x and one for NT.
  89. Return Value:
  90. ERROR_SUCCESS, if successful
  91. Error code from GetLastError(), otherwise
  92. --*/
  93. {
  94. RPC_STATUS status;
  95. TCHAR *lpszSanitizedName;
  96. DWORD dwReturnCode;
  97. DWORD bufsize;
  98. PVOID buf;
  99. BOOL bSuccess;
  100. if ( (lpdwIpAddr == NULL)
  101. || (lpszDestination == NULL))
  102. {
  103. return ERROR_INVALID_PARAMETER;
  104. }
  105. *lpdwIpAddr = 0x0;
  106. lpszSanitizedName = NULL;
  107. dwReturnCode = ERROR_HOST_UNREACHABLE;
  108. bSuccess = FALSE;
  109. lpszSanitizedName = new TCHAR[_tcslen(lpszDestination)+1];
  110. if (!lpszSanitizedName)
  111. {
  112. return (ERROR_OUTOFMEMORY);
  113. }
  114. bSuccess = GetNetBIOSName(lpszDestination, lpszSanitizedName, _tcslen(lpszDestination)+1);
  115. if (bSuccess == FALSE)
  116. {
  117. SensPrint(SENS_INFO, (SENS_STRING("Bad format for destination name - %s\n"), lpszDestination));
  118. delete lpszSanitizedName;
  119. return (ERROR_INVALID_PARAMETER);
  120. }
  121. SensPrint(SENS_INFO, (SENS_STRING("Actual Name - [%s]\n"), lpszDestination));
  122. SensPrint(SENS_INFO, (SENS_STRING("Sanitized Name - [%s]\n"), lpszSanitizedName));
  123. bufsize = sizeof(WSAQUERYSET) + IP_BUFFER_SIZE;
  124. buf = (PVOID) new char[bufsize];
  125. if (NULL == buf)
  126. {
  127. delete lpszSanitizedName;
  128. return (ERROR_OUTOFMEMORY);
  129. }
  130. IP_ADDRESS_RESOLVER resolver(lpszSanitizedName, bufsize, buf);
  131. status = resolver.NextAddress(lpdwIpAddr);
  132. switch (status)
  133. {
  134. case RPC_S_OK:
  135. dwReturnCode = ERROR_SUCCESS;
  136. break;
  137. case RPC_S_OUT_OF_MEMORY:
  138. dwReturnCode = ERROR_OUTOFMEMORY;
  139. break;
  140. case RPC_S_SERVER_UNAVAILABLE:
  141. default:
  142. //
  143. // Should we return HOST_NOT_FOUND in some cases depending
  144. // upon the WSAGetLastError() value? Maybe. But, the error
  145. // ERROR_HOST_UNREACHABLE is pretty close enough.
  146. //
  147. dwReturnCode = ERROR_HOST_UNREACHABLE;
  148. break;
  149. }
  150. //
  151. // Cleanup
  152. //
  153. if (NULL != lpszSanitizedName)
  154. {
  155. delete lpszSanitizedName;
  156. }
  157. if (NULL != buf)
  158. {
  159. delete buf;
  160. }
  161. return (dwReturnCode);
  162. }
  163. #if !defined(SENS_CHICAGO)
  164. RPC_STATUS
  165. IP_ADDRESS_RESOLVER::NextAddress(
  166. OUT LPDWORD lpdwIpAddr
  167. )
  168. /*++
  169. Routine Description:
  170. Returns the next IP address associated with the Name
  171. parameter to the constructor.
  172. During the first call if check for loopback and for dotted numeric IP
  173. address formats. If these fail then it begins a complex lookup
  174. (WSALookupServiceBegin) and returns the first available address.
  175. During successive calls in which a complex lookup was started
  176. it returns sucessive addressed returned by WSALookupServiceNext().
  177. Arguments:
  178. lpdwIpAddr - If successful, the member is set to an IP address.
  179. Return Value:
  180. RPC_S_OK - lpdwIpAddr points to a new IP address
  181. RPC_S_SERVER_UNAVAILABLE - Unable to find any more addresses
  182. RPC_S_OUT_OF_MEMORY - otherwise
  183. --*/
  184. {
  185. int err;
  186. RPC_STATUS status;
  187. *lpdwIpAddr = 0x0;
  188. // If this is the first call, _Name will be non-NULL and
  189. // we need to start the lookup process.
  190. if (_Name)
  191. {
  192. TCHAR *Name = _Name;
  193. _Name = 0;
  194. // Check for loopback first.
  195. if (! *Name)
  196. {
  197. // Loopback - assign result of htonl(INADDR_LOOPBACK)
  198. // Little-endian dependence.
  199. *lpdwIpAddr = 0x0100007F;
  200. return(RPC_S_OK);
  201. }
  202. // Assume dot address since this is faster to check.
  203. int size = sizeof(SOCKADDR_IN);
  204. SOCKADDR_IN addr;
  205. err = WSAStringToAddress(Name,
  206. AF_INET,
  207. 0,
  208. (PSOCKADDR)&addr,
  209. &size);
  210. if (err != SOCKET_ERROR)
  211. {
  212. *lpdwIpAddr = addr.sin_addr.s_addr;
  213. return(RPC_S_OK);
  214. }
  215. ASSERT(GetLastError() == WSAEINVAL);
  216. // Start a complex query operation
  217. const static AFPROTOCOLS aIpProtocols[2] =
  218. {
  219. {AF_INET, IPPROTO_UDP},
  220. {AF_INET, IPPROTO_TCP}
  221. };
  222. const static GUID guidHostAddressByName = SVCID_INET_HOSTADDRBYNAME;
  223. WSAQUERYSET wsqs;
  224. memset(&wsqs, 0, sizeof(wsqs));
  225. wsqs.dwSize = sizeof(WSAQUERYSET);
  226. // wsqs.dwNameSpace = NS_ALL;
  227. ASSERT(NS_ALL == 0);
  228. wsqs.lpszServiceInstanceName = Name;
  229. wsqs.lpServiceClassId = (GUID *)&guidHostAddressByName;
  230. wsqs.dwNumberOfProtocols = 2;
  231. wsqs.lpafpProtocols = (PAFPROTOCOLS)&aIpProtocols[0];
  232. err = WSALookupServiceBegin(&wsqs,
  233. LUP_RETURN_ADDR,
  234. &_hRnr);
  235. if (err == SOCKET_ERROR)
  236. {
  237. SensPrintA(SENS_INFO, ("WSALookupServiceBegin() failed: %d\n", GetLastError()));
  238. return(RPC_S_SERVER_UNAVAILABLE);
  239. }
  240. _index = 0;
  241. if (_pwsqs)
  242. {
  243. _pwsqs->dwNumberOfCsAddrs = 0;
  244. }
  245. }
  246. else
  247. {
  248. if (!_hRnr)
  249. {
  250. // First call finished but didn't start a complex query. Abort now.
  251. return(RPC_S_SERVER_UNAVAILABLE);
  252. }
  253. }
  254. // A complex query has been started.
  255. ASSERT(_hRnr);
  256. // If the cached query structure is empty, call WSALookupNext to get
  257. // more addresses.
  258. if (!_pwsqs || (_index >= _pwsqs->dwNumberOfCsAddrs))
  259. {
  260. DWORD needed = _size;
  261. // Loop needed to realloc a larger _pwsqs buffer.
  262. for(;;)
  263. {
  264. err = WSALookupServiceNext(_hRnr,
  265. 0, // flags
  266. &needed,
  267. _pwsqs);
  268. // Success, break out of the loop.
  269. if (err != SOCKET_ERROR)
  270. {
  271. ASSERT(_pwsqs->dwNumberOfCsAddrs > 0);
  272. ASSERT(_pwsqs->lpcsaBuffer);
  273. // Reset to start of new result set.
  274. _index = 0;
  275. break;
  276. }
  277. status = GetLastError();
  278. // WSAEFAULT means the buffer was too small.
  279. if (status != WSAEFAULT)
  280. {
  281. // WSA_E_NO_MORE means all matching address have
  282. // already been returned.
  283. VALIDATE(status)
  284. {
  285. WSA_E_NO_MORE,
  286. WSANO_DATA,
  287. WSASERVICE_NOT_FOUND,
  288. WSAHOST_NOT_FOUND,
  289. WSATRY_AGAIN,
  290. WSANO_RECOVERY,
  291. WSANO_DATA,
  292. WSAEINVAL // In response to out of resources scenarios.
  293. } END_VALIDATE;
  294. SensPrintA(SENS_ERR, ("WSALookupServiceNext() failed: %d\n", status));
  295. return(RPC_S_SERVER_UNAVAILABLE);
  296. }
  297. // Allocate a larger buffer.
  298. if (needed <= _size)
  299. {
  300. ASSERT(needed > _size);
  301. return(RPC_S_SERVER_UNAVAILABLE);
  302. }
  303. if (_fFree)
  304. {
  305. delete _pwsqs;
  306. }
  307. _pwsqs = (PWSAQUERYSET) new char[needed];
  308. //_pwsqs = new WSAQUERYSETW[(needed - sizeof(WSAQUERYSETW))];
  309. //_pwsqs = (PWSAQUERYSETW) new char(needed - sizeof(WSAQUERYSETW));
  310. if (!_pwsqs)
  311. {
  312. return(RPC_S_OUT_OF_MEMORY);
  313. }
  314. _fFree = TRUE;
  315. _pwsqs->dwNumberOfCsAddrs = 0;
  316. _size = needed;
  317. #if DBG
  318. // On retail we start with enough space for two addresses during the
  319. // first call. If this debug print gets hit too much we can increase the
  320. // starting size (IP_BUFFER_SIZE).
  321. if (_size > sizeof(WSAQUERYSET) + IP_RETAIL_BUFFER_SIZE)
  322. {
  323. SensPrintA(SENS_ERR, ("WSALookupServerNext(): sizeof(WSAQUERYSETW) - %d\n"
  324. "WSALookupServerNext(): IP_RETAIL_BUFFER_SIZE - %d\n",
  325. sizeof(WSAQUERYSETW), IP_RETAIL_BUFFER_SIZE));
  326. SensPrintA(SENS_ERR, ("WSALookupServerNext() wants %d bytes. Make this the "
  327. "default?\n", _size));
  328. }
  329. #endif
  330. }
  331. }
  332. ASSERT(_pwsqs);
  333. ASSERT(_index < _pwsqs->dwNumberOfCsAddrs);
  334. LPCSADDR_INFO pInfo = &_pwsqs->lpcsaBuffer[_index];
  335. _index++;
  336. *lpdwIpAddr = ((SOCKADDR_IN *)pInfo->RemoteAddr.lpSockaddr)->sin_addr.s_addr;
  337. return(RPC_S_OK);
  338. }
  339. IP_ADDRESS_RESOLVER::~IP_ADDRESS_RESOLVER()
  340. {
  341. if (_hRnr)
  342. {
  343. WSALookupServiceEnd(_hRnr);
  344. }
  345. if (_fFree)
  346. {
  347. delete _pwsqs;
  348. }
  349. }
  350. #endif // SENS_CHICAGO