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.

1755 lines
48 KiB

  1. #include "allinc.h"
  2. DWORD
  3. LoadSystem()
  4. {
  5. DWORD dwResult;
  6. TraceEnter("LoadSystem");
  7. if(g_Cache.pRpcSysInfo)
  8. {
  9. if(g_Cache.pRpcSysInfo->aaSysObjectID.asnValue.object.ids)
  10. {
  11. SnmpUtilOidFree(&g_Cache.pRpcSysInfo->aaSysObjectID.asnValue.object);
  12. }
  13. HeapFree(g_hPrivateHeap,
  14. 0,
  15. g_Cache.pRpcSysInfo);
  16. g_Cache.pRpcSysInfo = NULL;
  17. }
  18. dwResult = GetSysInfo(&(g_Cache.pRpcSysInfo),
  19. g_hPrivateHeap,
  20. 0);
  21. if(dwResult isnot NO_ERROR)
  22. {
  23. TRACE1("GetSysInfo failed with error %x",dwResult);
  24. TraceLeave("LoadSysInfo");
  25. return dwResult;
  26. }
  27. TraceLeave("LoadSysInfo");
  28. return NO_ERROR;
  29. }
  30. DWORD
  31. LoadIfTable()
  32. {
  33. DWORD dwResult;
  34. TraceEnter("LoadIfTable");
  35. if(g_Cache.pRpcIfTable)
  36. {
  37. HeapFree(g_hPrivateHeap,
  38. 0,
  39. g_Cache.pRpcIfTable);
  40. g_Cache.pRpcIfTable = NULL;
  41. }
  42. dwResult = InternalGetIfTable(&(g_Cache.pRpcIfTable),
  43. g_hPrivateHeap,
  44. 0);
  45. if(dwResult isnot NO_ERROR)
  46. {
  47. TRACE1("GetIfTable failed with error %x",
  48. dwResult);
  49. TraceLeave("LoadIfTable");
  50. return dwResult;
  51. }
  52. TraceLeave("LoadIfTable");
  53. return NO_ERROR;
  54. }
  55. DWORD
  56. LoadIpAddrTable()
  57. {
  58. DWORD dwResult;
  59. TraceEnter("LoadIpAddrTable");
  60. if(g_Cache.pRpcIpAddrTable)
  61. {
  62. HeapFree(g_hPrivateHeap,
  63. 0,
  64. g_Cache.pRpcIpAddrTable);
  65. g_Cache.pRpcIpAddrTable = NULL;
  66. }
  67. dwResult = InternalGetIpAddrTable(&(g_Cache.pRpcIpAddrTable),
  68. g_hPrivateHeap,
  69. 0);
  70. if(dwResult isnot NO_ERROR)
  71. {
  72. TRACE1("GetIpAddrTable failed with error %x",
  73. dwResult);
  74. TraceLeave("LoadIpAddrTable");
  75. return dwResult;
  76. }
  77. TraceLeave("LoadIpAddrTable");
  78. return NO_ERROR;
  79. }
  80. DWORD
  81. LoadIpNetTable()
  82. {
  83. DWORD dwResult;
  84. TraceEnter("LoadIpNetTable");
  85. if(g_Cache.pRpcIpNetTable)
  86. {
  87. HeapFree(g_hPrivateHeap,
  88. 0,
  89. g_Cache.pRpcIpNetTable);
  90. g_Cache.pRpcIpNetTable = NULL;
  91. }
  92. dwResult = InternalGetIpNetTable(&(g_Cache.pRpcIpNetTable),
  93. g_hPrivateHeap,
  94. 0);
  95. if(dwResult isnot NO_ERROR)
  96. {
  97. TRACE1("GetIpNetTable failed with error %x",
  98. dwResult);
  99. TraceLeave("LoadIpNetTable");
  100. return dwResult;
  101. }
  102. TraceLeave("LoadIpNetTable");
  103. return NO_ERROR;
  104. }
  105. DWORD
  106. LoadIpForwardTable()
  107. {
  108. DWORD dwResult;
  109. TraceEnter("LoadIpForwardTable");
  110. if(g_Cache.pRpcIpForwardTable)
  111. {
  112. HeapFree(g_hPrivateHeap,
  113. 0,
  114. g_Cache.pRpcIpForwardTable);
  115. g_Cache.pRpcIpForwardTable = NULL;
  116. }
  117. dwResult = InternalGetIpForwardTable(&(g_Cache.pRpcIpForwardTable),
  118. g_hPrivateHeap,
  119. 0);
  120. if(dwResult isnot NO_ERROR)
  121. {
  122. TRACE1("GetIpForwardTable failed with error %x",
  123. dwResult);
  124. TraceLeave("LoadIpForwardTable");
  125. return dwResult;
  126. }
  127. TraceLeave("LoadIpForwardTable");
  128. return NO_ERROR;
  129. }
  130. DWORD
  131. LoadTcpTable()
  132. {
  133. DWORD dwResult, i;
  134. TraceEnter("LoadTcpTable");
  135. if(g_Cache.pRpcTcpTable)
  136. {
  137. HeapFree(g_hPrivateHeap,
  138. 0,
  139. g_Cache.pRpcTcpTable);
  140. g_Cache.pRpcTcpTable = NULL;
  141. }
  142. dwResult = InternalGetTcpTable(&(g_Cache.pRpcTcpTable),
  143. g_hPrivateHeap,
  144. 0);
  145. if(dwResult isnot NO_ERROR)
  146. {
  147. TRACE1("GetTcpTable failed with error %x",
  148. dwResult);
  149. TraceLeave("LoadTcpTable");
  150. return dwResult;
  151. }
  152. //
  153. // modify port numbers to be in host byte order
  154. //
  155. for (i = 0; i < g_Cache.pRpcTcpTable->dwNumEntries; i++)
  156. {
  157. g_Cache.pRpcTcpTable->table[i].dwLocalPort =
  158. (DWORD)ntohs((WORD)g_Cache.pRpcTcpTable->table[i].dwLocalPort);
  159. g_Cache.pRpcTcpTable->table[i].dwRemotePort =
  160. (DWORD)ntohs((WORD)g_Cache.pRpcTcpTable->table[i].dwRemotePort);
  161. }
  162. TraceLeave("LoadTcpTable");
  163. return NO_ERROR;
  164. }
  165. DWORD
  166. LoadTcp6Table()
  167. {
  168. DWORD dwResult, i;
  169. TraceEnter("LoadTcp6Table");
  170. if(g_Cache.pRpcTcp6Table)
  171. {
  172. HeapFree(g_hPrivateHeap,
  173. 0,
  174. g_Cache.pRpcTcp6Table);
  175. g_Cache.pRpcTcp6Table = NULL;
  176. }
  177. dwResult = AllocateAndGetTcpExTableFromStack(
  178. (TCP_EX_TABLE **)&(g_Cache.pRpcTcp6Table),
  179. TRUE, g_hPrivateHeap, 0, AF_INET6);
  180. if(dwResult isnot NO_ERROR)
  181. {
  182. TRACE1("GetTcp6Table failed with error %x",
  183. dwResult);
  184. TraceLeave("LoadTcp6Table");
  185. return dwResult;
  186. }
  187. //
  188. // modify port numbers to be in host byte order
  189. // and scope ids to be in network byte order
  190. //
  191. for (i = 0; i < g_Cache.pRpcTcp6Table->dwNumEntries; i++)
  192. {
  193. g_Cache.pRpcTcp6Table->table[i].tct_localport =
  194. (DWORD)ntohs((WORD)g_Cache.pRpcTcp6Table->table[i].tct_localport);
  195. g_Cache.pRpcTcp6Table->table[i].tct_remoteport =
  196. (DWORD)ntohs((WORD)g_Cache.pRpcTcp6Table->table[i].tct_remoteport);
  197. g_Cache.pRpcTcp6Table->table[i].tct_localscopeid =
  198. htonl(g_Cache.pRpcTcp6Table->table[i].tct_localscopeid);
  199. g_Cache.pRpcTcp6Table->table[i].tct_remotescopeid =
  200. htonl(g_Cache.pRpcTcp6Table->table[i].tct_remotescopeid);
  201. }
  202. TraceLeave("LoadTcp6Table");
  203. return NO_ERROR;
  204. }
  205. DWORD
  206. LoadUdpTable()
  207. {
  208. DWORD dwResult, i;
  209. TraceEnter("LoadUdpTable");
  210. if(g_Cache.pRpcUdpTable)
  211. {
  212. HeapFree(g_hPrivateHeap,
  213. 0,
  214. g_Cache.pRpcUdpTable);
  215. g_Cache.pRpcUdpTable = NULL;
  216. }
  217. dwResult = InternalGetUdpTable(&(g_Cache.pRpcUdpTable),
  218. g_hPrivateHeap,
  219. 0);
  220. if(dwResult isnot NO_ERROR)
  221. {
  222. TRACE1("GetUdpTable failed with error %x",
  223. dwResult);
  224. TraceLeave("LoadUdpTable");
  225. return dwResult;
  226. }
  227. //
  228. // modify port numbers to be in host byte order
  229. //
  230. for (i = 0; i < g_Cache.pRpcUdpTable->dwNumEntries; i++)
  231. {
  232. g_Cache.pRpcUdpTable->table[i].dwLocalPort =
  233. (DWORD)ntohs((WORD)g_Cache.pRpcUdpTable->table[i].dwLocalPort);
  234. }
  235. TraceLeave("LoadUdpTable");
  236. return NO_ERROR;
  237. }
  238. DWORD
  239. LoadUdp6ListenerTable()
  240. {
  241. DWORD dwResult, i;
  242. TraceEnter("LoadUdp6ListenerTable");
  243. if(g_Cache.pRpcUdp6ListenerTable)
  244. {
  245. HeapFree(g_hPrivateHeap,
  246. 0,
  247. g_Cache.pRpcUdp6ListenerTable);
  248. g_Cache.pRpcUdp6ListenerTable = NULL;
  249. }
  250. dwResult = AllocateAndGetUdpExTableFromStack(
  251. (UDP_EX_TABLE **)&(g_Cache.pRpcUdp6ListenerTable),
  252. TRUE, g_hPrivateHeap, 0, AF_INET6);
  253. if(dwResult isnot NO_ERROR)
  254. {
  255. TRACE1("GetUdp6ListenerTable failed with error %x",
  256. dwResult);
  257. TraceLeave("LoadUdp6ListenerTable");
  258. return dwResult;
  259. }
  260. //
  261. // modify port numbers to be in host byte order
  262. // and scope ids to be in network byte order
  263. //
  264. for (i = 0; i < g_Cache.pRpcUdp6ListenerTable->dwNumEntries; i++)
  265. {
  266. g_Cache.pRpcUdp6ListenerTable->table[i].ule_localport =
  267. (DWORD)ntohs((WORD)g_Cache.pRpcUdp6ListenerTable->table[i].ule_localport);
  268. g_Cache.pRpcUdp6ListenerTable->table[i].ule_localscopeid =
  269. htonl(g_Cache.pRpcUdp6ListenerTable->table[i].ule_localscopeid);
  270. }
  271. TraceLeave("LoadUdp6ListenerTable");
  272. return NO_ERROR;
  273. }
  274. DWORD
  275. GetSysInfo(
  276. MIB_SYSINFO **ppRpcSysInfo,
  277. HANDLE hHeap,
  278. DWORD dwAllocFlags
  279. )
  280. {
  281. DWORD dwResult,dwValueType,dwValueLen;
  282. PMIB_SYSINFO pRpcSysInfo;
  283. HKEY hkeySysInfo;
  284. DWORD dwBytes = 0, i, dwOidLen;
  285. PCHAR pchBuff, pchStr, pchToken;
  286. BOOL bOverride;
  287. TraceEnter("GetSysInfo");
  288. *ppRpcSysInfo = NULL;
  289. pRpcSysInfo = HeapAlloc(hHeap,
  290. dwAllocFlags,
  291. sizeof(MIB_SYSINFO));
  292. if(pRpcSysInfo is NULL)
  293. {
  294. dwResult = GetLastError();
  295. TRACE1("Allocation failed with error %d",
  296. dwResult);
  297. TraceLeave("GetSysInfo");
  298. return dwResult;
  299. }
  300. dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  301. REG_KEY_MIB2,
  302. 0,
  303. KEY_ALL_ACCESS,
  304. &hkeySysInfo);
  305. if (dwResult isnot NO_ERROR) {
  306. HeapFree(hHeap,
  307. dwAllocFlags,
  308. pRpcSysInfo);
  309. TRACE1("Couldnt open mib2 registry key. Error %d", dwResult);
  310. TraceLeave("GetSysInfo");
  311. return dwResult;
  312. }
  313. dwValueLen = sizeof(pRpcSysInfo->dwSysServices);
  314. dwResult = RegQueryValueEx(hkeySysInfo,
  315. TEXT("sysServices"),
  316. 0,
  317. &dwValueType,
  318. (LPBYTE)&pRpcSysInfo->dwSysServices,
  319. &dwValueLen
  320. );
  321. if (dwResult isnot NO_ERROR) {
  322. HeapFree(hHeap,
  323. dwAllocFlags,
  324. pRpcSysInfo);
  325. TRACE1("Couldnt read sysServices value. Error %d", dwResult);
  326. TraceLeave("GetSysInfo");
  327. return dwResult;
  328. }
  329. bOverride = FALSE;
  330. do
  331. {
  332. //
  333. // First get the length of the OID
  334. //
  335. dwValueLen = 0;
  336. dwResult = RegQueryValueExA(hkeySysInfo,
  337. "sysObjectID",
  338. 0,
  339. &dwValueType,
  340. NULL,
  341. &dwValueLen);
  342. if(((dwResult isnot ERROR_MORE_DATA) and (dwResult isnot NO_ERROR)) or
  343. (dwValueLen is 0))
  344. {
  345. //
  346. // The only two codes that give us a good buffer len are
  347. // NO_ERROR and ERROR_MORE_DATA. If the error code is not one
  348. // of those, or if the oid len is 0, just set the OID to system oid
  349. //
  350. break;
  351. }
  352. pchBuff = HeapAlloc(g_hPrivateHeap,
  353. HEAP_ZERO_MEMORY,
  354. dwValueLen + 1);
  355. if(pchBuff is NULL)
  356. {
  357. break;
  358. }
  359. dwResult = RegQueryValueExA(hkeySysInfo,
  360. "sysObjectID",
  361. 0,
  362. &dwValueType,
  363. pchBuff,
  364. &dwValueLen);
  365. if((dwResult isnot NO_ERROR) or
  366. (dwValueType isnot REG_SZ) or
  367. (dwValueLen is 0))
  368. {
  369. break;
  370. }
  371. //
  372. // Parse out the oid and store it away
  373. // pchBuff is NULL terminated so we use strtok to overwrite
  374. // all the "." with \0. This way we figure out the number
  375. // of ids. Then we allocate memory to hold those many ids
  376. //
  377. dwOidLen = 1;
  378. pchToken = strtok(pchBuff,".");
  379. while(pchToken)
  380. {
  381. dwOidLen++;
  382. pchToken = strtok(NULL,".");
  383. }
  384. //
  385. // If the leading OID is 0, there is a problem
  386. //
  387. if(atoi(pchBuff) is 0)
  388. {
  389. break;
  390. }
  391. pRpcSysInfo->aaSysObjectID.asnType = ASN_OBJECTIDENTIFIER;
  392. pRpcSysInfo->aaSysObjectID.asnValue.object.idLength = dwOidLen;
  393. pRpcSysInfo->aaSysObjectID.asnValue.object.ids =
  394. SnmpUtilMemAlloc(dwOidLen * sizeof(UINT));
  395. for(i = 0, pchStr = pchBuff; i < dwOidLen; i++)
  396. {
  397. pRpcSysInfo->aaSysObjectID.asnValue.object.ids[i] = atoi(pchStr);
  398. pchStr += strlen(pchStr) + 1;
  399. }
  400. HeapFree(g_hPrivateHeap,
  401. 0,
  402. pchBuff);
  403. bOverride = TRUE;
  404. }while(FALSE);
  405. if(!bOverride)
  406. {
  407. SnmpUtilOidCpy(&pRpcSysInfo->aaSysObjectID.asnValue.object,
  408. SnmpSvcGetEnterpriseOID());
  409. }
  410. dwValueLen = sizeof(pRpcSysInfo->rgbySysName);
  411. dwResult = RegQueryValueEx(hkeySysInfo,
  412. TEXT("sysName"),
  413. 0,
  414. &dwValueType,
  415. pRpcSysInfo->rgbySysName,
  416. &dwValueLen
  417. );
  418. if (dwResult isnot NO_ERROR) {
  419. TRACE1("Couldnt read sysName value. Error %d", dwResult);
  420. dwValueLen = sizeof(pRpcSysInfo->rgbySysName);
  421. if (!GetComputerNameA(pRpcSysInfo->rgbySysName, &dwValueLen)) {
  422. HeapFree(hHeap,
  423. dwAllocFlags,
  424. pRpcSysInfo);
  425. dwResult = GetLastError();
  426. TRACE1("Couldnt read computer name. Error %d", dwResult);
  427. TraceLeave("GetSysInfo");
  428. return dwResult;
  429. }
  430. }
  431. dwValueLen = sizeof(pRpcSysInfo->rgbySysContact);
  432. dwResult = RegQueryValueEx(hkeySysInfo,
  433. TEXT("sysContact"),
  434. 0,
  435. &dwValueType,
  436. pRpcSysInfo->rgbySysContact,
  437. &dwValueLen
  438. );
  439. if (dwResult isnot NO_ERROR) {
  440. pRpcSysInfo->rgbySysContact[0] = '\0';
  441. }
  442. dwValueLen = sizeof(pRpcSysInfo->rgbySysLocation);
  443. dwResult = RegQueryValueEx(hkeySysInfo,
  444. TEXT("sysLocation"),
  445. 0,
  446. &dwValueType,
  447. pRpcSysInfo->rgbySysLocation,
  448. &dwValueLen
  449. );
  450. if (dwResult isnot NO_ERROR)
  451. {
  452. pRpcSysInfo->rgbySysLocation[0] = '\0';
  453. }
  454. RegCloseKey(hkeySysInfo);
  455. strcpy(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("Hardware: "));
  456. dwBytes += strlen(TEXT("Hardware: "));
  457. dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  458. REG_KEY_CPU,
  459. 0,
  460. KEY_QUERY_VALUE |
  461. KEY_ENUMERATE_SUB_KEYS,
  462. &hkeySysInfo);
  463. if (dwResult is NO_ERROR) {
  464. dwValueLen = sizeof(pRpcSysInfo->rgbySysDescr) - dwBytes;
  465. dwResult = RegQueryValueEx(hkeySysInfo,
  466. TEXT("Identifier"),
  467. 0,
  468. &dwValueType,
  469. &pRpcSysInfo->rgbySysDescr[dwBytes],
  470. &dwValueLen);
  471. if (dwResult is NO_ERROR) {
  472. dwBytes += dwValueLen - 1;
  473. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes++], TEXT(" "));
  474. } else {
  475. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("CPU Unknown "));
  476. dwBytes += strlen(TEXT("CPU Unknown "));
  477. }
  478. RegCloseKey(hkeySysInfo);
  479. } else {
  480. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("CPU Unknown "));
  481. dwBytes += strlen(TEXT("CPU Unknown "));
  482. }
  483. dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  484. REG_KEY_SYSTEM,
  485. 0,
  486. KEY_QUERY_VALUE |
  487. KEY_ENUMERATE_SUB_KEYS,
  488. &hkeySysInfo);
  489. if (dwResult is NO_ERROR) {
  490. dwValueLen = sizeof(pRpcSysInfo->rgbySysDescr) - dwBytes;
  491. dwResult = RegQueryValueEx(hkeySysInfo,
  492. TEXT("Identifier"),
  493. 0,
  494. &dwValueType,
  495. &pRpcSysInfo->rgbySysDescr[dwBytes],
  496. &dwValueLen);
  497. if (dwResult is NO_ERROR) {
  498. dwBytes += dwValueLen - 1;
  499. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes++], TEXT(" "));
  500. } else {
  501. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("SystemType Unknown "));
  502. dwBytes += strlen(TEXT("SystemType Unknown "));
  503. }
  504. RegCloseKey(hkeySysInfo);
  505. } else {
  506. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("SystemType Unknown "));
  507. dwBytes += strlen(TEXT("SystemType Unknown "));
  508. }
  509. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT_SOFTWARE_WINDOWS_VERSION);
  510. dwBytes += strlen(TEXT_SOFTWARE_WINDOWS_VERSION);
  511. dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  512. REG_KEY_VERSION,
  513. 0,
  514. KEY_QUERY_VALUE |
  515. KEY_ENUMERATE_SUB_KEYS,
  516. &hkeySysInfo);
  517. if (dwResult is NO_ERROR) {
  518. dwValueLen = sizeof(pRpcSysInfo->rgbySysDescr) - dwBytes;
  519. dwResult = RegQueryValueEx(hkeySysInfo,
  520. TEXT("CurrentVersion"),
  521. 0,
  522. &dwValueType,
  523. &pRpcSysInfo->rgbySysDescr[dwBytes],
  524. &dwValueLen);
  525. if (dwResult is NO_ERROR) {
  526. dwBytes += dwValueLen - 1;
  527. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes++], TEXT(" "));
  528. } else {
  529. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("Unknown "));
  530. dwBytes += strlen(TEXT("Unknown "));
  531. }
  532. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("(Build "));
  533. dwBytes += strlen(TEXT("(Build "));
  534. dwValueLen = sizeof(pRpcSysInfo->rgbySysDescr) - dwBytes;
  535. dwResult = RegQueryValueEx(hkeySysInfo,
  536. TEXT("CurrentBuildNumber"),
  537. 0,
  538. &dwValueType,
  539. &pRpcSysInfo->rgbySysDescr[dwBytes],
  540. &dwValueLen);
  541. if (dwResult is NO_ERROR) {
  542. dwBytes += dwValueLen - 1;
  543. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes++], TEXT(" "));
  544. } else {
  545. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("Unknown "));
  546. dwBytes += strlen(TEXT("Unknown "));
  547. }
  548. dwValueLen = sizeof(pRpcSysInfo->rgbySysDescr) - dwBytes;
  549. dwResult = RegQueryValueEx(hkeySysInfo,
  550. TEXT("CurrentType"),
  551. 0,
  552. &dwValueType,
  553. &pRpcSysInfo->rgbySysDescr[dwBytes],
  554. &dwValueLen);
  555. if (dwResult is NO_ERROR) {
  556. dwBytes += dwValueLen - 1;
  557. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes++], TEXT(")"));
  558. } else {
  559. pRpcSysInfo->rgbySysDescr[dwBytes - 1] = ')';
  560. }
  561. RegCloseKey(hkeySysInfo);
  562. } else {
  563. strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("Unknown"));
  564. dwBytes += strlen(TEXT("Unknown"));
  565. }
  566. *ppRpcSysInfo = pRpcSysInfo;
  567. TraceLeave("GetSysInfo");
  568. return NO_ERROR;
  569. }
  570. VOID
  571. FreeIpv6IfTable()
  572. {
  573. if (g_Cache.pRpcIpv6IfTable.table) {
  574. HeapFree(g_hPrivateHeap,
  575. 0,
  576. g_Cache.pRpcIpv6IfTable.table);
  577. g_Cache.pRpcIpv6IfTable.table = NULL;
  578. g_Cache.pRpcIpv6IfTable.dwNumEntries = 0;
  579. }
  580. }
  581. VOID
  582. FreeIpv6AddrTable()
  583. {
  584. if (g_Cache.pRpcIpv6AddrTable.table) {
  585. HeapFree(g_hPrivateHeap,
  586. 0,
  587. g_Cache.pRpcIpv6AddrTable.table);
  588. g_Cache.pRpcIpv6AddrTable.table = NULL;
  589. g_Cache.pRpcIpv6AddrTable.dwNumEntries = 0;
  590. }
  591. }
  592. VOID
  593. FreeIpv6NetToMediaTable()
  594. {
  595. if (g_Cache.pRpcIpv6NetToMediaTable.table) {
  596. HeapFree(g_hPrivateHeap,
  597. 0,
  598. g_Cache.pRpcIpv6NetToMediaTable.table);
  599. g_Cache.pRpcIpv6NetToMediaTable.table = NULL;
  600. g_Cache.pRpcIpv6NetToMediaTable.dwNumEntries = 0;
  601. }
  602. }
  603. VOID
  604. FreeInetIcmpTable()
  605. {
  606. if (g_Cache.pRpcInetIcmpTable.table) {
  607. HeapFree(g_hPrivateHeap,
  608. 0,
  609. g_Cache.pRpcInetIcmpTable.table);
  610. g_Cache.pRpcInetIcmpTable.table = NULL;
  611. g_Cache.pRpcInetIcmpTable.dwNumEntries = 0;
  612. }
  613. }
  614. VOID
  615. FreeInetIcmpMsgTable()
  616. {
  617. if (g_Cache.pRpcInetIcmpMsgTable.table) {
  618. HeapFree(g_hPrivateHeap,
  619. 0,
  620. g_Cache.pRpcInetIcmpMsgTable.table);
  621. g_Cache.pRpcInetIcmpMsgTable.table = NULL;
  622. g_Cache.pRpcInetIcmpMsgTable.dwNumEntries = 0;
  623. }
  624. }
  625. VOID
  626. FreeIpv6RouteTable()
  627. {
  628. if (g_Cache.pRpcIpv6RouteTable.table) {
  629. HeapFree(g_hPrivateHeap,
  630. 0,
  631. g_Cache.pRpcIpv6RouteTable.table);
  632. g_Cache.pRpcIpv6RouteTable.table = NULL;
  633. g_Cache.pRpcIpv6RouteTable.dwNumEntries = 0;
  634. }
  635. if (g_Cache.pRpcIpv6AddrPrefixTable.table) {
  636. HeapFree(g_hPrivateHeap,
  637. 0,
  638. g_Cache.pRpcIpv6AddrPrefixTable.table);
  639. g_Cache.pRpcIpv6AddrPrefixTable.table = NULL;
  640. g_Cache.pRpcIpv6AddrPrefixTable.dwNumEntries = 0;
  641. }
  642. }
  643. typedef enum {
  644. Preferred = 1,
  645. Deprecated,
  646. Invalid,
  647. Inaccessible,
  648. Unknown
  649. }MIB_ADDR_STATUS;
  650. //
  651. // This array gives the MIB state we report for each internal
  652. // address state.
  653. //
  654. DWORD
  655. MibAddrState[] = {
  656. Invalid, // DAD_STATE_INVALID
  657. Unknown, // DAD_STATE_TENTATIVE
  658. Unknown, // DAD_STATE_DUPLICATE
  659. Deprecated, // DAD_STATE_DEPRECATED
  660. Preferred // DAD_STATE_PREFERRED
  661. };
  662. int
  663. __cdecl
  664. CompareIpv6IfRow(
  665. CONST VOID *pvElem1,
  666. CONST VOID *pvElem2
  667. )
  668. {
  669. LONG lResult;
  670. PMIB_IPV6_IF pRow1 = (PMIB_IPV6_IF)pvElem1;
  671. PMIB_IPV6_IF pRow2 = (PMIB_IPV6_IF)pvElem2;
  672. return Cmp(pRow1->dwIndex, pRow2->dwIndex, lResult);
  673. }
  674. int
  675. __cdecl
  676. CompareInetIcmpRow(
  677. CONST VOID *pvElem1,
  678. CONST VOID *pvElem2
  679. )
  680. {
  681. LONG lResult;
  682. PMIB_INET_ICMP pRow1 = (PMIB_INET_ICMP)pvElem1;
  683. PMIB_INET_ICMP pRow2 = (PMIB_INET_ICMP)pvElem2;
  684. if(Cmp(pRow1->dwAFType,
  685. pRow2->dwAFType,
  686. lResult) isnot 0)
  687. {
  688. return lResult;
  689. }
  690. return Cmp(pRow1->dwIfIndex, pRow2->dwIfIndex, lResult);
  691. }
  692. int
  693. __cdecl
  694. CompareInetIcmpMsgRow(
  695. CONST VOID *pvElem1,
  696. CONST VOID *pvElem2
  697. )
  698. {
  699. LONG lResult;
  700. PMIB_INET_ICMP_MSG pRow1 = (PMIB_INET_ICMP_MSG)pvElem1;
  701. PMIB_INET_ICMP_MSG pRow2 = (PMIB_INET_ICMP_MSG)pvElem2;
  702. if(Cmp(pRow1->dwAFType,
  703. pRow2->dwAFType,
  704. lResult) isnot 0)
  705. {
  706. return lResult;
  707. }
  708. if(Cmp(pRow1->dwIfIndex,
  709. pRow2->dwIfIndex,
  710. lResult) isnot 0)
  711. {
  712. return lResult;
  713. }
  714. if(Cmp(pRow1->dwType,
  715. pRow2->dwType,
  716. lResult) isnot 0)
  717. {
  718. return lResult;
  719. }
  720. return Cmp(pRow1->dwCode, pRow2->dwCode, lResult);
  721. }
  722. int
  723. __cdecl
  724. CompareIpv6AddrRow(
  725. CONST VOID *pvElem1,
  726. CONST VOID *pvElem2
  727. )
  728. {
  729. LONG lResult;
  730. PMIB_IPV6_ADDR pRow1 = (PMIB_IPV6_ADDR)pvElem1;
  731. PMIB_IPV6_ADDR pRow2 = (PMIB_IPV6_ADDR)pvElem2;
  732. if(Cmp(pRow1->dwIfIndex,
  733. pRow2->dwIfIndex,
  734. lResult) isnot 0)
  735. {
  736. return lResult;
  737. }
  738. return memcmp(&pRow1->ipAddress,
  739. &pRow2->ipAddress,
  740. sizeof(IN6_ADDR));
  741. }
  742. int
  743. __cdecl
  744. CompareIpv6NetToMediaRow(
  745. CONST VOID *pvElem1,
  746. CONST VOID *pvElem2
  747. )
  748. {
  749. LONG lResult;
  750. PMIB_IPV6_NET_TO_MEDIA pRow1 = (PMIB_IPV6_NET_TO_MEDIA)pvElem1;
  751. PMIB_IPV6_NET_TO_MEDIA pRow2 = (PMIB_IPV6_NET_TO_MEDIA)pvElem2;
  752. if(Cmp(pRow1->dwIfIndex,
  753. pRow2->dwIfIndex,
  754. lResult) isnot 0)
  755. {
  756. return lResult;
  757. }
  758. return memcmp(&pRow1->ipAddress,
  759. &pRow2->ipAddress,
  760. sizeof(IN6_ADDR));
  761. }
  762. int
  763. __cdecl
  764. CompareIpv6RouteRow(
  765. CONST VOID *pvElem1,
  766. CONST VOID *pvElem2
  767. )
  768. {
  769. LONG lResult;
  770. PMIB_IPV6_ROUTE pRow1 = (PMIB_IPV6_ROUTE)pvElem1;
  771. PMIB_IPV6_ROUTE pRow2 = (PMIB_IPV6_ROUTE)pvElem2;
  772. lResult = memcmp(&pRow1->ipPrefix,
  773. &pRow2->ipPrefix,
  774. sizeof(IN6_ADDR));
  775. if (lResult isnot 0)
  776. {
  777. return lResult;
  778. }
  779. if(Cmp(pRow1->dwPrefixLength,
  780. pRow2->dwPrefixLength,
  781. lResult) isnot 0)
  782. {
  783. return lResult;
  784. }
  785. return Cmp(pRow1->dwIndex,
  786. pRow2->dwIndex,
  787. lResult);
  788. }
  789. int
  790. __cdecl
  791. CompareIpv6AddrPrefixRow(
  792. CONST VOID *pvElem1,
  793. CONST VOID *pvElem2
  794. )
  795. {
  796. LONG lResult;
  797. PMIB_IPV6_ADDR_PREFIX pRow1 = (PMIB_IPV6_ADDR_PREFIX)pvElem1;
  798. PMIB_IPV6_ADDR_PREFIX pRow2 = (PMIB_IPV6_ADDR_PREFIX)pvElem2;
  799. if(Cmp(pRow1->dwIfIndex,
  800. pRow2->dwIfIndex,
  801. lResult) isnot 0)
  802. {
  803. return lResult;
  804. }
  805. lResult = memcmp(&pRow1->ipPrefix,
  806. &pRow2->ipPrefix,
  807. sizeof(IN6_ADDR));
  808. if (lResult isnot 0)
  809. {
  810. return lResult;
  811. }
  812. return Cmp(pRow1->dwPrefixLength,
  813. pRow2->dwPrefixLength,
  814. lResult);
  815. }
  816. DWORD
  817. LoadIpv6IfTable()
  818. {
  819. DWORD dwResult, dwOutBufLen = 0;
  820. DWORD dwIfCount, dwAddrCount, i;
  821. PIP_ADAPTER_ADDRESSES pFirstIf, pIf;
  822. PIP_ADAPTER_UNICAST_ADDRESS pUni;
  823. PIP_ADAPTER_ANYCAST_ADDRESS pAny;
  824. PMIB_IPV6_ADDR pAddr;
  825. PMIB_IPV6_IF pMibIf;
  826. TraceEnter("LoadIpv6IfTable");
  827. FreeIpv6IfTable();
  828. FreeIpv6AddrTable();
  829. dwResult = GetAdaptersAddresses(AF_INET6,
  830. GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER,
  831. NULL, NULL, &dwOutBufLen);
  832. if (dwResult == ERROR_NO_DATA) {
  833. return NO_ERROR;
  834. }
  835. pFirstIf = HeapAlloc(g_hPrivateHeap, 0, dwOutBufLen);
  836. if(pFirstIf == NULL)
  837. {
  838. TraceLeave("LoadIpv6IfTable");
  839. return GetLastError();
  840. }
  841. dwResult = GetAdaptersAddresses(AF_INET6,
  842. GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER,
  843. NULL, pFirstIf, &dwOutBufLen);
  844. if(dwResult isnot NO_ERROR)
  845. {
  846. TRACE1("GetIpv6IfTable failed with error %x",
  847. dwResult);
  848. goto Cleanup;
  849. }
  850. dwAddrCount = dwIfCount = 0;
  851. for (pIf=pFirstIf; pIf; pIf=pIf->Next) {
  852. dwIfCount++;
  853. for (pUni=pIf->FirstUnicastAddress; pUni; pUni=pUni->Next) {
  854. dwAddrCount++;
  855. }
  856. for (pAny=pIf->FirstAnycastAddress; pAny; pAny=pAny->Next) {
  857. dwAddrCount++;
  858. }
  859. }
  860. //
  861. // Create the interface table
  862. //
  863. g_Cache.pRpcIpv6IfTable.table = HeapAlloc(g_hPrivateHeap, 0, dwIfCount * sizeof(MIB_IPV6_IF));
  864. if (!g_Cache.pRpcIpv6IfTable.table) {
  865. TraceLeave("LoadIpv6IfTable");
  866. dwResult = GetLastError();
  867. goto Cleanup;
  868. }
  869. for (pIf=pFirstIf; pIf; pIf=pIf->Next) {
  870. i = g_Cache.pRpcIpv6IfTable.dwNumEntries++;
  871. pMibIf = &g_Cache.pRpcIpv6IfTable.table[i];
  872. pMibIf->dwIndex = pIf->Ipv6IfIndex;
  873. pMibIf->dwEffectiveMtu = pIf->Mtu;
  874. pMibIf->dwReasmMaxSize = 65535;
  875. pMibIf->dwAdminStatus = 1; /* up */
  876. pMibIf->dwOperStatus = pIf->OperStatus;
  877. pMibIf->dwLastChange = 0;
  878. pMibIf->dwPhysicalAddressLength = pIf->PhysicalAddressLength;
  879. memcpy(pMibIf->bPhysicalAddress, pIf->PhysicalAddress,
  880. pIf->PhysicalAddressLength);
  881. wcscpy(pMibIf->wszDescription, pIf->Description);
  882. }
  883. qsort(g_Cache.pRpcIpv6IfTable.table,
  884. dwIfCount,
  885. sizeof(MIB_IPV6_IF),
  886. CompareIpv6IfRow);
  887. //
  888. // Create the address table
  889. //
  890. g_Cache.pRpcIpv6AddrTable.table = HeapAlloc(g_hPrivateHeap, 0, dwAddrCount * sizeof(MIB_IPV6_ADDR));
  891. if (!g_Cache.pRpcIpv6AddrTable.table) {
  892. dwResult = GetLastError();
  893. goto Cleanup;
  894. }
  895. for (pIf=pFirstIf; pIf; pIf=pIf->Next) {
  896. for (pUni=pIf->FirstUnicastAddress; pUni; pUni=pUni->Next) {
  897. i = g_Cache.pRpcIpv6AddrTable.dwNumEntries++;
  898. pAddr = &g_Cache.pRpcIpv6AddrTable.table[i];
  899. pAddr->dwIfIndex = pIf->Ipv6IfIndex;
  900. pAddr->ipAddress = ((LPSOCKADDR_IN6)pUni->Address.lpSockaddr)->sin6_addr;
  901. pAddr->dwPrefixLength = 64;
  902. pAddr->dwType = 1;
  903. pAddr->dwAnycastFlag = 2;
  904. pAddr->dwStatus = (pIf->OperStatus == IfOperStatusUp)
  905. ? MibAddrState[pUni->DadState]
  906. : Inaccessible;
  907. }
  908. for (pAny=pIf->FirstAnycastAddress; pAny; pAny=pAny->Next) {
  909. i = g_Cache.pRpcIpv6AddrTable.dwNumEntries++;
  910. pAddr = &g_Cache.pRpcIpv6AddrTable.table[i];
  911. pAddr->dwIfIndex = pIf->Ipv6IfIndex;
  912. pAddr->ipAddress = ((LPSOCKADDR_IN6)pAny->Address.lpSockaddr)->sin6_addr;
  913. pAddr->dwPrefixLength = 64;
  914. pAddr->dwType = 1;
  915. pAddr->dwAnycastFlag = 1;
  916. pAddr->dwStatus = 1;
  917. }
  918. }
  919. qsort(g_Cache.pRpcIpv6AddrTable.table,
  920. dwAddrCount,
  921. sizeof(MIB_IPV6_ADDR),
  922. CompareIpv6AddrRow);
  923. Cleanup:
  924. HeapFree(g_hPrivateHeap, 0, pFirstIf);
  925. TraceLeave("LoadIpv6IfTable");
  926. return dwResult;
  927. }
  928. //
  929. // This array gives the ICMP message type value for each field
  930. // in the ICMPStats structure (in ipinfo.h) and MIBICMPSTATS
  931. // structure (in iprtrmib.h), which are identical. A value of
  932. // -1 means that the field does not count messages for a specific
  933. // type value.
  934. //
  935. DWORD
  936. Ipv4IcmpFieldMsg[] = {
  937. -1, // dwMsgs
  938. -1, // dwErrors
  939. 3, // dwDestUnreachs
  940. 11, // dwTimeExcds
  941. 12, // dwParmProbs
  942. 4, // dwSrcQuenchs
  943. 5, // dwRedirects
  944. 8, // dwEchos
  945. 0, // dwEchoReps
  946. 13, // dwTimestamps
  947. 14, // dwTimestampReps
  948. 17, // dwAddrMasks
  949. 18, // dwAddrMaskReps
  950. };
  951. DWORD
  952. LoadInetIcmpTable()
  953. {
  954. PMIB_INET_ICMP pRow;
  955. PMIB_INET_ICMP_MSG pMsg;
  956. MIB_ICMP Icmp4;
  957. ICMPv6SNMPInfo Icmp6;
  958. DWORD dwResult4, dwResult6, dwResult = NO_ERROR;
  959. DWORD i, j, k, dwRowCount = 0, dwMsgCount = 0;
  960. TraceEnter("LoadInetIcmpTable");
  961. FreeInetIcmpTable();
  962. FreeInetIcmpMsgTable();
  963. dwResult4 = GetIcmpStatistics(&Icmp4);
  964. if (dwResult4 == NO_ERROR) {
  965. dwRowCount++;
  966. for (j=0; j<sizeof(MIBICMPSTATS)/sizeof(DWORD); j++) {
  967. if (Ipv4IcmpFieldMsg[j] == -1) {
  968. continue;
  969. }
  970. if ((((DWORD*)&Icmp4.stats.icmpInStats)[j] > 0) ||
  971. (((DWORD*)&Icmp4.stats.icmpOutStats)[j] > 0)) {
  972. dwMsgCount++;
  973. }
  974. }
  975. }
  976. dwResult6 = GetIcmpStatsFromStackEx((PVOID)&Icmp6, AF_INET6);
  977. if (dwResult6 == NO_ERROR) {
  978. dwRowCount++;
  979. for (k=0; k<256; k++) {
  980. if ((Icmp6.icsi_instats.icmps_typecount[k] > 0) ||
  981. (Icmp6.icsi_outstats.icmps_typecount[k] > 0)) {
  982. dwMsgCount++;
  983. }
  984. }
  985. }
  986. //
  987. // Create the ICMP table
  988. //
  989. g_Cache.pRpcInetIcmpTable.table = HeapAlloc(g_hPrivateHeap, 0,
  990. dwRowCount * sizeof(MIB_INET_ICMP));
  991. if (!g_Cache.pRpcInetIcmpTable.table) {
  992. TraceLeave("LoadInetIcmpTable");
  993. dwResult = GetLastError();
  994. goto Cleanup;
  995. }
  996. if (dwResult4 == NO_ERROR) {
  997. i = g_Cache.pRpcInetIcmpTable.dwNumEntries++;
  998. pRow = &g_Cache.pRpcInetIcmpTable.table[i];
  999. pRow->dwAFType = 1; // IPv4
  1000. pRow->dwIfIndex = 0; // global
  1001. pRow->dwInMsgs = Icmp4.stats.icmpInStats.dwMsgs;
  1002. pRow->dwInErrors = Icmp4.stats.icmpInStats.dwErrors;
  1003. pRow->dwOutMsgs = Icmp4.stats.icmpOutStats.dwMsgs;
  1004. pRow->dwOutErrors = Icmp4.stats.icmpOutStats.dwErrors;
  1005. }
  1006. if (dwResult6 == NO_ERROR) {
  1007. i = g_Cache.pRpcInetIcmpTable.dwNumEntries++;
  1008. pRow = &g_Cache.pRpcInetIcmpTable.table[i];
  1009. pRow->dwAFType = 2; // IPv6
  1010. pRow->dwIfIndex = 0; // global
  1011. pRow->dwInMsgs = Icmp6.icsi_instats.icmps_msgs;
  1012. pRow->dwInErrors = Icmp6.icsi_instats.icmps_errors;
  1013. pRow->dwOutMsgs = Icmp6.icsi_outstats.icmps_msgs;
  1014. pRow->dwOutErrors = Icmp6.icsi_outstats.icmps_errors;
  1015. }
  1016. qsort(g_Cache.pRpcInetIcmpTable.table,
  1017. dwRowCount,
  1018. sizeof(MIB_INET_ICMP),
  1019. CompareInetIcmpRow);
  1020. //
  1021. // Create the ICMP message table
  1022. //
  1023. g_Cache.pRpcInetIcmpMsgTable.table = HeapAlloc(g_hPrivateHeap, 0,
  1024. dwMsgCount * sizeof(MIB_INET_ICMP_MSG));
  1025. if (!g_Cache.pRpcInetIcmpMsgTable.table) {
  1026. dwResult = GetLastError();
  1027. goto Cleanup;
  1028. }
  1029. if (dwResult4 == NO_ERROR) {
  1030. for (j=0; j<sizeof(MIBICMPSTATS)/sizeof(DWORD); j++) {
  1031. k = Ipv4IcmpFieldMsg[j];
  1032. if (k == -1) {
  1033. continue;
  1034. }
  1035. if ((((DWORD*)&Icmp4.stats.icmpInStats)[j] > 0) ||
  1036. (((DWORD*)&Icmp4.stats.icmpOutStats)[j] > 0)) {
  1037. i = g_Cache.pRpcInetIcmpMsgTable.dwNumEntries++;
  1038. pMsg = &g_Cache.pRpcInetIcmpMsgTable.table[i];
  1039. pMsg->dwAFType = 1; // IPv4
  1040. pMsg->dwIfIndex = 0; // global
  1041. pMsg->dwType = k;
  1042. pMsg->dwCode = 256; // all codes combined
  1043. pMsg->dwInPkts = ((DWORD*)&Icmp4.stats.icmpInStats)[j];
  1044. pMsg->dwOutPkts = ((DWORD*)&Icmp4.stats.icmpOutStats)[j];
  1045. }
  1046. }
  1047. }
  1048. if (dwResult6 == NO_ERROR) {
  1049. for (k=0; k<256; k++) {
  1050. if ((Icmp6.icsi_instats.icmps_typecount[k] > 0) ||
  1051. (Icmp6.icsi_outstats.icmps_typecount[k] > 0)) {
  1052. i = g_Cache.pRpcInetIcmpMsgTable.dwNumEntries++;
  1053. pMsg = &g_Cache.pRpcInetIcmpMsgTable.table[i];
  1054. pMsg->dwAFType = 2; // IPv6
  1055. pMsg->dwIfIndex = 0; // global
  1056. pMsg->dwType = k;
  1057. pMsg->dwCode = 256; // all codes combined
  1058. pMsg->dwInPkts = Icmp6.icsi_instats.icmps_typecount[k];
  1059. pMsg->dwOutPkts = Icmp6.icsi_outstats.icmps_typecount[k];
  1060. }
  1061. }
  1062. }
  1063. qsort(g_Cache.pRpcInetIcmpMsgTable.table,
  1064. dwMsgCount,
  1065. sizeof(MIB_INET_ICMP_MSG),
  1066. CompareInetIcmpMsgRow);
  1067. Cleanup:
  1068. TraceLeave("LoadInetIcmpTable");
  1069. return dwResult;
  1070. }
  1071. HANDLE g_hIpv6Handle = INVALID_HANDLE_VALUE;
  1072. VOID
  1073. OpenIpv6()
  1074. {
  1075. g_hIpv6Handle = CreateFileW(WIN_IPV6_DEVICE_NAME,
  1076. 0,
  1077. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1078. NULL, // security attributes
  1079. OPEN_EXISTING,
  1080. 0, // flags & attributes
  1081. NULL); // template file
  1082. }
  1083. DWORD
  1084. CountNeighbors(
  1085. IN IPV6_INFO_INTERFACE *IF,
  1086. IN PVOID Arg)
  1087. {
  1088. BYTE bNceBuffer[sizeof(IPV6_INFO_NEIGHBOR_CACHE) + MAX_LINK_LAYER_ADDRESS_LENGTH];
  1089. IPV6_INFO_NEIGHBOR_CACHE *NCE = (IPV6_INFO_NEIGHBOR_CACHE *)bNceBuffer;
  1090. IPV6_QUERY_NEIGHBOR_CACHE Query, NextQuery;
  1091. DWORD dwInfoSize, dwBytesReturned;
  1092. DWORD *pdwCount = (DWORD*)Arg;
  1093. NextQuery.IF = IF->This;
  1094. NextQuery.Address = in6addr_any;
  1095. for (;;) {
  1096. Query = NextQuery;
  1097. dwInfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH;
  1098. if (!DeviceIoControl(g_hIpv6Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE,
  1099. &Query, sizeof Query,
  1100. NCE, dwInfoSize, &dwBytesReturned, NULL)) {
  1101. return GetLastError();
  1102. }
  1103. NextQuery = NCE->Query;
  1104. if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
  1105. (*pdwCount)++;
  1106. }
  1107. if (IN6_ADDR_EQUAL(&NextQuery.Address, &in6addr_any))
  1108. break;
  1109. }
  1110. return NO_ERROR;
  1111. }
  1112. typedef enum {
  1113. NtmsReachable = 1,
  1114. NtmsStale,
  1115. NtmsDelay,
  1116. NtmsProbe,
  1117. NtmsInvalid,
  1118. NtmsUnknown
  1119. }NET_TO_MEDIA_STATE;
  1120. DWORD
  1121. NDToMibState[] = {
  1122. NtmsStale, NtmsProbe, NtmsDelay, NtmsStale, NtmsReachable, NtmsReachable
  1123. };
  1124. typedef enum {
  1125. NtmtOther = 1,
  1126. NtmtDynamic,
  1127. NtmtStatic,
  1128. NtmtLocal
  1129. }NET_TO_MEDIA_TYPE;
  1130. DWORD
  1131. LoadNeighbors(
  1132. IN IPV6_INFO_INTERFACE *IF,
  1133. IN PVOID Arg)
  1134. {
  1135. BYTE bNceBuffer[sizeof(IPV6_INFO_NEIGHBOR_CACHE) + MAX_LINK_LAYER_ADDRESS_LENGTH];
  1136. IPV6_INFO_NEIGHBOR_CACHE *NCE = (IPV6_INFO_NEIGHBOR_CACHE *)bNceBuffer;
  1137. IPV6_QUERY_NEIGHBOR_CACHE Query, NextQuery;
  1138. DWORD dwInfoSize, dwBytesReturned, i;
  1139. PMIB_IPV6_NET_TO_MEDIA pRow;
  1140. DWORD *pdwCount = (DWORD*)Arg;
  1141. NextQuery.IF = IF->This;
  1142. NextQuery.Address = in6addr_any;
  1143. for (;;) {
  1144. Query = NextQuery;
  1145. dwInfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH;
  1146. if (!DeviceIoControl(g_hIpv6Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE,
  1147. &Query, sizeof Query,
  1148. NCE, dwInfoSize, &dwBytesReturned, NULL)) {
  1149. return GetLastError();
  1150. }
  1151. NextQuery = NCE->Query;
  1152. if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
  1153. i = g_Cache.pRpcIpv6NetToMediaTable.dwNumEntries++;
  1154. pRow = &g_Cache.pRpcIpv6NetToMediaTable.table[i];
  1155. pRow->dwIfIndex = Query.IF.Index;
  1156. pRow->ipAddress = Query.Address;
  1157. memcpy(pRow->bPhysAddress, NCE+1, NCE->LinkLayerAddressLength);
  1158. pRow->dwPhysAddressLen = NCE->LinkLayerAddressLength;
  1159. if (pRow->dwState == ND_STATE_PERMANENT) {
  1160. pRow->dwType = NtmtStatic;
  1161. } else {
  1162. pRow->dwType = NtmtDynamic;
  1163. }
  1164. pRow->dwState = NDToMibState[NCE->NDState];
  1165. pRow->dwLastUpdated = 0;
  1166. pRow->dwValid = 1;
  1167. if (g_Cache.pRpcIpv6NetToMediaTable.dwNumEntries == *pdwCount)
  1168. break;
  1169. }
  1170. if (IN6_ADDR_EQUAL(&NextQuery.Address, &in6addr_any))
  1171. break;
  1172. }
  1173. return NO_ERROR;
  1174. }
  1175. DWORD
  1176. ForEachInterface(
  1177. IN DWORD (*func)(IPV6_INFO_INTERFACE *, PVOID),
  1178. IN PVOID arg)
  1179. {
  1180. IPV6_QUERY_INTERFACE Query;
  1181. IPV6_INFO_INTERFACE *IF;
  1182. DWORD InfoSize, BytesReturned, dwResult = NO_ERROR;
  1183. InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  1184. IF = (IPV6_INFO_INTERFACE *) HeapAlloc(g_hPrivateHeap, 0, InfoSize);
  1185. if (IF == NULL) {
  1186. return GetLastError();
  1187. }
  1188. Query.Index = (u_int) -1;
  1189. for (;;) {
  1190. if (!DeviceIoControl(g_hIpv6Handle, IOCTL_IPV6_QUERY_INTERFACE,
  1191. &Query, sizeof Query,
  1192. IF, InfoSize, &BytesReturned,
  1193. NULL)) {
  1194. dwResult = GetLastError();
  1195. goto Cleanup;
  1196. }
  1197. if (Query.Index != (u_int) -1) {
  1198. if ((BytesReturned < sizeof *IF) ||
  1199. (IF->Length < sizeof *IF) ||
  1200. (BytesReturned != IF->Length +
  1201. ((IF->LocalLinkLayerAddress != 0) ?
  1202. IF->LinkLayerAddressLength : 0) +
  1203. ((IF->RemoteLinkLayerAddress != 0) ?
  1204. IF->LinkLayerAddressLength : 0))) {
  1205. goto Cleanup;
  1206. }
  1207. dwResult = (*func)(IF, arg);
  1208. if (dwResult != NO_ERROR) {
  1209. return dwResult;
  1210. }
  1211. }
  1212. if (IF->Next.Index == (u_int) -1)
  1213. break;
  1214. Query = IF->Next;
  1215. }
  1216. Cleanup:
  1217. HeapFree(g_hPrivateHeap, 0, IF);
  1218. return dwResult;
  1219. }
  1220. DWORD
  1221. ForEachRoute(
  1222. IN DWORD (*func)(IPV6_INFO_ROUTE_TABLE *, PVOID, PVOID),
  1223. IN PVOID Arg1,
  1224. IN PVOID Arg2)
  1225. {
  1226. IPV6_QUERY_ROUTE_TABLE Query, NextQuery;
  1227. IPV6_INFO_ROUTE_TABLE RTE;
  1228. DWORD BytesReturned;
  1229. NextQuery.Neighbor.IF.Index = 0;
  1230. for (;;) {
  1231. Query = NextQuery;
  1232. if (!DeviceIoControl(g_hIpv6Handle, IOCTL_IPV6_QUERY_ROUTE_TABLE,
  1233. &Query, sizeof Query,
  1234. &RTE, sizeof RTE, &BytesReturned,
  1235. NULL)) {
  1236. return GetLastError();
  1237. }
  1238. NextQuery = RTE.Next;
  1239. if (Query.Neighbor.IF.Index != 0) {
  1240. RTE.This = Query;
  1241. (*func)(&RTE, Arg1, Arg2);
  1242. }
  1243. if (NextQuery.Neighbor.IF.Index == 0)
  1244. break;
  1245. }
  1246. return NO_ERROR;
  1247. }
  1248. DWORD
  1249. LoadIpv6NetToMediaTable()
  1250. {
  1251. DWORD dwResult, dwOutBufLen = 0;
  1252. DWORD dwCount, i;
  1253. TraceEnter("LoadIpv6NetToMediaTable");
  1254. FreeIpv6NetToMediaTable();
  1255. OpenIpv6();
  1256. //
  1257. // Count entries
  1258. //
  1259. dwCount = 0;
  1260. ForEachInterface(CountNeighbors, &dwCount);
  1261. //
  1262. // Create the neighbor table
  1263. //
  1264. g_Cache.pRpcIpv6NetToMediaTable.table = HeapAlloc(g_hPrivateHeap, 0, dwCount * sizeof(MIB_IPV6_NET_TO_MEDIA));
  1265. if (!g_Cache.pRpcIpv6NetToMediaTable.table) {
  1266. TraceLeave("LoadIpv6NetToMediaTable");
  1267. return GetLastError();
  1268. }
  1269. //
  1270. // Load entries
  1271. //
  1272. dwResult = ForEachInterface(LoadNeighbors, &dwCount);
  1273. qsort(g_Cache.pRpcIpv6NetToMediaTable.table,
  1274. g_Cache.pRpcIpv6NetToMediaTable.dwNumEntries,
  1275. sizeof(MIB_IPV6_NET_TO_MEDIA),
  1276. CompareIpv6NetToMediaRow);
  1277. CloseHandle(g_hIpv6Handle);
  1278. TraceLeave("LoadIpv6NetToMediaTable");
  1279. return dwResult;
  1280. }
  1281. DWORD
  1282. CountRoute(
  1283. IN IPV6_INFO_ROUTE_TABLE *RTE,
  1284. IN PVOID Arg1,
  1285. IN PVOID Arg2)
  1286. {
  1287. DWORD *pdwRouteCount = (DWORD *)Arg1;
  1288. DWORD *pdwAddrPrefixCount = (DWORD *)Arg2;
  1289. //
  1290. // Suppress system routes (used for loopback).
  1291. //
  1292. if (RTE->Type == RTE_TYPE_SYSTEM) {
  1293. return NO_ERROR;
  1294. }
  1295. (*pdwRouteCount)++;
  1296. if ((RTE->This.PrefixLength > 0)
  1297. && (RTE->This.PrefixLength < 128)) {
  1298. (*pdwAddrPrefixCount)++;
  1299. }
  1300. return NO_ERROR;
  1301. }
  1302. DWORD
  1303. LoadRoute(
  1304. IN IPV6_INFO_ROUTE_TABLE *RTE,
  1305. IN PVOID Arg1,
  1306. IN PVOID Arg2)
  1307. {
  1308. DWORD *pdwRouteCount = (DWORD *)Arg1;
  1309. DWORD *pdwAddrPrefixCount = (DWORD *)Arg2;
  1310. DWORD i;
  1311. PMIB_IPV6_ROUTE pRoute;
  1312. PMIB_IPV6_ADDR_PREFIX pPrefix;
  1313. //
  1314. // Suppress system routes (used for loopback).
  1315. //
  1316. if (RTE->Type == RTE_TYPE_SYSTEM) {
  1317. return NO_ERROR;
  1318. }
  1319. if (g_Cache.pRpcIpv6RouteTable.dwNumEntries < *pdwRouteCount) {
  1320. i = g_Cache.pRpcIpv6RouteTable.dwNumEntries++;
  1321. pRoute = &g_Cache.pRpcIpv6RouteTable.table[i];
  1322. pRoute->ipPrefix = RTE->This.Prefix;
  1323. pRoute->dwPrefixLength = RTE->This.PrefixLength;
  1324. pRoute->ipNextHop = RTE->This.Neighbor.Address;
  1325. pRoute->dwIndex = g_Cache.pRpcIpv6RouteTable.dwNumEntries;
  1326. pRoute->dwIfIndex = RTE->This.Neighbor.IF.Index;
  1327. if (!memcmp(&RTE->This.Neighbor.Address, &in6addr_any, sizeof(IN6_ADDR))) {
  1328. pRoute->dwType = 3; /* Local */
  1329. } else {
  1330. pRoute->dwType = 4; /* Remote */
  1331. }
  1332. pRoute->dwProtocol = RTE->Type;
  1333. pRoute->dwPolicy = 0;
  1334. pRoute->dwAge = 0;
  1335. pRoute->dwNextHopRDI = 0;
  1336. pRoute->dwMetric = RTE->Preference;
  1337. pRoute->dwWeight = 0;
  1338. pRoute->dwValid = 1;
  1339. }
  1340. if ((g_Cache.pRpcIpv6AddrPrefixTable.dwNumEntries < *pdwAddrPrefixCount)
  1341. && (RTE->This.PrefixLength > 0)
  1342. && (RTE->This.PrefixLength < 128)) {
  1343. i = g_Cache.pRpcIpv6AddrPrefixTable.dwNumEntries++;
  1344. pPrefix = &g_Cache.pRpcIpv6AddrPrefixTable.table[i];
  1345. pPrefix->dwIfIndex = RTE->This.Neighbor.IF.Index;
  1346. pPrefix->ipPrefix = RTE->This.Prefix;
  1347. pPrefix->dwPrefixLength = RTE->This.PrefixLength;
  1348. if (!memcmp(&RTE->This.Neighbor.Address, &in6addr_any, sizeof(IN6_ADDR))) {
  1349. pPrefix->dwOnLinkFlag = 1; /* True */
  1350. } else {
  1351. pPrefix->dwOnLinkFlag = 2; /* False */
  1352. }
  1353. //
  1354. // TODO: The stack doesn't currently store this information,
  1355. // so always report True for now.
  1356. //
  1357. pPrefix->dwAutonomousFlag = 1; /* True */
  1358. pPrefix->dwPreferredLifetime = RTE->PreferredLifetime;
  1359. pPrefix->dwValidLifetime = RTE->ValidLifetime;
  1360. }
  1361. return NO_ERROR;
  1362. }
  1363. DWORD
  1364. LoadIpv6RouteTable()
  1365. {
  1366. DWORD dwResult, dwOutBufLen = 0;
  1367. DWORD dwRouteCount = 0, dwAddrPrefixCount = 0, i;
  1368. TraceEnter("LoadIpv6RouteTable");
  1369. FreeIpv6RouteTable();
  1370. OpenIpv6();
  1371. //
  1372. // Count entries
  1373. //
  1374. ForEachRoute(CountRoute, &dwRouteCount, &dwAddrPrefixCount);
  1375. //
  1376. // Create the tables
  1377. //
  1378. if (dwRouteCount) {
  1379. g_Cache.pRpcIpv6RouteTable.table = HeapAlloc(g_hPrivateHeap, 0, dwRouteCount * sizeof(MIB_IPV6_ROUTE));
  1380. if (!g_Cache.pRpcIpv6RouteTable.table) {
  1381. TraceLeave("LoadIpv6RouteTable");
  1382. return GetLastError();
  1383. }
  1384. }
  1385. if (dwAddrPrefixCount) {
  1386. g_Cache.pRpcIpv6AddrPrefixTable.table = HeapAlloc(g_hPrivateHeap, 0, dwAddrPrefixCount * sizeof(MIB_IPV6_ADDR_PREFIX));
  1387. if (!g_Cache.pRpcIpv6AddrPrefixTable.table) {
  1388. FreeIpv6RouteTable();
  1389. TraceLeave("LoadIpv6RouteTable");
  1390. return GetLastError();
  1391. }
  1392. }
  1393. //
  1394. // Load entries
  1395. //
  1396. dwResult = ForEachRoute(LoadRoute, &dwRouteCount, &dwAddrPrefixCount);
  1397. qsort(g_Cache.pRpcIpv6RouteTable.table,
  1398. g_Cache.pRpcIpv6RouteTable.dwNumEntries,
  1399. sizeof(MIB_IPV6_ROUTE),
  1400. CompareIpv6RouteRow);
  1401. qsort(g_Cache.pRpcIpv6AddrPrefixTable.table,
  1402. g_Cache.pRpcIpv6AddrPrefixTable.dwNumEntries,
  1403. sizeof(MIB_IPV6_ADDR_PREFIX),
  1404. CompareIpv6AddrPrefixRow);
  1405. CloseHandle(g_hIpv6Handle);
  1406. TraceLeave("LoadIpv6RouteTable");
  1407. return dwResult;
  1408. }