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.

3368 lines
81 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. ipconfig.cxx
  5. Abstract:
  6. CIpConfig class implementation
  7. Contents:
  8. CIpAddress::GetAddress
  9. CIpAddressList::Find
  10. CIpAddressList::Add(CIpAddress *)
  11. CIpAddressList::Add(DWORD, DWORD, DWORD)
  12. CIpAddressList::GetAddress
  13. CIpAddressList::ThrowOutUnfoundEntries
  14. CAdapterInterface::CAdapterInterface
  15. CAdapterInterface::~CAdapterInterface
  16. CIpConfig::CIpConfig
  17. CIpConfig::~CIpConfig
  18. CIpConfig::GetRouterAddress
  19. CIpConfig::GetDnsAddress
  20. CIpConfig::IsKnownIpAddress
  21. CIpConfig::Refresh
  22. (CIpConfig::GetAdapterList)
  23. (CIpConfig::LoadEntryPoints)
  24. (CIpConfig::UnloadEntryPoints)
  25. (CIpConfig::FindOrCreateInterface)
  26. (CIpConfig::FindInterface)
  27. (CIpConfig::ThrowOutUnfoundEntries)
  28. WsControl
  29. (WinNtWsControl)
  30. (OpenTcpipDriverHandle)
  31. (CloseTcpipDriverHandle)
  32. (GetEntityList)
  33. [InternetMapEntity]
  34. [InternetMapInterface]
  35. Author:
  36. Richard L Firth (rfirth) 29-Oct-1996
  37. Environment:
  38. Win32 user-mode DLL
  39. Notes:
  40. In order to operate correctly, we require the Microsoft Winsock implementation
  41. (WSOCK32.DLL) and the Microsoft TCP/IP stack to be loaded
  42. Revision History:
  43. 29-Oct-1996 rfirth
  44. Created
  45. 15-Jul-1998 arthurbi
  46. Resurrected from the dead
  47. --*/
  48. #include <wininetp.h>
  49. #include "aproxp.h"
  50. #include <dhcpcsdk.h>
  51. //
  52. // manifests
  53. //
  54. #define MAX_ADAPTER_DESCRIPTION_LENGTH 128 // arbitrary
  55. //#define DEFAULT_MINIMUM_ENTITIES MAX_TDI_ENTITIES
  56. //
  57. // macros
  58. //
  59. //
  60. // IS_INTERESTING_ADAPTER - TRUE if the type of this adapter (IFEntry) is NOT
  61. // loopback. Loopback (corresponding to local host) is the only one we filter
  62. // out right now
  63. //
  64. #define IS_INTERESTING_ADAPTER(p) (!((p)->if_type == IF_TYPE_LOOPBACK))
  65. #define IS_INTERESTING_ADAPTER_NT5(p) (!((p)->Type == IF_TYPE_RFC877_X25))
  66. //
  67. // globals
  68. //
  69. const char SERVICES_KEY_NAME[] = "SYSTEM\\CurrentControlSet\\Services";
  70. HKEY TcpipLinkageKey = NULL;// = INVALID_HANDLE_VALUE;
  71. HKEY ServicesKey = NULL; // = INVALID_HANDLE_VALUE;
  72. BOOL CIpConfig::m_Loaded;
  73. //
  74. // private prototypes
  75. //
  76. PRIVATE
  77. DWORD
  78. WinNtWsControl(
  79. DWORD dwProtocol,
  80. DWORD dwRequest,
  81. LPVOID lpInputBuffer,
  82. LPDWORD lpdwInputBufferLength,
  83. LPVOID lpOutputBuffer,
  84. LPDWORD lpdwOutputBufferLength
  85. );
  86. PRIVATE
  87. DWORD
  88. OpenTcpipDriverHandle(
  89. VOID
  90. );
  91. PRIVATE
  92. VOID
  93. CloseTcpipDriverHandle(
  94. VOID
  95. );
  96. PRIVATE
  97. DWORD
  98. GetEntityList(
  99. OUT TDIEntityID * * lplpEntities
  100. );
  101. //
  102. // private debug prototypes
  103. //
  104. PRIVATE
  105. LPCSTR
  106. InternetMapEntity(
  107. IN INT EntityId
  108. );
  109. PRIVATE
  110. LPCSTR
  111. InternetMapInterface(
  112. IN DWORD InterfaceType
  113. );
  114. PRIVATE
  115. LPCSTR
  116. InternetMapInterfaceOnNT5(
  117. IN DWORD InterfaceType
  118. );
  119. //
  120. // private data
  121. //
  122. //
  123. // NTDLL info - if the platform is NT then we use the following entry points in
  124. // NTDLL.DLL to talk to the TCP/IP device driver
  125. //
  126. PRIVATE VOID (* _I_RtlInitUnicodeString)(PUNICODE_STRING, PCWSTR) = NULL;
  127. PRIVATE NTSTATUS (* _I_NtCreateFile)(PHANDLE,
  128. ACCESS_MASK,
  129. POBJECT_ATTRIBUTES,
  130. PIO_STATUS_BLOCK,
  131. PLARGE_INTEGER,
  132. ULONG,
  133. ULONG,
  134. ULONG,
  135. ULONG,
  136. PVOID,
  137. ULONG
  138. ) = NULL;
  139. PRIVATE ULONG (* _I_RtlNtStatusToDosError)(NTSTATUS) = NULL;
  140. PRIVATE DLL_ENTRY_POINT NtDllEntryPoints[] = {
  141. DLL_ENTRY_POINT_ELEMENT(RtlInitUnicodeString),
  142. DLL_ENTRY_POINT_ELEMENT(NtCreateFile),
  143. DLL_ENTRY_POINT_ELEMENT(RtlNtStatusToDosError)
  144. };
  145. PRIVATE DLL_INFO NtDllInfo = DLL_INFO_INIT("NTDLL.DLL", NtDllEntryPoints);
  146. PRIVATE HANDLE TcpipDriverHandle = INVALID_HANDLE_VALUE;
  147. //
  148. // Iphlpapi - Ip Helper APIs only found on NT 5 and Win 98, must dynaload,
  149. // Used to gather information on what adapters are avaible on the machine
  150. //
  151. PRIVATE DWORD (PASCAL FAR * _I_GetAdaptersInfo)(PIP_ADAPTER_INFO,
  152. PULONG
  153. ) = NULL;
  154. PRIVATE DLL_ENTRY_POINT IpHlpApiEntryPoints[] = {
  155. DLL_ENTRY_POINT_ELEMENT(GetAdaptersInfo)
  156. };
  157. PRIVATE DLL_INFO IpHlpApiDllInfo = DLL_INFO_INIT("IPHLPAPI.DLL", IpHlpApiEntryPoints);
  158. //
  159. // DhcpcSvc - DHCP dll, Only found on Win'98 and NT 5. This function does almost all the
  160. // work for us using the native DHCP services found on these cool new OSes.
  161. //
  162. PRIVATE DWORD (__stdcall * _I_DhcpRequestParams)(DWORD,
  163. LPVOID,
  164. LPWSTR,
  165. LPDHCPCAPI_CLASSID,
  166. DHCPCAPI_PARAMS_ARRAY,
  167. DHCPCAPI_PARAMS_ARRAY,
  168. LPBYTE,
  169. LPDWORD,
  170. LPWSTR
  171. ) = NULL;
  172. PRIVATE DLL_ENTRY_POINT DhcpcSvcEntryPoints[] = {
  173. DLL_ENTRY_POINT_ELEMENT(DhcpRequestParams)
  174. };
  175. PRIVATE DLL_INFO DhcpcSvcDllInfo = DLL_INFO_INIT("DHCPCSVC.DLL", DhcpcSvcEntryPoints);
  176. //
  177. // global data
  178. //
  179. // none.
  180. //
  181. // methods
  182. //
  183. //
  184. // public CIpAddress methods
  185. //
  186. BOOL
  187. CIpAddress::GetAddress(
  188. OUT LPBYTE lpbAddress,
  189. IN OUT LPDWORD lpdwAddressLength
  190. )
  191. /*++
  192. Routine Description:
  193. Returns the IP address from this CIpAddress
  194. Arguments:
  195. lpbAddress - pointer to returned address
  196. lpdwAddressLength - size of IP address
  197. Return Value:
  198. BOOL
  199. TRUE - address copied
  200. FALSE - address not copied (buffer not large enough)
  201. --*/
  202. {
  203. if (*lpdwAddressLength >= sizeof(DWORD)) {
  204. *(LPDWORD)lpbAddress = m_dwIpAddress;
  205. *lpdwAddressLength = sizeof(DWORD);
  206. return TRUE;
  207. }
  208. return FALSE;
  209. }
  210. //
  211. // public CIpAddressList methods
  212. //
  213. BOOL
  214. CIpAddressList::IsContextInList(
  215. IN DWORD dwContext
  216. )
  217. {
  218. for (CIpAddress * pEntry = m_List; pEntry != NULL; pEntry = pEntry->m_Next) {
  219. if (pEntry->Context() == dwContext) {
  220. return TRUE;
  221. }
  222. }
  223. return FALSE;
  224. }
  225. CIpAddress *
  226. CIpAddressList::Find(
  227. IN DWORD dwIpAddress,
  228. IN DWORD dwIpMask
  229. )
  230. /*++
  231. Routine Description:
  232. Finds the CIpAddress object corresponding to (dwIpAddress, dwIpMask)
  233. Arguments:
  234. dwIpAddress - IP address to find
  235. dwIpMask - IP address mask, or INADDR_ANY (0) if we don't care
  236. Return Value:
  237. CIpAddress *
  238. Success - pointer to found object
  239. Failure - NULL
  240. --*/
  241. {
  242. for (CIpAddress * pEntry = m_List; pEntry != NULL; pEntry = pEntry->m_Next) {
  243. if ((pEntry->IpAddress() == dwIpAddress)
  244. && ((dwIpMask == INADDR_ANY) || (pEntry->IpMask() == dwIpMask))) {
  245. break;
  246. }
  247. }
  248. return pEntry;
  249. }
  250. VOID
  251. CIpAddressList::Add(
  252. IN CIpAddress * pAddress
  253. )
  254. /*++
  255. Routine Description:
  256. Adds an IP address entry to the list
  257. Arguments:
  258. pAddress - pointer to CIpAddress to add
  259. Return Value:
  260. None.
  261. --*/
  262. {
  263. INET_ASSERT(pAddress->m_Next == NULL);
  264. CIpAddress * pEntry = (CIpAddress *)&m_List;
  265. while (pEntry->m_Next != NULL) {
  266. pEntry = pEntry->m_Next;
  267. }
  268. pEntry->m_Next = pAddress;
  269. }
  270. BOOL
  271. CIpAddressList::Add(
  272. IN DWORD dwIpAddress,
  273. IN DWORD dwIpMask,
  274. IN DWORD dwContext
  275. )
  276. /*++
  277. Routine Description:
  278. Adds an IP address entry to the list
  279. Arguments:
  280. dwIpAddress - IP address to add
  281. dwIpMask - IP subnet mask
  282. dwContext - unique interface context value
  283. Return Value:
  284. BOOL
  285. TRUE - item added
  286. FALSE - out of memory
  287. --*/
  288. {
  289. CIpAddress * pIpAddress = new CIpAddress(dwIpAddress, dwIpMask, dwContext);
  290. if (pIpAddress != NULL) {
  291. Add(pIpAddress);
  292. return TRUE;
  293. }
  294. return FALSE;
  295. }
  296. BOOL
  297. CIpAddressList::GetAddress(
  298. IN OUT LPDWORD lpdwIndex,
  299. OUT LPBYTE lpbAddress,
  300. IN OUT LPDWORD lpdwAddressLength
  301. )
  302. /*++
  303. Routine Description:
  304. Returns the *lpdwIndex'th address from the list
  305. Arguments:
  306. lpdwIndex - which address to return. Updated on output
  307. lpbAddress - pointer to returned address
  308. lpdwAddressLength - pointer to returned address length
  309. Return Value:
  310. BOOL
  311. TRUE - address returned
  312. FALSE - address not returned
  313. --*/
  314. {
  315. DEBUG_ENTER((DBG_SOCKETS,
  316. Bool,
  317. "CIpAddressList::GetAddress",
  318. "%#x [%d], %#x, %#x [%d]",
  319. lpdwIndex,
  320. *lpdwIndex,
  321. lpbAddress,
  322. lpdwAddressLength,
  323. *lpdwAddressLength
  324. ));
  325. CIpAddress * p = m_List;
  326. for (DWORD i = 0; (i < *lpdwIndex) && (p != NULL); ++i) {
  327. p = p->m_Next;
  328. }
  329. BOOL found;
  330. if (p != NULL) {
  331. found = p->GetAddress(lpbAddress, lpdwAddressLength);
  332. if (found) {
  333. ++*lpdwIndex;
  334. }
  335. } else {
  336. found = FALSE;
  337. }
  338. DEBUG_LEAVE(found);
  339. return found;
  340. }
  341. PRIVATE
  342. BOOL
  343. CIpAddressList::ThrowOutUnfoundEntries(
  344. VOID
  345. )
  346. /*++
  347. Routine Description:
  348. Throws out (deletes) any addresses that are marked not-found
  349. Arguments:
  350. None.
  351. Return Value:
  352. BOOL
  353. TRUE - interfaces thrown out
  354. FALSE - " not " "
  355. --*/
  356. {
  357. DEBUG_ENTER((DBG_SOCKETS,
  358. Bool,
  359. "CIpAddressList::ThrowOutUnfoundEntries",
  360. NULL
  361. ));
  362. CIpAddress * pLast = (CIpAddress *)&m_List;
  363. CIpAddress * pEntry;
  364. BOOL bThrownOut = FALSE;
  365. for (pEntry = m_List; pEntry != NULL; pEntry = pEntry->m_Next) {
  366. if (!pEntry->IsFound()) {
  367. pLast->m_Next = pEntry->m_Next;
  368. delete pEntry;
  369. bThrownOut = TRUE;
  370. pEntry = pLast;
  371. } else {
  372. pLast = pEntry;
  373. }
  374. }
  375. DEBUG_LEAVE(bThrownOut);
  376. return bThrownOut;
  377. }
  378. //
  379. // public CAdapterInterface methods
  380. //
  381. CAdapterInterface::CAdapterInterface(
  382. IN DWORD dwIndex,
  383. IN DWORD dwType,
  384. IN DWORD dwSpeed,
  385. IN LPSTR lpszDescription,
  386. IN DWORD dwDescriptionLength,
  387. IN LPBYTE lpPhysicalAddress,
  388. IN DWORD dwPhysicalAddressLength
  389. )
  390. /*++
  391. Routine Description:
  392. CAdapterInterface constructor
  393. Arguments:
  394. dwIndex - unique adapter interface index
  395. dwType - type of interface
  396. dwSpeed - speed of interface
  397. lpszDescription - pointer to descriptive name of adapter
  398. dwDescriptionLength - length of lpszDescription
  399. lpPhysicalAddress -
  400. dwPhysicalAddressLength -
  401. Return Value:
  402. None.
  403. --*/
  404. {
  405. if ((lpszDescription != NULL) && (dwDescriptionLength != 0)) {
  406. m_lpszDescription = new char[dwDescriptionLength + 1];
  407. if (m_lpszDescription != NULL) {
  408. memcpy(m_lpszDescription, lpszDescription, dwDescriptionLength);
  409. } else {
  410. dwDescriptionLength = 0;
  411. }
  412. }
  413. if ((lpPhysicalAddress != NULL) && (dwPhysicalAddressLength != 0)) {
  414. m_lpPhysicalAddress = new BYTE[dwPhysicalAddressLength];
  415. if ( m_lpPhysicalAddress != NULL ) {
  416. memcpy(m_lpPhysicalAddress, lpPhysicalAddress, dwPhysicalAddressLength);
  417. }
  418. else {
  419. dwPhysicalAddressLength = 0;
  420. }
  421. }
  422. switch( dwType )
  423. {
  424. case IF_TYPE_ETHERNET:
  425. m_dwPhysicalAddressType = HARDWARE_TYPE_10MB_EITHERNET;
  426. break;
  427. case IF_TYPE_TOKENRING:
  428. case IF_TYPE_FDDI:
  429. m_dwPhysicalAddressType = HARDWARE_TYPE_IEEE_802;
  430. break;
  431. case IF_TYPE_OTHER:
  432. m_dwPhysicalAddressType = HARDWARE_ARCNET;
  433. break;
  434. case IF_TYPE_PPP:
  435. m_dwPhysicalAddressType = HARDWARE_PPP;
  436. break;
  437. case IF_TYPE_IEEE1394:
  438. m_dwPhysicalAddressType = HARDWARE_IEEE1394;
  439. break;
  440. default:
  441. m_dwPhysicalAddressType = HARDWARE_ARCNET;
  442. break;
  443. }
  444. m_dwPhysicalAddressLength = dwPhysicalAddressLength;
  445. m_dwDescriptionLength = dwDescriptionLength;
  446. m_lpszAdapterName = NULL;
  447. m_dwIndex = dwIndex;
  448. m_dwType = dwType;
  449. m_dwSpeed = dwSpeed;
  450. m_Flags.Word = 0;
  451. SetFound(TRUE);
  452. }
  453. CAdapterInterface::~CAdapterInterface(
  454. VOID
  455. )
  456. /*++
  457. Routine Description:
  458. CAdapterInterface destructor
  459. Arguments:
  460. None.
  461. Return Value:
  462. None.
  463. --*/
  464. {
  465. if (m_lpszDescription != NULL) {
  466. delete m_lpszDescription;
  467. }
  468. if (m_lpPhysicalAddress != NULL) {
  469. delete m_lpPhysicalAddress;
  470. }
  471. if ( m_lpszAdapterName != NULL) {
  472. FREE_MEMORY(m_lpszAdapterName);
  473. }
  474. }
  475. BOOL
  476. CAdapterInterface::DhcpDoInformNT5(
  477. OUT LPSTR * ppszAutoProxyUrl
  478. )
  479. /*++
  480. Routine Description:
  481. For a given Interface, this nifly little method uses the new wizbang NT 5/Win'98 specific API
  482. to do the DHCP Inform request and determine an auto-proxy Url that we can use.
  483. Kinda of nice when we're on NT 5, otherwise we need to pull in the kitchen sink equivlent of
  484. DHCP code that has been ripped off from the NT 4/Win'95 code base
  485. Arguments:
  486. lpszAutoProxyUrl - a piece of memory where we can stuff our new auto-proxy URL
  487. dwAutoProxyUrlLength - size of the space to store the string above
  488. Return Value:
  489. BOOL
  490. TRUE - successfully talked to server and got Url
  491. FALSE - failed to allocate memory or failure talking to TCP/IP or failure to get an Url needed to continue
  492. --*/
  493. {
  494. DWORD error;
  495. WCHAR wszAdapterName[(MAX_ADAPTER_NAME_LENGTH + 6)];
  496. int len;
  497. LPSTR lpszAutoProxyUrl = NULL;
  498. len = MultiByteToWideChar(
  499. CP_ACP,
  500. 0, // flags
  501. GetAdapterName(),
  502. -1, // assume null-terminated
  503. wszAdapterName,
  504. (MAX_ADAPTER_NAME_LENGTH + 6)
  505. );
  506. if ( len == 0 ) {
  507. return FALSE; // failed to convert string
  508. }
  509. if (_I_DhcpRequestParams == NULL)
  510. {
  511. return FALSE;
  512. }
  513. DHCPCAPI_PARAMS_ARRAY SendParams;
  514. DHCPCAPI_PARAMS_ARRAY RecvParams;
  515. DHCPAPI_PARAMS WpadParam;
  516. BYTE * pBuffer = NULL;
  517. BYTE Buffer[400];
  518. DWORD dwBufferSize = sizeof(Buffer);
  519. ZeroMemory(&WpadParam, sizeof(WpadParam));
  520. WpadParam.OptionId = OPTION_WPAD_URL;
  521. WpadParam.IsVendor = FALSE;
  522. SendParams.nParams = 0;
  523. SendParams.Params = NULL;
  524. RecvParams.nParams = 1;
  525. RecvParams.Params = &WpadParam;
  526. error = _I_DhcpRequestParams(
  527. DHCPCAPI_REQUEST_SYNCHRONOUS,
  528. NULL,
  529. wszAdapterName,
  530. NULL,
  531. SendParams,
  532. RecvParams,
  533. Buffer,
  534. &dwBufferSize,
  535. NULL
  536. );
  537. if (error == ERROR_MORE_DATA)
  538. {
  539. dwBufferSize += 400;
  540. pBuffer = new BYTE[dwBufferSize];
  541. if (pBuffer != NULL)
  542. {
  543. ZeroMemory(&WpadParam, sizeof(WpadParam));
  544. WpadParam.OptionId = OPTION_WPAD_URL;
  545. WpadParam.IsVendor = FALSE;
  546. SendParams.nParams = 0;
  547. SendParams.Params = NULL;
  548. RecvParams.nParams = 1;
  549. RecvParams.Params = &WpadParam;
  550. error = _I_DhcpRequestParams(
  551. DHCPCAPI_REQUEST_SYNCHRONOUS,
  552. NULL,
  553. wszAdapterName,
  554. NULL,
  555. SendParams,
  556. RecvParams,
  557. pBuffer,
  558. &dwBufferSize,
  559. NULL
  560. );
  561. }
  562. else
  563. {
  564. error = ERROR_NOT_ENOUGH_MEMORY;
  565. }
  566. }
  567. if (error == ERROR_SUCCESS && WpadParam.Data != NULL && WpadParam.nBytesData != 0)
  568. {
  569. lpszAutoProxyUrl = NewString((LPCSTR)WpadParam.Data, WpadParam.nBytesData);
  570. if (lpszAutoProxyUrl)
  571. {
  572. *ppszAutoProxyUrl = lpszAutoProxyUrl;
  573. }
  574. }
  575. if (pBuffer)
  576. delete [] pBuffer;
  577. return (lpszAutoProxyUrl != NULL);
  578. }
  579. BOOL
  580. CAdapterInterface::CopyAdapterInfoToDhcpContext(
  581. PDHCP_CONTEXT pDhcpContext
  582. )
  583. {
  584. memset ((void *) pDhcpContext, 0, sizeof(DHCP_CONTEXT));
  585. // hardware address, length, and type
  586. pDhcpContext->HardwareAddressType = m_dwPhysicalAddressType;
  587. pDhcpContext->HardwareAddress = m_lpPhysicalAddress;
  588. pDhcpContext->HardwareAddressLength = m_dwPhysicalAddressLength;
  589. if (m_IpList.m_List) {
  590. // Selected IpAddress, NetworkOrder. htonl
  591. // note: assumed to be in network order
  592. pDhcpContext->IpAddress = ((m_IpList.m_List)->IpAddress());
  593. pDhcpContext->IpInterfaceContext = ((m_IpList.m_List)->Context());
  594. }
  595. if (m_DhcpList.m_List) {
  596. // Selected DHCP server address. Network Order. htonl
  597. // note: assumed to be in network order
  598. pDhcpContext->DhcpServerAddress = ((m_DhcpList.m_List)->IpAddress());
  599. }
  600. pDhcpContext->ClientIdentifier.fSpecified = FALSE;
  601. pDhcpContext->T2Time = 0;
  602. // when was the last time an inform was sent?
  603. pDhcpContext->LastInformSent = 0;
  604. // seconds passed since boot.
  605. pDhcpContext->SecondsSinceBoot = 0;
  606. // the list of options to send and the list of options received
  607. InitializeListHead(&pDhcpContext->RecdOptionsList);
  608. InitializeListHead(&pDhcpContext->SendOptionsList);
  609. // the class this adapter belongs to
  610. if ( m_lpszAdapterName )
  611. {
  612. pDhcpContext->ClassId = (unsigned char *) m_lpszAdapterName;
  613. pDhcpContext->ClassIdLength = lstrlen(m_lpszAdapterName);
  614. }
  615. else
  616. {
  617. pDhcpContext->ClassId = NULL;
  618. pDhcpContext->ClassIdLength = 0;
  619. }
  620. // Message buffer to send and receive DHCP message.
  621. pDhcpContext->MessageBuffer = (PDHCP_MESSAGE) pDhcpContext->szMessageBuffer;
  622. memset(pDhcpContext->szMessageBuffer, 0, sizeof(pDhcpContext->szMessageBuffer));
  623. //LocalInfo = (PLOCAL_CONTEXT_INFO)((*pDhcpContext)->LocalInformation);
  624. //LocalInfo->IpInterfaceContext = IpInterfaceContext;
  625. //LocalInfo->IpInterfaceInstance = IpInterfaceInstance;
  626. // IpInterfaceInstance is filled in make context
  627. pDhcpContext->Socket = INVALID_SOCKET;
  628. pDhcpContext->State.Plumbed = TRUE;
  629. pDhcpContext->State.ServerReached = FALSE;
  630. pDhcpContext->State.AutonetEnabled= FALSE;
  631. pDhcpContext->State.HasBeenLooked = FALSE;
  632. pDhcpContext->State.DhcpEnabled = FALSE;
  633. pDhcpContext->State.AutoMode = FALSE;
  634. pDhcpContext->State.MediaState = FALSE;
  635. pDhcpContext->State.MDhcp = FALSE;
  636. pDhcpContext->State.PowerResumed = FALSE;
  637. pDhcpContext->State.Broadcast = FALSE;
  638. return TRUE;
  639. }
  640. //
  641. // public CIpConfig methods
  642. //
  643. CIpConfig::CIpConfig(
  644. VOID
  645. )
  646. /*++
  647. Routine Description:
  648. CIpConfig constructor - initializes the object & loads the requird DLLs if
  649. not already loaded
  650. Arguments:
  651. None.
  652. Return Value:
  653. None.
  654. --*/
  655. {
  656. DEBUG_ENTER((DBG_OBJECTS,
  657. None,
  658. "CIpConfig::CIpConfig",
  659. NULL
  660. ));
  661. InitializeListHead(&m_List);
  662. m_dwNumberOfInterfaces = 0;
  663. DWORD error = LoadEntryPoints();
  664. if (error == ERROR_SUCCESS) {
  665. #ifndef unix
  666. GetAdapterList();
  667. #endif /* unix */
  668. }
  669. DEBUG_LEAVE(0);
  670. }
  671. CIpConfig::~CIpConfig()
  672. /*++
  673. Routine Description:
  674. CIpConfig destructor - destroys this object and unloads (or reduces the
  675. reference count on) the DLLs
  676. Arguments:
  677. None.
  678. Return Value:
  679. None.
  680. --*/
  681. {
  682. DEBUG_ENTER((DBG_OBJECTS,
  683. None,
  684. "CIpConfig::~CIpConfig",
  685. NULL
  686. ));
  687. while (!IsListEmpty(&m_List)) {
  688. PLIST_ENTRY pEntry = RemoveHeadList(&m_List);
  689. //
  690. // BUGBUG - need CONTAINING_RECORD() if m_List is not @ start of
  691. // CAdapterInterface
  692. //
  693. CAdapterInterface * pInterface = (CAdapterInterface *)pEntry;
  694. delete pInterface;
  695. }
  696. CloseTcpipDriverHandle();
  697. DEBUG_LEAVE(0);
  698. }
  699. BOOL
  700. CIpConfig::GetRouterAddress(
  701. IN LPBYTE lpbInterfaceAddress OPTIONAL,
  702. IN DWORD dwInterfaceAddressLength,
  703. IN OUT LPDWORD lpdwIndex,
  704. OUT LPBYTE lpbAddress,
  705. IN OUT LPDWORD lpdwAddressLength
  706. )
  707. /*++
  708. Routine Description:
  709. Returns the *lpdwIndex'th router address belonging to the interface
  710. corresponding to the address in lpbInterfaceAddress
  711. Arguments:
  712. lpbInterfaceAddress - pointer to interface address
  713. dwInterfaceAddressLength - length of interface address
  714. lpdwIndex - index of router address to return
  715. lpbAddress - returned router address
  716. lpdwAddressLength - length of router address
  717. Return Value:
  718. BOOL
  719. TRUE - *lpdwIndex'th router address returned for requested interface
  720. FALSE - requested address not returned
  721. --*/
  722. {
  723. UNREFERENCED_PARAMETER(lpbInterfaceAddress);
  724. UNREFERENCED_PARAMETER(dwInterfaceAddressLength);
  725. UNREFERENCED_PARAMETER(lpdwIndex);
  726. UNREFERENCED_PARAMETER(lpbAddress);
  727. UNREFERENCED_PARAMETER(lpdwAddressLength);
  728. DEBUG_ENTER((DBG_SOCKETS,
  729. Bool,
  730. "CIpConfig::GetRouterAddress",
  731. "%#x, %d, %#x [%d], %#x, %#x [%d]",
  732. lpbInterfaceAddress,
  733. dwInterfaceAddressLength,
  734. lpdwIndex,
  735. *lpdwIndex,
  736. lpbAddress,
  737. lpdwAddressLength,
  738. *lpdwAddressLength
  739. ));
  740. //
  741. // for now, we default to 1st interface
  742. //
  743. INET_ASSERT(lpbInterfaceAddress == NULL);
  744. INET_ASSERT(dwInterfaceAddressLength == sizeof(DWORD));
  745. BOOL found;
  746. //
  747. // no one uses this any more
  748. //
  749. INET_ASSERT(FALSE);
  750. //if (!IsListEmpty(&m_List)) {
  751. // found = ((CAdapterInterface *)m_List.Flink)->m_RouterList.GetAddress(
  752. // lpdwIndex,
  753. // lpbAddress,
  754. // lpdwAddressLength
  755. // );
  756. //} else {
  757. found = FALSE;
  758. //}
  759. DEBUG_LEAVE(found);
  760. return found;
  761. }
  762. BOOL
  763. CIpConfig::GetDnsAddress(
  764. IN LPBYTE lpbInterfaceAddress OPTIONAL,
  765. IN DWORD dwInterfaceAddressLength,
  766. IN OUT LPDWORD lpdwIndex,
  767. OUT LPBYTE lpbAddress,
  768. IN OUT LPDWORD lpdwAddressLength
  769. )
  770. /*++
  771. Routine Description:
  772. Returns the *lpdwIndex'th DNS address belonging to the interface
  773. corresponding to the address in lpbInterfaceAddress
  774. Arguments:
  775. lpbInterfaceAddress - pointer to interface address
  776. dwInterfaceAddressLength - length of interface address
  777. lpdwIndex - index of DNS address to return
  778. lpbAddress - returned DNS address
  779. lpdwAddressLength - length of DNS address
  780. Return Value:
  781. BOOL
  782. TRUE - *lpdwIndex'th DNS address returned for requested interface
  783. FALSE - requested address not returned
  784. --*/
  785. {
  786. UNREFERENCED_PARAMETER(lpbInterfaceAddress);
  787. UNREFERENCED_PARAMETER(dwInterfaceAddressLength);
  788. DEBUG_ENTER((DBG_SOCKETS,
  789. Bool,
  790. "CIpConfig::GetDnsAddress",
  791. "%#x, %d, %#x [%d], %#x, %#x [%d]",
  792. lpbInterfaceAddress,
  793. dwInterfaceAddressLength,
  794. lpdwIndex,
  795. *lpdwIndex,
  796. lpbAddress,
  797. lpdwAddressLength,
  798. *lpdwAddressLength
  799. ));
  800. //
  801. // for now, we only return the global DNS info
  802. //
  803. INET_ASSERT(lpbInterfaceAddress == NULL);
  804. INET_ASSERT(dwInterfaceAddressLength == sizeof(DWORD));
  805. BOOL found;
  806. if (!m_DnsList.IsEmpty()) {
  807. found = m_DnsList.GetAddress(lpdwIndex,
  808. lpbAddress,
  809. lpdwAddressLength
  810. );
  811. } else {
  812. found = FALSE;
  813. }
  814. DEBUG_LEAVE(found);
  815. return found;
  816. }
  817. BOOL
  818. CIpConfig::IsKnownIpAddress(
  819. IN LPBYTE lpbInterfaceAddress OPTIONAL,
  820. IN DWORD dwInterfaceAddressLength,
  821. IN LPBYTE lpbAddress,
  822. IN DWORD dwAddressLength
  823. )
  824. /*++
  825. Routine Description:
  826. Return TRUE if lpbAddress is a known interface address
  827. Arguments:
  828. lpbInterfaceAddress - pointer to interface address
  829. dwInterfaceAddressLength - length of interface address
  830. lpbAddress - pointer to address to check
  831. dwAddressLength - length of address
  832. Return Value:
  833. BOOL
  834. --*/
  835. {
  836. UNREFERENCED_PARAMETER(lpbInterfaceAddress);
  837. UNREFERENCED_PARAMETER(dwInterfaceAddressLength);
  838. UNREFERENCED_PARAMETER(dwAddressLength);
  839. DEBUG_ENTER((DBG_SOCKETS,
  840. Bool,
  841. "CIpConfig::IsKnownIpAddress",
  842. "%#x, %d, %#x, %d",
  843. lpbInterfaceAddress,
  844. dwInterfaceAddressLength,
  845. lpbAddress,
  846. dwAddressLength
  847. ));
  848. BOOL found = FALSE;
  849. for (CAdapterInterface * pEntry = (CAdapterInterface *)m_List.Flink;
  850. pEntry != (CAdapterInterface *)&m_List.Flink;
  851. pEntry = (CAdapterInterface *)pEntry->m_List.Flink) {
  852. if (pEntry->FindIpAddress(*(LPDWORD)lpbAddress)) {
  853. found = TRUE;
  854. break;
  855. }
  856. }
  857. DEBUG_LEAVE(found);
  858. return found;
  859. }
  860. BOOL
  861. CIpConfig::Refresh(
  862. VOID
  863. )
  864. /*++
  865. Routine Description:
  866. Refreshes the interface information - re-reads the interfaces and IP
  867. addresses
  868. Arguments:
  869. None.
  870. Return Value:
  871. BOOL
  872. TRUE - interfaces or IP address changed
  873. FALSE - nothing changed
  874. --*/
  875. {
  876. DEBUG_ENTER((DBG_SOCKETS,
  877. Bool,
  878. "CIpConfig::Refresh",
  879. NULL
  880. ));
  881. BOOL bChanged;
  882. GetAdapterList(&bChanged);
  883. if (bChanged) {
  884. //dprintf("flushing hostent cache\n");
  885. // FlushHostentCache();
  886. }
  887. DEBUG_LEAVE(bChanged);
  888. return bChanged;
  889. }
  890. //
  891. // private CIpConfig methods
  892. //
  893. PRIVATE
  894. BOOL
  895. CIpConfig::GetAdapterList(
  896. OUT LPBOOL lpbChanged
  897. )
  898. /*++
  899. Routine Description:
  900. Builds a list of interfaces corresponding to physical and logical adapters,
  901. Uses Win'95 and NT 4 private VxD driver/registry entry points to get this data.
  902. Arguments:
  903. lpbChanged - if present, returns interface changed state
  904. Return Value:
  905. BOOL
  906. TRUE - successfully built list
  907. FALSE - failed to allocate memory or failure talking to TCP/IP
  908. --*/
  909. {
  910. DEBUG_ENTER((DBG_SOCKETS,
  911. Bool,
  912. "CIpConfig::GetAdapterList",
  913. "%#x",
  914. lpbChanged
  915. ));
  916. TCP_REQUEST_QUERY_INFORMATION_EX req;
  917. TDIObjectID id;
  918. UINT numberOfEntities;
  919. TDIEntityID* pEntity;
  920. TDIEntityID* entityList = NULL;
  921. IPRouteEntry* routeTable = NULL;
  922. LPVOID buffer = NULL;
  923. DWORD status;
  924. DWORD inputLen;
  925. DWORD outputLen;
  926. BOOL ok = FALSE;
  927. UINT i; // major loop index
  928. UINT j; // minor loop index
  929. BOOL bChanged = FALSE;
  930. //
  931. // default is interfaces unchanged
  932. //
  933. if (lpbChanged) {
  934. *lpbChanged = FALSE;
  935. }
  936. //
  937. // On NT 5 we override and use a different method for
  938. // getting network settings.
  939. //
  940. if ( GlobalPlatformVersion5 ) {
  941. return GetAdapterListOnNT5();
  942. }
  943. //
  944. // get the list of entities supported by TCP/IP then make 2 passes on the
  945. // list. Pass 1 scans for IF_ENTITY's (interface entities perhaps?) which
  946. // describe adapter instances (physical and virtual). Once we have our list
  947. // of adapters, on pass 2 we look for CL_NL_ENTITY's (connection-less
  948. // network layer entities peut-etre?) which will give us the list of IP
  949. // addresses for the adapters we found in pass 1
  950. //
  951. numberOfEntities = GetEntityList(&entityList);
  952. if (numberOfEntities == 0) {
  953. INET_ASSERT(entityList == NULL);
  954. DEBUG_PRINT(UTIL,
  955. ERROR,
  956. ("GetAdapterList: failed to get entity list\n"
  957. ));
  958. goto quit;
  959. }
  960. //
  961. // first off, mark all the current interfaces (if any), including current
  962. // IP addresses, as not found
  963. //
  964. SetNotFound();
  965. //
  966. // pass 1
  967. //
  968. for (i = 0, pEntity = entityList; i < numberOfEntities; ++i, ++pEntity) {
  969. DEBUG_PRINT(UTIL,
  970. INFO,
  971. ("Pass 1: Entity %#x (%s) Instance #%d\n",
  972. pEntity->tei_entity,
  973. InternetMapEntity(pEntity->tei_entity),
  974. pEntity->tei_instance
  975. ));
  976. if (pEntity->tei_entity != IF_ENTITY) {
  977. DEBUG_PRINT(UTIL,
  978. INFO,
  979. ("Entity %#x (%s) Instance #%d not IF_ENTITY - skipping\n",
  980. pEntity->tei_entity,
  981. InternetMapEntity(pEntity->tei_entity),
  982. pEntity->tei_instance
  983. ));
  984. continue;
  985. }
  986. //
  987. // IF_ENTITY: this entity/instance describes an adapter
  988. //
  989. DWORD isMib;
  990. BYTE info[sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1];
  991. IFEntry* pIfEntry = (IFEntry*)info;
  992. int len;
  993. //
  994. // find out if this entity supports MIB requests
  995. //
  996. memset(&req, 0, sizeof(req));
  997. id.toi_entity = *pEntity;
  998. id.toi_class = INFO_CLASS_GENERIC;
  999. id.toi_type = INFO_TYPE_PROVIDER;
  1000. id.toi_id = ENTITY_TYPE_ID;
  1001. req.ID = id;
  1002. inputLen = sizeof(req);
  1003. outputLen = sizeof(isMib);
  1004. status = WsControl(IPPROTO_TCP,
  1005. WSCNTL_TCPIP_QUERY_INFO,
  1006. (LPVOID)&req,
  1007. &inputLen,
  1008. (LPVOID)&isMib,
  1009. &outputLen
  1010. );
  1011. //
  1012. // BUGBUG - this returns 0 as outputLen
  1013. //
  1014. // if ((status != TDI_SUCCESS) || (outputLen != sizeof(isMib))) {
  1015. if (status != TDI_SUCCESS) {
  1016. //
  1017. // unexpected results - bail out
  1018. //
  1019. DEBUG_PRINT(UTIL,
  1020. ERROR,
  1021. ("WsControl(ENTITY_TYPE_ID): status = %d, outputLen = %d\n",
  1022. status,
  1023. outputLen
  1024. ));
  1025. goto error_exit;
  1026. }
  1027. if (isMib != IF_MIB) {
  1028. //
  1029. // entity doesn't support MIB requests - try another
  1030. //
  1031. DEBUG_PRINT(UTIL,
  1032. WARNING,
  1033. ("Entity %#x, Instance #%d doesn't support MIB (%#x)\n",
  1034. id.toi_entity.tei_entity,
  1035. id.toi_entity.tei_instance,
  1036. isMib
  1037. ));
  1038. continue;
  1039. }
  1040. //
  1041. // MIB requests supported - query the adapter info
  1042. //
  1043. id.toi_class = INFO_CLASS_PROTOCOL;
  1044. id.toi_id = IF_MIB_STATS_ID;
  1045. memset(&req, 0, sizeof(req));
  1046. req.ID = id;
  1047. inputLen = sizeof(req);
  1048. outputLen = sizeof(info);
  1049. status = WsControl(IPPROTO_TCP,
  1050. WSCNTL_TCPIP_QUERY_INFO,
  1051. (LPVOID)&req,
  1052. &inputLen,
  1053. (LPVOID)info,
  1054. &outputLen
  1055. );
  1056. if (status != TDI_SUCCESS) {
  1057. //
  1058. // unexpected results - bail out
  1059. //
  1060. DEBUG_PRINT(UTIL,
  1061. ERROR,
  1062. ("WsControl(IF_MIB_STATS_ID) returns %d\n",
  1063. status
  1064. ));
  1065. goto error_exit;
  1066. }
  1067. //
  1068. // we only want physical adapters
  1069. //
  1070. if (!IS_INTERESTING_ADAPTER(pIfEntry)) {
  1071. DEBUG_PRINT(UTIL,
  1072. INFO,
  1073. ("ignoring adapter #%d [%s]\n",
  1074. pIfEntry->if_index,
  1075. InternetMapInterface(pIfEntry->if_type)
  1076. ));
  1077. continue;
  1078. }
  1079. //
  1080. // got this adapter info ok. Find or create an interface object and fill
  1081. // in what we can
  1082. //
  1083. CAdapterInterface * pInterface;
  1084. len = min(MAX_ADAPTER_ADDRESS_LENGTH, (size_t)pIfEntry->if_physaddrlen);
  1085. pInterface = FindOrCreateInterface(pIfEntry->if_index,
  1086. pIfEntry->if_type,
  1087. pIfEntry->if_speed,
  1088. (LPSTR)pIfEntry->if_descr,
  1089. pIfEntry->if_descrlen,
  1090. (LPBYTE)pIfEntry->if_physaddr,
  1091. (DWORD) len
  1092. );
  1093. if (pInterface == NULL) {
  1094. DEBUG_PRINT(UTIL,
  1095. ERROR,
  1096. ("failed to allocate memory for CAdapterInterface\n"
  1097. ));
  1098. goto error_exit;
  1099. }
  1100. }
  1101. //
  1102. // pass 2
  1103. //
  1104. for (i = 0, pEntity = entityList; i < numberOfEntities; ++i, ++pEntity) {
  1105. DEBUG_PRINT(UTIL,
  1106. INFO,
  1107. ("Pass 2: Entity %#x (%s) Instance %d\n",
  1108. pEntity->tei_entity,
  1109. InternetMapEntity(pEntity->tei_entity),
  1110. pEntity->tei_instance
  1111. ));
  1112. if (pEntity->tei_entity != CL_NL_ENTITY) {
  1113. DEBUG_PRINT(UTIL,
  1114. INFO,
  1115. ("Entity %#x (%s) Instance %d - not CL_NL_ENTITY - skipping\n",
  1116. pEntity->tei_entity,
  1117. InternetMapEntity(pEntity->tei_entity),
  1118. pEntity->tei_instance
  1119. ));
  1120. continue;
  1121. }
  1122. IPSNMPInfo info;
  1123. DWORD type;
  1124. //
  1125. // first off, see if this network layer entity supports IP
  1126. //
  1127. memset(&req, 0, sizeof(req));
  1128. id.toi_entity = *pEntity;
  1129. id.toi_class = INFO_CLASS_GENERIC;
  1130. id.toi_type = INFO_TYPE_PROVIDER;
  1131. id.toi_id = ENTITY_TYPE_ID;
  1132. req.ID = id;
  1133. inputLen = sizeof(req);
  1134. outputLen = sizeof(type);
  1135. status = WsControl(IPPROTO_TCP,
  1136. WSCNTL_TCPIP_QUERY_INFO,
  1137. (LPVOID)&req,
  1138. &inputLen,
  1139. (LPVOID)&type,
  1140. &outputLen
  1141. );
  1142. //
  1143. // BUGBUG - this returns 0 as outputLen
  1144. //
  1145. // if ((status != TDI_SUCCESS) || (outputLen != sizeof(type))) {
  1146. if (status != TDI_SUCCESS) {
  1147. //
  1148. // unexpected results - bail out
  1149. //
  1150. DEBUG_PRINT(UTIL,
  1151. ERROR,
  1152. ("WsControl(ENTITY_TYPE_ID): status = %d, outputLen = %d\n",
  1153. status,
  1154. outputLen
  1155. ));
  1156. goto error_exit;
  1157. }
  1158. if (type != CL_NL_IP) {
  1159. //
  1160. // nope, not IP - try next one
  1161. //
  1162. DEBUG_PRINT(UTIL,
  1163. INFO,
  1164. ("CL_NL_ENTITY #%d not CL_NL_IP - skipping\n",
  1165. pEntity->tei_instance
  1166. ));
  1167. continue;
  1168. }
  1169. //
  1170. // okay, this NL provider supports IP. Let's get them addresses: First
  1171. // we find out how many by getting the SNMP stats and looking at the
  1172. // number of addresses supported by this interface
  1173. //
  1174. memset(&req, 0, sizeof(req));
  1175. id.toi_class = INFO_CLASS_PROTOCOL;
  1176. id.toi_id = IP_MIB_STATS_ID;
  1177. req.ID = id;
  1178. inputLen = sizeof(req);
  1179. outputLen = sizeof(info);
  1180. status = WsControl(IPPROTO_TCP,
  1181. WSCNTL_TCPIP_QUERY_INFO,
  1182. (LPVOID)&req,
  1183. &inputLen,
  1184. (LPVOID)&info,
  1185. &outputLen
  1186. );
  1187. if ((status != TDI_SUCCESS) || (outputLen != sizeof(info))) {
  1188. //
  1189. // unexpected results - bail out
  1190. //
  1191. DEBUG_PRINT(UTIL,
  1192. ERROR,
  1193. ("WsControl(IP_MIB_STATS_ID): status = %d, outputLen = %d\n",
  1194. status,
  1195. outputLen
  1196. ));
  1197. goto error_exit;
  1198. }
  1199. //
  1200. // get the IP addresses & subnet masks
  1201. //
  1202. if (info.ipsi_numaddr != 0) {
  1203. //
  1204. // this interface has some addresses. What are they?
  1205. //
  1206. UINT numberOfAddresses;
  1207. IPAddrEntry* pAddr;
  1208. outputLen = info.ipsi_numaddr * sizeof(IPAddrEntry);
  1209. buffer = (LPVOID)ALLOCATE_MEMORY(outputLen);
  1210. if (buffer == NULL) {
  1211. //
  1212. // unexpected results - bail out
  1213. //
  1214. DEBUG_PRINT(UTIL,
  1215. ERROR,
  1216. ("failed to allocate %d bytes\n",
  1217. outputLen
  1218. ));
  1219. goto error_exit;
  1220. }
  1221. memset(&req, 0, sizeof(req));
  1222. id.toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;
  1223. req.ID = id;
  1224. inputLen = sizeof(req);
  1225. status = WsControl(IPPROTO_TCP,
  1226. WSCNTL_TCPIP_QUERY_INFO,
  1227. (LPVOID)&req,
  1228. &inputLen,
  1229. (LPVOID)buffer,
  1230. &outputLen
  1231. );
  1232. if (status != TDI_SUCCESS) {
  1233. //
  1234. // unexpected results - bail out
  1235. //
  1236. DEBUG_PRINT(UTIL,
  1237. ERROR,
  1238. ("WsControl(IP_MIB_ADDRTABLE_ENTRY_ID): status = %d, outputLen = %d\n",
  1239. status,
  1240. outputLen
  1241. ));
  1242. goto error_exit;
  1243. }
  1244. //
  1245. // now loop through this list of IP addresses, applying them
  1246. // to the correct adapter
  1247. //
  1248. numberOfAddresses = min((UINT)(outputLen / sizeof(IPAddrEntry)),
  1249. (UINT)info.ipsi_numaddr
  1250. );
  1251. DEBUG_PRINT(UTIL,
  1252. INFO,
  1253. ("%d IP addresses\n",
  1254. numberOfAddresses
  1255. ));
  1256. pAddr = (IPAddrEntry *)buffer;
  1257. for (j = 0; j < numberOfAddresses; ++j, ++pAddr) {
  1258. DEBUG_PRINT(UTIL,
  1259. INFO,
  1260. ("IP address %d.%d.%d.%d, index %d, context %d\n",
  1261. ((LPBYTE)&pAddr->iae_addr)[0] & 0xff,
  1262. ((LPBYTE)&pAddr->iae_addr)[1] & 0xff,
  1263. ((LPBYTE)&pAddr->iae_addr)[2] & 0xff,
  1264. ((LPBYTE)&pAddr->iae_addr)[3] & 0xff,
  1265. pAddr->iae_index,
  1266. pAddr->iae_context
  1267. ));
  1268. CAdapterInterface * pInterface = FindInterface(pAddr->iae_index);
  1269. if (pInterface != NULL) {
  1270. CIpAddress * pIpAddress;
  1271. pIpAddress = pInterface->m_IpList.Find(pAddr->iae_addr,
  1272. pAddr->iae_mask
  1273. );
  1274. if (pIpAddress == NULL) {
  1275. pInterface->m_IpList.Add(pAddr->iae_addr,
  1276. pAddr->iae_mask,
  1277. pAddr->iae_context
  1278. );
  1279. //
  1280. // added an address - interface is changed
  1281. //
  1282. //dprintf("adding IP address %d.%d.%d.%d - changed\n",
  1283. // ((LPBYTE)&pAddr->iae_addr)[0] & 0xff,
  1284. // ((LPBYTE)&pAddr->iae_addr)[1] & 0xff,
  1285. // ((LPBYTE)&pAddr->iae_addr)[2] & 0xff,
  1286. // ((LPBYTE)&pAddr->iae_addr)[3] & 0xff
  1287. // );
  1288. bChanged = TRUE;
  1289. } else {
  1290. INET_ASSERT(pAddr->iae_context == pIpAddress->Context());
  1291. pIpAddress->SetFound(TRUE);
  1292. }
  1293. }
  1294. }
  1295. INET_ASSERT(buffer);
  1296. FREE_MEMORY(buffer);
  1297. buffer = NULL;
  1298. }
  1299. }
  1300. //
  1301. // add the DNS servers, read from registry or DHCP depending on platform.
  1302. // Even if we don't get any DNS servers, we deem that this function has
  1303. // succeeded
  1304. //
  1305. char dnsBuffer[1024]; // arbitrary (how many DNS entries?)
  1306. UINT error;
  1307. error = SockGetSingleValue(CONFIG_NAME_SERVER,
  1308. (LPBYTE)dnsBuffer,
  1309. sizeof(dnsBuffer)
  1310. );
  1311. if (error == ERROR_SUCCESS) {
  1312. //m_DnsList.Clear();
  1313. char ipString[4 * 4];
  1314. LPSTR p = dnsBuffer;
  1315. DWORD buflen = (DWORD)lstrlen(dnsBuffer);
  1316. do {
  1317. if (SkipWhitespace(&p, &buflen)) {
  1318. i = 0;
  1319. while ((*p != '\0')
  1320. && (*p != ',')
  1321. && (buflen != 0)
  1322. && (i < sizeof(ipString))
  1323. && !isspace(*p)) {
  1324. ipString[i++] = *p++;
  1325. --buflen;
  1326. }
  1327. ipString[i] = '\0';
  1328. DWORD ipAddress = _I_inet_addr(ipString);
  1329. if (IS_VALID_NON_LOOPBACK_IP_ADDRESS(ipAddress)) {
  1330. CIpAddress * pIpAddress;
  1331. pIpAddress = m_DnsList.Find(ipAddress);
  1332. if (pIpAddress == NULL) {
  1333. m_DnsList.Add(ipAddress);
  1334. //
  1335. // added a DNS address - interface is changed
  1336. //
  1337. //dprintf("adding DNS address %d.%d.%d.%d - changed\n",
  1338. // ((LPBYTE)&ipAddress)[0] & 0xff,
  1339. // ((LPBYTE)&ipAddress)[1] & 0xff,
  1340. // ((LPBYTE)&ipAddress)[2] & 0xff,
  1341. // ((LPBYTE)&ipAddress)[3] & 0xff
  1342. // );
  1343. bChanged = TRUE;
  1344. } else {
  1345. pIpAddress->SetFound(TRUE);
  1346. }
  1347. }
  1348. while ((*p == ',') && (buflen != 0)) {
  1349. ++p;
  1350. --buflen;
  1351. }
  1352. } else {
  1353. break;
  1354. }
  1355. } while (TRUE);
  1356. }
  1357. //
  1358. // Refresh registry settings of DHCP server stuff
  1359. // and figure out what DHCP server we have
  1360. //
  1361. GetAdapterInfo();
  1362. //
  1363. // throw out any adapter interfaces which were not found this time. This may
  1364. // happen if we support PnP devices that are unplugged
  1365. //
  1366. BOOL bThrownOut;
  1367. bThrownOut = ThrowOutUnfoundEntries();
  1368. if (!bChanged) {
  1369. bChanged = bThrownOut;
  1370. }
  1371. INET_ASSERT(entityList != NULL);
  1372. FREE_MEMORY(entityList);
  1373. ok = TRUE;
  1374. //
  1375. // return the change state of the interfaces, if required
  1376. //
  1377. if (lpbChanged) {
  1378. *lpbChanged = bChanged;
  1379. }
  1380. quit:
  1381. if (routeTable != NULL) {
  1382. FREE_MEMORY(routeTable);
  1383. }
  1384. if (buffer != NULL) {
  1385. FREE_MEMORY(buffer);
  1386. }
  1387. DEBUG_LEAVE(ok);
  1388. return ok;
  1389. error_exit:
  1390. //
  1391. // here because of an error. Throw out all interfaces
  1392. //
  1393. SetNotFound();
  1394. ThrowOutUnfoundEntries();
  1395. INET_ASSERT(!ok);
  1396. goto quit;
  1397. }
  1398. PRIVATE
  1399. BOOL
  1400. CIpConfig::GetAdapterListOnNT5(
  1401. OUT LPBOOL lpbChanged
  1402. )
  1403. /*++
  1404. Routine Description:
  1405. Builds a list of interfaces corresponding to physical and logical adapters
  1406. using the new NT 5 and Win98 APIs.
  1407. Arguments:
  1408. lpbChanged - if present, returns interface changed state
  1409. Return Value:
  1410. BOOL
  1411. TRUE - successfully built list
  1412. FALSE - failed to allocate memory or failure talking to TCP/IP
  1413. --*/
  1414. {
  1415. DEBUG_ENTER((DBG_SOCKETS,
  1416. Bool,
  1417. "CIpConfig::GetAdapterListOnNT5",
  1418. "%#x",
  1419. lpbChanged
  1420. ));
  1421. BOOL ok = FALSE;
  1422. BOOL bChanged = FALSE;
  1423. int len;
  1424. PIP_ADAPTER_INFO pAdapterInfo = NULL;
  1425. PIP_ADAPTER_INFO pAdapterInfoAllocation = NULL;
  1426. DWORD dwError;
  1427. ULONG uSize;
  1428. //
  1429. // Load the IPHLPAPI DLL, cause we need this function find adapter info on NT 5/Win98
  1430. //
  1431. if (_I_GetAdaptersInfo == NULL )
  1432. {
  1433. DEBUG_PRINT(UTIL,
  1434. ERROR,
  1435. ("GetAdapterListOnNT5: IPHLPAPI dll could not be found with correct entry point\n"
  1436. ));
  1437. goto quit;
  1438. }
  1439. //
  1440. // get the list of adapters supported by TCP/IP
  1441. //
  1442. uSize = sizeof(IP_ADAPTER_INFO) * 5;
  1443. pAdapterInfoAllocation = (IP_ADAPTER_INFO *) ALLOCATE_FIXED_MEMORY(uSize);
  1444. // Alias the pAdapterInfoAllocation pointer. pAdapterInfo will be used
  1445. // to traverse the list of adapter info records. We need the
  1446. // pAdapterInfoAllocation pointer in order to free the memory block at
  1447. // the end of this function.
  1448. pAdapterInfo = pAdapterInfoAllocation;
  1449. if (pAdapterInfo == NULL)
  1450. {
  1451. goto quit;
  1452. }
  1453. dwError = _I_GetAdaptersInfo(pAdapterInfo, &uSize);
  1454. if (dwError == ERROR_BUFFER_OVERFLOW)
  1455. {
  1456. pAdapterInfoAllocation = (IP_ADAPTER_INFO *) ResizeBuffer(pAdapterInfoAllocation, uSize, FALSE);
  1457. pAdapterInfo = pAdapterInfoAllocation;
  1458. if (pAdapterInfo == NULL)
  1459. {
  1460. goto quit;
  1461. }
  1462. dwError = _I_GetAdaptersInfo(pAdapterInfo, &uSize);
  1463. }
  1464. if ( dwError != ERROR_SUCCESS )
  1465. {
  1466. DEBUG_PRINT(UTIL,
  1467. ERROR,
  1468. ("GetAdapterListOnNT5: failed to get adapters list\n"
  1469. ));
  1470. goto quit;
  1471. }
  1472. //
  1473. // first off, mark all the current interfaces (if any), including current
  1474. // IP addresses, as not found
  1475. //
  1476. SetNotFound();
  1477. //
  1478. // pass 1
  1479. //
  1480. for (; pAdapterInfo; pAdapterInfo = pAdapterInfo->Next)
  1481. {
  1482. DEBUG_PRINT(UTIL,
  1483. INFO,
  1484. ("Adapter Pass: [#%u] Adapter name=%s, description=%s\n",
  1485. pAdapterInfo->Index,
  1486. pAdapterInfo->AdapterName,
  1487. pAdapterInfo->Description
  1488. ));
  1489. //
  1490. // we only want physical adapters
  1491. //
  1492. if (!IS_INTERESTING_ADAPTER_NT5(pAdapterInfo)) {
  1493. DEBUG_PRINT(UTIL,
  1494. INFO,
  1495. ("ignoring adapter #%u [%s]\n",
  1496. pAdapterInfo->Index,
  1497. InternetMapInterfaceOnNT5(pAdapterInfo->Type)
  1498. ));
  1499. continue;
  1500. }
  1501. //
  1502. // got this adapter info ok. Find or create an interface object and fill
  1503. // in what we can
  1504. //
  1505. CAdapterInterface * pInterface;
  1506. len = min(MAX_ADAPTER_ADDRESS_LENGTH, (size_t)pAdapterInfo->AddressLength);
  1507. pInterface = FindOrCreateInterface(pAdapterInfo->Index,
  1508. pAdapterInfo->Type,
  1509. 0, // speed
  1510. pAdapterInfo->Description,
  1511. lstrlen(pAdapterInfo->Description),
  1512. pAdapterInfo->Address,
  1513. (DWORD) len
  1514. );
  1515. if (pInterface == NULL) {
  1516. DEBUG_PRINT(UTIL,
  1517. ERROR,
  1518. ("failed to allocate memory for CAdapterInterface\n"
  1519. ));
  1520. goto error_exit;
  1521. }
  1522. //
  1523. // Update the Adapter Name, this is the critical glue to make the new NT 5 DHCP Apis work,
  1524. // as they need this Adapter name as an ID to work.
  1525. //
  1526. if ( pInterface->GetAdapterName() == NULL ) {
  1527. pInterface->SetAdapterName(pAdapterInfo->AdapterName);
  1528. } else {
  1529. INET_ASSERT(lstrcmpi(pInterface->GetAdapterName(), pAdapterInfo->AdapterName) == 0 );
  1530. }
  1531. //
  1532. // Update the IP address found in the structure, as we're not getting anything back with this filled in.
  1533. //
  1534. if ( pAdapterInfo->CurrentIpAddress == NULL )
  1535. {
  1536. pAdapterInfo->CurrentIpAddress = &pAdapterInfo->IpAddressList;
  1537. }
  1538. else
  1539. {
  1540. INET_ASSERT(FALSE); // want to know about this case.
  1541. }
  1542. //
  1543. // Gather the IP addresses from the structure, doing all the necessary,
  1544. // IP string to network-ordered DWORD thingie usable for winsock.
  1545. //
  1546. // BUGBUG [arthurbi] do we really need to do this anymore? As the
  1547. // the new NT 5 APIs can handle themselves without IP addresses...
  1548. //
  1549. if ( pAdapterInfo->CurrentIpAddress->IpAddress.String &&
  1550. pAdapterInfo->CurrentIpAddress->IpMask.String )
  1551. {
  1552. DWORD dwAddress = _I_inet_addr(pAdapterInfo->CurrentIpAddress->IpAddress.String);
  1553. DWORD dwMask = _I_inet_addr(pAdapterInfo->CurrentIpAddress->IpMask.String);
  1554. DWORD dwContext = pAdapterInfo->CurrentIpAddress->Context;
  1555. if ( dwAddress != INADDR_NONE &&
  1556. dwMask != INADDR_NONE )
  1557. {
  1558. DEBUG_PRINT(UTIL,
  1559. INFO,
  1560. ("IP address %d.%d.%d.%d, index %d, context %d\n",
  1561. ((LPBYTE)&dwAddress)[0] & 0xff,
  1562. ((LPBYTE)&dwAddress)[1] & 0xff,
  1563. ((LPBYTE)&dwAddress)[2] & 0xff,
  1564. ((LPBYTE)&dwAddress)[3] & 0xff,
  1565. pAdapterInfo->Index,
  1566. dwContext
  1567. ));
  1568. INET_ASSERT(pInterface != NULL);
  1569. CIpAddress * pIpAddress;
  1570. pIpAddress = pInterface->m_IpList.Find(dwAddress,
  1571. dwMask
  1572. );
  1573. if (pIpAddress == NULL) {
  1574. pInterface->m_IpList.Add(dwAddress,
  1575. dwMask,
  1576. dwContext
  1577. );
  1578. //
  1579. // added an address - interface is changed
  1580. //
  1581. bChanged = TRUE;
  1582. } else {
  1583. INET_ASSERT(dwContext == pIpAddress->Context());
  1584. pIpAddress->SetFound(TRUE);
  1585. }
  1586. }
  1587. }
  1588. //
  1589. // Gather DHCP server addresses to use, once again do we need this info on NT 5?
  1590. //
  1591. if ( pAdapterInfo->DhcpEnabled )
  1592. {
  1593. PIP_ADDR_STRING pDhcpServer;
  1594. INET_ASSERT(pInterface != NULL);
  1595. for ( pDhcpServer = &pAdapterInfo->DhcpServer; pDhcpServer; pDhcpServer = pDhcpServer->Next )
  1596. {
  1597. DWORD dwAddress = _I_inet_addr(pDhcpServer->IpAddress.String);
  1598. DWORD dwMask = _I_inet_addr(pDhcpServer->IpMask.String);
  1599. DWORD dwContext = pDhcpServer->Context;
  1600. if ( dwAddress != INADDR_NONE )
  1601. {
  1602. CIpAddress * pIpAddress;
  1603. pInterface->SetDhcp();
  1604. pIpAddress = pInterface->m_DhcpList.Find(dwAddress,
  1605. dwMask
  1606. );
  1607. if (pIpAddress == NULL)
  1608. {
  1609. pInterface->m_DhcpList.Add(dwAddress,
  1610. dwMask,
  1611. dwContext
  1612. );
  1613. //
  1614. // added an address - interface is changed
  1615. //
  1616. bChanged = TRUE;
  1617. } else {
  1618. INET_ASSERT(dwContext == pIpAddress->Context());
  1619. pIpAddress->SetFound(TRUE);
  1620. }
  1621. }
  1622. }
  1623. }
  1624. }
  1625. //
  1626. // add the DNS servers, read from registry or DHCP depending on platform.
  1627. // Even if we don't get any DNS servers, we deem that this function has
  1628. // succeeded
  1629. //
  1630. char dnsBuffer[1024]; // arbitrary (how many DNS entries?)
  1631. UINT error;
  1632. error = SockGetSingleValue(CONFIG_NAME_SERVER,
  1633. (LPBYTE)dnsBuffer,
  1634. sizeof(dnsBuffer)
  1635. );
  1636. if (error == ERROR_SUCCESS) {
  1637. //m_DnsList.Clear();
  1638. char ipString[4 * 4];
  1639. LPSTR p = dnsBuffer;
  1640. DWORD buflen = (DWORD)lstrlen(dnsBuffer);
  1641. do {
  1642. if (SkipWhitespace(&p, &buflen)) {
  1643. int i = 0;
  1644. while ((*p != '\0')
  1645. && (*p != ',')
  1646. && (buflen != 0)
  1647. && (i < sizeof(ipString))
  1648. && !isspace(*p)) {
  1649. ipString[i++] = *p++;
  1650. --buflen;
  1651. }
  1652. ipString[i] = '\0';
  1653. DWORD ipAddress = _I_inet_addr(ipString);
  1654. if (IS_VALID_NON_LOOPBACK_IP_ADDRESS(ipAddress)) {
  1655. CIpAddress * pIpAddress;
  1656. pIpAddress = m_DnsList.Find(ipAddress);
  1657. if (pIpAddress == NULL) {
  1658. m_DnsList.Add(ipAddress);
  1659. //
  1660. // added a DNS address - interface is changed
  1661. //
  1662. bChanged = TRUE;
  1663. } else {
  1664. pIpAddress->SetFound(TRUE);
  1665. }
  1666. }
  1667. while ((*p == ',') && (buflen != 0)) {
  1668. ++p;
  1669. --buflen;
  1670. }
  1671. } else {
  1672. break;
  1673. }
  1674. } while (TRUE);
  1675. }
  1676. //
  1677. // throw out any adapter interfaces which were not found this time. This may
  1678. // happen if we support PnP devices that are unplugged
  1679. //
  1680. // Do we need to still do this ???
  1681. //
  1682. BOOL bThrownOut;
  1683. bThrownOut = ThrowOutUnfoundEntries();
  1684. if (!bChanged) {
  1685. bChanged = bThrownOut;
  1686. }
  1687. ok = TRUE;
  1688. //
  1689. // return the change state of the interfaces, if required
  1690. //
  1691. if (lpbChanged) {
  1692. *lpbChanged = bChanged;
  1693. }
  1694. quit:
  1695. if (pAdapterInfoAllocation)
  1696. {
  1697. FREE_MEMORY(pAdapterInfoAllocation);
  1698. }
  1699. DEBUG_LEAVE(ok);
  1700. return ok;
  1701. error_exit:
  1702. //
  1703. // here because of an error. Throw out all interfaces
  1704. //
  1705. SetNotFound();
  1706. ThrowOutUnfoundEntries();
  1707. INET_ASSERT(!ok);
  1708. goto quit;
  1709. }
  1710. BOOL
  1711. CIpConfig::DoInformsOnEachInterface(
  1712. OUT LPSTR * ppszAutoProxyUrl
  1713. )
  1714. {
  1715. for (CAdapterInterface * pEntry = (CAdapterInterface *)m_List.Flink;
  1716. pEntry != (CAdapterInterface *)&m_List.Flink;
  1717. pEntry = (CAdapterInterface *)pEntry->m_List.Flink)
  1718. {
  1719. if ( pEntry->IsDhcp() )
  1720. {
  1721. BOOL fSuccess;
  1722. if ( GlobalPlatformVersion5 )
  1723. {
  1724. fSuccess = pEntry->DhcpDoInformNT5(ppszAutoProxyUrl);
  1725. }
  1726. else
  1727. {
  1728. fSuccess = DhcpDoInform( // send an inform packet if necessary
  1729. pEntry,
  1730. FALSE,
  1731. ppszAutoProxyUrl
  1732. );
  1733. }
  1734. if ( fSuccess ) {
  1735. return TRUE;
  1736. }
  1737. }
  1738. }
  1739. return FALSE;
  1740. }
  1741. /*******************************************************************************
  1742. *
  1743. * GetAdapterInfo
  1744. *
  1745. * Gets a list of all adapters to which TCP/IP is bound and reads the per-
  1746. * adapter information that we want to display. Most of the information now
  1747. * comes from the TCP/IP stack itself. In order to keep the 'short' names that
  1748. * exist in the registry to refer to the individual adapters, we read the names
  1749. * from the registry then match them to the adapters returned by TCP/IP by
  1750. * matching the IPInterfaceContext value with the adapter which owns the IP
  1751. * address with that context value
  1752. *
  1753. * ENTRY nothing
  1754. *
  1755. * EXIT nothing
  1756. *
  1757. * RETURNS pointer to linked list of ADAPTER_INFO structures
  1758. *
  1759. * ASSUMES
  1760. *
  1761. ******************************************************************************/
  1762. VOID
  1763. CIpConfig::GetAdapterInfo()
  1764. {
  1765. LPSTR* boundAdapterNames = NULL;
  1766. DWORD err = ERROR_SUCCESS;
  1767. if (GlobalPlatformType == PLATFORM_TYPE_WINNT)
  1768. {
  1769. if ( ServicesKey == NULL )
  1770. {
  1771. err = REGOPENKEY(HKEY_LOCAL_MACHINE,
  1772. SERVICES_KEY_NAME,
  1773. &ServicesKey
  1774. );
  1775. }
  1776. if ( err == ERROR_SUCCESS && TcpipLinkageKey == NULL )
  1777. {
  1778. err = REGOPENKEY(ServicesKey,
  1779. "Tcpip\\Linkage",
  1780. //"Tcpip\\Parameters\\Interfaces",
  1781. &TcpipLinkageKey
  1782. );
  1783. }
  1784. if (err == ERROR_SUCCESS && (NULL != (boundAdapterNames = GetBoundAdapterList(TcpipLinkageKey))))
  1785. {
  1786. int i;
  1787. //
  1788. // apply the short name to the right adapter info by comparing
  1789. // the IPInterfaceContext value in the adapter\Parameters\Tcpip
  1790. // section with the context values read from the stack for the
  1791. // IP addresses
  1792. //
  1793. for (i = 0; boundAdapterNames[i]; ++i) {
  1794. LPSTR name;
  1795. DWORD context;
  1796. HKEY key;
  1797. name = boundAdapterNames[i];
  1798. if (!OpenAdapterKey(KEY_TCP, name, &key)) {
  1799. DEBUG_PRINT(UTIL, ERROR, ("GetAdapterInfo cannot open %s\n",
  1800. name ));
  1801. goto quit;
  1802. }
  1803. if (!ReadRegistryDword(key,
  1804. "IPInterfaceContext",
  1805. &context
  1806. )) {
  1807. DEBUG_PRINT(UTIL, ERROR, ("GetAdapterInfo: IPInterfaceContext failed\n"));
  1808. goto quit;
  1809. }
  1810. REGCLOSEKEY(key);
  1811. //
  1812. // now search through the list of adapters, looking for the one
  1813. // that has the IP address with the same context value as that
  1814. // just read. When found, apply the short name to that adapter
  1815. //
  1816. for (CAdapterInterface * pEntry = (CAdapterInterface *)m_List.Flink;
  1817. pEntry != (CAdapterInterface *)&m_List.Flink;
  1818. pEntry = (CAdapterInterface *)pEntry->m_List.Flink)
  1819. {
  1820. if ( pEntry->IsContextInIPAddrList(context) )
  1821. {
  1822. pEntry->SetAdapterName(name);
  1823. GetDhcpServerFromDhcp(pEntry);
  1824. break;
  1825. }
  1826. }
  1827. }
  1828. } else {
  1829. DEBUG_PRINT(UTIL, ERROR, ("GetAdapterInfo failed\n"));
  1830. }
  1831. }
  1832. else
  1833. {
  1834. //
  1835. // Win95: search through the list of adapters, gather DHCP server names
  1836. // for each.
  1837. //
  1838. for (CAdapterInterface * pEntry = (CAdapterInterface *)m_List.Flink;
  1839. pEntry != (CAdapterInterface *)&m_List.Flink;
  1840. pEntry = (CAdapterInterface *)pEntry->m_List.Flink)
  1841. {
  1842. GetDhcpServerFromDhcp(pEntry);
  1843. }
  1844. }
  1845. quit:
  1846. if (boundAdapterNames != NULL )
  1847. {
  1848. FREE_MEMORY(boundAdapterNames);
  1849. }
  1850. return;
  1851. }
  1852. PRIVATE
  1853. DWORD
  1854. CIpConfig::LoadEntryPoints(
  1855. VOID
  1856. )
  1857. /*++
  1858. Routine Description:
  1859. Loads IPHLPAPI.DLL and DHCPCSVC.DLL entry points if platform is
  1860. Windows 2000 (or later), or NTDLL.DLL entry points if Windows NT.
  1861. Arguments:
  1862. None.
  1863. Return Value:
  1864. DWORD
  1865. Success - ERROR_SUCCESS
  1866. Failure -
  1867. --*/
  1868. {
  1869. DEBUG_ENTER((DBG_SOCKETS,
  1870. Dword,
  1871. "CIpConfig::LoadEntryPoints",
  1872. NULL
  1873. ));
  1874. DWORD error = ERROR_SUCCESS;
  1875. if (!m_Loaded)
  1876. {
  1877. if (GlobalDataInitCritSec.Lock())
  1878. {
  1879. if (!m_Loaded)
  1880. {
  1881. INET_ASSERT(GlobalPlatformType == PLATFORM_TYPE_WINNT);
  1882. if (GlobalPlatformVersion5)
  1883. {
  1884. INET_ASSERT(_I_GetAdaptersInfo == NULL);
  1885. error = LoadDllEntryPoints(&IpHlpApiDllInfo, 0);
  1886. if (error == ERROR_SUCCESS)
  1887. {
  1888. error = LoadDllEntryPoints(&DhcpcSvcDllInfo, 0);
  1889. }
  1890. }
  1891. else
  1892. { INET_ASSERT(_I_RtlInitUnicodeString == NULL);
  1893. error = LoadDllEntryPoints(&NtDllInfo, 0);
  1894. }
  1895. m_Loaded = (error == ERROR_SUCCESS);
  1896. }
  1897. GlobalDataInitCritSec.Unlock();
  1898. }
  1899. else
  1900. {
  1901. error = ERROR_NOT_ENOUGH_MEMORY;
  1902. }
  1903. }
  1904. DEBUG_LEAVE(error);
  1905. return error;
  1906. }
  1907. DWORD
  1908. CIpConfig::UnloadEntryPoints(
  1909. VOID
  1910. )
  1911. /*++
  1912. Routine Description:
  1913. Unloads NTDLL.DLL if platform is Windows NT
  1914. Arguments:
  1915. None.
  1916. Return Value:
  1917. DWORD
  1918. --*/
  1919. {
  1920. DEBUG_ENTER((DBG_SOCKETS,
  1921. Dword,
  1922. "CIpConfig::UnloadEntryPoints",
  1923. NULL
  1924. ));
  1925. DWORD error = ERROR_SUCCESS;
  1926. if (m_Loaded)
  1927. {
  1928. if (GlobalDataInitCritSec.Lock())
  1929. {
  1930. if (m_Loaded)
  1931. {
  1932. if (GlobalPlatformVersion5)
  1933. {
  1934. if (_I_GetAdaptersInfo != NULL)
  1935. {
  1936. error = UnloadDllEntryPoints(&IpHlpApiDllInfo, FALSE);
  1937. }
  1938. if (_I_DhcpRequestParams != NULL)
  1939. {
  1940. error = UnloadDllEntryPoints(&DhcpcSvcDllInfo, FALSE);
  1941. }
  1942. }
  1943. else
  1944. {
  1945. error = UnloadDllEntryPoints(&NtDllInfo, FALSE);
  1946. }
  1947. m_Loaded = FALSE;
  1948. }
  1949. GlobalDataInitCritSec.Unlock();
  1950. }
  1951. else
  1952. {
  1953. error = ERROR_NOT_ENOUGH_MEMORY;
  1954. }
  1955. }
  1956. DEBUG_LEAVE(error);
  1957. return error;
  1958. }
  1959. //
  1960. // UnloadAutoProxy()
  1961. //
  1962. // Called from GlobalDataTerminate to unload IPHLPAPI.DLL & DHCPCSVC.DLL (Win2K+)
  1963. // or NTDLL.DLL (NT4) if necessary.
  1964. //
  1965. void UnloadAutoProxy()
  1966. {
  1967. CIpConfig::UnloadEntryPoints();
  1968. }
  1969. PRIVATE
  1970. CAdapterInterface *
  1971. CIpConfig::FindOrCreateInterface(
  1972. IN DWORD dwIndex,
  1973. IN DWORD dwType,
  1974. IN DWORD dwSpeed,
  1975. IN LPSTR lpszDescription,
  1976. IN DWORD dwDescriptionLength,
  1977. IN LPBYTE lpPhysicalAddress,
  1978. IN DWORD dwPhysicalAddressLength
  1979. )
  1980. /*++
  1981. Routine Description:
  1982. Returns a pointer to the CAdapterInterface object corresponding to dwIndex.
  1983. If none found in the list, a new entry is created
  1984. Arguments:
  1985. dwIndex - unique interface identifier to find or create
  1986. dwType - type of adapter
  1987. dwSpeed - adapter media speed
  1988. lpszDescription - name of this interface
  1989. dwDescriptionLength - length of the name
  1990. Return Value:
  1991. CAdapterInterface *
  1992. Success - pointer to found or created object
  1993. Failure - NULL
  1994. --*/
  1995. {
  1996. DEBUG_ENTER((DBG_SOCKETS,
  1997. Pointer,
  1998. "CIpConfig::FindOrCreateInterface",
  1999. "%d, %s (%d), %d, %.*q, %d, %x, (%u)",
  2000. dwIndex,
  2001. InternetMapInterface(dwType),
  2002. dwType,
  2003. dwSpeed,
  2004. dwDescriptionLength,
  2005. lpszDescription,
  2006. dwDescriptionLength,
  2007. lpPhysicalAddress,
  2008. dwPhysicalAddressLength
  2009. ));
  2010. CAdapterInterface * pInterface = FindInterface(dwIndex);
  2011. if (pInterface == NULL) {
  2012. pInterface = new CAdapterInterface(dwIndex,
  2013. dwType,
  2014. dwSpeed,
  2015. lpszDescription,
  2016. dwDescriptionLength,
  2017. lpPhysicalAddress,
  2018. dwPhysicalAddressLength
  2019. );
  2020. if (pInterface != NULL) {
  2021. InsertHeadList(&m_List, &pInterface->m_List);
  2022. ++m_dwNumberOfInterfaces;
  2023. }
  2024. }
  2025. DEBUG_LEAVE(pInterface);
  2026. return pInterface;
  2027. }
  2028. PRIVATE
  2029. CAdapterInterface *
  2030. CIpConfig::FindInterface(
  2031. IN DWORD dwIndex
  2032. )
  2033. /*++
  2034. Routine Description:
  2035. Returns a pointer to the CAdapterInterface object corresponding to dwIndex
  2036. Arguments:
  2037. dwIndex - unique interface identifier to find
  2038. Return Value:
  2039. CAdapterInterface *
  2040. Success - pointer to found object
  2041. Failure - NULL
  2042. --*/
  2043. {
  2044. DEBUG_ENTER((DBG_SOCKETS,
  2045. Pointer,
  2046. "CIpConfig::FindInterface",
  2047. "%d",
  2048. dwIndex
  2049. ));
  2050. CAdapterInterface * pInterface = NULL;
  2051. for (PLIST_ENTRY pEntry = m_List.Flink;
  2052. pEntry != (PLIST_ENTRY)&m_List;
  2053. pEntry = pEntry->Flink) {
  2054. if (((CAdapterInterface *)pEntry)->m_dwIndex == dwIndex) {
  2055. ((CAdapterInterface *)pEntry)->SetFound(TRUE);
  2056. //
  2057. // ASSUMES: pEntry == &CAdapterInterface
  2058. //
  2059. pInterface = (CAdapterInterface *)pEntry;
  2060. break;
  2061. }
  2062. }
  2063. DEBUG_LEAVE(pInterface);
  2064. return pInterface;
  2065. }
  2066. PRIVATE
  2067. BOOL
  2068. CIpConfig::ThrowOutUnfoundEntries(
  2069. VOID
  2070. )
  2071. /*++
  2072. Routine Description:
  2073. Throws out (deletes) any entries that are marked not-found
  2074. Arguments:
  2075. None.
  2076. Return Value:
  2077. BOOL
  2078. TRUE - interfaces thrown out
  2079. FALSE - " not " "
  2080. --*/
  2081. {
  2082. DEBUG_ENTER((DBG_SOCKETS,
  2083. Bool,
  2084. "CIpConfig::ThrowOutUnfoundEntries",
  2085. NULL
  2086. ));
  2087. //
  2088. // ASSUMES: CAdapterInterface.m_List.Flink is first element in structure
  2089. //
  2090. PLIST_ENTRY pPrevious = (PLIST_ENTRY)&m_List.Flink;
  2091. PLIST_ENTRY pEntry = m_List.Flink;
  2092. BOOL bThrownOut = FALSE;
  2093. while (pEntry != (PLIST_ENTRY)&m_List) {
  2094. CAdapterInterface * pInterface = (CAdapterInterface *)pEntry;
  2095. if (!pInterface->IsFound()) {
  2096. DEBUG_PRINT(UTIL,
  2097. WARNING,
  2098. ("adapter index %d (%q) not located in list\n",
  2099. pInterface->m_dwIndex,
  2100. pInterface->m_lpszDescription
  2101. ));
  2102. RemoveEntryList(&pInterface->m_List);
  2103. --m_dwNumberOfInterfaces;
  2104. INET_ASSERT((int)m_dwNumberOfInterfaces >= 0);
  2105. delete pInterface;
  2106. bThrownOut = TRUE;
  2107. } else {
  2108. //
  2109. // throw out any IP addresses
  2110. //
  2111. bThrownOut |= pInterface->m_IpList.ThrowOutUnfoundEntries();
  2112. //bThrownOut |= pInterface->m_RouterList.ThrowOutUnfoundEntries();
  2113. //bThrownOut |= pInterface->m_DnsList.ThrowOutUnfoundEntries();
  2114. pPrevious = pEntry;
  2115. }
  2116. pEntry = pPrevious->Flink;
  2117. }
  2118. DEBUG_LEAVE(bThrownOut);
  2119. return bThrownOut;
  2120. }
  2121. //
  2122. // public functions
  2123. //
  2124. DWORD
  2125. WsControl(
  2126. IN DWORD dwProtocol,
  2127. IN DWORD dwRequest,
  2128. IN LPVOID lpInputBuffer,
  2129. IN OUT LPDWORD lpdwInputBufferLength,
  2130. OUT LPVOID lpOutputBuffer,
  2131. IN OUT LPDWORD lpdwOutputBufferLength
  2132. )
  2133. /*++
  2134. Routine Description:
  2135. Makes device-dependent driver call based on O/S
  2136. Arguments:
  2137. dwProtocol - ignored
  2138. dwRequest - ignored
  2139. lpInputBuffer - pointer to request buffer
  2140. lpdwInputBufferLength - pointer to DWORD: IN = request buffer length
  2141. lpOutputBuffer - pointer to output buffer
  2142. lpdwOutputBufferLength - pointer to DWORD: IN = length of output buffer;
  2143. OUT = length of returned data
  2144. Return Value:
  2145. DWORD
  2146. Success - ERROR_SUCCESS
  2147. Failure -
  2148. --*/
  2149. {
  2150. DEBUG_ENTER((DBG_SOCKETS,
  2151. Dword,
  2152. "WsControl",
  2153. "%d, %d, %#x, %#x [%d], %#x, %#x [%d]",
  2154. dwProtocol,
  2155. dwRequest,
  2156. lpInputBuffer,
  2157. lpdwInputBufferLength,
  2158. *lpdwInputBufferLength,
  2159. lpOutputBuffer,
  2160. lpdwOutputBufferLength,
  2161. *lpdwOutputBufferLength
  2162. ));
  2163. DWORD error;
  2164. if (GlobalPlatformType == PLATFORM_TYPE_WINNT)
  2165. {
  2166. error = WinNtWsControl(dwProtocol,
  2167. dwRequest,
  2168. lpInputBuffer,
  2169. lpdwInputBufferLength,
  2170. lpOutputBuffer,
  2171. lpdwOutputBufferLength
  2172. );
  2173. }
  2174. else
  2175. {
  2176. error = ERROR_NOT_SUPPORTED;
  2177. }
  2178. DEBUG_LEAVE(error);
  2179. return error;
  2180. }
  2181. //
  2182. // private functions
  2183. //
  2184. PRIVATE
  2185. DWORD
  2186. WinNtWsControl(
  2187. DWORD dwProtocol,
  2188. DWORD dwRequest,
  2189. LPVOID lpInputBuffer,
  2190. LPDWORD lpdwInputBufferLength,
  2191. LPVOID lpOutputBuffer,
  2192. LPDWORD lpdwOutputBufferLength
  2193. )
  2194. /*++
  2195. Routine Description:
  2196. Handles WsControl() functionality on NT platform. Assumes NTDLL.DLL has
  2197. already been loaded
  2198. Arguments:
  2199. dwProtocol - unused
  2200. dwRequest - unused
  2201. lpInputBuffer - contains driver request structure
  2202. lpdwInputBufferLength - pointer to length of InputBuffer
  2203. lpOutputBuffer - pointer to buffer where results written
  2204. lpdwOutputBufferLength - pointer to length of OutputBuffer. Updated with
  2205. returned data length on successful return
  2206. Return Value:
  2207. DWORD
  2208. Success - ERROR_SUCCESS
  2209. Failure -
  2210. --*/
  2211. {
  2212. DEBUG_ENTER((DBG_SOCKETS,
  2213. Dword,
  2214. "WinNtWsControl",
  2215. "%d, %d, %#x, %#x [%d], %#x, %#x [%d]",
  2216. dwProtocol,
  2217. dwRequest,
  2218. lpInputBuffer,
  2219. lpdwInputBufferLength,
  2220. *lpdwInputBufferLength,
  2221. lpOutputBuffer,
  2222. lpdwOutputBufferLength,
  2223. *lpdwOutputBufferLength
  2224. ));
  2225. UNREFERENCED_PARAMETER(dwProtocol);
  2226. UNREFERENCED_PARAMETER(dwRequest);
  2227. DWORD error;
  2228. if (TcpipDriverHandle == INVALID_HANDLE_VALUE) {
  2229. error = OpenTcpipDriverHandle();
  2230. if (error != ERROR_SUCCESS) {
  2231. goto quit;
  2232. }
  2233. }
  2234. DWORD bytesReturned;
  2235. BOOL ok;
  2236. ok = DeviceIoControl(TcpipDriverHandle,
  2237. IOCTL_TCP_QUERY_INFORMATION_EX,
  2238. lpInputBuffer,
  2239. *lpdwInputBufferLength,
  2240. lpOutputBuffer,
  2241. *lpdwOutputBufferLength,
  2242. &bytesReturned,
  2243. NULL
  2244. );
  2245. if (!ok) {
  2246. error = GetLastError();
  2247. } else {
  2248. *lpdwOutputBufferLength = bytesReturned;
  2249. error = ERROR_SUCCESS;
  2250. }
  2251. quit:
  2252. DEBUG_LEAVE(error);
  2253. return error;
  2254. }
  2255. PRIVATE
  2256. DWORD
  2257. OpenTcpipDriverHandle(
  2258. VOID
  2259. )
  2260. /*++
  2261. Routine Description:
  2262. Opens handle to TCP/IP device driver
  2263. Arguments:
  2264. None.
  2265. Return Value:
  2266. DWORD
  2267. Success - ERROR_SUCCESS
  2268. Failure -
  2269. --*/
  2270. {
  2271. DWORD error = ERROR_SUCCESS;
  2272. if (TcpipDriverHandle == INVALID_HANDLE_VALUE) {
  2273. OBJECT_ATTRIBUTES objectAttributes;
  2274. IO_STATUS_BLOCK iosb;
  2275. UNICODE_STRING string;
  2276. NTSTATUS status;
  2277. _I_RtlInitUnicodeString(&string, DD_TCP_DEVICE_NAME);
  2278. InitializeObjectAttributes(&objectAttributes,
  2279. &string,
  2280. OBJ_CASE_INSENSITIVE,
  2281. NULL,
  2282. NULL
  2283. );
  2284. status = _I_NtCreateFile(&TcpipDriverHandle,
  2285. SYNCHRONIZE | GENERIC_EXECUTE,
  2286. &objectAttributes,
  2287. &iosb,
  2288. NULL,
  2289. FILE_ATTRIBUTE_NORMAL,
  2290. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2291. FILE_OPEN_IF,
  2292. FILE_SYNCHRONOUS_IO_NONALERT,
  2293. NULL,
  2294. 0
  2295. );
  2296. if (!NT_SUCCESS(status)) {
  2297. error = _I_RtlNtStatusToDosError(status);
  2298. }
  2299. }
  2300. return error;
  2301. }
  2302. PRIVATE
  2303. VOID
  2304. CloseTcpipDriverHandle(
  2305. VOID
  2306. )
  2307. /*++
  2308. Routine Description:
  2309. Closes TCP/IP device driver handle
  2310. Arguments:
  2311. None.
  2312. Return Value:
  2313. None.
  2314. --*/
  2315. {
  2316. if (TcpipDriverHandle != INVALID_HANDLE_VALUE) {
  2317. CloseHandle(TcpipDriverHandle);
  2318. TcpipDriverHandle = INVALID_HANDLE_VALUE;
  2319. }
  2320. }
  2321. PRIVATE
  2322. DWORD
  2323. GetEntityList(
  2324. OUT TDIEntityID * * lplpEntities
  2325. )
  2326. /*++
  2327. Routine Description:
  2328. Allocates a buffer for, and retrieves, the list of entities supported by the
  2329. TCP/IP device driver
  2330. Arguments:
  2331. lplpEntities - pointer to allocated returned list of entities. Caller
  2332. must free
  2333. Return Value:
  2334. UINT - number of entities returned
  2335. --*/
  2336. {
  2337. DEBUG_ENTER((DBG_SOCKETS,
  2338. Int,
  2339. "GetEntityList",
  2340. "%#x",
  2341. lplpEntities
  2342. ));
  2343. TCP_REQUEST_QUERY_INFORMATION_EX req;
  2344. memset(&req, 0, sizeof(req));
  2345. req.ID.toi_entity.tei_entity = GENERIC_ENTITY;
  2346. req.ID.toi_entity.tei_instance = 0;
  2347. req.ID.toi_class = INFO_CLASS_GENERIC;
  2348. req.ID.toi_type = INFO_TYPE_PROVIDER;
  2349. req.ID.toi_id = ENTITY_LIST_ID;
  2350. DWORD inputLen = sizeof(req);
  2351. DWORD outputLen = sizeof(TDIEntityID) * DEFAULT_MINIMUM_ENTITIES;
  2352. TDIEntityID * pEntity = NULL;
  2353. DWORD status = TDI_SUCCESS;
  2354. //
  2355. // this is over-engineered - its very unlikely that we'll ever get >32
  2356. // entities returned, never mind >64K's worth
  2357. //
  2358. // Go round this loop a maximum of 4 times - length of list shouldn't
  2359. // change between calls. Stops us getting stuck in infinite loop if
  2360. // something bad happens with outputLen
  2361. //
  2362. for (int i = 0; i < 4; ++i) {
  2363. DWORD previousOutputLen = outputLen;
  2364. pEntity = (TDIEntityID *)ResizeBuffer(pEntity, outputLen, FALSE);
  2365. if (pEntity == NULL) {
  2366. outputLen = 0;
  2367. break;
  2368. }
  2369. status = WsControl(IPPROTO_TCP,
  2370. WSCNTL_TCPIP_QUERY_INFO,
  2371. (LPVOID)&req,
  2372. &inputLen,
  2373. (LPVOID)pEntity,
  2374. &outputLen
  2375. );
  2376. //
  2377. // TDI_SUCCESS is returned if all data is not returned: driver
  2378. // communicates all/partial data via outputLen
  2379. //
  2380. if (status == TDI_SUCCESS) {
  2381. DEBUG_PRINT(UTIL,
  2382. INFO,
  2383. ("GENERIC_ENTITY required length = %d\n",
  2384. outputLen
  2385. ));
  2386. if (outputLen && (outputLen <= previousOutputLen)) {
  2387. break;
  2388. }
  2389. } else {
  2390. outputLen = 0;
  2391. }
  2392. }
  2393. if ((status != TDI_SUCCESS) && (pEntity != NULL)) {
  2394. ResizeBuffer(pEntity, 0, FALSE);
  2395. }
  2396. DEBUG_PRINT(UTIL,
  2397. INFO,
  2398. ("%d entities returned in %#x\n",
  2399. (outputLen / sizeof(TDIEntityID)),
  2400. pEntity
  2401. ));
  2402. *lplpEntities = pEntity;
  2403. DEBUG_LEAVE((UINT)(outputLen / sizeof(TDIEntityID)));
  2404. return (UINT)(outputLen / sizeof(TDIEntityID));
  2405. }
  2406. //
  2407. // private debug functions
  2408. //
  2409. #if INET_DEBUG
  2410. PRIVATE
  2411. LPCSTR
  2412. InternetMapEntity(
  2413. IN INT EntityId
  2414. ) {
  2415. switch (EntityId) {
  2416. case CO_TL_ENTITY:
  2417. return "CO_TL_ENTITY";
  2418. case CL_TL_ENTITY:
  2419. return "CL_TL_ENTITY";
  2420. case ER_ENTITY:
  2421. return "ER_ENTITY";
  2422. case CO_NL_ENTITY:
  2423. return "CO_NL_ENTITY";
  2424. case CL_NL_ENTITY:
  2425. return "CL_NL_ENTITY";
  2426. case AT_ENTITY:
  2427. return "AT_ENTITY";
  2428. case IF_ENTITY:
  2429. return "IF_ENTITY";
  2430. }
  2431. return "*** UNKNOWN ENTITY ***";
  2432. }
  2433. PRIVATE
  2434. LPCSTR
  2435. InternetMapInterface(
  2436. IN DWORD InterfaceType
  2437. ) {
  2438. switch (InterfaceType) {
  2439. case IF_TYPE_OTHER:
  2440. return "other";
  2441. case IF_TYPE_ETHERNET:
  2442. return "ethernet";
  2443. case IF_TYPE_TOKENRING:
  2444. return "token ring";
  2445. case IF_TYPE_FDDI:
  2446. return "FDDI";
  2447. case IF_TYPE_PPP:
  2448. return "PPP";
  2449. case IF_TYPE_LOOPBACK:
  2450. return "loopback";
  2451. }
  2452. return "???";
  2453. }
  2454. PRIVATE
  2455. LPCSTR
  2456. InternetMapInterfaceOnNT5(
  2457. IN DWORD InterfaceType
  2458. ) {
  2459. switch (InterfaceType) {
  2460. case IF_TYPE_OTHER:
  2461. return "other";
  2462. case IF_TYPE_ETHERNET_CSMACD:
  2463. return "ethernet";
  2464. case IF_TYPE_ISO88025_TOKENRING:
  2465. return "token ring";
  2466. case IF_TYPE_FDDI:
  2467. return "FDDI";
  2468. case IF_TYPE_PPP:
  2469. return "PPP";
  2470. case IF_TYPE_SOFTWARE_LOOPBACK:
  2471. return "loopback";
  2472. case IF_TYPE_SLIP:
  2473. return "SLIP";
  2474. default:
  2475. break;
  2476. }
  2477. return "???";
  2478. }
  2479. #endif