Source code of Windows XP (NT5)
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.

3526 lines
84 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. Revision History:
  6. Amritansh Raghav
  7. --*/
  8. #include "inc.h"
  9. #pragma hdrstop
  10. #include <ntddip.h>
  11. #ifdef CHICAGO
  12. LPWSCONTROL pWsControl = NULL;
  13. HANDLE hWsock = NULL;
  14. #endif
  15. extern HANDLE g_hIPDriverHandle;
  16. extern HANDLE g_hIPGetDriverHandle;
  17. extern HANDLE ChangeNotificationHandle;
  18. extern HANDLE g_hIP6DriverHandle;
  19. extern HANDLE g_hIP6GetDriverHandle;
  20. extern HANDLE Change6NotificationHandle;
  21. #ifdef DBG
  22. int trace = 1;
  23. #endif
  24. DWORD
  25. OpenTCPDriver(
  26. IN DWORD dwFamily
  27. );
  28. DWORD
  29. OpenIPDriver(
  30. IN DWORD dwFamily
  31. );
  32. DWORD
  33. CloseIPDriver();
  34. DWORD
  35. CloseIP6Driver();
  36. TDIEntityID*
  37. GetTdiEntityCount(
  38. PULONG pulNumEntities
  39. );
  40. DWORD
  41. GetArpEntryCount(
  42. OUT PDWORD pdwNumEntries
  43. );
  44. int
  45. TCPQueryInformationEx(
  46. DWORD Family,
  47. void *InBuf,
  48. ulong *InBufLen,
  49. void *OutBuf,
  50. ulong *OutBufLen
  51. );
  52. int
  53. TCPSetInformationEx(
  54. void *InBuf,
  55. ULONG *InBufLen,
  56. void *OutBuf,
  57. ULONG *OutBufLen
  58. );
  59. DWORD
  60. AccessIfEntryInStack(
  61. IN DWORD dwAction,
  62. IN DWORD dwInstance,
  63. IN OUT PMIB_IFROW pIfEntry
  64. );
  65. int
  66. TCPSendIoctl(
  67. HANDLE hHandle,
  68. ulong Ioctl,
  69. void *InBuf,
  70. ulong *InBufLen,
  71. void *OutBuf,
  72. ulong *OutBufLen
  73. );
  74. // ========================================================================
  75. #ifdef CHICAGO
  76. uint
  77. ConvertTdiErrorToDosError(uint TdiErr)
  78. {
  79. switch (TdiErr) {
  80. case TDI_INVALID_REQUEST:
  81. case TDI_INVALID_QUERY:
  82. return ERROR_INVALID_FUNCTION;
  83. case TDI_BUFFER_TOO_SMALL:
  84. return ERROR_INSUFFICIENT_BUFFER;
  85. case TDI_BUFFER_OVERFLOW:
  86. return ERROR_INSUFFICIENT_BUFFER;
  87. case TDI_PENDING:
  88. return ERROR_SIGNAL_PENDING;
  89. default:
  90. return ERROR_INVALID_PARAMETER;
  91. }
  92. }
  93. #endif
  94. DWORD
  95. AllocateAndGetIfTableFromStack(
  96. OUT MIB_IFTABLE **ppIfTable,
  97. IN BOOL bOrder,
  98. IN HANDLE hHeap,
  99. IN DWORD dwFlags,
  100. IN BOOL bForceUpdate
  101. )
  102. {
  103. DWORD dwResult, dwCount, dwOutBufLen;
  104. MIB_IPSTATS miStats;
  105. *ppIfTable = NULL;
  106. dwResult = GetIpStatsFromStack(&miStats);
  107. if(dwResult isnot NO_ERROR)
  108. {
  109. Trace1(ERR,
  110. "AllocateAndGetIfTableFromStack: Couldnt get Ip Stats From stack. Error %d",
  111. dwResult);
  112. return dwResult;
  113. }
  114. dwCount = miStats.dwNumIf + OVERFLOW_COUNT;
  115. dwOutBufLen = SIZEOF_IFTABLE(dwCount);
  116. *ppIfTable = HeapAlloc(hHeap,
  117. dwFlags,
  118. dwOutBufLen);
  119. if(*ppIfTable is NULL)
  120. {
  121. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  122. Trace1(ERR,
  123. "AllocateAndGetIfTableFromStack: Couldnt allocate memory. Error %d",
  124. dwResult);
  125. return dwResult;
  126. }
  127. if(miStats.dwNumIf is 0)
  128. {
  129. (*ppIfTable)->dwNumEntries = 0;
  130. return NO_ERROR;
  131. }
  132. EnterCriticalSection(&g_ifLock);
  133. if (!bForceUpdate && miStats.dwNumIf != g_dwNumIf)
  134. {
  135. bForceUpdate = TRUE;
  136. }
  137. g_dwNumIf = miStats.dwNumIf;
  138. LeaveCriticalSection(&g_ifLock);
  139. dwResult = GetIfTableFromStack(*ppIfTable,
  140. dwOutBufLen,
  141. bOrder,
  142. bForceUpdate);
  143. if(dwResult isnot NO_ERROR)
  144. {
  145. Trace1(ERR,
  146. "AllocateAndGetIfTableFromStack: Error %d calling GetIfTableFromStack",
  147. dwResult);
  148. HeapFree(hHeap, dwFlags, *ppIfTable);
  149. *ppIfTable = NULL;
  150. }
  151. return dwResult;
  152. }
  153. // ========================================================================
  154. DWORD
  155. GetIfTableFromStack(
  156. OUT PMIB_IFTABLE pIfTable,
  157. IN DWORD dwSize,
  158. IN BOOL bOrder,
  159. IN BOOL bForceUpdate
  160. )
  161. /*++
  162. Routine Description
  163. Locks
  164. None needed on entry. It takes the If lock within the function
  165. Arguments
  166. Return Value
  167. NO_ERROR
  168. --*/
  169. {
  170. DWORD i, dwNumRows, dwCount, dwErr, dwResult;
  171. PLIST_ENTRY pCurrentNode;
  172. LPAIHASH lpAIBlock;
  173. dwNumRows = (dwSize - FIELD_OFFSET(MIB_IFTABLE,table[0]))/sizeof(MIB_IFROW);
  174. dwCount = 0;
  175. dwErr = NO_ERROR;
  176. CheckTcpipState();
  177. if (!g_bIpConfigured)
  178. {
  179. return ERROR_NOT_SUPPORTED;
  180. }
  181. EnterCriticalSection(&g_ifLock);
  182. if(bForceUpdate or
  183. (g_dwLastIfUpdateTime is 0) or
  184. ((GetCurrentTime() - g_dwLastIfUpdateTime) > IF_CACHE_LIFE))
  185. {
  186. dwResult = UpdateAdapterToIFInstanceMapping();
  187. Trace0(ERR, "Update the mapping \n");
  188. if(dwResult isnot NO_ERROR)
  189. {
  190. Trace1(ERR,
  191. "GetIfTableFromStack: Couldnt update map. Error %d",
  192. dwResult);
  193. LeaveCriticalSection(&g_ifLock);
  194. return ERROR_CAN_NOT_COMPLETE;
  195. }
  196. }
  197. for(i = 0; i < MAP_HASH_SIZE; i ++)
  198. {
  199. for(pCurrentNode = g_pAdapterMappingTable[i].Flink;
  200. pCurrentNode isnot &(g_pAdapterMappingTable[i]);
  201. pCurrentNode = pCurrentNode->Flink)
  202. {
  203. lpAIBlock = CONTAINING_RECORD(pCurrentNode,AIHASH,leList);
  204. Trace1(ERR,
  205. "Instance %d \n", lpAIBlock->dwIFInstance);
  206. if(lpAIBlock->dwIFInstance is INVALID_IF_INSTANCE)
  207. {
  208. continue;
  209. }
  210. //
  211. // If there is no more space in the buffer, bail out
  212. //
  213. if(dwCount >= dwNumRows)
  214. {
  215. Trace2(ERR,
  216. "return here dwCount %d dwNumRows %d \n", dwCount, dwNumRows);
  217. dwErr = ERROR_MORE_DATA;
  218. break;
  219. }
  220. dwResult = AccessIfEntryInStack(GET_IF_ENTRY,
  221. lpAIBlock->dwIFInstance,
  222. &(pIfTable->table[dwCount]));
  223. if(dwResult isnot NO_ERROR)
  224. {
  225. Trace2(ERR,
  226. "GetIfTableFromStack: Err %d getting row for inst %d",
  227. dwResult, lpAIBlock->dwIFInstance);
  228. // dwErr = ERROR_MORE_DATA;
  229. // at this point the stack doesn't have the interface
  230. continue;
  231. g_dwLastIfUpdateTime = 0;
  232. }
  233. else
  234. {
  235. dwCount++;
  236. }
  237. }
  238. }
  239. g_dwNumIf = dwCount;
  240. LeaveCriticalSection(&g_ifLock);
  241. pIfTable->dwNumEntries = dwCount;
  242. if(bOrder && (dwCount > 0))
  243. {
  244. qsort(pIfTable->table,
  245. dwCount,
  246. sizeof(MIB_IFROW),
  247. CompareIfRow);
  248. }
  249. return dwErr;
  250. }
  251. // ========================================================================
  252. DWORD
  253. GetIfEntryFromStack(
  254. OUT PMIB_IFROW pIfEntry,
  255. IN DWORD dwAdapterIndex,
  256. IN BOOL bForceUpdate
  257. )
  258. /*++
  259. Routine Description
  260. Locks
  261. Arguments
  262. Return Value
  263. NO_ERROR
  264. --*/
  265. {
  266. DWORD dwResult,dwInBufLen,dwOutBufLen,dwInstance;
  267. TDIObjectID *ID;
  268. BYTE *Context;
  269. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  270. if (pIfEntry == NULL) {
  271. return ERROR_INVALID_PARAMETER;
  272. }
  273. CheckTcpipState();
  274. if (!g_bIpConfigured)
  275. {
  276. return ERROR_NOT_SUPPORTED;
  277. }
  278. EnterCriticalSection(&g_ifLock);
  279. if(bForceUpdate)
  280. {
  281. dwResult = UpdateAdapterToIFInstanceMapping();
  282. if(dwResult isnot NO_ERROR)
  283. {
  284. Trace1(ERR,
  285. "GetIfEntryFromStack: Couldnt update map. Error %d",
  286. dwResult);
  287. LeaveCriticalSection(&g_ifLock);
  288. return ERROR_CAN_NOT_COMPLETE;
  289. }
  290. dwInstance = GetIFInstanceFromAdapter(dwAdapterIndex);
  291. }
  292. else
  293. {
  294. dwInstance = GetIFInstanceFromAdapter(dwAdapterIndex);
  295. if(dwInstance is INVALID_IF_INSTANCE)
  296. {
  297. Trace0(ERR,
  298. "GetIfEntryFromStack: Couldnt map to instance - first try");
  299. dwResult = UpdateAdapterToIFInstanceMapping();
  300. if(dwResult isnot NO_ERROR)
  301. {
  302. Trace1(ERR,
  303. "GetIfEntryFromStack: Couldnt update map. Error %d",
  304. dwResult);
  305. LeaveCriticalSection(&g_ifLock);
  306. return ERROR_CAN_NOT_COMPLETE;
  307. }
  308. dwInstance = GetIFInstanceFromAdapter(dwAdapterIndex);
  309. }
  310. }
  311. LeaveCriticalSection(&g_ifLock);
  312. if(dwInstance is INVALID_IF_INSTANCE)
  313. {
  314. Trace0(ERR,
  315. "GetIfEntryFromStack: Couldnt map to instance second try!!!!");
  316. return ERROR_INVALID_DATA;
  317. }
  318. ID = &(trqiInBuf.ID);
  319. ID->toi_entity.tei_entity = IF_ENTITY;
  320. ID->toi_class = INFO_CLASS_PROTOCOL;
  321. ID->toi_type = INFO_TYPE_PROVIDER;
  322. ID->toi_id = IF_MIB_STATS_ID;
  323. ID->toi_entity.tei_instance = dwInstance;
  324. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  325. dwOutBufLen = sizeof(IFEntry);
  326. Context = (BYTE *) &(trqiInBuf.Context[0]);
  327. ZeroMemory( Context, CONTEXT_SIZE );
  328. dwResult = AccessIfEntryInStack(GET_IF_ENTRY,
  329. dwInstance,
  330. pIfEntry);
  331. return dwResult;
  332. }
  333. // ========================================================================
  334. DWORD
  335. SetIfEntryToStack(
  336. IN MIB_IFROW *pIfEntry,
  337. IN BOOL bForceUpdate
  338. )
  339. /*++
  340. Routine Description
  341. Locks
  342. Arguments
  343. Return Value
  344. NO_ERROR
  345. --*/
  346. {
  347. DWORD dwResult,dwInstance;
  348. CheckTcpipState();
  349. if (!g_bIpConfigured)
  350. {
  351. return ERROR_NOT_SUPPORTED;
  352. }
  353. EnterCriticalSection(&g_ifLock);
  354. if(bForceUpdate)
  355. {
  356. dwResult = UpdateAdapterToIFInstanceMapping();
  357. if(dwResult isnot NO_ERROR)
  358. {
  359. LeaveCriticalSection(&g_ifLock);
  360. Trace1(ERR,
  361. "SetIfEntryToStack: Couldnt update map. Error %d",
  362. dwResult);
  363. return ERROR_CAN_NOT_COMPLETE;
  364. }
  365. dwInstance = GetIFInstanceFromAdapter(pIfEntry->dwIndex);
  366. }
  367. else
  368. {
  369. dwInstance = GetIFInstanceFromAdapter(pIfEntry->dwIndex);
  370. if(dwInstance is INVALID_IF_INSTANCE)
  371. {
  372. Trace0(ERR,
  373. "SetIfEntryToStack: Couldnt map to instance - first try");
  374. dwResult = UpdateAdapterToIFInstanceMapping();
  375. if(dwResult isnot NO_ERROR)
  376. {
  377. LeaveCriticalSection(&g_ifLock);
  378. Trace1(ERR,
  379. "SetIfEntryToStack: Couldnt update map. Error %d",
  380. dwResult);
  381. return ERROR_CAN_NOT_COMPLETE;
  382. }
  383. dwInstance = GetIFInstanceFromAdapter(pIfEntry->dwIndex);
  384. }
  385. }
  386. if(dwInstance is INVALID_IF_INSTANCE)
  387. {
  388. LeaveCriticalSection(&g_ifLock);
  389. Trace0(ERR,
  390. "SetIfEntryToStack: Couldnt map to instance");
  391. return ERROR_INVALID_DATA;
  392. }
  393. dwResult = AccessIfEntryInStack(SET_IF_ENTRY,
  394. dwInstance,
  395. pIfEntry);
  396. LeaveCriticalSection(&g_ifLock);
  397. return dwResult;
  398. }
  399. // ========================================================================
  400. /*++
  401. Routine Description
  402. Arguments
  403. dwAction Can be SET_IF or GET_IF
  404. picb the Interface Control Block
  405. lpOutBuf
  406. Return Value
  407. DWORD: NO_ERROR or some error code
  408. --*/
  409. DWORD
  410. AccessIfEntryInStack(
  411. IN DWORD dwAction,
  412. IN DWORD dwInstance,
  413. IN OUT PMIB_IFROW pIfEntry
  414. )
  415. {
  416. DWORD dwResult;
  417. DWORD dwInBufLen,dwOutBufLen;
  418. TDIObjectID *ID;
  419. BYTE *Context;
  420. switch(dwAction)
  421. {
  422. case GET_IF_ENTRY:
  423. {
  424. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  425. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  426. ID = &(trqiInBuf.ID);
  427. Context = (BYTE *) &(trqiInBuf.Context[0]);
  428. ID->toi_entity.tei_entity = IF_ENTITY;
  429. ID->toi_class = INFO_CLASS_PROTOCOL;
  430. ID->toi_type = INFO_TYPE_PROVIDER;
  431. ID->toi_id = IF_MIB_STATS_ID;
  432. dwOutBufLen = sizeof(MIB_IFROW) - FIELD_OFFSET(MIB_IFROW, dwIndex);
  433. ID->toi_entity.tei_instance = dwInstance;
  434. ZeroMemory( Context, CONTEXT_SIZE );
  435. dwResult = TCPQueryInformationEx(AF_INET,
  436. &trqiInBuf,
  437. &dwInBufLen,
  438. &(pIfEntry->dwIndex),
  439. &dwOutBufLen);
  440. break;
  441. }
  442. case SET_IF_ENTRY:
  443. {
  444. TCP_REQUEST_SET_INFORMATION_EX *lptrsiInBuf;
  445. IFEntry *pifeSetInfo;
  446. dwInBufLen = sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(IFEntry) - 1;
  447. lptrsiInBuf = HeapAlloc(g_hPrivateHeap,0,dwInBufLen);
  448. if(lptrsiInBuf is NULL)
  449. {
  450. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  451. Trace1(ERR,
  452. "AccessIfEntryInStack: Error %d allocating memory",
  453. dwResult);
  454. return dwResult;
  455. }
  456. ID = &lptrsiInBuf->ID;
  457. ID->toi_class = INFO_CLASS_PROTOCOL;
  458. ID->toi_type = INFO_TYPE_PROVIDER;
  459. ID->toi_entity.tei_entity = IF_ENTITY;
  460. ID->toi_id = IF_MIB_STATS_ID;
  461. ID->toi_entity.tei_instance = dwInstance;
  462. lptrsiInBuf->BufferSize = sizeof(IFEntry);
  463. dwOutBufLen = 0;
  464. pifeSetInfo = (IFEntry*)lptrsiInBuf->Buffer;
  465. *pifeSetInfo = *(IFEntry*)(&(pIfEntry->dwIndex));
  466. dwResult = TCPSetInformationEx((PVOID) lptrsiInBuf,
  467. &dwInBufLen,
  468. NULL,
  469. &dwOutBufLen);
  470. HeapFree(g_hPrivateHeap,0,lptrsiInBuf);
  471. break;
  472. }
  473. }
  474. return dwResult;
  475. }
  476. DWORD
  477. NhpGetInterfaceIndexFromStack(
  478. IN PWCHAR pwszIfName,
  479. OUT PDWORD pdwIfIndex
  480. )
  481. /*++
  482. Routine Description
  483. Gets the interface index from IP
  484. Locks
  485. None
  486. Arguments
  487. pwszIfName NULL terminated unique name for interface
  488. dwIfIndex [OUT] Interface Index
  489. Return Value
  490. NO_ERROR
  491. ERROR_INVALID_PARAMETER
  492. --*/
  493. {
  494. DWORD rgdwBuffer[255], dwStatus, dwInSize, dwOutSize;
  495. PIP_GET_IF_INDEX_INFO pInfo;
  496. #ifdef _WIN95_
  497. return ERROR_NOT_SUPPORTED;
  498. #else
  499. CheckTcpipState();
  500. if (!g_bIpConfigured)
  501. {
  502. return ERROR_NOT_SUPPORTED;
  503. }
  504. //
  505. // The if name should be NULL terminated and should fit in the buffer
  506. // above
  507. //
  508. if((FIELD_OFFSET(IP_GET_IF_INDEX_INFO, Name[0]) +
  509. ((wcslen(pwszIfName) + 1) * sizeof(WCHAR))) > sizeof(rgdwBuffer))
  510. {
  511. return ERROR_INVALID_PARAMETER;
  512. }
  513. pInfo = (PIP_GET_IF_INDEX_INFO)rgdwBuffer;
  514. ZeroMemory(rgdwBuffer,
  515. sizeof(rgdwBuffer));
  516. wcscpy(pInfo->Name,
  517. pwszIfName);
  518. dwInSize = FIELD_OFFSET(IP_GET_IF_INDEX_INFO, Name[0]) +
  519. ((wcslen(pwszIfName) + 1) * sizeof(WCHAR));
  520. dwOutSize = dwInSize;
  521. dwStatus = TCPSendIoctl(g_hIPGetDriverHandle,
  522. IOCTL_IP_GET_IF_INDEX,
  523. pInfo,
  524. &dwInSize,
  525. pInfo,
  526. &dwOutSize);
  527. *pdwIfIndex = pInfo->Index;
  528. return dwStatus;
  529. #endif
  530. }
  531. DWORD
  532. NhpAllocateAndGetInterfaceInfoFromStack(
  533. OUT IP_INTERFACE_NAME_INFO **ppTable,
  534. OUT PDWORD pdwCount,
  535. IN BOOL bOrder,
  536. IN HANDLE hHeap,
  537. IN DWORD dwFlags
  538. )
  539. /*++
  540. Routine Description
  541. Internal no fuss routine for getting the interface info.
  542. This is not an optimal routine when there are many interfaces in the
  543. stack, since the allocations become huge
  544. Locks
  545. None
  546. Arguments
  547. ppTable Allocated table
  548. pdwCount Number of entries in the allocated table
  549. bOrder If TRUE, the table is ordered
  550. hHeap Handle of heap to allocate from
  551. dwFlags Flags to use for allocation
  552. Return Value
  553. NO_ERROR
  554. --*/
  555. {
  556. MIB_IPSTATS miStats;
  557. PIP_GET_IF_NAME_INFO pInfo;
  558. DWORD i, dwResult, dwOutSize, dwInSize, dwCount;
  559. *ppTable = NULL;
  560. *pdwCount = 0;
  561. dwResult = GetIpStatsFromStack(&miStats);
  562. if(dwResult isnot NO_ERROR)
  563. {
  564. return dwResult;
  565. }
  566. dwCount = miStats.dwNumIf + OVERFLOW_COUNT;
  567. dwOutSize = FIELD_OFFSET(IP_GET_IF_NAME_INFO, Info) +
  568. (dwCount * sizeof(IP_INTERFACE_NAME_INFO));
  569. dwInSize = FIELD_OFFSET(IP_GET_IF_NAME_INFO, Info);
  570. pInfo = HeapAlloc(g_hPrivateHeap,
  571. 0,
  572. dwOutSize);
  573. if(pInfo is NULL)
  574. {
  575. return ERROR_NOT_ENOUGH_MEMORY;
  576. }
  577. pInfo->Context = 0;
  578. dwResult = TCPSendIoctl(g_hIPGetDriverHandle,
  579. IOCTL_IP_GET_IF_NAME,
  580. pInfo,
  581. &dwInSize,
  582. pInfo,
  583. &dwOutSize);
  584. if(dwResult isnot NO_ERROR)
  585. {
  586. HeapFree(g_hPrivateHeap,
  587. 0,
  588. pInfo);
  589. return dwResult;
  590. }
  591. #if DBG
  592. dwCount = (dwOutSize - FIELD_OFFSET(IP_GET_IF_NAME_INFO, Info))/sizeof(IP_INTERFACE_NAME_INFO);
  593. ASSERT(dwCount is pInfo->Count);
  594. #endif
  595. if(pInfo->Count is 0)
  596. {
  597. HeapFree(g_hPrivateHeap,
  598. 0,
  599. pInfo);
  600. return ERROR_NO_DATA;
  601. }
  602. //
  603. // Allocate for the user and copy out the info
  604. //
  605. dwOutSize = pInfo->Count * sizeof(IP_INTERFACE_NAME_INFO);
  606. *ppTable = HeapAlloc(hHeap,
  607. dwFlags,
  608. dwOutSize);
  609. if(*ppTable is NULL)
  610. {
  611. HeapFree(g_hPrivateHeap,
  612. 0,
  613. pInfo);
  614. return ERROR_NOT_ENOUGH_MEMORY;
  615. }
  616. //
  617. // Copy out the info
  618. //
  619. for(i = 0; i < pInfo->Count; i++)
  620. {
  621. //
  622. // Structure copy
  623. //
  624. (*ppTable)[i] = pInfo->Info[i];
  625. }
  626. if(pInfo->Count and bOrder)
  627. {
  628. qsort(*ppTable,
  629. pInfo->Count,
  630. sizeof(IP_INTERFACE_NAME_INFO),
  631. NhiCompareIfInfoRow);
  632. }
  633. *pdwCount = pInfo->Count;
  634. HeapFree(g_hPrivateHeap,
  635. 0,
  636. pInfo);
  637. return NO_ERROR;
  638. }
  639. // ========================================================================
  640. DWORD
  641. AllocateAndGetIpAddrTableFromStack(
  642. OUT MIB_IPADDRTABLE **ppIpAddrTable,
  643. IN BOOL bOrder,
  644. IN HANDLE hHeap,
  645. IN DWORD dwFlags
  646. )
  647. {
  648. DWORD dwResult,dwCount;
  649. DWORD dwOutBufLen;
  650. MIB_IPSTATS IpSnmpInfo;
  651. *ppIpAddrTable = NULL;
  652. //
  653. // Find out the number of entries the stack has. It returns this as part of
  654. // the IP Stats
  655. //
  656. dwResult = GetIpStatsFromStack(&IpSnmpInfo);
  657. if(dwResult isnot NO_ERROR)
  658. {
  659. Trace1(ERR,
  660. "AllocateAndGetIpAddrTableFromStack: Couldnt get Ip Stats From stack. Error %d",
  661. dwResult);
  662. return dwResult;
  663. }
  664. //
  665. // Add extra to take care of increase between the two calls
  666. //
  667. dwCount = IpSnmpInfo.dwNumAddr + OVERFLOW_COUNT;
  668. dwOutBufLen = SIZEOF_IPADDRTABLE(dwCount);
  669. *ppIpAddrTable = HeapAlloc(hHeap,
  670. dwFlags,
  671. dwOutBufLen);
  672. if(*ppIpAddrTable is NULL)
  673. {
  674. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  675. Trace1(ERR,
  676. "AllocateAndGetIpAddrTableFromStack: Couldnt allocate memory. Error %d",
  677. dwResult);
  678. return dwResult;
  679. }
  680. if(IpSnmpInfo.dwNumAddr is 0)
  681. {
  682. //
  683. // Just return an empty table.
  684. // We do this because there is some code in MIB-II agent that
  685. // expects to get a table back, even if there are not entries in
  686. // it.
  687. //
  688. (*ppIpAddrTable)->dwNumEntries = 0;
  689. return NO_ERROR;
  690. }
  691. dwResult = GetIpAddrTableFromStack(*ppIpAddrTable,
  692. dwOutBufLen,
  693. bOrder);
  694. if(dwResult isnot NO_ERROR)
  695. {
  696. Trace1(ERR,
  697. "AllocateAndGetIpAddrTableFromStack: Error %d GetIpAddrTableFromStack",
  698. dwResult);
  699. HeapFree(hHeap, dwFlags, *ppIpAddrTable);
  700. *ppIpAddrTable = NULL;
  701. }
  702. return dwResult;
  703. }
  704. // ========================================================================
  705. DWORD
  706. GetIpAddrTableFromStack(
  707. OUT PMIB_IPADDRTABLE pIpAddrTable,
  708. IN DWORD dwSize,
  709. IN BOOL bOrder
  710. )
  711. {
  712. DWORD dwOutBufLen, dwInBufLen, dwResult;
  713. BYTE *Context;
  714. TDIObjectID *ID;
  715. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  716. CheckTcpipState();
  717. if (!g_bIpConfigured)
  718. {
  719. return ERROR_NOT_SUPPORTED;
  720. }
  721. ID = &(trqiInBuf.ID);
  722. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  723. ID->toi_entity.tei_instance = 0;
  724. ID->toi_class = INFO_CLASS_PROTOCOL;
  725. ID->toi_type = INFO_TYPE_PROVIDER;
  726. ID->toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;
  727. Context = (BYTE *) &(trqiInBuf.Context[0]);
  728. ZeroMemory(Context,CONTEXT_SIZE);
  729. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  730. dwOutBufLen = dwSize - FIELD_OFFSET(MIB_IPADDRTABLE, table[0]);
  731. dwResult = TCPQueryInformationEx(AF_INET,
  732. &trqiInBuf,
  733. &dwInBufLen,
  734. (PVOID)(pIpAddrTable->table),
  735. &dwOutBufLen);
  736. if(dwResult isnot NO_ERROR)
  737. {
  738. Trace1(ERR,
  739. "GetIpAddrTableFromStack: Couldnt Query information from stack. Error %x",
  740. dwResult);
  741. return (dwResult);
  742. }
  743. pIpAddrTable->dwNumEntries = (dwOutBufLen / sizeof(MIB_IPADDRROW));
  744. //
  745. // Now sort the address table. Key is IP address.
  746. //
  747. if((pIpAddrTable->dwNumEntries > 0) and bOrder)
  748. {
  749. qsort(pIpAddrTable->table,
  750. pIpAddrTable->dwNumEntries,
  751. sizeof(MIB_IPADDRROW),
  752. CompareIpAddrRow);
  753. }
  754. return NO_ERROR;
  755. }
  756. // ========================================================================
  757. DWORD
  758. AllocateAndGetTcpTableFromStack(
  759. OUT MIB_TCPTABLE **ppTcpTable,
  760. IN BOOL bOrder,
  761. IN HANDLE hHeap,
  762. IN DWORD dwFlags
  763. )
  764. {
  765. DWORD dwResult,dwCount;
  766. DWORD dwOutBufLen;
  767. MIB_TCPSTATS TcpInfo;
  768. *ppTcpTable = NULL;
  769. //
  770. // Find out the number of entries the stack has. It returns this as part of
  771. // the Tcp Stats
  772. //
  773. dwResult = GetTcpStatsFromStack(&TcpInfo);
  774. if(dwResult isnot NO_ERROR)
  775. {
  776. Trace1(ERR,
  777. "AllocateAndGetTcpTableFromStack: Couldnt get Tcp Stats From stack. Error %d",
  778. dwResult);
  779. return dwResult;
  780. }
  781. dwCount = TcpInfo.dwNumConns + OVERFLOW_COUNT;
  782. dwOutBufLen = SIZEOF_TCPTABLE(dwCount);
  783. *ppTcpTable = HeapAlloc(hHeap,
  784. dwFlags,
  785. dwOutBufLen);
  786. if(*ppTcpTable is NULL)
  787. {
  788. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  789. Trace1(ERR,
  790. "AllocateAndGetTcpTableFromStack: Couldnt allocate memory. Error %d",
  791. dwResult);
  792. return dwResult;
  793. }
  794. if(TcpInfo.dwNumConns is 0)
  795. {
  796. (*ppTcpTable)->dwNumEntries = 0;
  797. return NO_ERROR;
  798. }
  799. dwResult = GetTcpTableFromStack(*ppTcpTable,
  800. dwOutBufLen,
  801. bOrder);
  802. if(dwResult isnot NO_ERROR)
  803. {
  804. Trace1(ERR,
  805. "AllocateAndGetTcpTableFromStack: Error %d GetTcpTableFromStack",
  806. dwResult);
  807. HeapFree(hHeap, dwFlags, *ppTcpTable);
  808. *ppTcpTable = NULL;
  809. }
  810. return dwResult;
  811. }
  812. // ========================================================================
  813. DWORD
  814. GetTcpTableFromStack(
  815. OUT PMIB_TCPTABLE pTcpTable,
  816. IN DWORD dwSize,
  817. IN BOOL bOrder
  818. )
  819. {
  820. DWORD dwInBufLen, dwOutBufLen, dwResult;
  821. TDIObjectID *ID;
  822. BYTE *Context;
  823. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  824. CheckTcpipState();
  825. if (!g_bIpConfigured)
  826. {
  827. return ERROR_NOT_SUPPORTED;
  828. }
  829. ID = &(trqiInBuf.ID);
  830. ID->toi_entity.tei_entity = CO_TL_ENTITY;
  831. ID->toi_entity.tei_instance = 0;
  832. ID->toi_class = INFO_CLASS_PROTOCOL;
  833. ID->toi_type = INFO_TYPE_PROVIDER;
  834. ID->toi_id = TCP_MIB_TABLE_ID;
  835. Context = (BYTE *) &(trqiInBuf.Context[0]);
  836. ZeroMemory( Context, CONTEXT_SIZE );
  837. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  838. dwOutBufLen = dwSize - FIELD_OFFSET(MIB_TCPTABLE, table[0]);
  839. dwResult = TCPQueryInformationEx(AF_INET,
  840. &trqiInBuf,
  841. &dwInBufLen,
  842. (PVOID)(pTcpTable->table),
  843. &dwOutBufLen);
  844. if(dwResult isnot NO_ERROR)
  845. {
  846. Trace1(ERR,
  847. "GetTcpTableFromStack: Couldnt query stack. Error %x",
  848. dwResult);
  849. return dwResult;
  850. }
  851. pTcpTable->dwNumEntries = (dwOutBufLen/sizeof(MIB_TCPROW));
  852. if((pTcpTable->dwNumEntries > 0) and bOrder)
  853. {
  854. qsort(pTcpTable->table,
  855. pTcpTable->dwNumEntries,
  856. sizeof(MIB_TCPROW),
  857. CompareTcpRow);
  858. }
  859. return NO_ERROR;
  860. }
  861. // ========================================================================
  862. DWORD
  863. SetTcpEntryToStack(
  864. IN PMIB_TCPROW pTcpRow
  865. )
  866. {
  867. TCP_REQUEST_SET_INFORMATION_EX *ptrsiInBuf;
  868. TDIObjectID *ID;
  869. MIB_TCPROW *copyInfo;
  870. DWORD dwInBufLen,dwOutBufLen,dwResult;
  871. #define REQ_SIZE sizeof(TCP_REQUEST_SET_INFORMATION_EX) + \
  872. sizeof(MIB_TCPROW) - 1
  873. BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
  874. ptrsiInBuf = (TCP_REQUEST_SET_INFORMATION_EX *)rgbyBuffer;
  875. dwInBufLen = REQ_SIZE;
  876. #undef REQ_SIZE
  877. CheckTcpipState();
  878. if (!g_bIpConfigured)
  879. {
  880. return ERROR_NOT_SUPPORTED;
  881. }
  882. ID = &ptrsiInBuf->ID;
  883. ID->toi_class = INFO_CLASS_PROTOCOL;
  884. ID->toi_type = INFO_TYPE_PROVIDER;
  885. ID->toi_entity.tei_entity = CO_TL_ENTITY;
  886. ID->toi_id = TCP_MIB_TABLE_ID;
  887. ID->toi_entity.tei_instance = 0;
  888. copyInfo = (MIB_TCPROW*)ptrsiInBuf->Buffer;
  889. *copyInfo = *pTcpRow;
  890. ptrsiInBuf->BufferSize = sizeof(TCPConnTableEntry);
  891. dwResult = TCPSetInformationEx((PVOID)ptrsiInBuf,
  892. &dwInBufLen,
  893. NULL,
  894. &dwOutBufLen);
  895. return dwResult;
  896. }
  897. // ========================================================================
  898. DWORD
  899. AllocateAndGetUdpTableFromStack(
  900. OUT MIB_UDPTABLE **ppUdpTable,
  901. IN BOOL bOrder,
  902. IN HANDLE hHeap,
  903. IN DWORD dwFlags
  904. )
  905. {
  906. DWORD dwResult, dwCount, dwOutBufLen;
  907. MIB_UDPSTATS UdpInfo;
  908. *ppUdpTable = NULL;
  909. //
  910. // Find out the number of entries the stack has. It returns this as part of
  911. // the Tcp Stats
  912. //
  913. dwResult = GetUdpStatsFromStack(&UdpInfo);
  914. if(dwResult isnot NO_ERROR)
  915. {
  916. Trace1(ERR,
  917. "AllocateAndGetUdpTableFromStack: Couldnt get Udp Stats From stack. Error %d",
  918. dwResult);
  919. return dwResult;
  920. }
  921. dwCount = UdpInfo.dwNumAddrs + OVERFLOW_COUNT;
  922. dwOutBufLen = SIZEOF_UDPTABLE(dwCount);
  923. *ppUdpTable = HeapAlloc(hHeap,
  924. dwFlags,
  925. dwOutBufLen);
  926. if(*ppUdpTable is NULL)
  927. {
  928. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  929. Trace1(ERR,
  930. "AllocateAndGetUdpTableFromStack: Couldnt allocate memory. Error %d",
  931. dwResult);
  932. return dwResult;
  933. }
  934. if(UdpInfo.dwNumAddrs is 0)
  935. {
  936. (*ppUdpTable)->dwNumEntries = 0;
  937. return NO_ERROR;
  938. }
  939. dwResult = GetUdpTableFromStack(*ppUdpTable,
  940. dwOutBufLen,
  941. bOrder);
  942. if(dwResult isnot NO_ERROR)
  943. {
  944. Trace1(ERR,
  945. "AllocateAndGetUdpTableFromStack: Error %d GetUdpTableFromStack",
  946. dwResult);
  947. HeapFree(hHeap, dwFlags, *ppUdpTable);
  948. *ppUdpTable = NULL;
  949. }
  950. return dwResult;
  951. }
  952. // ========================================================================
  953. DWORD
  954. GetUdpTableFromStack(
  955. OUT PMIB_UDPTABLE pUdpTable,
  956. IN DWORD dwSize,
  957. IN BOOL bOrder
  958. )
  959. {
  960. DWORD dwInBufLen, dwOutBufLen, dwResult;
  961. BYTE *Context;
  962. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  963. TDIObjectID *ID;
  964. CheckTcpipState();
  965. if (!g_bIpConfigured)
  966. {
  967. return ERROR_NOT_SUPPORTED;
  968. }
  969. ID = &(trqiInBuf.ID);
  970. ID->toi_entity.tei_entity = CL_TL_ENTITY;
  971. ID->toi_entity.tei_instance = 0;
  972. ID->toi_class = INFO_CLASS_PROTOCOL;
  973. ID->toi_type = INFO_TYPE_PROVIDER;
  974. ID->toi_id = UDP_MIB_TABLE_ID;
  975. Context = (BYTE *) &(trqiInBuf.Context[0]);
  976. ZeroMemory( Context, CONTEXT_SIZE );
  977. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  978. dwOutBufLen = dwSize - FIELD_OFFSET(MIB_UDPTABLE, table[0]);
  979. dwResult = TCPQueryInformationEx(AF_INET,
  980. &trqiInBuf,
  981. &dwInBufLen,
  982. (PVOID)(pUdpTable->table),
  983. &dwOutBufLen);
  984. if(dwResult isnot NO_ERROR)
  985. {
  986. Trace1(ERR,
  987. "GetUdpTableFromStack: Couldnt query TCP information. Error %d",
  988. dwResult);
  989. return dwResult;
  990. }
  991. pUdpTable->dwNumEntries = (dwOutBufLen / sizeof(MIB_UDPROW));
  992. //
  993. // Now sort the UDP connection table. Keys are: local address, and local
  994. // port.
  995. //
  996. if((pUdpTable->dwNumEntries > 0) and bOrder)
  997. {
  998. qsort(pUdpTable->table,
  999. pUdpTable->dwNumEntries,
  1000. sizeof(MIB_UDPROW),
  1001. CompareUdpRow);
  1002. }
  1003. TraceLeave("GetUdpTableFromStack");
  1004. return NO_ERROR;
  1005. }
  1006. // ========================================================================
  1007. DWORD
  1008. AllocateAndGetIpForwardTableFromStack(
  1009. OUT MIB_IPFORWARDTABLE **ppForwardTable,
  1010. IN BOOL bOrder,
  1011. IN HANDLE hHeap,
  1012. IN DWORD dwFlags
  1013. )
  1014. {
  1015. DWORD dwResult,dwCount,dwOutBufLen;
  1016. MIB_IPSTATS IpInfo;
  1017. DWORD dwLoops;
  1018. TraceEnter("AllocateAndGetIpForwardTableFromStack");
  1019. *ppForwardTable = NULL;
  1020. dwLoops = 0;
  1021. while(dwLoops <= 1)
  1022. {
  1023. //
  1024. // Find out the number of entries the stack has. It returns this as
  1025. // part of the IP Stats
  1026. //
  1027. dwResult = GetIpStatsFromStack(&IpInfo);
  1028. if(dwResult isnot NO_ERROR)
  1029. {
  1030. Trace1(ERR,"Couldnt get Ip Stats From stack. Error %d",
  1031. dwResult);
  1032. return dwResult;
  1033. }
  1034. dwCount = IpInfo.dwNumRoutes + ROUTE_OVERFLOW_COUNT + (dwLoops * 50);
  1035. dwOutBufLen = SIZEOF_IPFORWARDTABLE(dwCount);
  1036. *ppForwardTable = HeapAlloc(hHeap,
  1037. dwFlags,
  1038. dwOutBufLen);
  1039. if(*ppForwardTable is NULL)
  1040. {
  1041. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  1042. Trace1(ERR,
  1043. "AllocateAndGetIpForwardTableFromStack: Couldnt allocate memory. Error %d",
  1044. dwResult);
  1045. return dwResult;
  1046. }
  1047. if(IpInfo.dwNumRoutes is 0)
  1048. {
  1049. (*ppForwardTable)->dwNumEntries = 0;
  1050. TraceLeave("AllocateAndGetIPForwardTableFromStack");
  1051. return NO_ERROR;
  1052. }
  1053. dwResult = GetIpForwardTableFromStack(*ppForwardTable,
  1054. dwOutBufLen,
  1055. bOrder);
  1056. if(dwResult isnot NO_ERROR)
  1057. {
  1058. Trace1(ERR,
  1059. "AllocateAndGetIpForwardTableFromStack: Error %d GetIpForwardTableFromStack",
  1060. dwResult);
  1061. HeapFree(hHeap,
  1062. dwFlags,
  1063. *ppForwardTable);
  1064. *ppForwardTable = NULL;
  1065. }
  1066. if(dwResult is ERROR_MORE_DATA)
  1067. {
  1068. dwLoops++;
  1069. }
  1070. else
  1071. {
  1072. break;
  1073. }
  1074. }
  1075. return dwResult;
  1076. }
  1077. // ========================================================================
  1078. DWORD
  1079. GetIpForwardTableFromStack(
  1080. OUT PMIB_IPFORWARDTABLE pForwardTable,
  1081. IN DWORD dwSize,
  1082. IN BOOL bOrder
  1083. )
  1084. {
  1085. DWORD dwInBufLen, dwOutBufLen, dwNumRoutes;
  1086. DWORD i, dwCount, dwResult;
  1087. UCHAR *Context;
  1088. TDIObjectID *ID;
  1089. MIB_IPSTATS IpInfo;
  1090. IPRouteEntry *pTempTable;
  1091. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  1092. //
  1093. // How many routes can the input buffer hold?
  1094. //
  1095. dwNumRoutes = (dwSize - FIELD_OFFSET(MIB_IPFORWARDTABLE,table[0]))/sizeof(MIB_IPFORWARDROW);
  1096. //
  1097. // Find out the number of entries the stack has. It returns this as part of
  1098. // the IP Stats
  1099. //
  1100. dwResult = GetIpStatsFromStack(&IpInfo);
  1101. if(dwResult isnot NO_ERROR)
  1102. {
  1103. Trace1(ERR,"Couldnt get Ip Stats From stack. Error %d",
  1104. dwResult);
  1105. return dwResult;
  1106. }
  1107. dwCount = IpInfo.dwNumRoutes + ROUTE_OVERFLOW_COUNT;
  1108. dwOutBufLen = dwCount * sizeof(IPRouteEntry);
  1109. pTempTable = HeapAlloc(g_hPrivateHeap,
  1110. 0,
  1111. dwOutBufLen);
  1112. if(pTempTable is NULL)
  1113. {
  1114. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  1115. Trace1(ERR,
  1116. "Couldnt allocate memory for temporary table. Error %d",
  1117. dwResult);
  1118. return dwResult;
  1119. }
  1120. ID = &(trqiInBuf.ID);
  1121. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  1122. ID->toi_entity.tei_instance = 0;
  1123. ID->toi_class = INFO_CLASS_PROTOCOL;
  1124. ID->toi_type = INFO_TYPE_PROVIDER;
  1125. ID->toi_id = IP_MIB_RTTABLE_ENTRY_ID;
  1126. Context = (BYTE *) &(trqiInBuf.Context[0]);
  1127. ZeroMemory(Context,
  1128. CONTEXT_SIZE );
  1129. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  1130. dwResult = TCPQueryInformationEx(AF_INET,
  1131. &trqiInBuf,
  1132. &dwInBufLen,
  1133. (PVOID)pTempTable,
  1134. &dwOutBufLen );
  1135. if(dwResult isnot NO_ERROR)
  1136. {
  1137. HeapFree(g_hPrivateHeap,
  1138. 0,
  1139. pTempTable);
  1140. Trace1(ERR,"Couldnt query stack. Error %x",
  1141. dwResult);
  1142. TraceLeave("GetIpForwardTableFromStack");
  1143. return dwResult;
  1144. }
  1145. dwCount = (dwOutBufLen / sizeof(IPRouteEntry));
  1146. if(dwNumRoutes >= dwCount)
  1147. {
  1148. //
  1149. // There is space for all the entries returned by the stack
  1150. //
  1151. pForwardTable->dwNumEntries = dwCount;
  1152. }
  1153. else
  1154. {
  1155. //
  1156. // Take the first dwNumRoute entries
  1157. //
  1158. pForwardTable->dwNumEntries = dwNumRoutes;
  1159. dwResult = ERROR_MORE_DATA;
  1160. }
  1161. for (i = 0; i < pForwardTable->dwNumEntries; i++ )
  1162. {
  1163. ConvertRouteToForward(&(pTempTable[i]),
  1164. &(pForwardTable->table[i]));
  1165. }
  1166. HeapFree(g_hPrivateHeap,
  1167. 0,
  1168. pTempTable);
  1169. if((pForwardTable->dwNumEntries > 0) and bOrder)
  1170. {
  1171. qsort(pForwardTable->table,
  1172. pForwardTable->dwNumEntries,
  1173. sizeof(MIB_IPFORWARDROW),
  1174. CompareIpForwardRow);
  1175. }
  1176. TraceLeave("GetIPForwardTableFromStack");
  1177. return dwResult;
  1178. }
  1179. // ========================================================================
  1180. DWORD
  1181. AllocateAndGetIpNetTableFromStack(
  1182. OUT MIB_IPNETTABLE **ppNetTable,
  1183. IN BOOL bOrder,
  1184. IN HANDLE hHeap,
  1185. IN DWORD dwFlags,
  1186. IN BOOL bForceUpdate
  1187. )
  1188. {
  1189. DWORD dwResult, dwOutBufLen, dwNetEntryCount;
  1190. DWORD dwCount;
  1191. TraceEnter("AllocateAndGetIpNetTableFromStack");
  1192. CheckTcpipState();
  1193. if (!g_bIpConfigured)
  1194. {
  1195. return ERROR_NOT_SUPPORTED;
  1196. }
  1197. *ppNetTable = NULL;
  1198. EnterCriticalSection(&g_ipNetLock);
  1199. dwResult = GetArpEntryCount(&dwNetEntryCount);
  1200. LeaveCriticalSection(&g_ipNetLock);
  1201. if(dwResult isnot NO_ERROR)
  1202. {
  1203. Trace1(ERR,
  1204. "AllocateAndGetIpNetTableFromStack: Couldnt query Information from stack. Error %x",
  1205. dwResult);
  1206. TraceLeave("AllocateAndGetIpNetTableFromStack");
  1207. return dwResult;
  1208. }
  1209. //
  1210. // This is generally a memory hog
  1211. //
  1212. dwCount = dwNetEntryCount + (g_dwNumArpEntEntries) * OVERFLOW_COUNT;
  1213. dwOutBufLen = SIZEOF_IPNETTABLE(dwCount);
  1214. *ppNetTable = HeapAlloc(hHeap,
  1215. dwFlags,
  1216. dwOutBufLen);
  1217. if(*ppNetTable is NULL)
  1218. {
  1219. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  1220. Trace1(ERR,
  1221. "AllocateAndGetIpNetTableFromStack: Couldnt allocate memory. Error %d",
  1222. dwResult);
  1223. TraceLeave("AllocateAndGetIpNetTableFromStack");
  1224. return dwResult;
  1225. }
  1226. if(dwNetEntryCount is 0)
  1227. {
  1228. (*ppNetTable)->dwNumEntries = 0;
  1229. TraceLeave("AllocateAndGetIpNetTableFromStack");
  1230. return NO_ERROR;
  1231. }
  1232. dwResult = GetIpNetTableFromStack(*ppNetTable,
  1233. dwOutBufLen,
  1234. bOrder,
  1235. bForceUpdate);
  1236. if(dwResult isnot NO_ERROR)
  1237. {
  1238. Trace1(ERR,
  1239. "AllocateAndGetIpNetTableFromStack: Error %d GetIpNetTableFromStack",
  1240. dwResult);
  1241. HeapFree(hHeap, dwFlags, *ppNetTable);
  1242. *ppNetTable = NULL;
  1243. }
  1244. TraceLeave("AllocateAndGetIpNetTableFromStack");
  1245. return dwResult;
  1246. }
  1247. // ========================================================================
  1248. DWORD
  1249. GetIpNetTableFromStack(
  1250. OUT PMIB_IPNETTABLE pNetTable,
  1251. IN DWORD dwSize,
  1252. IN BOOL bOrder,
  1253. IN BOOL bForceUpdate
  1254. )
  1255. {
  1256. TDIObjectID *ID;
  1257. PBYTE pbyEnd, pbyStart, Context;
  1258. DWORD dwNumAdded,dwValidNetEntries;
  1259. DWORD dwInBufLen,dwOutBufLen;
  1260. DWORD dwResult, dwErr, i;
  1261. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  1262. CheckTcpipState();
  1263. if (!g_bIpConfigured)
  1264. {
  1265. return ERROR_NOT_SUPPORTED;
  1266. }
  1267. dwValidNetEntries = 0;
  1268. dwErr = NO_ERROR;
  1269. //
  1270. // Now query the stack for the IpNet tables of each of the arp entities
  1271. //
  1272. Context = (BYTE *) &(trqiInBuf.Context[0]);
  1273. ZeroMemory( Context, CONTEXT_SIZE );
  1274. ID = &(trqiInBuf.ID);
  1275. ID->toi_entity.tei_entity = AT_ENTITY;
  1276. ID->toi_type = INFO_TYPE_PROVIDER;
  1277. ID->toi_class = INFO_CLASS_PROTOCOL;
  1278. ID->toi_id = AT_MIB_ADDRXLAT_ENTRY_ID;
  1279. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  1280. pbyStart = (PBYTE)(pNetTable->table);
  1281. pbyEnd = (PBYTE)((PBYTE)pNetTable + dwSize);
  1282. EnterCriticalSection(&g_ipNetLock);
  1283. if(bForceUpdate or
  1284. (g_dwLastArpUpdateTime is 0) or
  1285. ((GetCurrentTime() - g_dwLastArpUpdateTime) > ARP_CACHE_LIFE))
  1286. {
  1287. dwResult = UpdateAdapterToATInstanceMapping();
  1288. if(dwResult isnot NO_ERROR)
  1289. {
  1290. LeaveCriticalSection(&g_ipNetLock);
  1291. Trace1(ERR,
  1292. "GetIpNetTableFromStack: Couldnt update AT Map. Error %d",
  1293. dwResult);
  1294. TraceLeave("GetIpNetTableFromStack");
  1295. return ERROR_CAN_NOT_COMPLETE;
  1296. }
  1297. }
  1298. for(i = 0; i < g_dwNumArpEntEntries; i++ )
  1299. {
  1300. //
  1301. // If the current buffer wont hold even one row, stop
  1302. //
  1303. dwOutBufLen = (DWORD)(pbyEnd - pbyStart);
  1304. if(dwOutBufLen < sizeof(MIB_IPNETROW))
  1305. {
  1306. dwErr = ERROR_MORE_DATA;
  1307. break;
  1308. }
  1309. ID->toi_entity.tei_instance = g_pdwArpEntTable[i];
  1310. ZeroMemory(Context, CONTEXT_SIZE);
  1311. dwResult = TCPQueryInformationEx(AF_INET,
  1312. &trqiInBuf,
  1313. &dwInBufLen,
  1314. (PVOID)pbyStart,
  1315. &dwOutBufLen);
  1316. if (dwResult isnot NO_ERROR)
  1317. {
  1318. Trace1(ERR,"Query to Arp Entity id %d for ARP Table failed. Error %d",
  1319. dwResult);
  1320. dwErr = ERROR_MORE_DATA;
  1321. continue;
  1322. }
  1323. dwNumAdded = dwOutBufLen/(sizeof(MIB_IPNETROW));
  1324. pbyStart += dwOutBufLen;
  1325. dwValidNetEntries += dwNumAdded;
  1326. }
  1327. pNetTable->dwNumEntries = dwValidNetEntries;
  1328. //
  1329. // Now sort the net table. Keys are IF index and address
  1330. //
  1331. if((dwValidNetEntries > 0) and bOrder)
  1332. {
  1333. qsort(pNetTable->table,
  1334. dwValidNetEntries,
  1335. sizeof(MIB_IPNETROW),
  1336. CompareIpNetRow);
  1337. }
  1338. LeaveCriticalSection(&g_ipNetLock);
  1339. TraceLeave("GetIpNetTableFromStack");
  1340. return dwErr;
  1341. }
  1342. // ========================================================================
  1343. DWORD
  1344. GetIpStatsFromStackEx(
  1345. OUT PMIB_IPSTATS pIpStats,
  1346. IN DWORD dwFamily
  1347. )
  1348. {
  1349. DWORD dwResult, dwInBufLen, dwOutBufLen;
  1350. TDIObjectID *ID;
  1351. BYTE *Context;
  1352. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  1353. TraceEnter("GetIpStatsFromStackEx");
  1354. if ((dwFamily != AF_INET) && (dwFamily != AF_INET6))
  1355. {
  1356. return ERROR_INVALID_PARAMETER;
  1357. }
  1358. CheckTcpipState();
  1359. if (((dwFamily == AF_INET) && !g_bIpConfigured) ||
  1360. ((dwFamily == AF_INET6) && !g_bIp6Configured))
  1361. {
  1362. return ERROR_NOT_SUPPORTED;
  1363. }
  1364. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  1365. dwOutBufLen = sizeof(MIB_IPSTATS);
  1366. ID = &(trqiInBuf.ID);
  1367. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  1368. ID->toi_entity.tei_instance = 0;
  1369. ID->toi_class = INFO_CLASS_PROTOCOL;
  1370. ID->toi_type = INFO_TYPE_PROVIDER;
  1371. ID->toi_id = IP_MIB_STATS_ID;
  1372. Context = (BYTE *) &(trqiInBuf.Context[0]);
  1373. ZeroMemory(Context, CONTEXT_SIZE);
  1374. dwResult = TCPQueryInformationEx(dwFamily,
  1375. &trqiInBuf,
  1376. &dwInBufLen,
  1377. (PVOID)pIpStats,
  1378. &dwOutBufLen);
  1379. if (dwResult isnot NO_ERROR)
  1380. {
  1381. Trace1(ERR,"Couldnt query stack. Error %d",
  1382. dwResult);
  1383. TraceLeave("GetIpStatsFromStackEx");
  1384. return dwResult;
  1385. }
  1386. TraceLeave("GetIpStatsFromStackEx");
  1387. return NO_ERROR;
  1388. }
  1389. // ========================================================================
  1390. DWORD
  1391. GetIpStatsFromStack(
  1392. OUT PMIB_IPSTATS pIpStats
  1393. )
  1394. {
  1395. return GetIpStatsFromStackEx(pIpStats, AF_INET);
  1396. }
  1397. // ========================================================================
  1398. DWORD
  1399. SetIpStatsToStack(
  1400. IN PMIB_IPSTATS pIpStats
  1401. )
  1402. {
  1403. TCP_REQUEST_SET_INFORMATION_EX *ptrsiInBuf;
  1404. TDIObjectID *ID;
  1405. MIB_IPSTATS *copyInfo;
  1406. DWORD dwInBufLen,dwOutBufLen,dwResult;
  1407. #define REQ_SIZE sizeof(TCP_REQUEST_SET_INFORMATION_EX) + \
  1408. sizeof(MIB_IPSTATS) - 1
  1409. BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
  1410. ptrsiInBuf = (TCP_REQUEST_SET_INFORMATION_EX *)rgbyBuffer;
  1411. dwInBufLen = REQ_SIZE;
  1412. #undef REQ_SIZE
  1413. TraceEnter("SetIpStatsToStack");
  1414. CheckTcpipState();
  1415. if (!g_bIpConfigured)
  1416. {
  1417. return ERROR_NOT_SUPPORTED;
  1418. }
  1419. ID = &ptrsiInBuf->ID;
  1420. ID->toi_class = INFO_CLASS_PROTOCOL;
  1421. ID->toi_type = INFO_TYPE_PROVIDER;
  1422. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  1423. ID->toi_id = IP_MIB_STATS_ID;
  1424. ID->toi_entity.tei_instance = 0;
  1425. copyInfo = (MIB_IPSTATS*)ptrsiInBuf->Buffer;
  1426. *copyInfo = *pIpStats;
  1427. ptrsiInBuf->BufferSize = sizeof(IPSNMPInfo);
  1428. dwResult = TCPSetInformationEx((PVOID)ptrsiInBuf,
  1429. &dwInBufLen,
  1430. NULL,
  1431. &dwOutBufLen);
  1432. TraceLeave("SetIpStatsToStack");
  1433. return dwResult;
  1434. }
  1435. // ========================================================================
  1436. DWORD
  1437. GetIcmpStatsFromStackEx(
  1438. OUT PVOID pIcmpStats,
  1439. IN DWORD dwFamily
  1440. )
  1441. {
  1442. DWORD dwResult;
  1443. DWORD dwInBufLen;
  1444. DWORD dwOutBufLen;
  1445. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  1446. TDIObjectID *ID;
  1447. BYTE *Context;
  1448. TraceEnter("GetIcmpStatsFromStackEx");
  1449. if ((dwFamily != AF_INET) && (dwFamily != AF_INET6))
  1450. {
  1451. return ERROR_INVALID_PARAMETER;
  1452. }
  1453. CheckTcpipState();
  1454. if (((dwFamily == AF_INET) && !g_bIpConfigured) ||
  1455. ((dwFamily == AF_INET6) && !g_bIp6Configured))
  1456. {
  1457. return ERROR_NOT_SUPPORTED;
  1458. }
  1459. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  1460. ID = &(trqiInBuf.ID);
  1461. ID->toi_entity.tei_instance = 0;
  1462. ID->toi_class = INFO_CLASS_PROTOCOL;
  1463. ID->toi_type = INFO_TYPE_PROVIDER;
  1464. if (dwFamily == AF_INET)
  1465. {
  1466. ID->toi_entity.tei_entity = ER_ENTITY;
  1467. ID->toi_id = ICMP_MIB_STATS_ID;
  1468. dwOutBufLen = sizeof(MIB_ICMP);
  1469. }
  1470. else
  1471. {
  1472. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  1473. ID->toi_id = ICMP6_MIB_STATS_ID;
  1474. dwOutBufLen = sizeof(ICMPv6SNMPInfo);
  1475. }
  1476. Context = (BYTE *) &(trqiInBuf.Context[0]);
  1477. ZeroMemory(Context,CONTEXT_SIZE);
  1478. dwResult = TCPQueryInformationEx(dwFamily,
  1479. &trqiInBuf,
  1480. &dwInBufLen,
  1481. (PVOID)pIcmpStats,
  1482. &dwOutBufLen);
  1483. if (dwResult isnot NO_ERROR)
  1484. {
  1485. Trace1(ERR,"Couldnt query stack. Error %x",
  1486. dwResult);
  1487. TraceLeave("GetIcmpStatsFromStackEx");
  1488. return dwResult;
  1489. }
  1490. TraceLeave("GetIcmpStatsFromStackEx");
  1491. return NO_ERROR;
  1492. }
  1493. // ========================================================================
  1494. DWORD
  1495. GetIcmpStatsFromStack(
  1496. OUT PMIB_ICMP pIcmpStats
  1497. )
  1498. {
  1499. return GetIcmpStatsFromStackEx(pIcmpStats, AF_INET);
  1500. }
  1501. // ========================================================================
  1502. DWORD
  1503. GetUdpStatsFromStackEx(
  1504. OUT PMIB_UDPSTATS pUdpStats,
  1505. IN DWORD dwFamily
  1506. )
  1507. {
  1508. DWORD dwResult;
  1509. DWORD dwInBufLen;
  1510. DWORD dwOutBufLen;
  1511. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  1512. TDIObjectID *ID;
  1513. BYTE *Context;
  1514. TraceEnter("GetUdpStatsFromStack");
  1515. if ((dwFamily != AF_INET) && (dwFamily != AF_INET6))
  1516. {
  1517. return ERROR_INVALID_PARAMETER;
  1518. }
  1519. CheckTcpipState();
  1520. if (((dwFamily == AF_INET) && !g_bIpConfigured) ||
  1521. ((dwFamily == AF_INET6) && !g_bIp6Configured))
  1522. {
  1523. return ERROR_NOT_SUPPORTED;
  1524. }
  1525. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  1526. dwOutBufLen = sizeof(MIB_UDPSTATS);
  1527. ID = &(trqiInBuf.ID);
  1528. ID->toi_entity.tei_entity = CL_TL_ENTITY;
  1529. ID->toi_entity.tei_instance = 0;
  1530. ID->toi_class = INFO_CLASS_PROTOCOL;
  1531. ID->toi_type = INFO_TYPE_PROVIDER;
  1532. ID->toi_id = UDP_MIB_STAT_ID;
  1533. Context = (BYTE *) &(trqiInBuf.Context[0]);
  1534. ZeroMemory( Context, CONTEXT_SIZE );
  1535. dwResult = TCPQueryInformationEx(dwFamily,
  1536. &trqiInBuf,
  1537. &dwInBufLen,
  1538. (PVOID)pUdpStats,
  1539. &dwOutBufLen );
  1540. if(dwResult isnot NO_ERROR)
  1541. {
  1542. Trace1(ERR,"Couldnt query stack. Error %x",
  1543. dwResult);
  1544. TraceLeave("GetUdpStatsFromStack");
  1545. return dwResult;
  1546. }
  1547. TraceLeave("GetUdpStatsFromStack");
  1548. return NO_ERROR;
  1549. }
  1550. // ========================================================================
  1551. DWORD
  1552. GetUdpStatsFromStack(
  1553. OUT PMIB_UDPSTATS pUdpStats
  1554. )
  1555. {
  1556. return GetUdpStatsFromStackEx(pUdpStats, AF_INET);
  1557. }
  1558. // ========================================================================
  1559. DWORD
  1560. GetTcpStatsFromStackEx(
  1561. OUT PMIB_TCPSTATS pTcpStats,
  1562. IN DWORD dwFamily
  1563. )
  1564. {
  1565. DWORD dwResult;
  1566. DWORD dwInBufLen;
  1567. DWORD dwOutBufLen;
  1568. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  1569. TDIObjectID *ID;
  1570. BYTE *Context;
  1571. TraceEnter("GetTcpStatsFromStack");
  1572. if ((dwFamily != AF_INET) && (dwFamily != AF_INET6))
  1573. {
  1574. return ERROR_INVALID_PARAMETER;
  1575. }
  1576. CheckTcpipState();
  1577. if (((dwFamily == AF_INET) && !g_bIpConfigured) ||
  1578. ((dwFamily == AF_INET6) && !g_bIp6Configured))
  1579. {
  1580. return ERROR_NOT_SUPPORTED;
  1581. }
  1582. dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX );
  1583. dwOutBufLen = sizeof( MIB_TCPSTATS );
  1584. ID = &(trqiInBuf.ID);
  1585. ID->toi_entity.tei_entity = CO_TL_ENTITY;
  1586. ID->toi_entity.tei_instance = 0;
  1587. ID->toi_class = INFO_CLASS_PROTOCOL;
  1588. ID->toi_type = INFO_TYPE_PROVIDER;
  1589. ID->toi_id = TCP_MIB_STAT_ID;
  1590. Context = (BYTE *) &(trqiInBuf.Context[0]);
  1591. ZeroMemory(Context,CONTEXT_SIZE);
  1592. dwResult = TCPQueryInformationEx(dwFamily,
  1593. &trqiInBuf,
  1594. &dwInBufLen,
  1595. (PVOID)pTcpStats,
  1596. &dwOutBufLen );
  1597. if(dwResult isnot NO_ERROR)
  1598. {
  1599. Trace1(ERR,"Couldnt query stack. Error %x",
  1600. dwResult);
  1601. TraceLeave("GetTcpStatsFromStack");
  1602. return dwResult;
  1603. }
  1604. TraceLeave("GetTcpStatsFromStack");
  1605. return NO_ERROR;
  1606. }
  1607. // ========================================================================
  1608. DWORD
  1609. GetTcpStatsFromStack(
  1610. OUT PMIB_TCPSTATS pTcpStats
  1611. )
  1612. {
  1613. return GetTcpStatsFromStackEx(pTcpStats, AF_INET);
  1614. }
  1615. // ========================================================================
  1616. DWORD
  1617. SetIpNetEntryToStack(
  1618. IN MIB_IPNETROW *pNetRow,
  1619. IN BOOL bForceUpdate
  1620. )
  1621. {
  1622. TCP_REQUEST_SET_INFORMATION_EX *ptrsiInBuf;
  1623. TDIObjectID *ID;
  1624. MIB_IPNETROW *copyInfo;
  1625. DWORD dwInBufLen,dwOutBufLen,dwResult;
  1626. DWORD dwInstance;
  1627. #define REQ_SIZE sizeof(TCP_REQUEST_SET_INFORMATION_EX) + \
  1628. sizeof(MIB_IPNETROW) - 1
  1629. BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
  1630. ptrsiInBuf = (TCP_REQUEST_SET_INFORMATION_EX *)rgbyBuffer;
  1631. dwInBufLen = REQ_SIZE;
  1632. #undef REQ_SIZE
  1633. TraceEnter("SetIpNetEntryToStack");
  1634. CheckTcpipState();
  1635. if (!g_bIpConfigured)
  1636. {
  1637. return ERROR_NOT_SUPPORTED;
  1638. }
  1639. EnterCriticalSection(&g_ipNetLock);
  1640. if(bForceUpdate or
  1641. (g_dwLastArpUpdateTime is 0) or
  1642. ((GetCurrentTime() - g_dwLastArpUpdateTime) < ARP_CACHE_LIFE))
  1643. {
  1644. dwResult = UpdateAdapterToATInstanceMapping();
  1645. if(dwResult isnot NO_ERROR)
  1646. {
  1647. LeaveCriticalSection(&g_ipNetLock);
  1648. Trace1(ERR,"Couldnt update AT Map. Error %d",dwResult);
  1649. TraceLeave("SetIpNetEntryToStack");
  1650. return ERROR_CAN_NOT_COMPLETE;
  1651. }
  1652. }
  1653. dwInstance = GetATInstanceFromAdapter(pNetRow->dwIndex);
  1654. if(dwInstance is INVALID_AT_INSTANCE)
  1655. {
  1656. dwResult = UpdateAdapterToATInstanceMapping();
  1657. if(dwResult isnot NO_ERROR)
  1658. {
  1659. LeaveCriticalSection(&g_ipNetLock);
  1660. Trace1(ERR,"Couldnt update AT Map. Error %d",dwResult);
  1661. return ERROR_CAN_NOT_COMPLETE;
  1662. }
  1663. }
  1664. LeaveCriticalSection(&g_ipNetLock);
  1665. ID = &ptrsiInBuf->ID;
  1666. ID->toi_class = INFO_CLASS_PROTOCOL;
  1667. ID->toi_entity.tei_entity = AT_ENTITY;
  1668. ID->toi_type = INFO_TYPE_PROVIDER;
  1669. ID->toi_id = AT_MIB_ADDRXLAT_ENTRY_ID;
  1670. ID->toi_entity.tei_instance = dwInstance;
  1671. //
  1672. // Since MIB_IPNETROW is a fixed size structure
  1673. //
  1674. copyInfo = (MIB_IPNETROW*)ptrsiInBuf->Buffer;
  1675. *copyInfo = *pNetRow;
  1676. dwOutBufLen = 0;
  1677. ptrsiInBuf->BufferSize = sizeof(IPNetToMediaEntry);
  1678. dwResult = TCPSetInformationEx((PVOID)ptrsiInBuf,
  1679. &dwInBufLen,
  1680. NULL,
  1681. &dwOutBufLen);
  1682. TraceLeave("SetIpNetEntryToStack");
  1683. return dwResult;
  1684. }
  1685. DWORD
  1686. FlushIpNetTableFromStack(
  1687. IN DWORD dwIfIndex
  1688. )
  1689. {
  1690. #ifdef _WIN95_
  1691. return ERROR_NOT_SUPPORTED;
  1692. #else
  1693. DWORD status;
  1694. DWORD requestBufferSize = sizeof(DWORD);
  1695. DWORD OutBufLen= 0;
  1696. CheckTcpipState();
  1697. if (!g_bIpConfigured)
  1698. {
  1699. return ERROR_NOT_SUPPORTED;
  1700. }
  1701. status = TCPSendIoctl(g_hIPDriverHandle,
  1702. IOCTL_IP_FLUSH_ARP_TABLE,
  1703. &dwIfIndex,
  1704. &requestBufferSize,
  1705. NULL,
  1706. &OutBufLen);
  1707. #endif
  1708. return(status);
  1709. }
  1710. DWORD
  1711. SetProxyArpEntryToStack(
  1712. DWORD dwAddress,
  1713. DWORD dwMask,
  1714. DWORD dwAdapterIndex,
  1715. BOOL bAddEntry,
  1716. BOOL bForceUpdate
  1717. )
  1718. {
  1719. DWORD dwResult, dwATInstance, dwInBufLen, dwOutBufLen;
  1720. ProxyArpEntry *pEntry;
  1721. TDIObjectID *pID;
  1722. PTCP_REQUEST_SET_INFORMATION_EX ptrsiInBuf;
  1723. #define REQ_SIZE sizeof(TCP_REQUEST_SET_INFORMATION_EX) + \
  1724. sizeof(ProxyArpEntry) - 1
  1725. BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
  1726. ptrsiInBuf = (TCP_REQUEST_SET_INFORMATION_EX *)rgbyBuffer;
  1727. dwInBufLen = REQ_SIZE;
  1728. #undef REQ_SIZE
  1729. TraceEnter("SetProxyArpEntryToStack");
  1730. CheckTcpipState();
  1731. if (!g_bIpConfigured)
  1732. {
  1733. return ERROR_NOT_SUPPORTED;
  1734. }
  1735. EnterCriticalSection(&g_ipNetLock);
  1736. if(bForceUpdate or
  1737. (g_dwLastArpUpdateTime is 0) or
  1738. ((GetCurrentTime() - g_dwLastArpUpdateTime) < ARP_CACHE_LIFE))
  1739. {
  1740. dwResult = UpdateAdapterToATInstanceMapping();
  1741. if(dwResult isnot NO_ERROR)
  1742. {
  1743. LeaveCriticalSection(&g_ipNetLock);
  1744. Trace1(ERR,"Couldnt update AT Map. Error %d",dwResult);
  1745. TraceLeave("SetProxyArpEntryToStack");
  1746. return ERROR_CAN_NOT_COMPLETE;
  1747. }
  1748. }
  1749. dwATInstance = GetATInstanceFromAdapter(dwAdapterIndex);
  1750. if(dwATInstance is INVALID_IF_INSTANCE)
  1751. {
  1752. LeaveCriticalSection(&g_ipNetLock);
  1753. Trace1(ERR,
  1754. "SetProxyArpEntryToStacki: Couldnt get AT instance for %d",
  1755. dwAdapterIndex);
  1756. TraceLeave("SetProxyArpEntryToStack");
  1757. return ERROR_INVALID_PARAMETER;
  1758. }
  1759. LeaveCriticalSection(&g_ipNetLock);
  1760. pID = &ptrsiInBuf->ID;
  1761. pID->toi_entity.tei_entity = AT_ENTITY;
  1762. pID->toi_entity.tei_instance = dwATInstance;
  1763. pID->toi_type = INFO_TYPE_PROVIDER;
  1764. pID->toi_class = INFO_CLASS_IMPLEMENTATION;
  1765. pID->toi_id = AT_ARP_PARP_ENTRY_ID;
  1766. //
  1767. // Fill in the set entry, and pass it down.
  1768. //
  1769. pEntry = (ProxyArpEntry *)ptrsiInBuf->Buffer;
  1770. pEntry->pae_status = (bAddEntry ? PAE_STATUS_VALID : PAE_STATUS_INVALID);
  1771. pEntry->pae_addr = dwAddress;
  1772. pEntry->pae_mask = dwMask;
  1773. ptrsiInBuf->BufferSize = sizeof(ProxyArpEntry);
  1774. dwOutBufLen = 0;
  1775. dwResult = TCPSetInformationEx((PVOID)ptrsiInBuf,
  1776. &dwInBufLen,
  1777. NULL,
  1778. &dwOutBufLen);
  1779. TraceLeave("SetProxyArpEntryToStack");
  1780. return dwResult;
  1781. }
  1782. // ========================================================================
  1783. DWORD
  1784. GetArpEntryCount(
  1785. OUT PDWORD pdwNumEntries
  1786. )
  1787. {
  1788. DWORD dwResult, i;
  1789. DWORD dwInBufLen, dwOutBufLen;
  1790. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  1791. TDIObjectID *ID;
  1792. UCHAR *Context;
  1793. AddrXlatInfo AXI;
  1794. *pdwNumEntries = 0;
  1795. Context = (BYTE *) &(trqiInBuf.Context[0]);
  1796. ZeroMemory( Context, CONTEXT_SIZE );
  1797. ID = &(trqiInBuf.ID);
  1798. ID->toi_entity.tei_entity = AT_ENTITY;
  1799. ID->toi_type = INFO_TYPE_PROVIDER;
  1800. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  1801. for (i = 0; i < g_dwNumArpEntEntries; i++ )
  1802. {
  1803. //
  1804. // First add up the AXI counts
  1805. //
  1806. ID->toi_class = INFO_CLASS_PROTOCOL;
  1807. ID->toi_id = AT_MIB_ADDRXLAT_INFO_ID;
  1808. ID->toi_entity.tei_instance = g_pdwArpEntTable[i];
  1809. dwOutBufLen = sizeof(AXI);
  1810. ZeroMemory(Context, CONTEXT_SIZE);
  1811. dwResult = TCPQueryInformationEx(AF_INET,
  1812. &trqiInBuf,
  1813. &dwInBufLen,
  1814. &AXI,
  1815. &dwOutBufLen);
  1816. if (dwResult == ERROR_INVALID_FUNCTION)
  1817. {
  1818. Trace0(ERR, "GetArpEntryCount: ERROR_INVALID_FUNCTION, axi_count = 0");
  1819. AXI.axi_count = 0;
  1820. }
  1821. else if(dwResult isnot NO_ERROR)
  1822. {
  1823. Trace1(ERR,"GetArpEntryCount: Couldnt query Information from stack. Error %x",
  1824. dwResult);
  1825. return dwResult;
  1826. }
  1827. //
  1828. // Increment the total number of entries
  1829. //
  1830. *pdwNumEntries += AXI.axi_count;
  1831. }
  1832. return NO_ERROR;
  1833. }
  1834. // ========================================================================
  1835. DWORD
  1836. AllocateAndGetArpEntTableFromStack(
  1837. OUT PDWORD *ppdwArpEntTable,
  1838. OUT PDWORD pdwNumEntries,
  1839. IN HANDLE hHeap,
  1840. IN DWORD dwAllocFlags,
  1841. IN DWORD dwReAllocFlags
  1842. )
  1843. {
  1844. DWORD dwResult;
  1845. DWORD dwInBufLen;
  1846. DWORD dwOutBufLen;
  1847. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  1848. DWORD dwATType;
  1849. UCHAR *Context;
  1850. TDIObjectID *ID;
  1851. TDIEntityID *pEntTable;
  1852. DWORD dwNumEntities,dwCurrEntries;
  1853. DWORD i,dwCount ;
  1854. TraceEnter("GetArpEntTableFromStack");
  1855. CheckTcpipState();
  1856. if (!g_bIpConfigured)
  1857. {
  1858. return ERROR_NOT_SUPPORTED;
  1859. }
  1860. *ppdwArpEntTable = NULL;
  1861. *pdwNumEntries = 0;
  1862. pEntTable = GetTdiEntityCount(&dwNumEntities);
  1863. if (!pEntTable)
  1864. {
  1865. return ERROR_NOT_ENOUGH_MEMORY;
  1866. }
  1867. //
  1868. // Create a table that will hold 16 entries
  1869. //
  1870. dwCurrEntries = 16;
  1871. *ppdwArpEntTable = HeapAlloc(hHeap,
  1872. dwAllocFlags,
  1873. dwCurrEntries*sizeof(DWORD));
  1874. if(*ppdwArpEntTable is NULL)
  1875. {
  1876. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  1877. Trace1(ERR,"GetArpEntTableFromStack: Couldnt allocate memory. Error %d",
  1878. dwResult);
  1879. HeapFree(g_hPrivateHeap,0,pEntTable);
  1880. return dwResult;
  1881. }
  1882. dwCount = 0;
  1883. Trace1(ERR, "Numberofentities %d \n", dwNumEntities);
  1884. for(i = 0; i < dwNumEntities; i++)
  1885. {
  1886. //
  1887. // See which ones are AT
  1888. //
  1889. if(pEntTable[i].tei_entity is AT_ENTITY)
  1890. {
  1891. //
  1892. // Query the entity to see if it supports ARP
  1893. //
  1894. ID = &(trqiInBuf.ID);
  1895. ID->toi_entity.tei_entity = AT_ENTITY;
  1896. ID->toi_class = INFO_CLASS_GENERIC;
  1897. ID->toi_type = INFO_TYPE_PROVIDER;
  1898. ID->toi_id = ENTITY_TYPE_ID;
  1899. ID->toi_entity.tei_instance = pEntTable[i].tei_instance;
  1900. Trace1(ERR,
  1901. "Querying for instance %d \n", pEntTable[i].tei_instance);
  1902. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  1903. dwOutBufLen = sizeof(dwATType);
  1904. Context = (BYTE *) &(trqiInBuf.Context[0]);
  1905. ZeroMemory(Context,CONTEXT_SIZE);
  1906. dwResult = TCPQueryInformationEx(AF_INET,
  1907. &trqiInBuf,
  1908. &dwInBufLen,
  1909. (PVOID)&dwATType,
  1910. &dwOutBufLen );
  1911. if(dwResult is ERROR_INVALID_FUNCTION)
  1912. {
  1913. //
  1914. // Doesnt support ARP
  1915. //
  1916. continue;
  1917. }
  1918. if(dwResult isnot NO_ERROR)
  1919. {
  1920. Trace1(ERR,"GetArpEntTableFromStack: Couldnt query information. Error %x",
  1921. dwResult);
  1922. HeapFree(hHeap,0,*ppdwArpEntTable);
  1923. HeapFree(g_hPrivateHeap,0,pEntTable);
  1924. return dwResult;
  1925. }
  1926. if(dwATType is AT_ARP)
  1927. {
  1928. //
  1929. // The entity is an AT_ENTITY that supports ARP. Add the instance
  1930. // to the arp entity table. If the current count >= current size of
  1931. // table, means we have run out of space, so reallocate and get double
  1932. // the space
  1933. //
  1934. if(dwCount is dwCurrEntries)
  1935. {
  1936. PDWORD pdwNewTable;
  1937. pdwNewTable = HeapReAlloc(hHeap,
  1938. dwReAllocFlags,
  1939. (PVOID)*ppdwArpEntTable,
  1940. ((dwCurrEntries)<<1)*sizeof(DWORD));
  1941. if(pdwNewTable is NULL)
  1942. {
  1943. dwResult = GetLastError();
  1944. Trace1(ERR,"GetArpEntTableFromStack: Couldnt reallocate memory. Error %d",
  1945. dwResult);
  1946. HeapFree(hHeap,0,*ppdwArpEntTable);
  1947. HeapFree(g_hPrivateHeap,0,pEntTable);
  1948. return dwResult;
  1949. }
  1950. *ppdwArpEntTable = pdwNewTable;
  1951. dwCurrEntries = dwCurrEntries<<1;
  1952. }
  1953. (*ppdwArpEntTable)[dwCount] = pEntTable[i].tei_instance;
  1954. dwCount++;
  1955. }
  1956. }
  1957. }
  1958. HeapFree(g_hPrivateHeap,0,pEntTable);
  1959. *pdwNumEntries = dwCount;
  1960. return NO_ERROR;
  1961. }
  1962. // ========================================================================
  1963. DWORD
  1964. SetIpForwardEntryToStack(
  1965. IN PMIB_IPFORWARDROW pForwardRow
  1966. )
  1967. {
  1968. IPRouteEntry route;
  1969. CheckTcpipState();
  1970. if (!g_bIpConfigured)
  1971. {
  1972. return ERROR_NOT_SUPPORTED;
  1973. }
  1974. ConvertForwardToRoute((&route),pForwardRow);
  1975. return SetIpRouteEntryToStack(&route);
  1976. }
  1977. // ========================================================================
  1978. DWORD
  1979. SetIpRouteEntryToStack(
  1980. IN IPRouteEntry *pRoute
  1981. )
  1982. {
  1983. TDIObjectID *pObject;
  1984. DWORD dwOutBufLen, dwInBufLen, dwResult;
  1985. TCP_REQUEST_SET_INFORMATION_EX *ptrsiBuffer;
  1986. IPRouteEntry *copyInfo;
  1987. #define REQ_SIZE sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(IPRouteEntry) - 1
  1988. BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
  1989. ptrsiBuffer = (TCP_REQUEST_SET_INFORMATION_EX *)rgbyBuffer;
  1990. dwInBufLen = REQ_SIZE;
  1991. #undef REQ_SIZE
  1992. CheckTcpipState();
  1993. if (!g_bIpConfigured)
  1994. {
  1995. return ERROR_NOT_SUPPORTED;
  1996. }
  1997. ptrsiBuffer->BufferSize = sizeof(IPRouteEntry);
  1998. pObject = &ptrsiBuffer->ID;
  1999. pObject->toi_id = IP_MIB_RTTABLE_ENTRY_ID;
  2000. pObject->toi_type = INFO_TYPE_PROVIDER;
  2001. pObject->toi_class = INFO_CLASS_PROTOCOL;
  2002. pObject->toi_entity.tei_entity = CL_NL_ENTITY;
  2003. pObject->toi_entity.tei_instance = 0;
  2004. dwOutBufLen = 0;
  2005. copyInfo = (IPRouteEntry *)ptrsiBuffer->Buffer;
  2006. *copyInfo = *pRoute;
  2007. dwResult = TCPSetInformationEx((PVOID)ptrsiBuffer,
  2008. &dwInBufLen,
  2009. NULL,
  2010. &dwOutBufLen);
  2011. return dwResult;
  2012. }
  2013. DWORD
  2014. SetIpMultihopRouteEntryToStack(
  2015. IN IPMultihopRouteEntry *RouteEntry
  2016. )
  2017. {
  2018. ULONG inpbuflen;
  2019. ULONG outbuflen;
  2020. CheckTcpipState();
  2021. if (!g_bIpConfigured)
  2022. {
  2023. return ERROR_NOT_SUPPORTED;
  2024. }
  2025. inpbuflen = sizeof(IPMultihopRouteEntry);
  2026. if (RouteEntry->imre_numnexthops > 2)
  2027. {
  2028. inpbuflen += (RouteEntry->imre_numnexthops - 2) *
  2029. sizeof(IPRouteNextHopEntry);
  2030. }
  2031. if (IsBadReadPtr(RouteEntry, inpbuflen)) {
  2032. return ERROR_INVALID_PARAMETER;
  2033. }
  2034. return (TCPSendIoctl(
  2035. g_hIPDriverHandle,
  2036. IOCTL_IP_SET_MULTIHOPROUTE,
  2037. RouteEntry,
  2038. &inpbuflen,
  2039. NULL,
  2040. &outbuflen
  2041. ));
  2042. }
  2043. DWORD
  2044. GetBestInterfaceFromStack(
  2045. DWORD dwDestAddress,
  2046. PDWORD pdwBestIfIndex
  2047. )
  2048. {
  2049. #ifdef _WIN95_
  2050. return ERROR_NOT_SUPPORTED;
  2051. #else
  2052. DWORD status;
  2053. DWORD requestBufferSize = sizeof(DWORD);
  2054. DWORD OutBufLen= sizeof(DWORD);
  2055. CheckTcpipState();
  2056. if (!g_bIpConfigured)
  2057. {
  2058. return ERROR_NOT_SUPPORTED;
  2059. }
  2060. status = TCPSendIoctl(g_hIPGetDriverHandle,
  2061. IOCTL_IP_GET_BEST_INTERFACE,
  2062. &dwDestAddress,
  2063. &requestBufferSize,
  2064. pdwBestIfIndex,
  2065. &OutBufLen);
  2066. return(status);
  2067. #endif
  2068. }
  2069. // ========================================================================
  2070. //* TCPQueryInformationEx
  2071. //
  2072. // Description: Get information from the stack.
  2073. //
  2074. // Parameters: HANDLE hHandle: handle to the stack.
  2075. // TDIObjectID *ID: pointer to TDIObjectID info.
  2076. // void *Buffer: buffer to receive data from the stack.
  2077. // ulong *Bufferlen: IN: tells stack size of available buffer,
  2078. // OUT: tells us how much data is available.
  2079. // CONTEXT *Context: allows queries spanning more than one call.
  2080. //
  2081. // Returns: int:
  2082. //
  2083. //*
  2084. int
  2085. TCPQueryInformationEx(
  2086. DWORD Family,
  2087. void *InBuf,
  2088. ulong *InBufLen,
  2089. void *OutBuf,
  2090. ulong *OutBufLen
  2091. )
  2092. {
  2093. #ifdef CHICAGO
  2094. //
  2095. // This section is obsolete code
  2096. //
  2097. DWORD result;
  2098. if( ! pWsControl ) {
  2099. OpenTCPDriver(AF_INET);
  2100. }
  2101. if( ! pWsControl || (Family != AF_INET)) {
  2102. DEBUG_PRINT(("TCPQueryInformationEx: !pWsControl.\n"));
  2103. return ERROR_NOT_SUPPORTED;
  2104. }
  2105. assert( pWsControl );
  2106. result = (
  2107. (*pWsControl)(
  2108. IPPROTO_TCP,
  2109. WSCNTL_TCPIP_QUERY_INFO,
  2110. InBuf,
  2111. InBufLen ,
  2112. OutBuf,
  2113. OutBufLen
  2114. ) );
  2115. if( result ){
  2116. return ConvertTdiErrorToDosError(result);
  2117. }
  2118. return NO_ERROR;
  2119. #else
  2120. NTSTATUS Status;
  2121. IO_STATUS_BLOCK IoStatusBlock;
  2122. HANDLE hEvent;
  2123. HANDLE hDriver = (Family == AF_INET)? g_hTCPDriverGetHandle :
  2124. g_hTCP6DriverGetHandle;
  2125. hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
  2126. if( NULL == hEvent ) return GetLastError();
  2127. Status = NtDeviceIoControlFile(hDriver,
  2128. hEvent,
  2129. NULL,
  2130. NULL,
  2131. &IoStatusBlock,
  2132. IOCTL_TCP_QUERY_INFORMATION_EX,
  2133. InBuf,
  2134. *InBufLen,
  2135. OutBuf,
  2136. *OutBufLen );
  2137. if ( Status == STATUS_PENDING )
  2138. {
  2139. Status = NtWaitForSingleObject(hEvent, FALSE, NULL );
  2140. Status = IoStatusBlock.Status;
  2141. }
  2142. CloseHandle(hEvent);
  2143. if ( !NT_SUCCESS( Status ) )
  2144. {
  2145. Trace1(ERR,"Device IOCTL failed in TCPQuery %x",Status);
  2146. *OutBufLen = 0;
  2147. return ( RtlNtStatusToDosError(Status) );
  2148. }
  2149. //
  2150. // Tell caller how much was written
  2151. //
  2152. *OutBufLen = (ULONG)IoStatusBlock.Information;
  2153. return ( NO_ERROR );
  2154. #endif
  2155. }
  2156. // ========================================================================
  2157. //* TCPSendIoctl
  2158. //
  2159. // Description: Get information from the stack.
  2160. //
  2161. // Parameters: HANDLE hHandle: handle to the stack.
  2162. // TDIObjectID *ID: pointer to TDIObjectID info.
  2163. // void *Buffer: buffer to receive data from the stack.
  2164. // ulong *Bufferlen: IN: tells stack size of available buffer,
  2165. // OUT: tells us how much data is available.
  2166. // CONTEXT *Context: allows queries spanning more than one call.
  2167. //
  2168. // Returns: int:
  2169. //
  2170. //*
  2171. int
  2172. TCPSendIoctl( HANDLE hHandle,
  2173. ulong Ioctl,
  2174. void *InBuf,
  2175. ulong *InBufLen,
  2176. void *OutBuf,
  2177. ulong *OutBufLen)
  2178. {
  2179. #ifdef CHICAGO
  2180. // OVERLAPPED overlap;
  2181. uint ok;
  2182. ok = DeviceIoControl( hHandle, Ioctl,
  2183. InBuf, *InBufLen,
  2184. OutBuf, *OutBufLen, OutBufLen,
  2185. NULL // &overlap
  2186. );
  2187. if( !ok ){
  2188. int err = GetLastError();
  2189. DEBUG_PRINT(("TCPSendIoctl: DeviceIoControl err %d\n", err ));
  2190. return err;
  2191. }
  2192. return NO_ERROR;
  2193. #else
  2194. NTSTATUS Status;
  2195. IO_STATUS_BLOCK IoStatusBlock;
  2196. HANDLE hEvent;
  2197. hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
  2198. if( NULL == hEvent ) return GetLastError();
  2199. ZeroMemory(&IoStatusBlock, sizeof(IoStatusBlock));
  2200. Status = NtDeviceIoControlFile(hHandle,
  2201. hEvent,
  2202. NULL,
  2203. NULL,
  2204. &IoStatusBlock,
  2205. Ioctl,
  2206. InBuf,
  2207. *InBufLen,
  2208. OutBuf,
  2209. *OutBufLen );
  2210. if ( Status == STATUS_PENDING )
  2211. {
  2212. Status = NtWaitForSingleObject( hEvent, FALSE, NULL );
  2213. Status = IoStatusBlock.Status;
  2214. }
  2215. CloseHandle(hEvent);
  2216. if ( !NT_SUCCESS( Status ) )
  2217. {
  2218. Trace1(ERR,"Device IOCTL failed in TCPSendIoctl %x",Status);
  2219. if (OutBufLen)
  2220. *OutBufLen = (ULONG)IoStatusBlock.Information;
  2221. return ( RtlNtStatusToDosError(Status) );
  2222. }
  2223. //
  2224. // Tell caller how much was written
  2225. //
  2226. if (OutBufLen)
  2227. *OutBufLen = (ULONG)IoStatusBlock.Information;
  2228. return ( NO_ERROR );
  2229. #endif
  2230. }
  2231. // ========================================================================
  2232. //* TCPSetInformationEx()
  2233. //
  2234. // Description: Send information to the stack
  2235. //
  2236. // Parameters: HANDLE hHandle: handle to the stack.
  2237. // TDIObjectID *ID: pointer to TDIObjectID info.
  2238. // void *Buffer: buffer to receive data from the stack.
  2239. // ulong Bufferlen: tells stack size of available buffer,
  2240. //
  2241. // Returns: int:
  2242. //
  2243. //*
  2244. int
  2245. TCPSetInformationEx(
  2246. void *InBuf,
  2247. ULONG *InBufLen,
  2248. void *OutBuf,
  2249. ULONG *OutBufLen
  2250. )
  2251. {
  2252. #ifdef CHICAGO
  2253. DWORD result;
  2254. if( ! pWsControl )
  2255. OpenTCPDriver(AF_INET);
  2256. if( ! pWsControl ){
  2257. DEBUG_PRINT(("TCPQueryInformationEx: !pWsControl.\n"));
  2258. return 0;
  2259. }
  2260. assert( pWsControl );
  2261. result = (
  2262. (*pWsControl)(
  2263. IPPROTO_TCP,
  2264. WSCNTL_TCPIP_SET_INFO,
  2265. InBuf,
  2266. InBufLen,
  2267. OutBuf,
  2268. OutBufLen
  2269. ) );
  2270. if( result ){
  2271. return ConvertTdiErrorToDosError(result);
  2272. }
  2273. return NO_ERROR;
  2274. #else
  2275. NTSTATUS Status;
  2276. IO_STATUS_BLOCK IoStatusBlock;
  2277. if(g_hTCPDriverSetHandle is NULL)
  2278. {
  2279. return ERROR_NETWORK_ACCESS_DENIED;
  2280. }
  2281. Status = NtDeviceIoControlFile(g_hTCPDriverSetHandle,
  2282. NULL,
  2283. NULL,
  2284. NULL,
  2285. &IoStatusBlock,
  2286. IOCTL_TCP_SET_INFORMATION_EX,
  2287. InBuf,
  2288. *InBufLen,
  2289. OutBuf,
  2290. *OutBufLen );
  2291. if ( Status == STATUS_PENDING )
  2292. {
  2293. Status = NtWaitForSingleObject(g_hTCPDriverSetHandle, FALSE, NULL );
  2294. Status = IoStatusBlock.Status;
  2295. }
  2296. if ( !NT_SUCCESS( Status ) )
  2297. {
  2298. return ( RtlNtStatusToDosError(Status) );
  2299. }
  2300. return ( NO_ERROR );
  2301. #endif
  2302. }
  2303. // ========================================================================
  2304. // SYNOPSIS: opens handles to tcpip driver.
  2305. //
  2306. // returns
  2307. // 0 == NO_ERROR == STATUS_SUCCESS on success.
  2308. // err or 1 on failure.
  2309. //
  2310. // - MohsinA, 02-Jul-97.
  2311. //
  2312. DWORD
  2313. OpenTCPDriver(
  2314. IN DWORD dwFamily
  2315. )
  2316. {
  2317. #ifdef CHICAGO
  2318. int err = 0;
  2319. if (dwFamily != AF_INET) {
  2320. return ERROR_INVALID_PARAMETER;
  2321. }
  2322. hWsock = LoadLibrary(TEXT("wsock32.dll"));
  2323. if(! hWsock ){
  2324. err = GetLastError();
  2325. DEBUG_PRINT(("RTStartup: can't load wsock32.dll, %d\n", err ));
  2326. DEBUG_PRINT(("OpenTcp: !hWsock\n"));
  2327. return err? err: 1;
  2328. }
  2329. pWsControl = (LPWSCONTROL) GetProcAddress(hWsock, "WsControl");
  2330. if (! pWsControl ){
  2331. err = GetLastError();
  2332. DEBUG_PRINT((
  2333. "RTStartup: GetProcAddress(wsock32,WsControl) failed %d\n",
  2334. GetLastError()));
  2335. return err? err: 1;
  2336. }
  2337. // open the handle to VIP
  2338. g_hIPDriverHandle = NULL;
  2339. g_hIPGetDriverHandle = NULL;
  2340. #ifndef _WIN95_
  2341. g_hIPDriverHandle = OsOpenVxdHandle( "VIP", VIP_Device_ID );
  2342. if( ! g_hIPDriverHandle ){
  2343. err = GetLastError();
  2344. DEBUG_PRINT(("no ip handle, err %d\n", err ));
  2345. return err? err : 1;
  2346. }
  2347. g_hIPGetDriverHandle = g_hIPDriverHandle;
  2348. #endif
  2349. return NO_ERROR;
  2350. #else
  2351. NTSTATUS status;
  2352. UNICODE_STRING nameString;
  2353. IO_STATUS_BLOCK ioStatusBlock;
  2354. OBJECT_ATTRIBUTES objectAttributes;
  2355. PWCHAR pwszDdDeviceName;
  2356. HANDLE *pDriverGetHandle, *pDriverSetHandle;
  2357. switch (dwFamily) {
  2358. case AF_INET:
  2359. pwszDdDeviceName = DD_TCP_DEVICE_NAME;
  2360. pDriverGetHandle = &g_hTCPDriverGetHandle;
  2361. pDriverSetHandle = &g_hTCPDriverSetHandle;
  2362. break;
  2363. case AF_INET6:
  2364. pwszDdDeviceName = DD_TCPV6_DEVICE_NAME;
  2365. pDriverGetHandle = &g_hTCP6DriverGetHandle;
  2366. pDriverSetHandle = &g_hTCP6DriverSetHandle;
  2367. break;
  2368. default:
  2369. return ERROR_INVALID_PARAMETER;
  2370. }
  2371. RtlInitUnicodeString(&nameString, pwszDdDeviceName);
  2372. InitializeObjectAttributes(&objectAttributes, &nameString,
  2373. OBJ_CASE_INSENSITIVE, NULL, NULL);
  2374. status = NtCreateFile(pDriverGetHandle,
  2375. GENERIC_EXECUTE,
  2376. &objectAttributes,
  2377. &ioStatusBlock,
  2378. NULL,
  2379. FILE_ATTRIBUTE_NORMAL,
  2380. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2381. FILE_OPEN_IF,
  2382. 0,
  2383. NULL,
  2384. 0);
  2385. if(status isnot STATUS_SUCCESS)
  2386. {
  2387. return ERROR_OPEN_FAILED;
  2388. }
  2389. RtlInitUnicodeString(&nameString, pwszDdDeviceName);
  2390. InitializeObjectAttributes(&objectAttributes, &nameString,
  2391. OBJ_CASE_INSENSITIVE, NULL, NULL);
  2392. NtCreateFile(pDriverSetHandle,
  2393. GENERIC_WRITE,
  2394. &objectAttributes,
  2395. &ioStatusBlock,
  2396. NULL,
  2397. FILE_ATTRIBUTE_NORMAL,
  2398. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2399. FILE_OPEN_IF,
  2400. 0,
  2401. NULL,
  2402. 0);
  2403. OpenIPDriver(dwFamily);
  2404. return NO_ERROR;
  2405. #endif
  2406. }
  2407. // ========================================================================
  2408. DWORD
  2409. CloseTCPDriver()
  2410. {
  2411. #ifdef CHICAGO
  2412. if( hWsock )
  2413. FreeLibrary( hWsock );
  2414. hWsock = NULL;
  2415. pWsControl = NULL;
  2416. if (g_hIPDriverHandle)
  2417. OsCloseVxdHandle( g_hIPDriverHandle );
  2418. g_hIPDriverHandle = NULL;
  2419. g_hIPGetDriverHandle = NULL;
  2420. #else
  2421. if(g_hTCPDriverGetHandle isnot NULL)
  2422. {
  2423. CloseHandle (g_hTCPDriverGetHandle) ;
  2424. }
  2425. if(g_hTCPDriverSetHandle isnot NULL)
  2426. {
  2427. CloseHandle (g_hTCPDriverSetHandle) ;
  2428. }
  2429. CloseIPDriver();
  2430. #endif
  2431. return NO_ERROR ;
  2432. }
  2433. DWORD
  2434. CloseTCP6Driver()
  2435. {
  2436. if(g_hTCP6DriverGetHandle isnot NULL)
  2437. {
  2438. CloseHandle (g_hTCP6DriverGetHandle) ;
  2439. }
  2440. if(g_hTCP6DriverSetHandle isnot NULL)
  2441. {
  2442. CloseHandle (g_hTCP6DriverSetHandle) ;
  2443. }
  2444. CloseIP6Driver();
  2445. return NO_ERROR ;
  2446. }
  2447. #ifndef CHICAGO
  2448. DWORD
  2449. OpenIPDriver(
  2450. IN DWORD dwFamily
  2451. )
  2452. {
  2453. NTSTATUS status;
  2454. UNICODE_STRING nameString;
  2455. IO_STATUS_BLOCK ioStatusBlock;
  2456. OBJECT_ATTRIBUTES objectAttributes;
  2457. PWCHAR pwszDdDeviceName;
  2458. LPCTSTR ptszWinDeviceName;
  2459. HANDLE *pDriverHandle, *pGetDriverHandle, *pChangeHandle;
  2460. switch (dwFamily) {
  2461. case AF_INET:
  2462. pwszDdDeviceName = DD_IP_DEVICE_NAME;
  2463. ptszWinDeviceName = TEXT ("\\\\.\\Ip");
  2464. pDriverHandle = &g_hIPDriverHandle;
  2465. pGetDriverHandle = &g_hIPGetDriverHandle;
  2466. pChangeHandle = &ChangeNotificationHandle;
  2467. break;
  2468. case AF_INET6:
  2469. pwszDdDeviceName = DD_IPV6_DEVICE_NAME;
  2470. ptszWinDeviceName = TEXT ("\\\\.\\Ip6");;
  2471. pDriverHandle = &g_hIP6GetDriverHandle;
  2472. pGetDriverHandle = &g_hIP6GetDriverHandle;
  2473. pChangeHandle = &Change6NotificationHandle;
  2474. break;
  2475. default:
  2476. return ERROR_INVALID_PARAMETER;
  2477. }
  2478. RtlInitUnicodeString(&nameString, pwszDdDeviceName);
  2479. InitializeObjectAttributes(&objectAttributes, &nameString,
  2480. OBJ_CASE_INSENSITIVE, NULL, NULL);
  2481. status = NtCreateFile(pGetDriverHandle,
  2482. GENERIC_EXECUTE,
  2483. &objectAttributes, &ioStatusBlock, NULL,
  2484. FILE_ATTRIBUTE_NORMAL,
  2485. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2486. FILE_OPEN_IF, 0, NULL, 0);
  2487. if (status == STATUS_SUCCESS) {
  2488. RtlInitUnicodeString(&nameString, pwszDdDeviceName);
  2489. InitializeObjectAttributes(&objectAttributes, &nameString,
  2490. OBJ_CASE_INSENSITIVE, NULL, NULL);
  2491. NtCreateFile(pDriverHandle,
  2492. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  2493. &objectAttributes, &ioStatusBlock, NULL,
  2494. FILE_ATTRIBUTE_NORMAL,
  2495. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2496. FILE_OPEN_IF, 0, NULL, 0);
  2497. *pChangeHandle = CreateFile(ptszWinDeviceName,
  2498. GENERIC_EXECUTE,
  2499. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2500. NULL,
  2501. OPEN_EXISTING,
  2502. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  2503. NULL);
  2504. }
  2505. return (NO_ERROR);
  2506. }
  2507. DWORD
  2508. CloseIPDriver()
  2509. {
  2510. if(g_hIPDriverHandle isnot NULL)
  2511. {
  2512. CloseHandle (g_hIPDriverHandle) ;
  2513. }
  2514. if(g_hIPGetDriverHandle isnot NULL)
  2515. {
  2516. CloseHandle (g_hIPGetDriverHandle) ;
  2517. }
  2518. if (ChangeNotificationHandle isnot NULL)
  2519. {
  2520. CloseHandle (ChangeNotificationHandle);
  2521. }
  2522. return NO_ERROR ;
  2523. }
  2524. DWORD
  2525. CloseIP6Driver()
  2526. {
  2527. if(g_hIP6DriverHandle isnot NULL)
  2528. {
  2529. CloseHandle (g_hIP6DriverHandle) ;
  2530. }
  2531. if(g_hIP6GetDriverHandle isnot NULL)
  2532. {
  2533. CloseHandle (g_hIP6GetDriverHandle) ;
  2534. }
  2535. if (Change6NotificationHandle isnot NULL)
  2536. {
  2537. CloseHandle (Change6NotificationHandle);
  2538. }
  2539. return NO_ERROR ;
  2540. }
  2541. #endif
  2542. DWORD
  2543. GetBestRouteFromStack(
  2544. IN DWORD dwDestAddr,
  2545. IN DWORD dwSrcAddr, OPTIONAL
  2546. OUT PMIB_IPFORWARDROW pBestRoute
  2547. )
  2548. {
  2549. DWORD dwResult;
  2550. DWORD dwInBufLen, dwOutBufLen;
  2551. TDIObjectID *ID;
  2552. BYTE *Context;
  2553. IPRouteEntry Route;
  2554. PIPRouteLookupData pLookup;
  2555. PTCP_REQUEST_QUERY_INFORMATION_EX ptrqiInBuf;
  2556. #define REQ_SIZE sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) + \
  2557. sizeof(IPRouteLookupData) - 1
  2558. BYTE rgbyBuffer[REQ_SIZE + 4]; // +4 to avoid any alignment problems
  2559. ptrqiInBuf = (PTCP_REQUEST_QUERY_INFORMATION_EX)rgbyBuffer;
  2560. dwInBufLen = REQ_SIZE;
  2561. #undef REQ_SIZE
  2562. CheckTcpipState();
  2563. if (!g_bIpConfigured)
  2564. {
  2565. return ERROR_NOT_SUPPORTED;
  2566. }
  2567. ID = &(ptrqiInBuf->ID);
  2568. pLookup = (PIPRouteLookupData)(ptrqiInBuf->Context);
  2569. pLookup->Version = 1;
  2570. pLookup->DestAdd = dwDestAddr;
  2571. pLookup->SrcAdd = dwSrcAddr;
  2572. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  2573. ID->toi_entity.tei_instance = 0;
  2574. ID->toi_class = INFO_CLASS_PROTOCOL;
  2575. ID->toi_type = INFO_TYPE_PROVIDER;
  2576. ID->toi_id = IP_MIB_SINGLE_RT_ENTRY_ID;
  2577. dwOutBufLen = sizeof(IPRouteEntry);
  2578. dwResult = TCPQueryInformationEx(AF_INET,
  2579. ptrqiInBuf,
  2580. &dwInBufLen,
  2581. &Route,
  2582. &dwOutBufLen);
  2583. ConvertRouteToForward(&Route, pBestRoute);
  2584. return dwResult;
  2585. }
  2586. TDIEntityID*
  2587. GetTdiEntityCount(
  2588. PULONG pulNumEntities
  2589. )
  2590. {
  2591. DWORD dwResult;
  2592. DWORD dwInBufLen;
  2593. DWORD dwOutBufLen;
  2594. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  2595. UCHAR *Context;
  2596. TDIObjectID *ID;
  2597. TDIEntityID *pEntTable = NULL;
  2598. TraceEnter("GetTdiEntityCount");
  2599. *pulNumEntities = 0;
  2600. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  2601. dwOutBufLen = sizeof(TDIEntityID) * MAX_TDI_ENTITIES;
  2602. pEntTable = (TDIEntityID*)HeapAlloc(g_hPrivateHeap,0,dwOutBufLen);
  2603. if (!pEntTable) {
  2604. Trace1(ERR,"GetTdiEntityCount: Couldnt allocate memory of size %d",
  2605. dwOutBufLen);
  2606. return NULL;
  2607. }
  2608. ID = &(trqiInBuf.ID);
  2609. ID->toi_entity.tei_entity = GENERIC_ENTITY;
  2610. ID->toi_entity.tei_instance = 0;
  2611. ID->toi_class = INFO_CLASS_GENERIC;
  2612. ID->toi_type = INFO_TYPE_PROVIDER;
  2613. ID->toi_id = ENTITY_LIST_ID;
  2614. Context = (BYTE *) &(trqiInBuf.Context[0]);
  2615. ZeroMemory(Context, CONTEXT_SIZE);
  2616. dwResult = TCPQueryInformationEx(AF_INET,
  2617. &trqiInBuf,
  2618. &dwInBufLen,
  2619. (PVOID)pEntTable,
  2620. &dwOutBufLen);
  2621. if(dwResult isnot NO_ERROR)
  2622. {
  2623. Trace1(ERR,"GetTdiEntityCount: Couldnt query information. Error %x",
  2624. dwResult);
  2625. HeapFree(g_hPrivateHeap,0,pEntTable);
  2626. return NULL;
  2627. }
  2628. //
  2629. // Now we have all the TDI entities
  2630. //
  2631. *pulNumEntities = dwOutBufLen / sizeof(TDIEntityID);
  2632. return pEntTable;
  2633. }