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.

3519 lines
100 KiB

  1. //=============================================================================
  2. // Copyright (c) 2001 Microsoft Corporation
  3. // Abstract:
  4. // This module implements IPv6 configuration commands.
  5. //
  6. // This code is based off ipv6.c from Rich Draves
  7. //=============================================================================
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. HANDLE Handle = INVALID_HANDLE_VALUE;
  11. BOOL AdminAccess = TRUE;
  12. #define IPv6_MINIMUM_MTU 1280
  13. #define MillisToSeconds(millis) ((millis) / 1000)
  14. DWORD
  15. SetString(
  16. IN HKEY hKey,
  17. IN LPCTSTR lpName,
  18. IN PWCHAR pwcValue
  19. );
  20. PWCHAR
  21. FormatTime(
  22. IN DWORD dwLife,
  23. OUT PWCHAR pwszLife
  24. )
  25. {
  26. DWORD dwDays, dwHours, dwMinutes;
  27. PWCHAR pwszNext = pwszLife;
  28. if (dwLife == INFINITE_LIFETIME) {
  29. swprintf(pwszNext, L"%s", TOKEN_VALUE_INFINITE);
  30. return pwszLife;
  31. }
  32. if (dwLife < MINUTES)
  33. goto FormatSeconds;
  34. if (dwLife < HOURS)
  35. goto FormatMinutes;
  36. if (dwLife < DAYS)
  37. goto FormatHours;
  38. dwDays = dwLife / DAYS;
  39. pwszNext += swprintf(pwszNext, L"%ud", dwDays);
  40. dwLife -= dwDays * DAYS;
  41. FormatHours:
  42. dwHours = dwLife / HOURS;
  43. if (dwHours != 0)
  44. pwszNext += swprintf(pwszNext, L"%uh", dwHours);
  45. dwLife -= dwHours * HOURS;
  46. FormatMinutes:
  47. dwMinutes = dwLife / MINUTES;
  48. if (dwMinutes != 0)
  49. pwszNext += swprintf(pwszNext, L"%um", dwMinutes);
  50. dwLife -= dwMinutes * MINUTES;
  51. if (dwLife == 0) {
  52. return pwszLife;
  53. }
  54. FormatSeconds:
  55. swprintf(pwszNext, L"%us", dwLife);
  56. return pwszLife;
  57. }
  58. DWORD
  59. OpenIPv6(
  60. FORMAT Format
  61. )
  62. {
  63. WSADATA wsaData;
  64. BOOL bInstalled;
  65. DWORD dwErr = NO_ERROR;
  66. if (Handle != INVALID_HANDLE_VALUE) {
  67. return NO_ERROR;
  68. }
  69. dwErr = IsIpv6Installed(&bInstalled);
  70. if (dwErr != NO_ERROR) {
  71. return dwErr;
  72. }
  73. if (!bInstalled) {
  74. if (Format != FORMAT_DUMP) {
  75. DisplayMessage(g_hModule, EMSG_PROTO_NOT_INSTALLED);
  76. }
  77. return ERROR_SUPPRESS_OUTPUT;
  78. }
  79. //
  80. // We initialize Winsock just so we can have access
  81. // to WSAStringToAddress and WSAAddressToString.
  82. //
  83. if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
  84. return WSAGetLastError();
  85. }
  86. //
  87. // First request write access.
  88. // This will fail if the process does not have local Administrator privs.
  89. //
  90. Handle = CreateFileW(WIN_IPV6_DEVICE_NAME,
  91. GENERIC_WRITE,
  92. FILE_SHARE_READ | FILE_SHARE_WRITE,
  93. NULL, // security attributes
  94. OPEN_EXISTING,
  95. 0, // flags & attributes
  96. NULL); // template file
  97. if (Handle == INVALID_HANDLE_VALUE) {
  98. //
  99. // We will not have Administrator access to the stack.
  100. //
  101. AdminAccess = FALSE;
  102. Handle = CreateFileW(WIN_IPV6_DEVICE_NAME,
  103. 0,
  104. FILE_SHARE_READ | FILE_SHARE_WRITE,
  105. NULL, // security attributes
  106. OPEN_EXISTING,
  107. 0, // flags & attributes
  108. NULL); // template file
  109. if (Handle == INVALID_HANDLE_VALUE) {
  110. return GetLastError();
  111. }
  112. }
  113. return NO_ERROR;
  114. }
  115. //////////////////////////////////////////////////////////////////////////////
  116. // Generic interface-related functions
  117. //////////////////////////////////////////////////////////////////////////////
  118. IPV6_INFO_INTERFACE *
  119. GetInterfaceByIpv6IfIndex(
  120. IN DWORD dwIfIndex
  121. )
  122. {
  123. IPV6_QUERY_INTERFACE Query;
  124. IPV6_INFO_INTERFACE *IF;
  125. DWORD dwInfoSize, dwBytesReturned;
  126. Query.Index = dwIfIndex;
  127. dwInfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  128. IF = (IPV6_INFO_INTERFACE *) MALLOC(dwInfoSize);
  129. if (IF == NULL) {
  130. return NULL;
  131. }
  132. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_INTERFACE,
  133. &Query, sizeof Query,
  134. IF, dwInfoSize, &dwBytesReturned,
  135. NULL)) {
  136. FREE(IF);
  137. return NULL;
  138. }
  139. if ((dwBytesReturned < sizeof *IF) ||
  140. (IF->Length < sizeof *IF) ||
  141. (dwBytesReturned != IF->Length +
  142. ((IF->LocalLinkLayerAddress != 0) ?
  143. IF->LinkLayerAddressLength : 0) +
  144. ((IF->RemoteLinkLayerAddress != 0) ?
  145. IF->LinkLayerAddressLength : 0))) {
  146. FREE(IF);
  147. return NULL;
  148. }
  149. return IF;
  150. }
  151. BOOL
  152. ConvertAdapterNameToGuid(
  153. IN LPSTR AdapterName,
  154. OUT GUID *Guid
  155. )
  156. {
  157. WCHAR GuidStr[40+1];
  158. UNICODE_STRING UGuidStr;
  159. if (MultiByteToWideChar(CP_ACP, 0, AdapterName, -1, GuidStr, 40) == 0) {
  160. return FALSE;
  161. }
  162. RtlInitUnicodeString(&UGuidStr, GuidStr);
  163. return RtlGUIDFromString(&UGuidStr, Guid) == STATUS_SUCCESS;
  164. }
  165. IPV6_INFO_INTERFACE *
  166. GetPersistentInterfaceByGuid(
  167. IN LPSTR AdapterName
  168. )
  169. {
  170. IPV6_PERSISTENT_QUERY_INTERFACE Query;
  171. IPV6_INFO_INTERFACE *IF;
  172. DWORD dwInfoSize, dwBytesReturned;
  173. Query.RegistryIndex = (u_int)-1;
  174. if (!ConvertAdapterNameToGuid(AdapterName, &Query.Guid)) {
  175. return NULL;
  176. }
  177. dwInfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  178. IF = (IPV6_INFO_INTERFACE *) MALLOC(dwInfoSize);
  179. if (IF == NULL) {
  180. return NULL;
  181. }
  182. if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_QUERY_INTERFACE,
  183. &Query, sizeof Query,
  184. IF, dwInfoSize, &dwBytesReturned,
  185. NULL)) {
  186. FREE(IF);
  187. return NULL;
  188. }
  189. if ((dwBytesReturned < sizeof *IF) ||
  190. (IF->Length < sizeof *IF) ||
  191. (dwBytesReturned != IF->Length +
  192. ((IF->LocalLinkLayerAddress != 0) ?
  193. IF->LinkLayerAddressLength : 0) +
  194. ((IF->RemoteLinkLayerAddress != 0) ?
  195. IF->LinkLayerAddressLength : 0))) {
  196. FREE(IF);
  197. return NULL;
  198. }
  199. return IF;
  200. }
  201. DWORD
  202. GetInterfaceByFriendlyName(
  203. IN PWCHAR pwszFriendlyName,
  204. IN IP_ADAPTER_ADDRESSES *pAdapterInfo,
  205. IN BOOL bPersistent,
  206. OUT IPV6_INFO_INTERFACE **pIF
  207. )
  208. {
  209. DWORD dwErr;
  210. if (bPersistent) {
  211. LPSTR AdapterName;
  212. dwErr = MapFriendlyNameToAdapterName(NULL, pwszFriendlyName,
  213. pAdapterInfo, &AdapterName);
  214. if (dwErr != NO_ERROR) {
  215. return dwErr;
  216. }
  217. *pIF = GetPersistentInterfaceByGuid(AdapterName);
  218. } else {
  219. UINT IfIndex;
  220. dwErr = MapFriendlyNameToIpv6IfIndex(pwszFriendlyName, pAdapterInfo,
  221. &IfIndex);
  222. if (dwErr != NO_ERROR) {
  223. return dwErr;
  224. }
  225. *pIF = GetInterfaceByIpv6IfIndex(IfIndex);
  226. }
  227. return (*pIF)? NO_ERROR : ERROR_NOT_FOUND;
  228. }
  229. DWORD
  230. MyGetAdaptersInfo(
  231. OUT PIP_ADAPTER_ADDRESSES *ppAdapterInfo
  232. )
  233. {
  234. IP_ADAPTER_ADDRESSES *pAdapterInfo;
  235. DWORD dwErr, BufLen = 0;
  236. DWORD Flags = GAA_FLAG_SKIP_MULTICAST;
  237. dwErr = GetAdaptersAddresses(AF_INET6, Flags, NULL, NULL, &BufLen);
  238. if (dwErr != ERROR_BUFFER_OVERFLOW) {
  239. return dwErr;
  240. }
  241. pAdapterInfo = (IP_ADAPTER_ADDRESSES *) MALLOC(BufLen);
  242. if (pAdapterInfo == NULL) {
  243. return GetLastError();
  244. }
  245. dwErr = GetAdaptersAddresses(AF_INET6, Flags, NULL, pAdapterInfo, &BufLen);
  246. if (dwErr != NO_ERROR) {
  247. FREE(pAdapterInfo);
  248. return dwErr;
  249. }
  250. *ppAdapterInfo = pAdapterInfo;
  251. return NO_ERROR;
  252. }
  253. DWORD
  254. ForEachPersistentInterface(
  255. IN DWORD (*pfnFunc)(IPV6_INFO_INTERFACE *,PIP_ADAPTER_ADDRESSES,DWORD,FORMAT,BOOL),
  256. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  257. IN FORMAT Format
  258. )
  259. {
  260. IPV6_PERSISTENT_QUERY_INTERFACE Query;
  261. IPV6_INFO_INTERFACE *IF;
  262. DWORD dwInfoSize, dwBytesReturned;
  263. DWORD dwCount = 0;
  264. dwInfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  265. IF = (IPV6_INFO_INTERFACE *) MALLOC(dwInfoSize);
  266. if (IF == NULL) {
  267. return 0;
  268. }
  269. for (Query.RegistryIndex = 0; ; Query.RegistryIndex++) {
  270. if (!DeviceIoControl(Handle,
  271. IOCTL_IPV6_PERSISTENT_QUERY_INTERFACE,
  272. &Query, sizeof Query,
  273. IF, dwInfoSize, &dwBytesReturned,
  274. NULL)) {
  275. break;
  276. }
  277. if ((dwBytesReturned < sizeof *IF) ||
  278. (IF->Length < sizeof *IF) ||
  279. (dwBytesReturned != IF->Length +
  280. ((IF->LocalLinkLayerAddress != 0) ?
  281. IF->LinkLayerAddressLength : 0) +
  282. ((IF->RemoteLinkLayerAddress != 0) ?
  283. IF->LinkLayerAddressLength : 0))) {
  284. break;
  285. }
  286. if ((*pfnFunc)(IF, pAdapterInfo, dwCount, Format, TRUE) == NO_ERROR) {
  287. dwCount++;
  288. }
  289. }
  290. FREE(IF);
  291. return dwCount;
  292. }
  293. DWORD
  294. ForEachInterface(
  295. IN DWORD (*pfnFunc)(IPV6_INFO_INTERFACE *,PIP_ADAPTER_ADDRESSES,DWORD,FORMAT,BOOL),
  296. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  297. IN FORMAT Format,
  298. IN BOOL bPersistent
  299. )
  300. {
  301. IPV6_QUERY_INTERFACE Query;
  302. IPV6_INFO_INTERFACE *IF;
  303. DWORD dwInfoSize, dwBytesReturned;
  304. DWORD dwCount = 0;
  305. if (bPersistent) {
  306. return ForEachPersistentInterface(pfnFunc, pAdapterInfo, Format);
  307. }
  308. dwInfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
  309. IF = (IPV6_INFO_INTERFACE *) MALLOC(dwInfoSize);
  310. if (IF == NULL) {
  311. return 0;
  312. }
  313. Query.Index = (u_int) -1;
  314. for (;;) {
  315. if (!DeviceIoControl(Handle,
  316. IOCTL_IPV6_QUERY_INTERFACE,
  317. &Query, sizeof Query,
  318. IF, dwInfoSize, &dwBytesReturned,
  319. NULL)) {
  320. break;
  321. }
  322. if (Query.Index != (u_int) -1) {
  323. if ((dwBytesReturned < sizeof *IF) ||
  324. (IF->Length < sizeof *IF) ||
  325. (dwBytesReturned != IF->Length +
  326. ((IF->LocalLinkLayerAddress != 0) ?
  327. IF->LinkLayerAddressLength : 0) +
  328. ((IF->RemoteLinkLayerAddress != 0) ?
  329. IF->LinkLayerAddressLength : 0))) {
  330. break;
  331. }
  332. if ((*pfnFunc)(IF, pAdapterInfo, dwCount, Format, FALSE) ==
  333. NO_ERROR) {
  334. dwCount++;
  335. }
  336. }
  337. else {
  338. if (dwBytesReturned != sizeof IF->Next) {
  339. break;
  340. }
  341. }
  342. if (IF->Next.Index == (u_int) -1)
  343. break;
  344. Query = IF->Next;
  345. }
  346. FREE(IF);
  347. return dwCount;
  348. }
  349. //////////////////////////////////////////////////////////////////////////////
  350. // Site prefix table functions
  351. //////////////////////////////////////////////////////////////////////////////
  352. DWORD
  353. ForEachSitePrefix(
  354. IN DWORD (*pfnFunc)(IPV6_INFO_SITE_PREFIX *,FORMAT,DWORD,IP_ADAPTER_ADDRESSES *),
  355. IN FORMAT Format,
  356. IN IP_ADAPTER_ADDRESSES *pAdapterInfo
  357. )
  358. {
  359. IPV6_QUERY_SITE_PREFIX Query, NextQuery;
  360. IPV6_INFO_SITE_PREFIX SPE;
  361. DWORD dwBytesReturned;
  362. DWORD dwCount = 0;
  363. NextQuery.IF.Index = 0;
  364. for (;;) {
  365. Query = NextQuery;
  366. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_SITE_PREFIX,
  367. &Query, sizeof Query,
  368. &SPE, sizeof SPE, &dwBytesReturned,
  369. NULL)) {
  370. break;
  371. }
  372. NextQuery = SPE.Query;
  373. if (Query.IF.Index != 0) {
  374. SPE.Query = Query;
  375. if ((*pfnFunc)(&SPE, Format, dwCount, pAdapterInfo) == NO_ERROR) {
  376. dwCount++;
  377. }
  378. }
  379. if (NextQuery.IF.Index == 0) {
  380. break;
  381. }
  382. }
  383. return dwCount;
  384. }
  385. DWORD
  386. PrintSitePrefix(
  387. IN IPV6_INFO_SITE_PREFIX *SPE,
  388. IN FORMAT Format,
  389. IN DWORD dwCount,
  390. IN IP_ADAPTER_ADDRESSES *pAdapterInfo
  391. )
  392. {
  393. DWORD dwErr;
  394. WCHAR *FriendlyName;
  395. WCHAR wszValid[64];
  396. dwErr = MapIpv6IfIndexToFriendlyName(SPE->Query.IF.Index, pAdapterInfo,
  397. &FriendlyName);
  398. if (dwErr != NO_ERROR) {
  399. return dwErr;
  400. }
  401. FormatTime(SPE->ValidLifetime, wszValid);
  402. if (Format == FORMAT_DUMP) {
  403. DisplayMessageT(DMP_IPV6_ADD_SITEPREFIX);
  404. DisplayMessageT(DMP_STRING_ARG, TOKEN_PREFIX,
  405. FormatIPv6Prefix(&SPE->Query.Prefix,
  406. SPE->Query.PrefixLength));
  407. DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE,
  408. FriendlyName);
  409. DisplayMessageT(DMP_STRING_ARG, TOKEN_LIFETIME, wszValid);
  410. DisplayMessage(g_hModule, MSG_NEWLINE);
  411. } else {
  412. if (!dwCount) {
  413. DisplayMessage(g_hModule, MSG_IPV6_SITE_PREFIX_HDR);
  414. }
  415. DisplayMessage(g_hModule, MSG_IPV6_SITE_PREFIX,
  416. FormatIPv6Prefix(&SPE->Query.Prefix, SPE->Query.PrefixLength),
  417. wszValid, FriendlyName);
  418. }
  419. return NO_ERROR;
  420. }
  421. DWORD
  422. QuerySitePrefixTable(
  423. IN FORMAT Format
  424. )
  425. {
  426. DWORD dwErr, dwCount = 0;
  427. IP_ADAPTER_ADDRESSES *pAdapterInfo;
  428. dwErr = OpenIPv6(Format);
  429. if (dwErr != NO_ERROR) {
  430. return dwErr;
  431. }
  432. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  433. if (dwErr != ERROR_NO_DATA) {
  434. if (dwErr == NO_ERROR) {
  435. dwCount = ForEachSitePrefix(PrintSitePrefix, Format, pAdapterInfo);
  436. FREE(pAdapterInfo);
  437. } else if (dwErr == ERROR_NO_DATA) {
  438. dwErr = NO_ERROR;
  439. }
  440. }
  441. if (!dwCount && (Format != FORMAT_DUMP)) {
  442. DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES);
  443. }
  444. return dwErr;
  445. }
  446. //////////////////////////////////////////////////////////////////////////////
  447. // General global parameters functions
  448. //////////////////////////////////////////////////////////////////////////////
  449. DWORD
  450. QueryGlobalParameters(
  451. IN FORMAT Format,
  452. IN BOOL bPersistent
  453. )
  454. {
  455. IPV6_GLOBAL_PARAMETERS Params;
  456. DWORD dwBytesReturned, dwErr;
  457. dwErr = OpenIPv6(Format);
  458. if (dwErr != NO_ERROR) {
  459. return dwErr;
  460. }
  461. if (Format != FORMAT_DUMP) {
  462. DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
  463. }
  464. if (!DeviceIoControl(Handle,
  465. (bPersistent)? IOCTL_IPV6_PERSISTENT_QUERY_GLOBAL_PARAMETERS : IOCTL_IPV6_QUERY_GLOBAL_PARAMETERS,
  466. NULL, 0,
  467. &Params, sizeof Params, &dwBytesReturned, NULL) ||
  468. (dwBytesReturned != sizeof Params)) {
  469. return GetLastError();
  470. }
  471. if (Format == FORMAT_DUMP) {
  472. if ((Params.DefaultCurHopLimit != -1) ||
  473. (Params.NeighborCacheLimit != -1) ||
  474. (Params.RouteCacheLimit != -1) ||
  475. (Params.ReassemblyLimit != -1)) {
  476. DisplayMessageT(DMP_IPV6_SET_GLOBAL);
  477. if (Params.DefaultCurHopLimit != -1) {
  478. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_DEFAULTCURHOPLIMIT,
  479. Params.DefaultCurHopLimit);
  480. }
  481. if (Params.NeighborCacheLimit != -1) {
  482. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_NEIGHBORCACHELIMIT,
  483. Params.NeighborCacheLimit);
  484. }
  485. if (Params.RouteCacheLimit != -1) {
  486. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_DESTINATIONCACHELIMIT,
  487. Params.RouteCacheLimit);
  488. }
  489. if (Params.ReassemblyLimit != -1) {
  490. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_REASSEMBLYLIMIT,
  491. Params.ReassemblyLimit);
  492. }
  493. }
  494. DisplayMessage(g_hModule, MSG_NEWLINE);
  495. } else {
  496. DisplayMessage(g_hModule, MSG_IPV6_GLOBAL_PARAMETERS,
  497. Params.DefaultCurHopLimit, Params.NeighborCacheLimit,
  498. Params.RouteCacheLimit, Params.ReassemblyLimit);
  499. }
  500. return NO_ERROR;
  501. }
  502. DWORD
  503. QueryPrivacyParameters(
  504. IN FORMAT Format,
  505. IN BOOL bPersistent
  506. )
  507. {
  508. IPV6_GLOBAL_PARAMETERS Params;
  509. DWORD dwBytesReturned, dwErr;
  510. WCHAR wszValid[64], wszPreferred[64], wszRegenerate[64];
  511. WCHAR wszMaxRandom[64], wszRandom[64];
  512. dwErr = OpenIPv6(Format);
  513. if (dwErr != NO_ERROR) {
  514. return dwErr;
  515. }
  516. if (Format != FORMAT_DUMP) {
  517. DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
  518. }
  519. if (!DeviceIoControl(Handle,
  520. (bPersistent)? IOCTL_IPV6_PERSISTENT_QUERY_GLOBAL_PARAMETERS : IOCTL_IPV6_QUERY_GLOBAL_PARAMETERS,
  521. NULL, 0,
  522. &Params, sizeof Params, &dwBytesReturned, NULL) ||
  523. (dwBytesReturned != sizeof Params)) {
  524. return GetLastError();
  525. }
  526. FormatTime(Params.MaxTempValidLifetime, wszValid);
  527. FormatTime(Params.MaxTempPreferredLifetime, wszPreferred);
  528. FormatTime(Params.TempRegenerateTime, wszRegenerate);
  529. FormatTime(Params.MaxTempRandomTime, wszMaxRandom);
  530. FormatTime(Params.TempRandomTime, wszRandom);
  531. if (Format == FORMAT_DUMP) {
  532. if ((Params.UseTemporaryAddresses != -1) ||
  533. (Params.MaxTempDADAttempts != -1) ||
  534. (Params.MaxTempValidLifetime != -1) ||
  535. (Params.MaxTempPreferredLifetime != -1) ||
  536. (Params.TempRegenerateTime != -1) ||
  537. (Params.MaxTempRandomTime != -1)) {
  538. DisplayMessageT(DMP_IPV6_SET_PRIVACY);
  539. if (Params.UseTemporaryAddresses != -1) {
  540. DisplayMessageT(DMP_STRING_ARG, TOKEN_STATE,
  541. ((Params.UseTemporaryAddresses == USE_TEMP_NO)?
  542. TOKEN_VALUE_DISABLED : TOKEN_VALUE_ENABLED));
  543. }
  544. if (Params.MaxTempDADAttempts != -1) {
  545. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_MAXDADATTEMPTS,
  546. Params.MaxTempDADAttempts);
  547. }
  548. if (Params.MaxTempValidLifetime != -1) {
  549. DisplayMessageT(DMP_STRING_ARG, TOKEN_MAXVALIDLIFETIME,
  550. wszValid);
  551. }
  552. if (Params.MaxTempPreferredLifetime != -1) {
  553. DisplayMessageT(DMP_STRING_ARG, TOKEN_MAXPREFERREDLIFETIME,
  554. wszPreferred);
  555. }
  556. if (Params.TempRegenerateTime != -1) {
  557. DisplayMessageT(DMP_STRING_ARG, TOKEN_REGENERATETIME,
  558. wszRegenerate);
  559. }
  560. if (Params.MaxTempRandomTime != -1) {
  561. DisplayMessageT(DMP_STRING_ARG, TOKEN_MAXRANDOMTIME,
  562. wszMaxRandom);
  563. }
  564. DisplayMessage(g_hModule, MSG_NEWLINE);
  565. }
  566. } else {
  567. DisplayMessage(
  568. g_hModule, MSG_IPV6_PRIVACY_PARAMETERS,
  569. ((Params.UseTemporaryAddresses == USE_TEMP_NO)
  570. ? TOKEN_VALUE_DISABLED
  571. : TOKEN_VALUE_ENABLED),
  572. Params.MaxTempDADAttempts,
  573. wszValid,
  574. wszPreferred,
  575. wszRegenerate,
  576. wszMaxRandom,
  577. wszRandom);
  578. }
  579. return NO_ERROR;
  580. }
  581. DWORD
  582. UpdateGlobalParameters(
  583. IN DWORD dwDefaultCurHopLimit,
  584. IN DWORD dwNeighborCacheLimit,
  585. IN DWORD dwRouteCacheLimit,
  586. IN DWORD dwReassemblyLimit,
  587. IN BOOL bPersistent
  588. )
  589. {
  590. IPV6_GLOBAL_PARAMETERS Params;
  591. DWORD dwBytesReturned;
  592. DWORD dwErr;
  593. dwErr = OpenIPv6(FORMAT_NORMAL);
  594. if (dwErr != NO_ERROR) {
  595. return dwErr;
  596. }
  597. IPV6_INIT_GLOBAL_PARAMETERS(&Params);
  598. Params.DefaultCurHopLimit = dwDefaultCurHopLimit;
  599. Params.NeighborCacheLimit = dwNeighborCacheLimit;
  600. Params.RouteCacheLimit = dwRouteCacheLimit;
  601. Params.ReassemblyLimit = dwReassemblyLimit;
  602. dwErr = ERROR_OKAY;
  603. if (bPersistent) {
  604. if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_GLOBAL_PARAMETERS,
  605. &Params, sizeof Params,
  606. NULL, 0,
  607. &dwBytesReturned, NULL)) {
  608. dwErr = GetLastError();
  609. }
  610. }
  611. if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_GLOBAL_PARAMETERS,
  612. &Params, sizeof Params,
  613. NULL, 0,
  614. &dwBytesReturned, NULL)) {
  615. if (dwErr == ERROR_OKAY) {
  616. dwErr = GetLastError();
  617. }
  618. }
  619. return dwErr;
  620. }
  621. DWORD
  622. UpdatePrivacyParameters(
  623. IN DWORD dwUseTemporaryAddresses,
  624. IN DWORD dwMaxDadAttempts,
  625. IN DWORD dwMaxValidLifetime,
  626. IN DWORD dwMaxPrefLifetime,
  627. IN DWORD dwRegenerateTime,
  628. IN DWORD dwMaxRandomTime,
  629. IN DWORD dwRandomTime,
  630. IN BOOL bPersistent
  631. )
  632. {
  633. IPV6_GLOBAL_PARAMETERS Params;
  634. DWORD dwBytesReturned;
  635. DWORD dwErr;
  636. dwErr = OpenIPv6(FORMAT_NORMAL);
  637. if (dwErr != NO_ERROR) {
  638. return dwErr;
  639. }
  640. IPV6_INIT_GLOBAL_PARAMETERS(&Params);
  641. Params.UseTemporaryAddresses = dwUseTemporaryAddresses;
  642. Params.MaxTempDADAttempts = dwMaxDadAttempts;
  643. Params.MaxTempValidLifetime = dwMaxValidLifetime;
  644. Params.MaxTempPreferredLifetime = dwMaxPrefLifetime;
  645. Params.TempRegenerateTime = dwRegenerateTime;
  646. Params.MaxTempRandomTime = dwMaxRandomTime;
  647. Params.TempRandomTime = dwRandomTime;
  648. dwErr = ERROR_OKAY;
  649. if (bPersistent) {
  650. if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_GLOBAL_PARAMETERS,
  651. &Params, sizeof Params,
  652. NULL, 0,
  653. &dwBytesReturned, NULL)) {
  654. dwErr = GetLastError();
  655. }
  656. }
  657. if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_GLOBAL_PARAMETERS,
  658. &Params, sizeof Params,
  659. NULL, 0,
  660. &dwBytesReturned, NULL)) {
  661. if (dwErr == ERROR_OKAY) {
  662. dwErr = GetLastError();
  663. }
  664. }
  665. return dwErr;
  666. }
  667. //////////////////////////////////////////////////////////////////////////////
  668. // Mobility-related functions
  669. //////////////////////////////////////////////////////////////////////////////
  670. DWORD
  671. ForEachBinding(
  672. IN DWORD (*pfnFunc)(IPV6_INFO_BINDING_CACHE *)
  673. )
  674. {
  675. IPV6_QUERY_BINDING_CACHE Query, NextQuery;
  676. IPV6_INFO_BINDING_CACHE BCE;
  677. DWORD dwBytesReturned;
  678. DWORD dwCount = 0;
  679. NextQuery.HomeAddress = in6addr_any;
  680. for (;;) {
  681. Query = NextQuery;
  682. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_BINDING_CACHE,
  683. &Query, sizeof Query,
  684. &BCE, sizeof BCE, &dwBytesReturned,
  685. NULL)) {
  686. DisplayMessage(g_hModule, IPV6_MESSAGE_126,
  687. FormatIPv6Address(&Query.HomeAddress, 0));
  688. break;
  689. }
  690. NextQuery = BCE.Query;
  691. if (!IN6_ADDR_EQUAL(&Query.HomeAddress, &in6addr_any)) {
  692. BCE.Query = Query;
  693. if ((*pfnFunc)(&BCE) == NO_ERROR) {
  694. dwCount++;
  695. }
  696. }
  697. if (IN6_ADDR_EQUAL(&NextQuery.HomeAddress, &in6addr_any)) {
  698. break;
  699. }
  700. }
  701. return dwCount;
  702. }
  703. DWORD
  704. PrintBindingCacheEntry(
  705. IN IPV6_INFO_BINDING_CACHE *BCE
  706. )
  707. {
  708. WCHAR wszTime[64];
  709. DisplayMessage(g_hModule, IPV6_MESSAGE_127,
  710. FormatIPv6Address(&BCE->HomeAddress, 0));
  711. DisplayMessage(g_hModule, IPV6_MESSAGE_128,
  712. FormatIPv6Address(&BCE->CareOfAddress, 0));
  713. DisplayMessage(g_hModule, IPV6_MESSAGE_129,
  714. BCE->BindingSeqNumber,
  715. FormatTime(BCE->BindingLifetime, wszTime));
  716. return NO_ERROR;
  717. }
  718. DWORD
  719. QueryBindingCache(
  720. VOID
  721. )
  722. {
  723. DWORD dwCount, dwErr;
  724. dwErr = OpenIPv6(FORMAT_NORMAL);
  725. if (dwErr != NO_ERROR) {
  726. return dwErr;
  727. }
  728. dwCount = ForEachBinding(PrintBindingCacheEntry);
  729. if (dwCount == 0) {
  730. DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES);
  731. }
  732. return NO_ERROR;
  733. }
  734. DWORD
  735. QueryMobilityParameters(
  736. IN FORMAT Format,
  737. IN BOOL bPersistent
  738. )
  739. {
  740. IPV6_GLOBAL_PARAMETERS Params;
  741. DWORD dwBytesReturned, dwErr;
  742. PWCHAR pwszTempString;
  743. PWCHAR pwszCNStateString;
  744. dwErr = OpenIPv6(Format);
  745. if (dwErr != NO_ERROR) {
  746. return dwErr;
  747. }
  748. if (Format != FORMAT_DUMP) {
  749. DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
  750. }
  751. if (!DeviceIoControl(Handle,
  752. (bPersistent)? IOCTL_IPV6_PERSISTENT_QUERY_GLOBAL_PARAMETERS : IOCTL_IPV6_QUERY_GLOBAL_PARAMETERS,
  753. NULL, 0,
  754. &Params, sizeof Params, &dwBytesReturned, NULL) ||
  755. (dwBytesReturned != sizeof Params)) {
  756. return GetLastError();
  757. }
  758. pwszTempString = Params.MobilitySecurity ?
  759. TOKEN_VALUE_ENABLED : TOKEN_VALUE_DISABLED;
  760. pwszCNStateString = (Params.MobileIPv6Mode & MOBILE_CORRESPONDENT)?
  761. TOKEN_VALUE_ENABLED : TOKEN_VALUE_DISABLED;
  762. if (Format == FORMAT_DUMP) {
  763. if ((Params.MobilitySecurity != -1) ||
  764. (Params.BindingCacheLimit != -1) ||
  765. (Params.MobileIPv6Mode != -1)) {
  766. DisplayMessageT(DMP_IPV6_SET_MOBILITY);
  767. if (Params.MobilitySecurity != -1) {
  768. DisplayMessageT(DMP_STRING_ARG, TOKEN_SECURITY, pwszTempString);
  769. }
  770. if (Params.BindingCacheLimit != -1) {
  771. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_BINDINGCACHELIMIT,
  772. Params.BindingCacheLimit);
  773. }
  774. if (Params.MobileIPv6Mode != -1) {
  775. DisplayMessageT(DMP_STRING_ARG, TOKEN_CNSTATE,
  776. pwszCNStateString);
  777. }
  778. DisplayMessage(g_hModule, MSG_NEWLINE);
  779. }
  780. } else {
  781. DisplayMessage(g_hModule, MSG_IPV6_MOBILITY_PARAMETERS, pwszTempString,
  782. Params.BindingCacheLimit, pwszCNStateString);
  783. }
  784. return NO_ERROR;
  785. }
  786. DWORD
  787. UpdateMobilityParameters(
  788. IN DWORD dwSecurity,
  789. IN DWORD dwBindingCacheLimit,
  790. IN DWORD dwMode,
  791. IN BOOL bPersistent
  792. )
  793. {
  794. DWORD dwBytesReturned;
  795. DWORD dwErr;
  796. dwErr = OpenIPv6(FORMAT_NORMAL);
  797. if (dwErr != NO_ERROR) {
  798. return dwErr;
  799. }
  800. dwErr = ERROR_OKAY;
  801. if ((dwBindingCacheLimit != -1) ||
  802. (dwSecurity != -1) ||
  803. (dwMode != -1)) {
  804. IPV6_GLOBAL_PARAMETERS Params;
  805. IPV6_INIT_GLOBAL_PARAMETERS(&Params);
  806. Params.BindingCacheLimit = dwBindingCacheLimit;
  807. Params.MobilitySecurity = dwSecurity;
  808. Params.MobileIPv6Mode = dwMode;
  809. if (bPersistent) {
  810. if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_GLOBAL_PARAMETERS,
  811. &Params, sizeof Params,
  812. NULL, 0,
  813. &dwBytesReturned, NULL)) {
  814. dwErr = GetLastError();
  815. }
  816. }
  817. if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_GLOBAL_PARAMETERS,
  818. &Params, sizeof Params,
  819. NULL, 0,
  820. &dwBytesReturned, NULL)) {
  821. if (dwErr == ERROR_OKAY) {
  822. dwErr = GetLastError();
  823. }
  824. }
  825. }
  826. return dwErr;
  827. }
  828. //////////////////////////////////////////////////////////////////////////////
  829. // Prefix policy table functions
  830. //////////////////////////////////////////////////////////////////////////////
  831. DWORD
  832. ForEachPrefixPolicy(
  833. IN DWORD (*pfnFunc)(IPV6_INFO_PREFIX_POLICY *,FORMAT,DWORD),
  834. IN FORMAT Format,
  835. IN BOOL bPersistent
  836. )
  837. {
  838. IPV6_QUERY_PREFIX_POLICY Query;
  839. IPV6_INFO_PREFIX_POLICY PPE;
  840. DWORD dwBytesReturned, dwCount = 0;
  841. Query.PrefixLength = (u_int) -1;
  842. for (;;) {
  843. if (!DeviceIoControl(Handle,
  844. (bPersistent)? IOCTL_IPV6_PERSISTENT_QUERY_PREFIX_POLICY : IOCTL_IPV6_QUERY_PREFIX_POLICY,
  845. &Query, sizeof Query,
  846. &PPE, sizeof PPE, &dwBytesReturned,
  847. NULL)) {
  848. break;
  849. }
  850. if (Query.PrefixLength != (u_int) -1) {
  851. if (dwBytesReturned != sizeof PPE)
  852. break;
  853. if ((*pfnFunc)(&PPE, Format, dwCount) == NO_ERROR) {
  854. dwCount++;
  855. }
  856. }
  857. else {
  858. if (dwBytesReturned != sizeof PPE.Next)
  859. break;
  860. }
  861. if (PPE.Next.PrefixLength == (u_int) -1)
  862. break;
  863. Query = PPE.Next;
  864. }
  865. return dwCount;
  866. }
  867. DWORD
  868. PrintPrefixPolicyEntry(
  869. IN IPV6_INFO_PREFIX_POLICY *PPE,
  870. IN FORMAT Format,
  871. IN DWORD dwCount
  872. )
  873. {
  874. if (Format == FORMAT_DUMP) {
  875. DisplayMessageT(DMP_IPV6_ADD_PREFIXPOLICY);
  876. DisplayMessageT(DMP_STRING_ARG, TOKEN_PREFIX,
  877. FormatIPv6Prefix(&PPE->This.Prefix,
  878. PPE->This.PrefixLength));
  879. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_PRECEDENCE,
  880. PPE->Precedence);
  881. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_LABEL,
  882. PPE->SrcLabel);
  883. DisplayMessage(g_hModule, MSG_NEWLINE);
  884. } else {
  885. if (!dwCount) {
  886. DisplayMessage(g_hModule, MSG_IPV6_PREFIX_POLICY_HDR);
  887. }
  888. DisplayMessage(g_hModule, MSG_IPV6_PREFIX_POLICY,
  889. FormatIPv6Prefix(&PPE->This.Prefix,
  890. PPE->This.PrefixLength),
  891. PPE->Precedence,
  892. PPE->SrcLabel,
  893. PPE->DstLabel);
  894. }
  895. return NO_ERROR;
  896. }
  897. DWORD
  898. QueryPrefixPolicy(
  899. IN FORMAT Format,
  900. IN BOOL bPersistent
  901. )
  902. {
  903. DWORD dwCount, dwErr;
  904. dwErr = OpenIPv6(Format);
  905. if (dwErr != NO_ERROR) {
  906. return dwErr;
  907. }
  908. if (Format != FORMAT_DUMP) {
  909. DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
  910. }
  911. dwCount = ForEachPrefixPolicy(PrintPrefixPolicyEntry, Format, bPersistent);
  912. if (!dwCount && (Format != FORMAT_DUMP)) {
  913. DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES);
  914. }
  915. return NO_ERROR;
  916. }
  917. DWORD
  918. UpdatePrefixPolicy(
  919. IN IN6_ADDR *IpAddress,
  920. IN DWORD dwPrefixLength,
  921. IN DWORD dwPrecedence,
  922. IN DWORD dwLabel,
  923. IN BOOL bPersistent
  924. )
  925. {
  926. IPV6_INFO_PREFIX_POLICY Info;
  927. DWORD dwBytesReturned, dwErr;
  928. dwErr = OpenIPv6(FORMAT_NORMAL);
  929. if (dwErr != NO_ERROR) {
  930. return dwErr;
  931. }
  932. Info.This.Prefix = *IpAddress;
  933. Info.This.PrefixLength = dwPrefixLength;
  934. Info.Precedence = dwPrecedence;
  935. Info.SrcLabel = Info.DstLabel = dwLabel;
  936. dwErr = ERROR_OKAY;
  937. if (bPersistent) {
  938. if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_PREFIX_POLICY,
  939. &Info, sizeof Info,
  940. NULL, 0,
  941. &dwBytesReturned, NULL)) {
  942. dwErr = GetLastError();
  943. }
  944. }
  945. if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_PREFIX_POLICY,
  946. &Info, sizeof Info,
  947. NULL, 0, &dwBytesReturned, NULL)) {
  948. if (dwErr == ERROR_OKAY) {
  949. dwErr = GetLastError();
  950. }
  951. }
  952. return dwErr;
  953. }
  954. DWORD
  955. DeletePrefixPolicy(
  956. IN IN6_ADDR *IpAddress,
  957. IN DWORD dwPrefixLength,
  958. IN BOOL bPersistent
  959. )
  960. {
  961. IPV6_QUERY_PREFIX_POLICY Query;
  962. DWORD dwBytesReturned, dwErr;
  963. dwErr = OpenIPv6(FORMAT_NORMAL);
  964. if (dwErr != NO_ERROR) {
  965. return dwErr;
  966. }
  967. Query.Prefix = *IpAddress;
  968. Query.PrefixLength = dwPrefixLength;
  969. dwErr = ERROR_OKAY;
  970. if (bPersistent) {
  971. if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_DELETE_PREFIX_POLICY,
  972. &Query, sizeof Query,
  973. NULL, 0,
  974. &dwBytesReturned, NULL)) {
  975. dwErr = GetLastError();
  976. }
  977. }
  978. if (!DeviceIoControl(Handle, IOCTL_IPV6_DELETE_PREFIX_POLICY,
  979. &Query, sizeof Query,
  980. NULL, 0, &dwBytesReturned, NULL)) {
  981. if (dwErr == ERROR_OKAY) {
  982. dwErr = GetLastError();
  983. }
  984. }
  985. return dwErr;
  986. }
  987. //////////////////////////////////////////////////////////////////////////////
  988. // Address table functions
  989. //////////////////////////////////////////////////////////////////////////////
  990. DWORD
  991. ForEachAddress(
  992. IN IPV6_INFO_INTERFACE *IF,
  993. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  994. IN FORMAT Format,
  995. IN DWORD (*pfnFunc)(IPV6_INFO_INTERFACE *IF, PIP_ADAPTER_ADDRESSES, FORMAT, DWORD, IPV6_INFO_ADDRESS *))
  996. {
  997. IPV6_QUERY_ADDRESS Query;
  998. IPV6_INFO_ADDRESS ADE;
  999. DWORD BytesReturned, dwCount = 0;
  1000. Query.IF = IF->This;
  1001. Query.Address = in6addr_any;
  1002. for (;;) {
  1003. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ADDRESS,
  1004. &Query, sizeof Query,
  1005. &ADE, sizeof ADE, &BytesReturned,
  1006. NULL)) {
  1007. break;
  1008. }
  1009. if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
  1010. if (BytesReturned != sizeof ADE)
  1011. break;
  1012. if ((*pfnFunc)(IF, pAdapterInfo, Format, dwCount, &ADE) == NO_ERROR) {
  1013. dwCount++;
  1014. }
  1015. }
  1016. else {
  1017. if (BytesReturned != sizeof ADE.Next)
  1018. break;
  1019. }
  1020. if (IN6_ADDR_EQUAL(&ADE.Next.Address, &in6addr_any))
  1021. break;
  1022. Query = ADE.Next;
  1023. }
  1024. return dwCount;
  1025. }
  1026. DWORD
  1027. ForEachPersistentAddress(
  1028. IN IPV6_INFO_INTERFACE *IF,
  1029. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  1030. IN FORMAT Format,
  1031. IN DWORD (*pfnFunc)(IPV6_INFO_INTERFACE *IF, PIP_ADAPTER_ADDRESSES, FORMAT, DWORD, IPV6_UPDATE_ADDRESS *))
  1032. {
  1033. IPV6_PERSISTENT_QUERY_ADDRESS Query;
  1034. IPV6_UPDATE_ADDRESS ADE;
  1035. DWORD BytesReturned, dwCount = 0;
  1036. Query.IF.RegistryIndex = (u_int) -1;
  1037. Query.IF.Guid = IF->This.Guid;
  1038. for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
  1039. if (!DeviceIoControl(Handle,
  1040. IOCTL_IPV6_PERSISTENT_QUERY_ADDRESS,
  1041. &Query, sizeof Query,
  1042. &ADE, sizeof ADE, &BytesReturned,
  1043. NULL) ||
  1044. (BytesReturned != sizeof ADE)) {
  1045. break;
  1046. }
  1047. if ((*pfnFunc)(IF, pAdapterInfo, Format, dwCount, &ADE) == NO_ERROR) {
  1048. dwCount++;
  1049. }
  1050. }
  1051. return dwCount;
  1052. }
  1053. PWCHAR
  1054. GetDadState(
  1055. IN DWORD dwDadState,
  1056. OUT BOOL *bDynamic
  1057. )
  1058. {
  1059. PWCHAR pwszTemp;
  1060. DWORD dwMsg = 0;
  1061. static WCHAR wszDadState[128];
  1062. switch (dwDadState) {
  1063. case DAD_STATE_INVALID:
  1064. dwMsg = STRING_INVALID;
  1065. break;
  1066. case DAD_STATE_DUPLICATE:
  1067. dwMsg = STRING_DUPLICATE;
  1068. break;
  1069. case DAD_STATE_TENTATIVE:
  1070. dwMsg = STRING_TENTATIVE;
  1071. break;
  1072. case DAD_STATE_DEPRECATED:
  1073. dwMsg = STRING_DEPRECATED;
  1074. break;
  1075. case DAD_STATE_PREFERRED:
  1076. dwMsg = STRING_PREFERRED;
  1077. break;
  1078. default:
  1079. swprintf(wszDadState, L"%u", dwDadState);
  1080. *bDynamic = FALSE;
  1081. return wszDadState;
  1082. }
  1083. *bDynamic = TRUE;
  1084. pwszTemp = MakeString(g_hModule, dwMsg);
  1085. return pwszTemp;
  1086. }
  1087. PWCHAR
  1088. GetAddressType(
  1089. IN DWORD dwScope,
  1090. IN DWORD dwPrefixConf,
  1091. IN DWORD dwIidConf
  1092. )
  1093. {
  1094. DWORD dwMsg = 0;
  1095. if ((dwScope == ADE_LINK_LOCAL) &&
  1096. (dwPrefixConf == PREFIX_CONF_WELLKNOWN) &&
  1097. (dwIidConf == IID_CONF_WELLKNOWN)) {
  1098. dwMsg = STRING_LOOPBACK;
  1099. } else if ((dwScope == ADE_LINK_LOCAL) &&
  1100. (dwPrefixConf == PREFIX_CONF_WELLKNOWN) &&
  1101. (dwIidConf == IID_CONF_LL_ADDRESS)) {
  1102. dwMsg = STRING_LINK;
  1103. } else if ((dwPrefixConf == PREFIX_CONF_MANUAL) &&
  1104. (dwIidConf == IID_CONF_MANUAL)) {
  1105. dwMsg = STRING_MANUAL;
  1106. } else if ((dwPrefixConf == PREFIX_CONF_RA) &&
  1107. (dwIidConf == IID_CONF_LL_ADDRESS)) {
  1108. dwMsg = STRING_PUBLIC;
  1109. } else if ((dwPrefixConf == PREFIX_CONF_RA) &&
  1110. (dwIidConf == IID_CONF_RANDOM)) {
  1111. dwMsg = STRING_TEMPORARY;
  1112. } else if ((dwPrefixConf == PREFIX_CONF_DHCP) &&
  1113. (dwIidConf == IID_CONF_DHCP)) {
  1114. dwMsg = STRING_DHCP;
  1115. } else {
  1116. dwMsg = STRING_OTHER;
  1117. }
  1118. return MakeString(g_hModule, dwMsg);
  1119. }
  1120. PWCHAR
  1121. GetScopeNoun(
  1122. IN DWORD dwScope,
  1123. OUT BOOL *bDynamic
  1124. )
  1125. {
  1126. PWCHAR pwszTemp;
  1127. DWORD dwMsg = 0;
  1128. static WCHAR wszScopeLevel[128];
  1129. switch (dwScope) {
  1130. case ADE_INTERFACE_LOCAL:
  1131. dwMsg = STRING_INTERFACE;
  1132. break;
  1133. case ADE_LINK_LOCAL:
  1134. dwMsg = STRING_LINK;
  1135. break;
  1136. case ADE_SUBNET_LOCAL:
  1137. dwMsg = STRING_SUBNET;
  1138. break;
  1139. case ADE_ADMIN_LOCAL:
  1140. dwMsg = STRING_ADMIN;
  1141. break;
  1142. case ADE_SITE_LOCAL:
  1143. dwMsg = STRING_SITE;
  1144. break;
  1145. case ADE_ORG_LOCAL:
  1146. dwMsg = STRING_ORG;
  1147. break;
  1148. case ADE_GLOBAL:
  1149. dwMsg = STRING_GLOBAL;
  1150. break;
  1151. default:
  1152. swprintf(wszScopeLevel, L"%u", dwScope);
  1153. *bDynamic = FALSE;
  1154. return wszScopeLevel;
  1155. }
  1156. *bDynamic = TRUE;
  1157. pwszTemp = MakeString(g_hModule, dwMsg);
  1158. return pwszTemp;
  1159. }
  1160. DWORD rgdwPrefixConfMsg[] = {
  1161. 0,
  1162. STRING_MANUAL,
  1163. STRING_WELLKNOWN,
  1164. STRING_DHCP,
  1165. STRING_RA
  1166. };
  1167. #define PREFIX_CONF_MSG_COUNT (sizeof(rgdwPrefixConfMsg)/sizeof(DWORD))
  1168. DWORD rgdwIidConfMsg[] = {
  1169. 0,
  1170. STRING_MANUAL,
  1171. STRING_WELLKNOWN,
  1172. STRING_DHCP,
  1173. STRING_LL_ADDRESS,
  1174. STRING_RANDOM
  1175. };
  1176. #define IID_CONF_MSG_COUNT (sizeof(rgdwIidConfMsg)/sizeof(DWORD))
  1177. DWORD
  1178. PrintMulticastAddress(
  1179. IN IPV6_INFO_INTERFACE *IF,
  1180. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  1181. IN FORMAT Format,
  1182. IN DWORD dwCount,
  1183. IN IPV6_INFO_ADDRESS *ADE
  1184. )
  1185. {
  1186. BOOL bDynamicScope;
  1187. PWCHAR pwszScope, pwszFriendlyName;
  1188. DWORD dwErr = NO_ERROR;
  1189. PWCHAR pwszLastReporter, pwszNever;
  1190. WCHAR wszTime[64];
  1191. if (ADE->Type != ADE_MULTICAST) {
  1192. return ERROR_NO_DATA;
  1193. }
  1194. if (dwCount == 0) {
  1195. dwErr = MapIpv6IfIndexToFriendlyName(IF->This.Index, pAdapterInfo,
  1196. &pwszFriendlyName);
  1197. if (dwErr != NO_ERROR) {
  1198. return dwErr;
  1199. }
  1200. DisplayMessage(g_hModule,
  1201. (Format == FORMAT_VERBOSE)? MSG_IPV6_ADDRESS_HDR_VERBOSE : MSG_IPV6_MULTICAST_ADDRESS_HDR,
  1202. IF->This.Index, pwszFriendlyName);
  1203. }
  1204. pwszScope = GetScopeNoun(ADE->Scope, &bDynamicScope);
  1205. pwszNever = MakeString(g_hModule, STRING_NEVER);
  1206. pwszLastReporter = MakeString(g_hModule, (ADE->MCastFlags & 0x02)? STRING_YES : STRING_NO);
  1207. DisplayMessage(g_hModule,
  1208. ((Format == FORMAT_VERBOSE)
  1209. ? MSG_IPV6_MULTICAST_ADDRESS_VERBOSE
  1210. : MSG_IPV6_MULTICAST_ADDRESS),
  1211. pwszScope,
  1212. FormatIPv6Address(&ADE->This.Address, 0),
  1213. ADE->MCastRefCount,
  1214. (ADE->MCastFlags & 0x01)
  1215. ? FormatTime(ADE->MCastTimer, wszTime)
  1216. : pwszNever,
  1217. pwszLastReporter);
  1218. FreeString(pwszLastReporter);
  1219. FreeString(pwszNever);
  1220. if (bDynamicScope) {
  1221. FreeString(pwszScope);
  1222. }
  1223. return dwErr;
  1224. }
  1225. DWORD
  1226. PrintAddress(
  1227. IN IPV6_INFO_INTERFACE *IF,
  1228. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  1229. IN FORMAT Format,
  1230. IN DWORD dwCount,
  1231. IN IPV6_INFO_ADDRESS *ADE
  1232. )
  1233. {
  1234. DWORD dwPrefixConf, dwInterfaceIdConf;
  1235. BOOL bDynamicDadState, bDynamicScope;
  1236. PWCHAR pwszDadState, pwszScope, pwszFriendlyName, pwszType;
  1237. WCHAR wszValid[64], wszPreferred[64];
  1238. DWORD dwErr = NO_ERROR;
  1239. if (Format != FORMAT_VERBOSE) {
  1240. //
  1241. // Suppress invalid addresses.
  1242. //
  1243. if ((ADE->Type == ADE_UNICAST) &&
  1244. (ADE->DADState == DAD_STATE_INVALID)) {
  1245. return ERROR_NO_DATA;
  1246. }
  1247. //
  1248. // Multicast addresses are handled by PrintMulticastAddress()
  1249. // instead.
  1250. //
  1251. if (ADE->Type == ADE_MULTICAST) {
  1252. return ERROR_NO_DATA;
  1253. }
  1254. }
  1255. if (dwCount == 0) {
  1256. if (IF->This.Index == 0) {
  1257. dwErr = MapGuidToFriendlyName(NULL, &IF->This.Guid, pAdapterInfo,
  1258. &pwszFriendlyName);
  1259. } else {
  1260. dwErr = MapIpv6IfIndexToFriendlyName(IF->This.Index, pAdapterInfo,
  1261. &pwszFriendlyName);
  1262. }
  1263. if (dwErr != NO_ERROR) {
  1264. return dwErr;
  1265. }
  1266. DisplayMessage(g_hModule,
  1267. ((Format == FORMAT_VERBOSE)? MSG_IPV6_ADDRESS_HDR_VERBOSE : MSG_IPV6_ADDRESS_HDR),
  1268. IF->This.Index, pwszFriendlyName);
  1269. }
  1270. pwszScope = GetScopeNoun(ADE->Scope, &bDynamicScope);
  1271. switch (ADE->Type) {
  1272. case ADE_UNICAST:
  1273. pwszDadState = GetDadState(ADE->DADState, &bDynamicDadState);
  1274. pwszType = GetAddressType(ADE->Scope, ADE->PrefixConf, ADE->InterfaceIdConf);
  1275. DisplayMessage(g_hModule,
  1276. ((Format == FORMAT_VERBOSE)? MSG_IPV6_UNICAST_ADDRESS_VERBOSE : MSG_IPV6_UNICAST_ADDRESS),
  1277. pwszType,
  1278. pwszDadState,
  1279. FormatIPv6Address(&ADE->This.Address, 0),
  1280. FormatTime(ADE->ValidLifetime, wszValid),
  1281. FormatTime(ADE->PreferredLifetime, wszPreferred),
  1282. pwszScope);
  1283. if (bDynamicDadState) {
  1284. FreeString(pwszDadState);
  1285. }
  1286. FreeString(pwszType);
  1287. if (Format == FORMAT_VERBOSE) {
  1288. //
  1289. // Show prefix origin / interface id origin
  1290. //
  1291. DisplayMessage(g_hModule, MSG_IPV6_PREFIX_ORIGIN);
  1292. dwPrefixConf = ADE->PrefixConf;
  1293. if ((dwPrefixConf == PREFIX_CONF_OTHER) ||
  1294. (dwPrefixConf >= PREFIX_CONF_MSG_COUNT)) {
  1295. DisplayMessage(g_hModule, MSG_IPV6_INTEGER, dwPrefixConf);
  1296. } else {
  1297. DisplayMessage(g_hModule, rgdwPrefixConfMsg[dwPrefixConf]);
  1298. }
  1299. DisplayMessage(g_hModule, MSG_NEWLINE);
  1300. DisplayMessage(g_hModule, MSG_IPV6_IID_ORIGIN);
  1301. dwInterfaceIdConf = ADE->InterfaceIdConf;
  1302. if ((dwInterfaceIdConf == IID_CONF_OTHER) ||
  1303. (dwInterfaceIdConf >= IID_CONF_MSG_COUNT)) {
  1304. DisplayMessage(g_hModule, MSG_IPV6_INTEGER, dwInterfaceIdConf);
  1305. } else {
  1306. DisplayMessage(g_hModule, rgdwIidConfMsg[dwInterfaceIdConf]);
  1307. }
  1308. DisplayMessage(g_hModule, MSG_NEWLINE);
  1309. }
  1310. break;
  1311. case ADE_ANYCAST:
  1312. DisplayMessage(g_hModule,
  1313. ((Format == FORMAT_VERBOSE)? MSG_IPV6_ANYCAST_ADDRESS_VERBOSE : MSG_IPV6_ANYCAST_ADDRESS),
  1314. FormatIPv6Address(&ADE->This.Address, 0),
  1315. pwszScope);
  1316. break;
  1317. case ADE_MULTICAST:
  1318. default:
  1319. dwErr = ERROR_NO_DATA;
  1320. break;
  1321. }
  1322. if (bDynamicScope) {
  1323. FreeString(pwszScope);
  1324. }
  1325. return dwErr;
  1326. }
  1327. DWORD
  1328. PrintPersistentAddress(
  1329. IN IPV6_INFO_INTERFACE *IF,
  1330. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  1331. IN FORMAT Format,
  1332. IN DWORD dwCount,
  1333. IN IPV6_UPDATE_ADDRESS *ADE
  1334. )
  1335. {
  1336. DWORD dwPrefixConf, dwInterfaceIdConf;
  1337. BOOL bDynamicDadState, bDynamicScope;
  1338. PWCHAR pwszDadState, pwszScope, pwszFriendlyName = NULL, pwszType;
  1339. WCHAR wszValid[64], wszPreferred[64];
  1340. DWORD dwErr = NO_ERROR, dwScope;
  1341. if (Format != FORMAT_VERBOSE) {
  1342. //
  1343. // Multicast addresses are handled by PrintMulticastAddress()
  1344. // instead.
  1345. //
  1346. if (ADE->Type == ADE_MULTICAST) {
  1347. return ERROR_NO_DATA;
  1348. }
  1349. }
  1350. if ((dwCount == 0) || (Format == FORMAT_DUMP)) {
  1351. dwErr = MapGuidToFriendlyName(NULL, &IF->This.Guid, pAdapterInfo,
  1352. &pwszFriendlyName);
  1353. if (dwErr != NO_ERROR) {
  1354. return dwErr;
  1355. }
  1356. if (Format != FORMAT_DUMP) {
  1357. DisplayMessage(g_hModule,
  1358. ((Format == FORMAT_VERBOSE)?
  1359. MSG_IPV6_ADDRESS_HDR_VERBOSE :
  1360. MSG_IPV6_ADDRESS_HDR),
  1361. IF->This.Index,
  1362. pwszFriendlyName);
  1363. }
  1364. }
  1365. if (IN6_IS_ADDR_LINKLOCAL(&ADE->This.Address)) {
  1366. dwScope = ADE_LINK_LOCAL;
  1367. } else if (IN6_IS_ADDR_SITELOCAL(&ADE->This.Address)) {
  1368. dwScope = ADE_SITE_LOCAL;
  1369. } else {
  1370. dwScope = ADE_GLOBAL;
  1371. }
  1372. pwszScope = GetScopeNoun(dwScope, &bDynamicScope);
  1373. switch (ADE->Type) {
  1374. case ADE_UNICAST:
  1375. FormatTime(ADE->ValidLifetime, wszValid);
  1376. FormatTime(ADE->PreferredLifetime, wszPreferred);
  1377. if (Format == FORMAT_DUMP) {
  1378. DisplayMessageT(DMP_IPV6_ADD_ADDRESS);
  1379. DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE,
  1380. pwszFriendlyName);
  1381. DisplayMessageT(DMP_STRING_ARG, TOKEN_ADDRESS,
  1382. FormatIPv6Address(&ADE->This.Address, 0));
  1383. if (ADE->ValidLifetime != INFINITE_LIFETIME) {
  1384. DisplayMessageT(DMP_STRING_ARG, TOKEN_VALIDLIFETIME, wszValid);
  1385. }
  1386. if (ADE->PreferredLifetime != INFINITE_LIFETIME) {
  1387. DisplayMessageT(DMP_STRING_ARG, TOKEN_PREFERREDLIFETIME,
  1388. wszPreferred);
  1389. }
  1390. DisplayMessage(g_hModule, MSG_NEWLINE);
  1391. break;
  1392. }
  1393. pwszDadState = GetDadState(DAD_STATE_TENTATIVE, &bDynamicDadState);
  1394. pwszType = GetAddressType(dwScope, ADE->PrefixConf, ADE->InterfaceIdConf);
  1395. DisplayMessage(g_hModule,
  1396. ((Format == FORMAT_VERBOSE)? MSG_IPV6_UNICAST_ADDRESS_VERBOSE : MSG_IPV6_UNICAST_ADDRESS),
  1397. pwszType,
  1398. pwszDadState,
  1399. FormatIPv6Address(&ADE->This.Address, 0),
  1400. wszValid,
  1401. wszPreferred,
  1402. pwszScope);
  1403. if (bDynamicDadState) {
  1404. FreeString(pwszDadState);
  1405. }
  1406. FreeString(pwszType);
  1407. if (Format == FORMAT_VERBOSE) {
  1408. //
  1409. // Show prefix origin / interface id origin
  1410. //
  1411. DisplayMessage(g_hModule, MSG_IPV6_PREFIX_ORIGIN);
  1412. dwPrefixConf = ADE->PrefixConf;
  1413. if ((dwPrefixConf == PREFIX_CONF_OTHER) ||
  1414. (dwPrefixConf >= PREFIX_CONF_MSG_COUNT)) {
  1415. DisplayMessage(g_hModule, MSG_IPV6_INTEGER, dwPrefixConf);
  1416. } else {
  1417. DisplayMessage(g_hModule, rgdwPrefixConfMsg[dwPrefixConf]);
  1418. }
  1419. DisplayMessage(g_hModule, MSG_NEWLINE);
  1420. DisplayMessage(g_hModule, MSG_IPV6_IID_ORIGIN);
  1421. dwInterfaceIdConf = ADE->InterfaceIdConf;
  1422. if ((dwInterfaceIdConf == IID_CONF_OTHER) ||
  1423. (dwInterfaceIdConf >= IID_CONF_MSG_COUNT)) {
  1424. DisplayMessage(g_hModule, MSG_IPV6_INTEGER, dwInterfaceIdConf);
  1425. } else {
  1426. DisplayMessage(g_hModule, rgdwIidConfMsg[dwInterfaceIdConf]);
  1427. }
  1428. DisplayMessage(g_hModule, MSG_NEWLINE);
  1429. }
  1430. break;
  1431. case ADE_ANYCAST:
  1432. if (Format == FORMAT_DUMP) {
  1433. DisplayMessageT(DMP_IPV6_ADD_ADDRESS);
  1434. DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE,
  1435. pwszFriendlyName);
  1436. DisplayMessageT(DMP_STRING_ARG, TOKEN_ADDRESS,
  1437. FormatIPv6Address(&ADE->This.Address, 0));
  1438. DisplayMessageT(DMP_STRING_ARG, TOKEN_TYPE, TOKEN_VALUE_ANYCAST);
  1439. DisplayMessage(g_hModule, MSG_NEWLINE);
  1440. break;
  1441. }
  1442. DisplayMessage(g_hModule,
  1443. ((Format == FORMAT_VERBOSE)? MSG_IPV6_ANYCAST_ADDRESS_VERBOSE : MSG_IPV6_ANYCAST_ADDRESS),
  1444. FormatIPv6Address(&ADE->This.Address, 0),
  1445. pwszScope);
  1446. break;
  1447. case ADE_MULTICAST:
  1448. default:
  1449. dwErr = ERROR_NO_DATA;
  1450. break;
  1451. }
  1452. if (bDynamicScope) {
  1453. FreeString(pwszScope);
  1454. }
  1455. return dwErr;
  1456. }
  1457. DWORD
  1458. PrintAddressTable(
  1459. IN IPV6_INFO_INTERFACE *IF,
  1460. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  1461. IN DWORD dwIfCount,
  1462. IN FORMAT Format,
  1463. IN BOOL bPersistent
  1464. )
  1465. {
  1466. DWORD dwCount;
  1467. if (bPersistent) {
  1468. dwCount = ForEachPersistentAddress(IF, pAdapterInfo, Format,
  1469. PrintPersistentAddress);
  1470. } else {
  1471. dwCount = ForEachAddress(IF, pAdapterInfo, Format, PrintAddress);
  1472. }
  1473. return (dwCount > 0)? NO_ERROR : ERROR_NO_DATA;
  1474. }
  1475. DWORD
  1476. PrintMulticastAddressTable(
  1477. IN IPV6_INFO_INTERFACE *IF,
  1478. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  1479. IN DWORD dwIfCount,
  1480. IN FORMAT Format,
  1481. IN BOOL bPersistent
  1482. )
  1483. {
  1484. DWORD dwCount = ForEachAddress(IF, pAdapterInfo, Format,
  1485. PrintMulticastAddress);
  1486. return (dwCount > 0)? NO_ERROR : ERROR_NO_DATA;
  1487. }
  1488. DWORD
  1489. QueryAddressTable(
  1490. IN PWCHAR pwszIfFriendlyName,
  1491. IN FORMAT Format,
  1492. IN BOOL bPersistent
  1493. )
  1494. {
  1495. DWORD dwErr, dwCount = 0;
  1496. IP_ADAPTER_ADDRESSES *pAdapterInfo;
  1497. IPV6_INFO_INTERFACE *IF;
  1498. dwErr = OpenIPv6(Format);
  1499. if (dwErr != NO_ERROR) {
  1500. return dwErr;
  1501. }
  1502. if (Format != FORMAT_DUMP) {
  1503. DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
  1504. }
  1505. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  1506. if (dwErr != ERROR_NO_DATA) {
  1507. if (dwErr == NO_ERROR) {
  1508. if (pwszIfFriendlyName == NULL) {
  1509. dwCount = ForEachInterface(PrintAddressTable, pAdapterInfo,
  1510. Format, bPersistent);
  1511. } else {
  1512. dwErr = GetInterfaceByFriendlyName(pwszIfFriendlyName,
  1513. pAdapterInfo, bPersistent,
  1514. &IF);
  1515. if (dwErr == NO_ERROR) {
  1516. PrintAddressTable(IF, pAdapterInfo, 0, Format, bPersistent);
  1517. FREE(IF);
  1518. }
  1519. }
  1520. FREE(pAdapterInfo);
  1521. } else if (dwErr == ERROR_NO_DATA) {
  1522. dwErr = NO_ERROR;
  1523. }
  1524. }
  1525. if (!dwCount && (Format != FORMAT_DUMP)) {
  1526. DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES);
  1527. }
  1528. return dwErr;
  1529. }
  1530. DWORD
  1531. QueryMulticastAddressTable(
  1532. IN PWCHAR pwszIfFriendlyName,
  1533. IN FORMAT Format
  1534. )
  1535. {
  1536. DWORD dwErr;
  1537. IP_ADAPTER_ADDRESSES *pAdapterInfo;
  1538. IPV6_INFO_INTERFACE *IF;
  1539. dwErr = OpenIPv6(Format);
  1540. if (dwErr != NO_ERROR) {
  1541. return dwErr;
  1542. }
  1543. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  1544. if (dwErr != ERROR_NO_DATA) {
  1545. if (dwErr == NO_ERROR) {
  1546. if (pwszIfFriendlyName == NULL) {
  1547. ForEachInterface(PrintMulticastAddressTable,
  1548. pAdapterInfo, Format, FALSE);
  1549. } else {
  1550. dwErr = GetInterfaceByFriendlyName(pwszIfFriendlyName,
  1551. pAdapterInfo, FALSE, &IF);
  1552. if (dwErr == NO_ERROR) {
  1553. dwErr = PrintMulticastAddressTable(IF, pAdapterInfo, 0,
  1554. Format, FALSE);
  1555. FREE(IF);
  1556. }
  1557. }
  1558. FREE(pAdapterInfo);
  1559. } else if (dwErr == ERROR_NO_DATA) {
  1560. dwErr = NO_ERROR;
  1561. }
  1562. }
  1563. return dwErr;
  1564. }
  1565. DWORD
  1566. UpdateAddress(
  1567. IN PWCHAR pwszIfFriendlyName,
  1568. IN IN6_ADDR *pipAddress,
  1569. IN DWORD dwType,
  1570. IN DWORD dwValidLifetime,
  1571. IN DWORD dwPreferredLifetime,
  1572. IN BOOL bPersistent
  1573. )
  1574. {
  1575. IPV6_UPDATE_ADDRESS Update;
  1576. DWORD dwBytesReturned, dwErr;
  1577. PIP_ADAPTER_ADDRESSES pAdapterInfo;
  1578. dwErr = OpenIPv6(FORMAT_NORMAL);
  1579. if (dwErr != NO_ERROR) {
  1580. return dwErr;
  1581. }
  1582. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  1583. if (dwErr != NO_ERROR) {
  1584. return dwErr;
  1585. }
  1586. dwErr = MapFriendlyNameToIpv6IfIndex(pwszIfFriendlyName, pAdapterInfo,
  1587. &Update.This.IF.Index);
  1588. if (dwErr != NO_ERROR) {
  1589. FREE(pAdapterInfo);
  1590. return dwErr;
  1591. }
  1592. if (dwType == (DWORD)-1) {
  1593. PIP_ADAPTER_ADDRESSES pIf;
  1594. PIP_ADAPTER_ANYCAST_ADDRESS pAddr;
  1595. //
  1596. // The caller doesn't know whether the existing address is unicast
  1597. // or anycast, so we'll check.
  1598. //
  1599. for (pIf = pAdapterInfo; ; pIf = pIf->Next) {
  1600. if (pIf->Ipv6IfIndex == Update.This.IF.Index) {
  1601. break;
  1602. }
  1603. }
  1604. dwType = ADE_UNICAST;
  1605. for (pAddr = pIf->FirstAnycastAddress;
  1606. pAddr != NULL;
  1607. pAddr = pAddr->Next) {
  1608. if (pAddr->Address.lpSockaddr->sa_family != AF_INET6) {
  1609. continue;
  1610. }
  1611. if (IN6_ADDR_EQUAL(&((PSOCKADDR_IN6)pAddr->Address.lpSockaddr)->
  1612. sin6_addr,
  1613. pipAddress)) {
  1614. dwType = ADE_ANYCAST;
  1615. break;
  1616. }
  1617. }
  1618. }
  1619. FREE(pAdapterInfo);
  1620. Update.This.Address = *pipAddress;
  1621. Update.Type = dwType;
  1622. Update.PrefixConf = PREFIX_CONF_MANUAL;
  1623. Update.InterfaceIdConf = IID_CONF_MANUAL;
  1624. Update.ValidLifetime = dwValidLifetime;
  1625. Update.PreferredLifetime = dwPreferredLifetime;
  1626. dwErr = ERROR_OKAY;
  1627. if (bPersistent) {
  1628. if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_ADDRESS,
  1629. &Update, sizeof Update,
  1630. NULL, 0,
  1631. &dwBytesReturned, NULL)) {
  1632. dwErr = GetLastError();
  1633. }
  1634. }
  1635. if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_ADDRESS,
  1636. &Update, sizeof Update,
  1637. NULL, 0, &dwBytesReturned, NULL)) {
  1638. if (dwErr == ERROR_OKAY) {
  1639. dwErr = GetLastError();
  1640. }
  1641. }
  1642. return dwErr;
  1643. }
  1644. //////////////////////////////////////////////////////////////////////////////
  1645. // Interface table functions
  1646. //////////////////////////////////////////////////////////////////////////////
  1647. DWORD
  1648. RenewViaReconnect(
  1649. IN IPV6_INFO_INTERFACE *IF,
  1650. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  1651. IN DWORD dwCount,
  1652. IN FORMAT Format,
  1653. IN BOOL bPersistent
  1654. )
  1655. {
  1656. DWORD dwBytesReturned;
  1657. if (!DeviceIoControl(Handle, IOCTL_IPV6_RENEW_INTERFACE,
  1658. &IF->This, sizeof IF->This,
  1659. NULL, 0, &dwBytesReturned, NULL)) {
  1660. return GetLastError();
  1661. }
  1662. return NO_ERROR;
  1663. }
  1664. DWORD
  1665. RenewInterface(
  1666. IN PWCHAR wszIfFriendlyName
  1667. )
  1668. {
  1669. DWORD dwErr;
  1670. BOOL PokeService = FALSE;
  1671. dwErr = OpenIPv6(FORMAT_NORMAL);
  1672. if (dwErr != NO_ERROR) {
  1673. return dwErr;
  1674. }
  1675. if (wszIfFriendlyName == NULL) {
  1676. ForEachInterface(RenewViaReconnect, NULL, FALSE, FALSE);
  1677. PokeService = TRUE;
  1678. } else {
  1679. IP_ADAPTER_ADDRESSES *pAdapterInfo;
  1680. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  1681. if (dwErr == NO_ERROR) {
  1682. IPV6_INFO_INTERFACE *IF;
  1683. dwErr = GetInterfaceByFriendlyName(wszIfFriendlyName, pAdapterInfo,
  1684. FALSE, &IF);
  1685. FREE(pAdapterInfo);
  1686. if (dwErr != NO_ERROR) {
  1687. return dwErr;
  1688. }
  1689. dwErr = RenewViaReconnect(IF, NULL, 0, FALSE, FALSE);
  1690. //
  1691. // Poke the 6to4 service if it manages the interface being renewed.
  1692. //
  1693. PokeService = (IF->Type == IPV6_IF_TYPE_TUNNEL_6TO4) ||
  1694. (IF->Type == IPV6_IF_TYPE_TUNNEL_TEREDO) ||
  1695. (IF->Type == IPV6_IF_TYPE_TUNNEL_AUTO);
  1696. FREE(IF);
  1697. } else if (dwErr == ERROR_NO_DATA) {
  1698. dwErr = NO_ERROR;
  1699. }
  1700. }
  1701. if (PokeService) {
  1702. Ip6to4PokeService();
  1703. }
  1704. return dwErr;
  1705. }
  1706. DWORD dwMediaSenseMsg[] = {
  1707. STRING_DISCONNECTED,
  1708. STRING_RECONNECTED,
  1709. STRING_CONNECTED,
  1710. };
  1711. #define MEDIA_SENSE_MSG_COUNT (sizeof(dwMediaSenseMsg)/sizeof(DWORD))
  1712. DWORD
  1713. PrintInterface(
  1714. IN IPV6_INFO_INTERFACE *IF,
  1715. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  1716. IN DWORD dwCount,
  1717. IN FORMAT Format,
  1718. IN BOOL bPersistent
  1719. )
  1720. {
  1721. PWCHAR pwszFriendlyName, pwszTemp;
  1722. DWORD dwErr, dwMsg, dwScope;
  1723. WCHAR wszReachable[64], wszBaseReachable[64], wszRetransTimer[64];
  1724. PIP_ADAPTER_ADDRESSES pIf;
  1725. CHAR szGuid[41];
  1726. PWCHAR pwszFirewallState;
  1727. dwErr = MapGuidToFriendlyName(NULL, &IF->This.Guid, pAdapterInfo,
  1728. &pwszFriendlyName);
  1729. if (dwErr != NO_ERROR) {
  1730. return dwErr;
  1731. }
  1732. if (IF->MediaStatus < MEDIA_SENSE_MSG_COUNT) {
  1733. dwMsg = dwMediaSenseMsg[IF->MediaStatus];
  1734. } else {
  1735. dwMsg = STRING_UNKNOWN;
  1736. }
  1737. if (IF->FirewallEnabled == -1) {
  1738. pwszFirewallState = TOKEN_VALUE_DEFAULT;
  1739. } else if (IF->FirewallEnabled == 0) {
  1740. pwszFirewallState = TOKEN_VALUE_DISABLED;
  1741. } else {
  1742. pwszFirewallState = TOKEN_VALUE_ENABLED;
  1743. }
  1744. switch (Format) {
  1745. case FORMAT_DUMP:
  1746. switch (IF->Type) {
  1747. case IPV6_IF_TYPE_TUNNEL_6OVER4:
  1748. DisplayMessageT(DMP_IPV6_ADD_6OVER4TUNNEL);
  1749. DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE,
  1750. pwszFriendlyName);
  1751. if (IF->LocalLinkLayerAddress != 0) {
  1752. DisplayMessageT(DMP_STRING_ARG, TOKEN_LOCALADDRESS,
  1753. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1754. (UCHAR *)IF + IF->LocalLinkLayerAddress));
  1755. }
  1756. DisplayMessage(g_hModule, MSG_NEWLINE);
  1757. break;
  1758. case IPV6_IF_TYPE_TUNNEL_V6V4:
  1759. DisplayMessageT(DMP_IPV6_ADD_V6V4TUNNEL);
  1760. DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE,
  1761. pwszFriendlyName);
  1762. if (IF->LocalLinkLayerAddress != 0) {
  1763. DisplayMessageT(DMP_STRING_ARG, TOKEN_LOCALADDRESS,
  1764. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1765. (UCHAR *)IF + IF->LocalLinkLayerAddress));
  1766. }
  1767. if (IF->RemoteLinkLayerAddress != 0) {
  1768. DisplayMessageT(DMP_STRING_ARG, TOKEN_REMOTEADDRESS,
  1769. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1770. (UCHAR *)IF + IF->RemoteLinkLayerAddress));
  1771. }
  1772. if (IF->NeighborDiscovers) {
  1773. DisplayMessageT(DMP_STRING_ARG, TOKEN_NEIGHBORDISCOVERY,
  1774. TOKEN_VALUE_ENABLED);
  1775. }
  1776. DisplayMessage(g_hModule, MSG_NEWLINE);
  1777. break;
  1778. }
  1779. if ((IF->Preference != -1) ||
  1780. (IF->LinkMTU != 0) ||
  1781. (IF->FirewallEnabled != -1) ||
  1782. (IF->Forwards != -1) ||
  1783. (IF->Advertises != -1) ||
  1784. (IF->DefSitePrefixLength != -1)) {
  1785. DisplayMessageT(DMP_IPV6_SET_INTERFACE);
  1786. DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE,
  1787. pwszFriendlyName);
  1788. if (IF->Preference != -1) {
  1789. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_METRIC,
  1790. IF->Preference);
  1791. }
  1792. if (IF->LinkMTU != 0) {
  1793. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_MTU,
  1794. IF->LinkMTU);
  1795. }
  1796. if (IF->FirewallEnabled != -1) {
  1797. DisplayMessageT(DMP_STRING_ARG, TOKEN_FIREWALL,
  1798. pwszFirewallState);
  1799. }
  1800. if (IF->DefSitePrefixLength != -1) {
  1801. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_SITEPREFIXLENGTH,
  1802. IF->DefSitePrefixLength);
  1803. }
  1804. if (IF->Advertises != -1) {
  1805. DisplayMessageT(DMP_STRING_ARG, TOKEN_ADVERTISE,
  1806. (IF->Advertises ?
  1807. TOKEN_VALUE_ENABLED :
  1808. TOKEN_VALUE_DISABLED));
  1809. }
  1810. if (IF->Forwards != -1) {
  1811. DisplayMessageT(DMP_STRING_ARG, TOKEN_FORWARDING,
  1812. (IF->Forwards ?
  1813. TOKEN_VALUE_ENABLED :
  1814. TOKEN_VALUE_DISABLED));
  1815. }
  1816. DisplayMessage(g_hModule, MSG_NEWLINE);
  1817. }
  1818. break;
  1819. case FORMAT_NORMAL:
  1820. if (dwCount == 0) {
  1821. DisplayMessage(g_hModule, MSG_IPV6_INTERFACE_HDR);
  1822. }
  1823. pwszTemp = MakeString(g_hModule, dwMsg);
  1824. DisplayMessage(g_hModule, MSG_IPV6_INTERFACE, IF->This.Index,
  1825. IF->Preference, IF->LinkMTU, pwszTemp, pwszFriendlyName);
  1826. FreeString(pwszTemp);
  1827. break;
  1828. case FORMAT_VERBOSE:
  1829. DisplayMessage(g_hModule, MSG_SEPARATOR);
  1830. ForEachAddress(IF, pAdapterInfo, FORMAT_NORMAL, PrintAddress);
  1831. //
  1832. // Get extra interface information.
  1833. //
  1834. pIf = MapIfIndexToAdapter(AF_INET6, IF->This.Index, pAdapterInfo);
  1835. pwszTemp = MakeString(g_hModule, dwMsg);
  1836. ConvertGuidToStringA(&IF->This.Guid, szGuid);
  1837. DisplayMessage(g_hModule, MSG_IPV6_INTERFACE_VERBOSE,
  1838. szGuid,
  1839. pwszTemp,
  1840. IF->Preference,
  1841. IF->LinkMTU,
  1842. IF->TrueLinkMTU,
  1843. IF->CurHopLimit,
  1844. FormatTime(MillisToSeconds(IF->ReachableTime),
  1845. wszReachable),
  1846. FormatTime(MillisToSeconds(IF->BaseReachableTime),
  1847. wszBaseReachable),
  1848. FormatTime(MillisToSeconds(IF->RetransTimer),
  1849. wszRetransTimer),
  1850. IF->DupAddrDetectTransmits,
  1851. (pIf)? pIf->DnsSuffix : L"",
  1852. pwszFriendlyName,
  1853. pwszFirewallState,
  1854. IF->DefSitePrefixLength);
  1855. FreeString(pwszTemp);
  1856. for (dwScope = ADE_LINK_LOCAL; dwScope < ADE_GLOBAL; dwScope++) {
  1857. DWORD Expected = 0;
  1858. //
  1859. // Always print link & site.
  1860. //
  1861. if ((dwScope != ADE_LINK_LOCAL) && (dwScope != ADE_SITE_LOCAL)) {
  1862. Expected = IF->ZoneIndices[dwScope + 1];
  1863. }
  1864. if (IF->ZoneIndices[dwScope] != Expected) {
  1865. BOOL bDynamic;
  1866. pwszTemp = GetScopeNoun(dwScope, &bDynamic);
  1867. DisplayMessage(g_hModule, MSG_IPV6_INTERFACE_SCOPE,
  1868. pwszTemp, IF->ZoneIndices[dwScope]);
  1869. if (bDynamic) {
  1870. FreeString(pwszTemp);
  1871. }
  1872. }
  1873. }
  1874. DisplayMessage(g_hModule, MSG_IPV6_ND_ENABLED);
  1875. DisplayMessage(g_hModule,
  1876. (IF->NeighborDiscovers ? STRING_YES : STRING_NO));
  1877. DisplayMessage(g_hModule, MSG_NEWLINE);
  1878. DisplayMessage(g_hModule, MSG_IPV6_SENDS_RAS);
  1879. DisplayMessage(g_hModule,
  1880. ((IF->Advertises == TRUE) ? STRING_YES : STRING_NO));
  1881. DisplayMessage(g_hModule, MSG_NEWLINE);
  1882. DisplayMessage(g_hModule, MSG_IPV6_FORWARDS);
  1883. DisplayMessage(g_hModule,
  1884. ((IF->Forwards == TRUE) ? STRING_YES : STRING_NO));
  1885. DisplayMessage(g_hModule, MSG_NEWLINE);
  1886. if (IF->LocalLinkLayerAddress != 0) {
  1887. DisplayMessage(g_hModule, MSG_IPV6_LL_ADDRESS,
  1888. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1889. (UCHAR *)IF + IF->LocalLinkLayerAddress));
  1890. }
  1891. if (IF->RemoteLinkLayerAddress != 0) {
  1892. DisplayMessage(g_hModule, MSG_IPV6_REMOTE_LL_ADDRESS,
  1893. FormatLinkLayerAddress(IF->LinkLayerAddressLength,
  1894. (UCHAR *)IF + IF->RemoteLinkLayerAddress));
  1895. }
  1896. break;
  1897. }
  1898. return NO_ERROR;
  1899. }
  1900. DWORD
  1901. QueryInterface(
  1902. IN PWCHAR pwszIfFriendlyName,
  1903. IN FORMAT Format,
  1904. IN BOOL bPersistent
  1905. )
  1906. {
  1907. IPV6_INFO_INTERFACE *IF;
  1908. PIP_ADAPTER_ADDRESSES pAdapterInfo;
  1909. DWORD dwErr;
  1910. dwErr = OpenIPv6(Format);
  1911. if (dwErr != NO_ERROR) {
  1912. return dwErr;
  1913. }
  1914. if (Format != FORMAT_DUMP) {
  1915. DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
  1916. }
  1917. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  1918. if (dwErr == ERROR_NO_DATA) {
  1919. if (Format != FORMAT_DUMP) {
  1920. DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES);
  1921. }
  1922. return NO_ERROR;
  1923. }
  1924. if (dwErr != NO_ERROR) {
  1925. return dwErr;
  1926. }
  1927. if (pwszIfFriendlyName == NULL) {
  1928. ForEachInterface(PrintInterface, pAdapterInfo, Format, bPersistent);
  1929. } else {
  1930. dwErr = GetInterfaceByFriendlyName(pwszIfFriendlyName, pAdapterInfo,
  1931. bPersistent, &IF);
  1932. if (dwErr == NO_ERROR) {
  1933. dwErr = PrintInterface(IF, pAdapterInfo, 0, Format, bPersistent);
  1934. FREE(IF);
  1935. }
  1936. }
  1937. FREE(pAdapterInfo);
  1938. return dwErr;
  1939. }
  1940. DWORD
  1941. DeleteInterface(
  1942. IN PWCHAR pwszIfFriendlyName,
  1943. IN BOOL bPersistent
  1944. )
  1945. {
  1946. IPV6_QUERY_INTERFACE Query;
  1947. IP_ADAPTER_ADDRESSES *pAdapterInfo;
  1948. DWORD dwBytesReturned, dwErr;
  1949. dwErr = OpenIPv6(FORMAT_NORMAL);
  1950. if (dwErr != NO_ERROR) {
  1951. return dwErr;
  1952. }
  1953. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  1954. if (dwErr != NO_ERROR) {
  1955. return dwErr;
  1956. }
  1957. dwErr = MapFriendlyNameToIpv6IfIndex(pwszIfFriendlyName, pAdapterInfo,
  1958. &Query.Index);
  1959. FREE(pAdapterInfo);
  1960. if (dwErr != NO_ERROR) {
  1961. return dwErr;
  1962. }
  1963. dwErr = ERROR_OKAY;
  1964. if (!DeviceIoControl(Handle,
  1965. (bPersistent)
  1966. ? IOCTL_IPV6_PERSISTENT_DELETE_INTERFACE
  1967. : IOCTL_IPV6_DELETE_INTERFACE,
  1968. &Query, sizeof Query,
  1969. NULL, 0, &dwBytesReturned, NULL)) {
  1970. if (dwErr == ERROR_OKAY) {
  1971. dwErr = GetLastError();
  1972. }
  1973. }
  1974. return dwErr;
  1975. }
  1976. #define KEY_TCPIP6_IF L"System\\CurrentControlSet\\Services\\Tcpip6\\Parameters\\Interfaces"
  1977. DWORD
  1978. SetFriendlyName(
  1979. IN GUID *pGuid,
  1980. IN PWCHAR pwszFriendlyName
  1981. )
  1982. {
  1983. DWORD dwErr;
  1984. HKEY hInterfaces = INVALID_HANDLE_VALUE, hIf = INVALID_HANDLE_VALUE;
  1985. UNICODE_STRING usGuid;
  1986. dwErr = RtlStringFromGUID(pGuid, &usGuid);
  1987. if (!NT_SUCCESS(dwErr)) {
  1988. return dwErr;
  1989. }
  1990. dwErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, KEY_TCPIP6_IF, 0, GENERIC_READ,
  1991. &hInterfaces);
  1992. if (dwErr != NO_ERROR) {
  1993. goto Cleanup;
  1994. }
  1995. dwErr = RegOpenKeyExW(hInterfaces, usGuid.Buffer, 0, GENERIC_WRITE, &hIf);
  1996. if (dwErr != NO_ERROR) {
  1997. goto Cleanup;
  1998. }
  1999. dwErr = SetString(hIf, L"FriendlyName", pwszFriendlyName);
  2000. Cleanup:
  2001. if (hInterfaces != INVALID_HANDLE_VALUE) {
  2002. RegCloseKey(hInterfaces);
  2003. }
  2004. if (hIf != INVALID_HANDLE_VALUE) {
  2005. RegCloseKey(hIf);
  2006. }
  2007. RtlFreeUnicodeString(&usGuid);
  2008. return dwErr;
  2009. }
  2010. DWORD
  2011. AddTunnelInterface(
  2012. IN PWCHAR pwszFriendlyName,
  2013. IN IN_ADDR *pipLocalAddr,
  2014. IN IN_ADDR *pipRemoteAddr,
  2015. IN DWORD dwType,
  2016. IN DWORD dwDiscovery,
  2017. IN BOOL bPersistent
  2018. )
  2019. {
  2020. struct {
  2021. IPV6_INFO_INTERFACE Info;
  2022. IN_ADDR SrcAddr;
  2023. IN_ADDR DstAddr;
  2024. } Create;
  2025. IPV6_QUERY_INTERFACE Result;
  2026. DWORD dwBytesReturned, dwErr;
  2027. dwErr = OpenIPv6(FORMAT_NORMAL);
  2028. if (dwErr != NO_ERROR) {
  2029. return dwErr;
  2030. }
  2031. //
  2032. // TODO: use pwszFriendlyName when persistent config is ready
  2033. //
  2034. IPV6_INIT_INFO_INTERFACE(&Create.Info);
  2035. Create.Info.Type = dwType;
  2036. Create.Info.NeighborDiscovers = dwDiscovery;
  2037. Create.Info.RouterDiscovers = dwDiscovery;
  2038. Create.Info.LinkLayerAddressLength = sizeof(IN_ADDR);
  2039. if (pipLocalAddr != NULL) {
  2040. Create.SrcAddr = *pipLocalAddr;
  2041. Create.Info.LocalLinkLayerAddress = (u_int)
  2042. ((char *)&Create.SrcAddr - (char *)&Create.Info);
  2043. }
  2044. if (pipRemoteAddr != NULL) {
  2045. Create.DstAddr = *pipRemoteAddr;
  2046. Create.Info.RemoteLinkLayerAddress = (u_int)
  2047. ((char *)&Create.DstAddr - (char *)&Create.Info);
  2048. }
  2049. dwErr = ERROR_OKAY;
  2050. if (!DeviceIoControl(Handle,
  2051. (bPersistent)
  2052. ? IOCTL_IPV6_PERSISTENT_CREATE_INTERFACE
  2053. : IOCTL_IPV6_CREATE_INTERFACE,
  2054. &Create, sizeof Create,
  2055. &Result, sizeof Result, &dwBytesReturned, NULL) ||
  2056. (dwBytesReturned != sizeof Result)) {
  2057. dwErr = GetLastError();
  2058. } else if (bPersistent) {
  2059. SetFriendlyName(&Result.Guid, pwszFriendlyName);
  2060. }
  2061. return dwErr;
  2062. }
  2063. DWORD
  2064. UpdateInterface(
  2065. IN PWCHAR pwszIfFriendlyName,
  2066. IN DWORD dwForwarding,
  2067. IN DWORD dwAdvertises,
  2068. IN DWORD dwMtu,
  2069. IN DWORD dwSiteId,
  2070. IN DWORD dwMetric,
  2071. IN DWORD dwFirewall,
  2072. IN DWORD dwDefSitePrefixLength,
  2073. IN BOOL bPersistent
  2074. )
  2075. {
  2076. IPV6_INFO_INTERFACE Update;
  2077. DWORD dwBytesReturned, dwErr;
  2078. PIP_ADAPTER_ADDRESSES pAdapterInfo;
  2079. dwErr = OpenIPv6(FORMAT_NORMAL);
  2080. if (dwErr != NO_ERROR) {
  2081. return dwErr;
  2082. }
  2083. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  2084. if (dwErr != NO_ERROR) {
  2085. return dwErr;
  2086. }
  2087. IPV6_INIT_INFO_INTERFACE(&Update);
  2088. dwErr = MapFriendlyNameToIpv6IfIndex(pwszIfFriendlyName, pAdapterInfo,
  2089. &Update.This.Index);
  2090. FREE(pAdapterInfo);
  2091. if (dwErr != NO_ERROR) {
  2092. return dwErr;
  2093. }
  2094. Update.Advertises = dwAdvertises;
  2095. Update.Forwards = dwForwarding;
  2096. Update.FirewallEnabled = dwFirewall;
  2097. Update.LinkMTU = dwMtu;
  2098. Update.Preference = dwMetric;
  2099. Update.ZoneIndices[ADE_SITE_LOCAL] = dwSiteId;
  2100. Update.DefSitePrefixLength = dwDefSitePrefixLength;
  2101. dwErr = ERROR_OKAY;
  2102. if (bPersistent) {
  2103. if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_INTERFACE,
  2104. &Update, sizeof Update,
  2105. NULL, 0,
  2106. &dwBytesReturned, NULL)) {
  2107. dwErr = GetLastError();
  2108. }
  2109. }
  2110. if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_INTERFACE,
  2111. &Update, sizeof Update,
  2112. NULL, 0, &dwBytesReturned, NULL)) {
  2113. if (dwErr == ERROR_OKAY) {
  2114. dwErr = GetLastError();
  2115. }
  2116. }
  2117. return dwErr;
  2118. }
  2119. //////////////////////////////////////////////////////////////////////////////
  2120. // Neighbor cache functions
  2121. //////////////////////////////////////////////////////////////////////////////
  2122. DWORD
  2123. PrintNeighborCacheEntry(
  2124. IN IPV6_INFO_NEIGHBOR_CACHE *NCE,
  2125. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2126. IN DWORD dwCount
  2127. )
  2128. {
  2129. DWORD dwErr;
  2130. PWCHAR pwszLinkLayerAddress = L"";
  2131. PWCHAR pwszUnreachable;
  2132. if (NCE->NDState != ND_STATE_INCOMPLETE) {
  2133. pwszLinkLayerAddress = FormatLinkLayerAddress(
  2134. NCE->LinkLayerAddressLength, (u_char *)(NCE + 1));
  2135. }
  2136. if (!dwCount) {
  2137. PWCHAR pwszFriendlyName;
  2138. dwErr = MapIpv6IfIndexToFriendlyName(NCE->Query.IF.Index, pAdapterInfo,
  2139. &pwszFriendlyName);
  2140. if (dwErr != NO_ERROR) {
  2141. return dwErr;
  2142. }
  2143. DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_CACHE_HDR,
  2144. NCE->Query.IF.Index, pwszFriendlyName);
  2145. }
  2146. pwszUnreachable = MakeString(g_hModule, MSG_IPV6_NEIGHBOR_UNREACHABLE);
  2147. DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_CACHE_ENTRY,
  2148. FormatIPv6Address(&NCE->Query.Address, 0),
  2149. ((NCE->IsUnreachable)? pwszUnreachable : pwszLinkLayerAddress));
  2150. FreeString(pwszUnreachable);
  2151. switch (NCE->NDState) {
  2152. case ND_STATE_INCOMPLETE:
  2153. DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_INCOMPLETE);
  2154. break;
  2155. case ND_STATE_PROBE:
  2156. DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_PROBE);
  2157. break;
  2158. case ND_STATE_DELAY:
  2159. DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_DELAY);
  2160. break;
  2161. case ND_STATE_STALE:
  2162. DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_STALE);
  2163. break;
  2164. case ND_STATE_REACHABLE:
  2165. DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_REACHABLE,
  2166. NCE->ReachableTimer / 1000);
  2167. break;
  2168. case ND_STATE_PERMANENT:
  2169. DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_PERMANENT);
  2170. break;
  2171. default:
  2172. DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_UNKNOWN,
  2173. NCE->NDState);
  2174. break;
  2175. }
  2176. if (NCE->IsRouter) {
  2177. DisplayMessage(g_hModule, MSG_IPV6_NEIGHBOR_ISROUTER);
  2178. }
  2179. DisplayMessage(g_hModule, MSG_NEWLINE);
  2180. return NO_ERROR;
  2181. }
  2182. DWORD
  2183. ForEachNeighborCacheEntry(
  2184. IN IPV6_INFO_INTERFACE *IF,
  2185. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2186. IN DWORD (*pfnFunc)(IPV6_INFO_NEIGHBOR_CACHE *,PIP_ADAPTER_ADDRESSES,DWORD)
  2187. )
  2188. {
  2189. IPV6_QUERY_NEIGHBOR_CACHE Query, NextQuery;
  2190. IPV6_INFO_NEIGHBOR_CACHE *NCE;
  2191. DWORD dwInfoSize, dwBytesReturned;
  2192. DWORD dwCount = 0;
  2193. dwInfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH;
  2194. NCE = (IPV6_INFO_NEIGHBOR_CACHE *) MALLOC(dwInfoSize);
  2195. if (NCE == NULL) {
  2196. return 0;
  2197. }
  2198. NextQuery.IF = IF->This;
  2199. NextQuery.Address = in6addr_any;
  2200. for (;;) {
  2201. Query = NextQuery;
  2202. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE,
  2203. &Query, sizeof Query,
  2204. NCE, dwInfoSize, &dwBytesReturned,
  2205. NULL)) {
  2206. return dwCount;
  2207. }
  2208. NextQuery = NCE->Query;
  2209. if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
  2210. if ((dwBytesReturned < sizeof *NCE) ||
  2211. (dwBytesReturned != sizeof *NCE + NCE->LinkLayerAddressLength)) {
  2212. return dwCount;
  2213. }
  2214. NCE->Query = Query;
  2215. if ((*pfnFunc)(NCE,pAdapterInfo,dwCount) == NO_ERROR) {
  2216. dwCount++;
  2217. }
  2218. }
  2219. if (IN6_ADDR_EQUAL(&NextQuery.Address, &in6addr_any))
  2220. break;
  2221. }
  2222. FREE(NCE);
  2223. return dwCount;
  2224. }
  2225. DWORD
  2226. PrintNeighborCache(
  2227. IN IPV6_INFO_INTERFACE *IF,
  2228. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2229. IN DWORD dwIfCount,
  2230. IN FORMAT Format,
  2231. IN BOOL bPersistent
  2232. )
  2233. {
  2234. DWORD dwCount = ForEachNeighborCacheEntry(IF, pAdapterInfo,
  2235. PrintNeighborCacheEntry);
  2236. return (dwCount > 0)? NO_ERROR : ERROR_NO_DATA;
  2237. }
  2238. IPV6_INFO_NEIGHBOR_CACHE *
  2239. GetNeighborCacheEntry(
  2240. IN IPV6_INFO_INTERFACE *IF,
  2241. IN IN6_ADDR *Address
  2242. )
  2243. {
  2244. IPV6_QUERY_NEIGHBOR_CACHE Query;
  2245. IPV6_INFO_NEIGHBOR_CACHE *NCE;
  2246. DWORD dwInfoSize, dwBytesReturned;
  2247. dwInfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH;
  2248. NCE = (IPV6_INFO_NEIGHBOR_CACHE *) malloc(dwInfoSize);
  2249. if (NCE == NULL) {
  2250. return NULL;
  2251. }
  2252. Query.IF = IF->This;
  2253. Query.Address = *Address;
  2254. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE,
  2255. &Query, sizeof Query,
  2256. NCE, dwInfoSize, &dwBytesReturned,
  2257. NULL)) {
  2258. return NULL;
  2259. }
  2260. if ((dwBytesReturned < sizeof *NCE) ||
  2261. (dwBytesReturned != sizeof *NCE + NCE->LinkLayerAddressLength)) {
  2262. return NULL;
  2263. }
  2264. NCE->Query = Query;
  2265. return NCE;
  2266. }
  2267. DWORD
  2268. QueryNeighborCache(
  2269. IN PWCHAR pwszInterface,
  2270. IN IN6_ADDR *pipAddress
  2271. )
  2272. {
  2273. IPV6_INFO_INTERFACE *IF;
  2274. IPV6_INFO_NEIGHBOR_CACHE *NCE;
  2275. PIP_ADAPTER_ADDRESSES pAdapterInfo;
  2276. DWORD dwErr;
  2277. dwErr = OpenIPv6(FORMAT_NORMAL);
  2278. if (dwErr != NO_ERROR) {
  2279. return dwErr;
  2280. }
  2281. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  2282. if (dwErr != NO_ERROR) {
  2283. return dwErr;
  2284. }
  2285. if (!pwszInterface) {
  2286. ForEachInterface(PrintNeighborCache, pAdapterInfo, FORMAT_NORMAL,
  2287. FALSE);
  2288. FREE(pAdapterInfo);
  2289. return NO_ERROR;
  2290. }
  2291. dwErr = GetInterfaceByFriendlyName(pwszInterface, pAdapterInfo, FALSE, &IF);
  2292. if (dwErr != NO_ERROR) {
  2293. return dwErr;
  2294. }
  2295. if (!pipAddress) {
  2296. PrintNeighborCache(IF, pAdapterInfo, 0, FALSE, FALSE);
  2297. } else {
  2298. NCE = GetNeighborCacheEntry(IF, pipAddress);
  2299. if (NCE != NULL) {
  2300. PrintNeighborCacheEntry(NCE, pAdapterInfo, 0);
  2301. FREE(NCE);
  2302. }
  2303. }
  2304. FREE(IF);
  2305. FREE(pAdapterInfo);
  2306. return dwErr;
  2307. }
  2308. DWORD
  2309. FlushNeighborCacheForInterface(
  2310. IN IPV6_INFO_INTERFACE *IF,
  2311. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2312. IN DWORD dwCount,
  2313. IN FORMAT Format,
  2314. IN BOOL bPersistent
  2315. )
  2316. {
  2317. IPV6_QUERY_NEIGHBOR_CACHE Query;
  2318. DWORD dwBytesReturned;
  2319. Query.IF = IF->This;
  2320. Query.Address = in6addr_any;
  2321. if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_NEIGHBOR_CACHE,
  2322. &Query, sizeof Query,
  2323. NULL, 0, &dwBytesReturned, NULL)) {
  2324. return GetLastError();
  2325. }
  2326. return NO_ERROR;
  2327. }
  2328. DWORD
  2329. FlushNeighborCache(
  2330. IN PWCHAR pwszInterface,
  2331. IN IN6_ADDR *pipAddress
  2332. )
  2333. {
  2334. IPV6_QUERY_NEIGHBOR_CACHE Query;
  2335. DWORD dwBytesReturned, dwErr;
  2336. PIP_ADAPTER_ADDRESSES pAdapterInfo;
  2337. dwErr = OpenIPv6(FORMAT_NORMAL);
  2338. if (dwErr != NO_ERROR) {
  2339. return dwErr;
  2340. }
  2341. if (!pwszInterface) {
  2342. ForEachInterface(FlushNeighborCacheForInterface, NULL, FORMAT_NORMAL,
  2343. FALSE);
  2344. return NO_ERROR;
  2345. }
  2346. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  2347. if (dwErr != NO_ERROR) {
  2348. return dwErr;
  2349. }
  2350. dwErr = MapFriendlyNameToIpv6IfIndex(pwszInterface,
  2351. pAdapterInfo,
  2352. &Query.IF.Index);
  2353. if (dwErr != NO_ERROR) {
  2354. return dwErr;
  2355. }
  2356. if (pipAddress) {
  2357. Query.Address = *pipAddress;
  2358. } else {
  2359. Query.Address = in6addr_any;
  2360. }
  2361. if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_NEIGHBOR_CACHE,
  2362. &Query, sizeof Query,
  2363. NULL, 0, &dwBytesReturned, NULL)) {
  2364. return GetLastError();
  2365. }
  2366. return ERROR_OKAY;
  2367. }
  2368. //////////////////////////////////////////////////////////////////////////////
  2369. // Destination cache functions
  2370. //////////////////////////////////////////////////////////////////////////////
  2371. DWORD
  2372. PrintDestination(
  2373. IN IPV6_INFO_ROUTE_CACHE *RCE,
  2374. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2375. IN DWORD dwCount,
  2376. IN FORMAT Format
  2377. )
  2378. {
  2379. DWORD dwErr;
  2380. PWCHAR pwszTemp;
  2381. WCHAR wszTime[64];
  2382. if (!dwCount) {
  2383. PWCHAR pwszFriendlyName;
  2384. dwErr = MapIpv6IfIndexToFriendlyName(RCE->Query.IF.Index, pAdapterInfo,
  2385. &pwszFriendlyName);
  2386. if (dwErr != NO_ERROR) {
  2387. return dwErr;
  2388. }
  2389. DisplayMessage(g_hModule,
  2390. ((Format == FORMAT_VERBOSE)? MSG_IPV6_DESTINATION_HDR_VERBOSE : MSG_IPV6_DESTINATION_HDR),
  2391. RCE->Query.IF.Index, pwszFriendlyName);
  2392. }
  2393. DisplayMessage(g_hModule,
  2394. ((Format == FORMAT_VERBOSE)? MSG_IPV6_DESTINATION_ENTRY_VERBOSE : MSG_IPV6_DESTINATION_ENTRY),
  2395. ((RCE->PathMTU == 0)? IPv6_MINIMUM_MTU : RCE->PathMTU),
  2396. FormatIPv6Address(&RCE->Query.Address, 0));
  2397. DisplayMessage(g_hModule,
  2398. ((Format == FORMAT_VERBOSE)? MSG_IPV6_DESTINATION_NEXTHOP_VERBOSE : MSG_IPV6_DESTINATION_NEXTHOP),
  2399. FormatIPv6Address(&RCE->NextHopAddress, 0));
  2400. if (Format == FORMAT_VERBOSE) {
  2401. DisplayMessage(g_hModule,
  2402. MSG_IPV6_DESTINATION_SOURCE_ADDR,
  2403. FormatIPv6Address(&RCE->SourceAddress, 0));
  2404. pwszTemp = MakeString(g_hModule, ((RCE->Valid)? STRING_NO : STRING_YES));
  2405. DisplayMessage(g_hModule, MSG_IPV6_STALE, pwszTemp);
  2406. FreeString(pwszTemp);
  2407. switch (RCE->Flags) {
  2408. case RCE_FLAG_CONSTRAINED:
  2409. DisplayMessage(g_hModule, MSG_IPV6_IF_SPECIFIC);
  2410. break;
  2411. case RCE_FLAG_CONSTRAINED_SCOPEID:
  2412. DisplayMessage(g_hModule, MSG_IPV6_ZONE_SPECIFIC);
  2413. break;
  2414. }
  2415. if (RCE->PMTUProbeTimer != INFINITE_LIFETIME) {
  2416. DisplayMessage(g_hModule, MSG_IPV6_PMTU_PROBE_TIME,
  2417. FormatTime(RCE->PMTUProbeTimer/1000, wszTime));
  2418. }
  2419. if ((RCE->ICMPLastError != 0) && (RCE->ICMPLastError < 10*60*1000)) {
  2420. DisplayMessage(g_hModule, MSG_IPV6_ICMP_ERROR_TIME,
  2421. FormatTime(RCE->ICMPLastError/1000, wszTime));
  2422. }
  2423. if ((RCE->BindingSeqNumber != 0) ||
  2424. (RCE->BindingLifetime != 0) ||
  2425. ! IN6_ADDR_EQUAL(&RCE->CareOfAddress, &in6addr_any)) {
  2426. DisplayMessage(g_hModule, MSG_IPV6_CAREOF,
  2427. FormatIPv6Address(&RCE->CareOfAddress, 0),
  2428. RCE->BindingSeqNumber,
  2429. FormatTime(RCE->BindingLifetime, wszTime));
  2430. }
  2431. }
  2432. return NO_ERROR;
  2433. }
  2434. DWORD
  2435. ForEachDestination(
  2436. IN IPV6_INFO_INTERFACE *IF,
  2437. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2438. IN FORMAT Format,
  2439. IN DWORD (*pfnFunc)(IPV6_INFO_ROUTE_CACHE *,PIP_ADAPTER_ADDRESSES,DWORD,FORMAT)
  2440. )
  2441. {
  2442. IPV6_QUERY_ROUTE_CACHE Query, NextQuery;
  2443. IPV6_INFO_ROUTE_CACHE RCE;
  2444. DWORD dwBytesReturned, dwCount = 0;
  2445. NextQuery.IF.Index = 0;
  2446. NextQuery.Address = in6addr_any;
  2447. for (;;) {
  2448. Query = NextQuery;
  2449. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_CACHE,
  2450. &Query, sizeof Query,
  2451. &RCE, sizeof(RCE), &dwBytesReturned,
  2452. NULL)) {
  2453. return dwCount;
  2454. }
  2455. NextQuery = RCE.Query;
  2456. if (Query.IF.Index == IF->This.Index) {
  2457. RCE.Query = Query;
  2458. if ((*pfnFunc)(&RCE,pAdapterInfo,dwCount,Format) == NO_ERROR) {
  2459. dwCount++;
  2460. }
  2461. } else if (dwCount > 0) {
  2462. //
  2463. // Stop if we're done with the desired interface.
  2464. //
  2465. break;
  2466. }
  2467. if (NextQuery.IF.Index == 0) {
  2468. break;
  2469. }
  2470. }
  2471. return dwCount;
  2472. }
  2473. IPV6_INFO_ROUTE_CACHE *
  2474. GetDestination(
  2475. IN IPV6_QUERY_INTERFACE *IF,
  2476. IN IN6_ADDR *Address
  2477. )
  2478. {
  2479. IPV6_QUERY_ROUTE_CACHE Query;
  2480. IPV6_INFO_ROUTE_CACHE *RCE;
  2481. DWORD dwBytesReturned;
  2482. Query.IF = *IF;
  2483. Query.Address = *Address;
  2484. RCE = (IPV6_INFO_ROUTE_CACHE *) malloc(sizeof *RCE);
  2485. if (RCE == NULL) {
  2486. return NULL;
  2487. }
  2488. if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_CACHE,
  2489. &Query, sizeof Query,
  2490. RCE, sizeof *RCE, &dwBytesReturned,
  2491. NULL)) {
  2492. return NULL;
  2493. }
  2494. RCE->Query = Query;
  2495. return RCE;
  2496. }
  2497. DWORD
  2498. PrintRouteCache(
  2499. IN IPV6_INFO_INTERFACE *IF,
  2500. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2501. IN DWORD dwIfCount,
  2502. IN FORMAT Format,
  2503. IN BOOL bPersistent
  2504. )
  2505. {
  2506. DWORD dwCount = ForEachDestination(IF, pAdapterInfo, Format, PrintDestination);
  2507. return (dwCount > 0)? NO_ERROR : ERROR_NO_DATA;
  2508. }
  2509. DWORD
  2510. QueryRouteCache(
  2511. IN PWCHAR pwszInterface,
  2512. IN IN6_ADDR *pipAddress,
  2513. IN FORMAT Format
  2514. )
  2515. {
  2516. IPV6_INFO_INTERFACE *IF;
  2517. IPV6_INFO_ROUTE_CACHE *RCE;
  2518. PIP_ADAPTER_ADDRESSES pAdapterInfo;
  2519. DWORD dwCount, dwErr;
  2520. dwErr = OpenIPv6(Format);
  2521. if (dwErr != NO_ERROR) {
  2522. return dwErr;
  2523. }
  2524. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  2525. if (dwErr != NO_ERROR) {
  2526. return dwErr;
  2527. }
  2528. if (!pwszInterface) {
  2529. dwCount = ForEachInterface(PrintRouteCache, pAdapterInfo, Format,
  2530. FALSE);
  2531. FREE(pAdapterInfo);
  2532. if (dwCount == 0) {
  2533. DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES);
  2534. }
  2535. return NO_ERROR;
  2536. }
  2537. dwErr = GetInterfaceByFriendlyName(pwszInterface, pAdapterInfo, FALSE, &IF);
  2538. if (dwErr != NO_ERROR) {
  2539. return dwErr;
  2540. }
  2541. if (!pipAddress) {
  2542. if (PrintRouteCache(IF, pAdapterInfo, 0, Format, FALSE) == ERROR_NO_DATA) {
  2543. DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES);
  2544. }
  2545. } else {
  2546. RCE = GetDestination(&IF->This, pipAddress);
  2547. if (RCE != NULL) {
  2548. PrintDestination(RCE, pAdapterInfo, 0, Format);
  2549. FREE(RCE);
  2550. }
  2551. }
  2552. FREE(IF);
  2553. FREE(pAdapterInfo);
  2554. return dwErr;
  2555. }
  2556. DWORD
  2557. FlushRouteCacheForInterface(
  2558. IN IPV6_INFO_INTERFACE *IF,
  2559. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2560. IN DWORD dwCount,
  2561. IN FORMAT Format,
  2562. IN BOOL bPersistent
  2563. )
  2564. {
  2565. IPV6_QUERY_ROUTE_CACHE Query;
  2566. DWORD dwBytesReturned;
  2567. Query.IF = IF->This;
  2568. Query.Address = in6addr_any;
  2569. if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_ROUTE_CACHE,
  2570. &Query, sizeof Query,
  2571. NULL, 0, &dwBytesReturned, NULL)) {
  2572. return GetLastError();
  2573. }
  2574. return NO_ERROR;
  2575. }
  2576. DWORD
  2577. FlushRouteCache(
  2578. IN PWCHAR pwszInterface,
  2579. IN IN6_ADDR *pipAddress
  2580. )
  2581. {
  2582. IPV6_QUERY_ROUTE_CACHE Query;
  2583. DWORD dwBytesReturned, dwErr;
  2584. PIP_ADAPTER_ADDRESSES pAdapterInfo;
  2585. dwErr = OpenIPv6(FORMAT_NORMAL);
  2586. if (dwErr != NO_ERROR) {
  2587. return dwErr;
  2588. }
  2589. if (!pwszInterface) {
  2590. ForEachInterface(FlushRouteCacheForInterface, NULL, FORMAT_NORMAL,
  2591. FALSE);
  2592. return NO_ERROR;
  2593. }
  2594. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  2595. if (dwErr != NO_ERROR) {
  2596. return dwErr;
  2597. }
  2598. dwErr = MapFriendlyNameToIpv6IfIndex(pwszInterface,
  2599. pAdapterInfo,
  2600. &Query.IF.Index);
  2601. if (dwErr != NO_ERROR) {
  2602. return dwErr;
  2603. }
  2604. if (pipAddress) {
  2605. Query.Address = *pipAddress;
  2606. } else {
  2607. Query.Address = in6addr_any;
  2608. }
  2609. if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_ROUTE_CACHE,
  2610. &Query, sizeof Query,
  2611. NULL, 0, &dwBytesReturned, NULL)) {
  2612. return GetLastError();
  2613. }
  2614. return ERROR_OKAY;
  2615. }
  2616. //////////////////////////////////////////////////////////////////////////////
  2617. // Route table functions
  2618. //////////////////////////////////////////////////////////////////////////////
  2619. DWORD
  2620. ForEachRoute(
  2621. IN DWORD (*pfnFunc)(IPV6_INFO_ROUTE_TABLE *, IPV6_INFO_INTERFACE *, DWORD, PIP_ADAPTER_ADDRESSES, FORMAT),
  2622. IN DWORD dwArg,
  2623. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2624. IN FORMAT Format,
  2625. IN BOOL bPersistent
  2626. )
  2627. {
  2628. IPV6_QUERY_ROUTE_TABLE Query, NextQuery;
  2629. IPV6_INFO_ROUTE_TABLE RTE;
  2630. DWORD dwBytesReturned, dwCount = 0;
  2631. ZeroMemory(&NextQuery, sizeof(NextQuery));
  2632. for (;;) {
  2633. Query = NextQuery;
  2634. if (!DeviceIoControl(Handle,
  2635. IOCTL_IPV6_QUERY_ROUTE_TABLE,
  2636. &Query, sizeof Query,
  2637. &RTE, sizeof RTE, &dwBytesReturned,
  2638. NULL)) {
  2639. return dwCount;
  2640. }
  2641. NextQuery = RTE.Next;
  2642. if (Query.Neighbor.IF.Index != 0) {
  2643. RTE.This = Query;
  2644. if ((*pfnFunc)(&RTE, NULL, dwCount, pAdapterInfo, Format) == NO_ERROR) {
  2645. dwCount++;
  2646. }
  2647. }
  2648. if (NextQuery.Neighbor.IF.Index == 0)
  2649. break;
  2650. }
  2651. return dwCount;
  2652. }
  2653. //
  2654. // These are RFC 2465 ipv6RouteProtocol values, and must match
  2655. // RTE_TYPE_... in ntddip6.h.
  2656. //
  2657. DWORD RteTypeMsg[] = { 0,0,
  2658. STRING_SYSTEM,
  2659. STRING_MANUAL,
  2660. STRING_AUTOCONF,
  2661. STRING_RIP,
  2662. STRING_OSPF,
  2663. STRING_BGP,
  2664. STRING_IDRP,
  2665. STRING_IGRP
  2666. };
  2667. #define RTE_TYPE_MSG_COUNT (sizeof(RteTypeMsg)/sizeof(DWORD))
  2668. DWORD
  2669. PrintRouteTableEntry(
  2670. IN IPV6_INFO_ROUTE_TABLE *RTE,
  2671. IN IPV6_INFO_INTERFACE *IF,
  2672. IN DWORD dwCount,
  2673. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2674. IN FORMAT Format
  2675. )
  2676. {
  2677. DWORD dwTypeMsg, dwErr;
  2678. PWCHAR pwszPublishMsg, pwszFriendlyName;
  2679. if (Format != FORMAT_VERBOSE) {
  2680. //
  2681. // Suppress system routes (used for loopback).
  2682. //
  2683. if (RTE->Type == RTE_TYPE_SYSTEM) {
  2684. return ERROR_NO_DATA;
  2685. }
  2686. }
  2687. if (RTE->This.Neighbor.IF.Index == 0) {
  2688. dwErr = MapGuidToFriendlyName(NULL, &RTE->This.Neighbor.IF.Guid,
  2689. pAdapterInfo, &pwszFriendlyName);
  2690. } else {
  2691. dwErr = MapIpv6IfIndexToFriendlyName(RTE->This.Neighbor.IF.Index,
  2692. pAdapterInfo, &pwszFriendlyName);
  2693. }
  2694. if (dwErr != NO_ERROR) {
  2695. return dwErr;
  2696. }
  2697. pwszPublishMsg = TOKEN_VALUE_NO;
  2698. if (RTE->Publish) {
  2699. pwszPublishMsg = (RTE->Immortal)? TOKEN_VALUE_YES : TOKEN_VALUE_AGE;
  2700. }
  2701. if (Format == FORMAT_DUMP) {
  2702. DisplayMessageT(DMP_IPV6_ADD_ROUTE);
  2703. DisplayMessageT(DMP_STRING_ARG, TOKEN_PREFIX,
  2704. FormatIPv6Prefix(&RTE->This.Prefix,
  2705. RTE->This.PrefixLength));
  2706. DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE,
  2707. pwszFriendlyName);
  2708. DisplayMessageT(DMP_INTEGER_ARG, TOKEN_METRIC, RTE->Preference);
  2709. if (!IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any)) {
  2710. DisplayMessageT(DMP_STRING_ARG, TOKEN_NEXTHOP,
  2711. FormatIPv6Address(&RTE->This.Neighbor.Address, 0));
  2712. }
  2713. if (RTE->Publish) {
  2714. DisplayMessageT(DMP_STRING_ARG, TOKEN_PUBLISH, pwszPublishMsg);
  2715. if ((RTE->SitePrefixLength != 0) &&
  2716. IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any)) {
  2717. DisplayMessageT(DMP_STRING_ARG, TOKEN_SITEPREFIXLENGTH,
  2718. RTE->SitePrefixLength);
  2719. }
  2720. }
  2721. DisplayMessage(g_hModule, MSG_NEWLINE);
  2722. } else {
  2723. WCHAR wszValid[64], wszPreferred[64];
  2724. PWCHAR pwszTemp, pwszPrefix, pwszGateway;
  2725. BOOL bFreeIf = FALSE;
  2726. DWORD Preference;
  2727. if ((Format == FORMAT_NORMAL) && (dwCount == 0)) {
  2728. DisplayMessage(g_hModule, MSG_IPV6_ROUTE_TABLE_HDR);
  2729. }
  2730. dwTypeMsg = (RTE->Type < RTE_TYPE_MSG_COUNT)? RteTypeMsg[RTE->Type] : STRING_UNKNOWN;
  2731. pwszTemp = MakeString(g_hModule, dwTypeMsg);
  2732. pwszPrefix = FormatIPv6Prefix(&RTE->This.Prefix,
  2733. RTE->This.PrefixLength);
  2734. if (IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any)) {
  2735. pwszGateway = pwszFriendlyName;
  2736. } else {
  2737. pwszGateway = FormatIPv6Address(&RTE->This.Neighbor.Address, 0);
  2738. }
  2739. if (IF == NULL) {
  2740. IF = GetInterfaceByIpv6IfIndex(RTE->This.Neighbor.IF.Index);
  2741. if (!IF) {
  2742. FreeString(pwszTemp);
  2743. return ERROR_NO_DATA;
  2744. }
  2745. bFreeIf = TRUE;
  2746. }
  2747. Preference = RTE->Preference;
  2748. if (IF->Preference != -1) {
  2749. Preference += IF->Preference;
  2750. }
  2751. DisplayMessage(g_hModule,
  2752. ((Format == FORMAT_VERBOSE)? MSG_IPV6_ROUTE_TABLE_ENTRY_VERBOSE : MSG_IPV6_ROUTE_TABLE_ENTRY),
  2753. pwszPrefix,
  2754. RTE->This.Neighbor.IF.Index,
  2755. pwszGateway,
  2756. Preference,
  2757. pwszPublishMsg,
  2758. pwszTemp,
  2759. pwszFriendlyName,
  2760. FormatTime(RTE->ValidLifetime, wszValid),
  2761. FormatTime(RTE->PreferredLifetime, wszPreferred),
  2762. RTE->SitePrefixLength);
  2763. if (bFreeIf) {
  2764. FREE(IF);
  2765. }
  2766. FreeString(pwszTemp);
  2767. }
  2768. return NO_ERROR;
  2769. }
  2770. DWORD
  2771. ForEachPersistentRoute(
  2772. IN IPV6_INFO_INTERFACE *IF,
  2773. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2774. IN FORMAT Format,
  2775. IN DWORD (*pfnFunc)(IPV6_INFO_ROUTE_TABLE *, IPV6_INFO_INTERFACE *, DWORD, PIP_ADAPTER_ADDRESSES, FORMAT)
  2776. )
  2777. {
  2778. IPV6_PERSISTENT_QUERY_ROUTE_TABLE Query;
  2779. IPV6_INFO_ROUTE_TABLE RTE;
  2780. DWORD BytesReturned;
  2781. DWORD dwCount = 0;
  2782. Query.IF.RegistryIndex = (DWORD) -1;
  2783. Query.IF.Guid = IF->This.Guid;
  2784. for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
  2785. if (!DeviceIoControl(Handle,
  2786. IOCTL_IPV6_PERSISTENT_QUERY_ROUTE_TABLE,
  2787. &Query, sizeof Query,
  2788. &RTE, sizeof RTE, &BytesReturned,
  2789. NULL) ||
  2790. (BytesReturned != sizeof RTE)) {
  2791. break;
  2792. }
  2793. if ((*pfnFunc)(&RTE, IF, dwCount, pAdapterInfo, Format) == NO_ERROR) {
  2794. dwCount++;
  2795. }
  2796. }
  2797. return dwCount;
  2798. }
  2799. DWORD
  2800. PrintPersistentRoutesOnInterface(
  2801. IN IPV6_INFO_INTERFACE *IF,
  2802. IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
  2803. IN DWORD dwIfCount,
  2804. IN FORMAT Format,
  2805. IN BOOL bPersistent
  2806. )
  2807. {
  2808. DWORD dwCount = ForEachPersistentRoute(IF, pAdapterInfo, Format,
  2809. PrintRouteTableEntry);
  2810. return (dwCount > 0)? NO_ERROR : ERROR_NO_DATA;
  2811. }
  2812. DWORD
  2813. QueryRouteTable(
  2814. IN FORMAT Format,
  2815. IN BOOL bPersistent
  2816. )
  2817. {
  2818. DWORD dwErr, dwCount = 0;
  2819. PIP_ADAPTER_ADDRESSES pAdapterInfo;
  2820. dwErr = OpenIPv6(Format);
  2821. if (dwErr != NO_ERROR) {
  2822. return dwErr;
  2823. }
  2824. if (Format != FORMAT_DUMP) {
  2825. DisplayMessage(g_hModule, (bPersistent)? MSG_PERSISTENT : MSG_ACTIVE);
  2826. }
  2827. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  2828. if (dwErr != ERROR_NO_DATA) {
  2829. if (dwErr != NO_ERROR) {
  2830. return dwErr;
  2831. }
  2832. if (bPersistent) {
  2833. dwCount = ForEachPersistentInterface(
  2834. PrintPersistentRoutesOnInterface,
  2835. pAdapterInfo, Format);
  2836. } else {
  2837. dwCount = ForEachRoute(PrintRouteTableEntry, 0, pAdapterInfo,
  2838. Format, bPersistent);
  2839. }
  2840. FREE(pAdapterInfo);
  2841. }
  2842. if ((Format != FORMAT_DUMP) && !dwCount) {
  2843. DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES);
  2844. }
  2845. return NO_ERROR;
  2846. }
  2847. DWORD
  2848. UpdateRouteTable(
  2849. IN IN6_ADDR *pipPrefix,
  2850. IN DWORD dwPrefixLength,
  2851. IN PWCHAR pwszIfFriendlyName,
  2852. IN IN6_ADDR *pipNextHop,
  2853. IN DWORD dwMetric,
  2854. IN PUBLISH Publish,
  2855. IN DWORD dwSitePrefixLength,
  2856. IN DWORD dwValidLifetime,
  2857. IN DWORD dwPreferredLifetime,
  2858. IN BOOL bPersistent
  2859. )
  2860. {
  2861. IPV6_INFO_ROUTE_TABLE Route;
  2862. DWORD dwBytesReturned;
  2863. PIP_ADAPTER_ADDRESSES pAdapterInfo;
  2864. DWORD dwErr;
  2865. dwErr = OpenIPv6(FORMAT_NORMAL);
  2866. if (dwErr != NO_ERROR) {
  2867. return dwErr;
  2868. }
  2869. dwErr = MyGetAdaptersInfo(&pAdapterInfo);
  2870. if (dwErr != NO_ERROR) {
  2871. return dwErr;
  2872. }
  2873. dwErr = MapFriendlyNameToIpv6IfIndex(pwszIfFriendlyName, pAdapterInfo,
  2874. &Route.This.Neighbor.IF.Index);
  2875. FREE(pAdapterInfo);
  2876. if (dwErr != NO_ERROR) {
  2877. return dwErr;
  2878. }
  2879. Route.This.Prefix = *pipPrefix;
  2880. Route.This.PrefixLength = dwPrefixLength;
  2881. Route.This.Neighbor.Address = (pipNextHop)? *pipNextHop : in6addr_any;
  2882. Route.SitePrefixLength = dwSitePrefixLength;
  2883. Route.ValidLifetime = dwValidLifetime;
  2884. Route.PreferredLifetime = dwPreferredLifetime;
  2885. Route.Preference = dwMetric;
  2886. Route.Type = RTE_TYPE_MANUAL;
  2887. switch (Publish) {
  2888. case PUBLISH_IMMORTAL:
  2889. Route.Publish = TRUE;
  2890. Route.Immortal = TRUE;
  2891. break;
  2892. case PUBLISH_AGE:
  2893. Route.Publish = TRUE;
  2894. Route.Immortal = FALSE;
  2895. break;
  2896. case PUBLISH_NO:
  2897. Route.Publish = FALSE;
  2898. Route.Immortal = FALSE;
  2899. break;
  2900. default:
  2901. ASSERT(FALSE);
  2902. }
  2903. dwErr = ERROR_OKAY;
  2904. if (bPersistent) {
  2905. if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_UPDATE_ROUTE_TABLE,
  2906. &Route, sizeof Route,
  2907. NULL, 0,
  2908. &dwBytesReturned, NULL)) {
  2909. dwErr = GetLastError();
  2910. }
  2911. }
  2912. if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_ROUTE_TABLE,
  2913. &Route, sizeof Route,
  2914. NULL, 0, &dwBytesReturned, NULL)) {
  2915. if (dwErr == ERROR_OKAY) {
  2916. dwErr = GetLastError();
  2917. }
  2918. }
  2919. return dwErr;
  2920. }
  2921. DWORD
  2922. ResetIpv6Config(
  2923. IN BOOL bPersistent
  2924. )
  2925. {
  2926. DWORD dwBytesReturned, dwErr;
  2927. dwErr = OpenIPv6(FORMAT_NORMAL);
  2928. if (dwErr != NO_ERROR) {
  2929. return dwErr;
  2930. }
  2931. dwErr = ERROR_OKAY;
  2932. if (bPersistent) {
  2933. if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_RESET,
  2934. NULL, 0,
  2935. NULL, 0, &dwBytesReturned, NULL)) {
  2936. dwErr = GetLastError();
  2937. }
  2938. }
  2939. if (!DeviceIoControl(Handle, IOCTL_IPV6_RESET,
  2940. NULL, 0,
  2941. NULL, 0, &dwBytesReturned, NULL)) {
  2942. if (dwErr == ERROR_OKAY) {
  2943. dwErr = GetLastError();
  2944. }
  2945. }
  2946. return dwErr;
  2947. }