Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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